🚀 GoSendAPI is in beta — Meta App Review in progress. Get on the waitlist →
Core ConceptsTemplates

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:

  1. The user starts the conversation (sends a message to the business) → 24h “conversation window” opens
  2. Inside the 24h window → you can send anything (text, media, anything)
  3. 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

CategoryUse caseApproval difficultyCost (per Meta pricing)
UTILITYTransactional: OTP, order confirmation, appointment reminder, password resetEasyLowest
AUTHENTICATIONOne-time codes only. Strict formatEasy if format rightLowest
MARKETINGPromo, sales, re-engagementHard, often rejectedHighest

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)
StatusMeaning
PENDINGSubmitted to Meta, awaiting approval
APPROVEDReady to send
REJECTEDMeta refused, see rejection reason. Fix and resubmit
PAUSEDWas approved but Meta paused due to low quality. Can be appealed

Components

A template is composed of optional parts:

ComponentRequired?Description
HEADEROptionalText / Image / Video / Document at the top
BODYRequiredMain text with variables {{1}}, {{2}}, etc.
FOOTEROptionalSmall text at bottom (e.g. “Reply STOP to unsubscribe”)
BUTTONSOptionalUp 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:

CodeLanguage
es_ARSpanish (Argentina)
es_MXSpanish (Mexico)
en_USEnglish (US)
enEnglish (generic)
pt_BRPortuguese (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

EventWhen it fires
whatsapp.template.approvedMeta approved your template
whatsapp.template.rejectedMeta rejected — check the reason in payload
whatsapp.template.pausedAuto-paused due to low quality

What’s next