Skip to main content
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

Quick Start: Send a Template Message

If you already have an approved template, here’s how to send it with variables:

How Variables Work

A template can use one of two placeholder formats, and you pass values the same way for both:
  • Positional: {{1}}, {{2}}, {{3}} — keyed by position.
  • Named: {{customer_name}}, {{order_id}} — keyed by name.
In both cases you provide the values through templateVariables. The keys match the placeholders in the template body — numbers for positional templates, names for named templates:
You must provide values for all variables defined in the template. Missing variables will cause the message to fail (#100 INVALID_PARAMETER from Meta).

Named vs Positional — which does my template use?

You normally don’t need to care: Zavu detects the format per template and builds the correct Meta payload. The distinction matters only when you decide what keys to use in templateVariables:
Fetch the template (GET /v1/templates/{id}) and read its body to see which placeholders it expects. If the body shows {{customer_name}}, use { "customer_name": "..." }; if it shows {{1}}, use { "1": "..." }.

Text Header Variables

A template can have a text header with its own variable, e.g. Invitación Boda {{novios}}. The header variable is independent from the body variables, but you pass its value through the same templateVariables object, keyed by the header placeholder’s name (or {{1}} for a positional header):
WhatsApp text headers allow at most one variable. Static text headers (no placeholder) need no value — Meta has the text baked into the approved template.

Full Workflow

Templates follow a 3-step process: Create -> Submit for Approval -> Send.

Step 1: Create a Template

The variables array is optional and purely for documentation - it helps you remember what each position represents.

Step 2: Submit for Approval

Templates start in draft status. You need to explicitly submit them to Meta for review:
The senderId must be a sender with a WhatsApp Business Account connected. The template is submitted to Meta through that WABA.

Step 3: Check Approval Status

Only approved templates can be used to send messages. Attempting to use draft, pending, or rejected templates will fail.

Step 4: Send the Template

Once approved, send it using the positional variables (see Quick Start above).

Template Categories

Choose the category that best matches your use case. Miscategorization can lead to rejection.

Templates with Buttons

Add call-to-action or quick reply buttons:

Button Types

Sending Templates with Dynamic URL Buttons

When a template has a URL button with a {{1}} placeholder, pass the substitution under templateButtonVariables keyed by the button’s position in the template’s buttons array. templateVariables is for body placeholders. templateButtonVariables is for buttons. They use different keys:
  • templateVariables keys → position of the placeholder in the body text ("1", "2", …).
  • templateButtonVariables keys → index of the button in the buttons array ("0", "1", "2").
WhatsApp URL buttons only accept {{1}} (positional, numeric, no whitespace, no name). Even though body placeholders may use named parameters like {{name}}, URL buttons do not. Anything else ({{token}}, {{ 1 }}, {{user.id}}, etc.) is approved by Meta as literal text in the URL — there is no way to substitute it later.If your template was approved with a non-{{1}} placeholder in a URL button, you must recreate the template with {{1}} and resubmit it for approval. Zavu now returns 400 invalid_request instead of silently delivering broken URLs like https://...%7B%7Bvariable%7D%7D.
Example. Suppose your approved template looks like this:
Send it like this:
The recipient receives a button that opens https://reporte.link/abc-report-token.

Multiple buttons

For templates with several buttons, supply one entry per dynamic button. Static URL buttons (no {{1}}) and quick_reply buttons are not included in templateButtonVariables.
Index 1 (quick reply) and index 2 (static URL) are skipped.

Validation rules

Authentication Templates (OTP)

For verification codes, use AUTHENTICATION category with OTP buttons:
Send the OTP:
See the OTP Templates guide for more details.

Managing Templates

List Templates

Delete Template

Best Practices

Naming Conventions

Use descriptive, lowercase names with underscores:

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

Testing Templates

Test with your own phone number before sending to customers:
Use test mode API keys (zv_test_xxx) during development to avoid charges.