Templates
A template is a message structure pre-approved by Meta. It’s the only way to initiate a conversation with a contact outside the 24h window of a previous inbound message.
"Hello {{1}}, your appointment is on {{2}} at {{3}}. Reply YES to confirm."The {{1}}, {{2}}, {{3}} are runtime variables you fill when sending. Meta approves the structure; you fill the values.
Why templates exist
WhatsApp is a private messaging app. To prevent businesses from spamming, Meta requires:
- The user starts the conversation (sends a message to the business) → 24h “conversation window” opens
- Inside the 24h window → you can send anything (text, media, anything)
- Outside the 24h window → you can only send approved templates
If your customer hasn’t messaged you in 24h+, you cannot text them “Hello, did you forget?”. You can only send a pre-approved template.
Categories
| Category | Use case | Approval difficulty | Cost (per Meta pricing) |
|---|---|---|---|
UTILITY | Transactional: OTP, order confirmation, appointment reminder, password reset | Easy | Lowest |
AUTHENTICATION | One-time codes only. Strict format | Easy if format right | Lowest |
MARKETING | Promo, sales, re-engagement | Hard, often rejected | Highest |
Meta is aggressive with MARKETING approvals. If your template can be argued as utility (e.g. “your shipment is on the way”), submit as UTILITY. Saves money and approval time.
Lifecycle
(POST template)
│
▼
PENDING (Meta review, 1-24h typically)
│
┌────┴────┐
│ │
▼ ▼
APPROVED REJECTED
│
▼
(use in messages)
│
└──> PAUSED (Meta auto-pauses if quality drops — too many user blocks/reports)| Status | Meaning |
|---|---|
PENDING | Submitted to Meta, awaiting approval |
APPROVED | Ready to send |
REJECTED | Meta refused, see rejection reason. Fix and resubmit |
PAUSED | Was approved but Meta paused due to low quality. Can be appealed |
Components
A template is composed of optional parts:
| Component | Required? | Description |
|---|---|---|
HEADER | Optional | Text / Image / Video / Document at the top |
BODY | Required | Main text with variables {{1}}, {{2}}, etc. |
FOOTER | Optional | Small text at bottom (e.g. “Reply STOP to unsubscribe”) |
BUTTONS | Optional | Up to 3 buttons: Quick Reply / Call / URL |
Example structure for a UTILITY appointment reminder:
{
"name": "appointment_reminder",
"language": "es_AR",
"category": "UTILITY",
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Recordatorio de turno"
},
{
"type": "BODY",
"text": "Hola {{1}}, te recordamos tu turno el {{2}} a las {{3}} en {{4}}.",
"example": { "body_text": [["Juan", "20/05", "14:00", "Clínica San Lucas"]] }
},
{
"type": "FOOTER",
"text": "Para reprogramar respondé este mensaje."
},
{
"type": "BUTTONS",
"buttons": [
{ "type": "QUICK_REPLY", "text": "Confirmar" },
{ "type": "QUICK_REPLY", "text": "Cancelar" }
]
}
]
}Languages
Templates are per-language. The same template name in es_AR and en_US are separate templates — each needs Meta approval independently.
Common language codes:
| Code | Language |
|---|---|
es_AR | Spanish (Argentina) |
es_MX | Spanish (Mexico) |
en_US | English (US) |
en | English (generic) |
pt_BR | Portuguese (Brazil) |
Sync from Meta
If templates were created/edited directly in Meta WhatsApp Manager (or via Meta API), they get out of sync with GoSendAPI’s DB.
Use the Sync button in the dashboard (or POST /v1/wabas/:wabaId/templates/sync) to pull the latest from Meta and upsert into our DB.
curl -X POST https://cloud.gosendapi.com/v1/wabas/42/templates/sync \
-H "X-API-Key: gsk_live_..."
# Response:
# { "synced": 7 }This is also useful when a template’s status changes (PENDING → APPROVED) — although we also receive a webhook for that.
Sending a template message
POST /v1/messages
{
"phone_number_id": "555123456789",
"to": "5491140123456",
"type": "template",
"template": {
"name": "appointment_reminder",
"language": { "code": "es_AR" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Juan" },
{ "type": "text", "text": "20/05" },
{ "type": "text", "text": "14:00" },
{ "type": "text", "text": "Clínica San Lucas" }
]
}
]
}
}The values fill {{1}}, {{2}}, etc. in order.
Best practices
- Submit your essentials first (OTP, appointment, order confirmation). Get approved before launching.
- Always include the variable example in
example.body_text— Meta rejects templates without examples. - Avoid promotional phrasing in UTILITY (“¡Increíble oferta!”). Meta downgrades them to MARKETING (more expensive).
- Reuse across customers. A template is per-WABA. If 100 customers all need “appointment reminder”, each customer’s WABA needs its own copy. Use the Sync API + a script to bulk-submit.
Webhooks for template events
| Event | When it fires |
|---|---|
whatsapp.template.approved | Meta approved your template |
whatsapp.template.rejected | Meta rejected — check the reason in payload |
whatsapp.template.paused | Auto-paused due to low quality |