Templates are pre-approved message formats required for contacting users outside the 24-hour conversation window. They must be submitted to Meta for approval before use.
Why Templates?
- Required by WhatsApp - Only way to message users outside 24-hour window
- Consistency - Ensure uniform messaging across your team
- Compliance - Meta reviews content for quality and policy compliance
- Analytics - Track performance by template
Creating a Template
Define Your Template
const template = await zavu.templates.create({
name: "order_confirmation",
category: "transactional",
language: "en",
body: "Hi {{customerName}}, your order #{{orderId}} has been confirmed! Estimated delivery: {{deliveryDate}}."
});
Variable Syntax
Use double curly braces for dynamic content:
Hi {{customerName}}, your order #{{orderId}} has been confirmed!
Variables are automatically extracted and validated when sending.
Template Categories
| Category | Use Case | Approval Speed |
|---|
transactional | Order updates, shipping, receipts | Fast (hours) |
marketing | Promotions, offers, newsletters | Slower (days) |
authentication | OTPs, verification codes | Fast (hours) |
utility | Account updates, alerts | Fast (hours) |
Choose the category that best matches your use case. Miscategorization can lead to rejection.
Approval Process
1. Submit Template
Templates are automatically submitted to Meta when created through the API.
2. Check Status
curl https://api.zavu.dev/v1/templates/tpl_abc123 \
-H "Authorization: Bearer zv_live_xxx"
Response:
{
"id": "tpl_abc123",
"name": "order_confirmation",
"status": "pending",
"category": "transactional",
"body": "Hi {{customerName}}, your order #{{orderId}} has been confirmed!..."
}
3. Status Values
| Status | Description |
|---|
pending | Submitted, awaiting Meta review |
approved | Ready to use |
rejected | Not approved - see rejection reason |
Only approved templates can be used to send messages. Attempting to use pending or rejected templates will fail.
Sending Template Messages
Once approved, use the template by ID:
const message = await zavu.messages.send({
to: "+56912345678",
messageType: "template",
content: {
templateId: "tpl_abc123",
templateVariables: {
customerName: "John",
orderId: "12345",
deliveryDate: "January 20, 2024"
}
}
});
Include images, videos, or documents in templates:
curl -X POST https://api.zavu.dev/v1/templates \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "shipping_update_with_image",
"category": "transactional",
"language": "en",
"header": {
"type": "image"
},
"body": "Hi {{customerName}}, your package is on the way! Track: {{trackingUrl}}"
}'
When sending, provide the media URL:
{
"to": "+56912345678",
"messageType": "template",
"content": {
"templateId": "tpl_abc123",
"header": {
"mediaUrl": "https://example.com/package-photo.jpg"
},
"templateVariables": {
"customerName": "John",
"trackingUrl": "https://track.co/abc"
}
}
}
Add call-to-action or quick reply buttons:
curl -X POST https://api.zavu.dev/v1/templates \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"name": "order_delivered",
"category": "transactional",
"language": "en",
"body": "Hi {{customerName}}, your order has been delivered!",
"buttons": [
{
"type": "url",
"text": "Track Order",
"url": "https://example.com/track/{{orderId}}"
},
{
"type": "quick_reply",
"text": "Rate Delivery"
}
]
}'
| Type | Description |
|---|
quick_reply | User response button |
url | Opens a URL (can include variables) |
phone_number | Initiates a phone call |
Managing Templates
List Templates
curl https://api.zavu.dev/v1/templates \
-H "Authorization: Bearer zv_live_xxx"
Update Template
curl -X PATCH https://api.zavu.dev/v1/templates/tpl_abc123 \
-H "Authorization: Bearer zv_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"body": "Hi {{customerName}}! Order #{{orderId}} confirmed. Arriving {{deliveryDate}}."
}'
Updating an approved template requires re-approval from Meta.
Delete Template
curl -X DELETE https://api.zavu.dev/v1/templates/tpl_abc123 \
-H "Authorization: Bearer zv_live_xxx"
Best Practices
Naming Conventions
Use descriptive, consistent names:
order_confirmation
shipping_update
password_reset
appointment_reminder
promotional_offer
Version Control
Include version in template names for updates:
order_confirmation_v1
order_confirmation_v2
Content Guidelines
Do:
- Use clear, concise language
- Include dynamic variables for personalization
- Provide value to the recipient
- Test with real data before production use
Don’t:
- Use placeholder text like “[insert name]”
- Include excessive capitalization or punctuation
- Send promotional content without consent
- Use misleading or clickbait content
Common Rejection Reasons
| Reason | Solution |
|---|
| Variable syntax error | Use format |
| Category mismatch | Choose correct category for content |
| Promotional in utility | Use marketing category for promotions |
| Missing opt-out | Include unsubscribe option for marketing |
| Policy violation | Review Meta’s commerce and messaging policies |
Testing Templates
Test with your own phone number before sending to customers:
curl -X POST https://api.zavu.dev/v1/messages \
-H "Authorization: Bearer zv_test_xxx" \
-H "Content-Type: application/json" \
-d '{
"to": "+your_phone_number",
"messageType": "template",
"content": {
"templateId": "tpl_abc123",
"templateVariables": {
"customerName": "Test User",
"orderId": "TEST-001"
}
}
}'
Use test mode API keys (zv_test_xxx) during development to avoid charges.