Send WhatsApp broadcast

View as Markdown
Creates a broadcast, records one message per recipient, atomically reserves credit (prepaid), and queues it for delivery over the WhatsApp Business Platform. Status updates reach your registered webhook URL. **Required scope:** `send_whatsapp` **Rate limit:** 10 requests / 15 min / client **Status lifecycle:** `pending → enqueued → accepted → sent → [delivered | read | failed]` `accepted` is an internal acknowledgement from the upstream provider and does **not** emit a webhook. The events you receive are `sent`, `delivered`, `read`, and `failed`. ## Template requirement WhatsApp messages are template-only - `templateName` is required and must reference an **approved** template owned by your client. Templates are managed in the Teekrr dashboard and pass through the platform's approval flow. If your client does not have its own WhatsApp Business Account (WABA), Teekrr falls back to the platform-default shared WABA automatically. ## Variables Template values are supplied as a single **named** map. There are no per-component (`header` / `body` / `button`) arrays and no positional parameters: ```json { "variables": { "templateParams": { "name": "Ali", "discount": "RM50 OFF" } } } ``` The keys are the `{{name}}` placeholders the template declares. Variable names must start with a letter or underscore and contain only letters, digits, and underscores. <Warning> The `variables` object is **strict** - it accepts `templateParams` and nothing else. Sending `header`, `body`, `button`, `headerImage`, `headerVideo`, `headerDocument`, or `bodyParams` is rejected with `400`, not ignored. </Warning> **Media headers and dynamic URL buttons are ordinary named variables.** Upload the asset via `POST /whatsapp/upload-header-image`, then pass the returned `url` as the value of whatever the template named that variable: ```json { "variables": { "templateParams": { "banner": "https://…/abc.jpg", "name": "Ali" } } } ``` In dynamic mode, `variables` is **required** on every `recipientVariables` row. ## Variable completeness Every variable the template declares must be supplied with a **non-empty** value - an empty string or whitespace counts as missing. Placeholders are declared across the template's header text, media-header URL, body, and buttons. A template with no declared variables accepts a request with no `variables` at all. Missing values are rejected with `400` before any credit is reserved: - **Standard mode** - `Template "<name>" requires values for: a, b. Declared variables: a, b.` - **Dynamic mode** - `Template "<name>" requires: a, b`, with an `errors` array naming the offending rows. Only the **first 10** offending rows are reported, even when more fail.

Authentication

AuthorizationBearer
Bearer API keys are issued from the in-app `/api-management` page. Each key has a permission scope (`send_sms`, `send_whatsapp`, `send_email`) and an optional IP whitelist. The IP whitelist, when set, is matched by **exact string equality** against the resolved caller IP - CIDR ranges are not supported. An empty whitelist allows any source address.

Request

This endpoint expects an object.
templateNamestringRequired1-512 characters
campaignNamestringRequired>=1 character
typeenumRequired
  • quick broadcast - send immediately
  • schedule broadcast - defer; requires scheduledAt. Not supported on the email channel.
scheduledAtdatetimeOptional

ISO 8601. Required when type = schedule broadcast.

recipientslist of stringsOptional
variablesobjectOptional

Template values for a WhatsApp send. This object is strict - templateParams is the only permitted key. Media headers and dynamic URL buttons are supplied as ordinary named entries inside templateParams, not as separate fields.

recipientVariableslist of objectsOptional

Response

Broadcast accepted (queued or scheduled)

dataobjectOptional

Errors

400
Bad Request Error
401
Unauthorized Error
402
Payment Required Error
403
Forbidden Error
404
Not Found Error
409
Conflict Error
413
Content Too Large Error
422
Unprocessable Entity Error
429
Too Many Requests Error
500
Internal Server Error