Enigma Developers

WhatsApp templates

Start or resume a WhatsApp conversation with an approved template.

WhatsApp only lets a business message a customer freely within 24 hours of the customer's last message. Outside that window, the first message must be a template that Meta has approved. Use templates for notifications such as order updates, reminders and one-time codes, and to re-open a conversation.

Endpoint: POST /v2/wa/template, scope message:send.

POST /v1/wa/template takes the same body but returns failures as an opaque 500. It still works but is deprecated; use v2.

Request

{
  "channelId": "3f6c1a2e-8b4d-4c7a-9e21-5d0b7f3a6c19",
  "to": "249912345678",
  "template": {
    "name": "order_update",
    "language": { "policy": "deterministic", "code": "en" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "Ahmed" },
          { "type": "text", "text": "#10234" }
        ]
      }
    ]
  }
}
  • channelId: copy it from your WhatsApp channel's card on the dashboard's Channels page.
  • to: the recipient's number in international format, digits only, no +.
  • template.name and template.language.code: exactly as approved in WhatsApp Manager. language.policy is always deterministic.
  • template.components: values for the template's variables, in order. Leave it out for a template without variables.

The first send to a number creates the contact and its conversation in Enigma, so replies show up in your inbox and on your webhook.

Components

Each {{n}} variable takes one parameter, in order.

Parameter typeFields
texttext
currencycurrency: { fallback_value, code, amount_1000 }. amount_1000 is the amount × 1000.
date_timedate_time: { fallback_value }
image, video, document, audioan object of the same name with link (public HTTPS URL) or id (WhatsApp media ID), plus optional caption and filename

A template with an image header:

{
  "type": "header",
  "parameters": [
    { "type": "image", "image": { "link": "https://example.com/banner.jpg" } }
  ]
}

Buttons

Buttons that need values take a button component per button. index is the button's zero-based position in the template.

sub_typeParameter
quick_reply{ "type": "payload", "payload": "…" }, returned to you when tapped
url{ "type": "text", "text": "…" }, appended to the template's dynamic URL
copy_code{ "type": "coupon_code", "coupon_code": "…" }
flow{ "type": "action", "action": { "flow_token": "…", "flow_action_data": { } } }
{
  "type": "button",
  "sub_type": "url",
  "index": 0,
  "parameters": [{ "type": "text", "text": "10234" }]
}

Response

201 means WhatsApp accepted the message:

{
  "success": true,
  "messageId": "wamid.HBgLMjQ5OTEyMzQ1Njc4FQIAERgS",
  "timestamp": "2026-10-10T08:45:35.000Z"
}

Keep messageId: the message_status webhook reports delivered, read or failed against it.

If the send fails, the response says why. 402 means not enough credits; 502 means WhatsApp rejected it, with the WhatsApp error code in errorDetails.code. See Errors.

On this page