# Send a WhatsApp template message

`POST https://api.chat-data.com/api/v2/send-whatsapp-template`

Canonical: https://www.chat-data.com/api-reference/send-whatsapp-template

## Authentication

Send an API key as a Bearer token: `Authorization: Bearer $CHAT_DATA_API_KEY`. Workspace keys reach every chatbot in the workspace; chatbot-scoped keys reach only their chatbot. Keep keys on the server.

## Description

Sends an approved template from the chatbot's official WhatsApp integration to one recipient. Use it to start a conversation, or to reach a customer whose last message is more than 24 hours old.

The message is added to the conversation with the recipient (created if needed), and the customer's reply continues in that same conversation, keyed by the canonical WhatsApp id returned in `to`. A lead is created for the recipient if there is none.

Values are checked before anything is sent: every slot listed in the template's `variables` needs a value, and values cannot be empty or contain line breaks, tabs or five or more spaces in a row. Copy-code values are at most 20 characters and one-time codes at most 15. Dynamic URL values are URL-encoded for you.

Quick-reply buttons need no value. A FLOW button is sent with a token that links the customer's form submission back to this message; pass `template.flow.data` to set the Flow's initial data. Media headers use the template's approved sample unless `template.media` gives a replacement.

Sends with the same `idempotencyKey` within 5 minutes return the first result instead of sending again. Delivery progress (`sent`, `delivered`, `read`, `failed`) is available from `/whatsapp-message-status` and the `whatsapp-message-status` webhook.

## Request body (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| chatbotId | string | yes |  |
| to | string | yes | Recipient phone number with country code, with or without '+'. |
| from | string | no | The sending number (digits are compared) or its phone number id. Required when the chatbot has more than one WhatsApp number. |
| template | object | yes |  |
| template.name | string | yes |  |
| template.language | string | no | Required only when the template is approved in more than one language. |
| template.variables | object | no | Values per slot, grouped like the template's `variables`. |
| template.media | object | no | Replacement for a media header, by https link or uploaded media id. |
| template.media.link | string | no |  |
| template.media.id | string | no |  |
| template.media.filename | string | no | Shown for document headers. |
| template.flow | object | no |  |
| template.flow.data | object | no | Initial data passed to the Flow (`flow_action_data`). |
| otp | string | no | The one-time code for an authentication template (at most 15 characters). |
| idempotencyKey | string | no |  |

## Example request

```bash
curl 'https://api.chat-data.com/api/v2/send-whatsapp-template' \
  -H "Authorization: Bearer $CHAT_DATA_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "chatbotId": "6650f1c2a9e4b83d2c7a1f05",
  "to": "+14155552671",
  "template": {
    "name": "order_update"
  }
}'
```

## Example response (201)

```json
{
  "messageId": "wamid.HBgLMTQxNTU1NTI2NzEVAgARGBI5QTNDQTVCM0Q0Q0Q2RTY3RTcA",
  "to": "14155552671",
  "conversationId": "14155550100:14155552671",
  "status": "accepted"
}
```

## Responses

| Status | Description |
| --- | --- |
| 201 | WhatsApp accepted the message. |
| 400 | The request or a value is invalid, or WhatsApp rejected the template's parameters. `code` says which: WHATSAPP_NOT_CONNECTED, PHONE_NUMBER_REQUIRED, TEMPLATE_LANGUAGE_REQUIRED, TEMPLATE_NOT_APPROVED, MISSING_TEMPLATE_VARIABLES, INVALID_TEMPLATE_VARIABLES, TEMPLATE_PARAMS_REJECTED, RECIPIENT_INVALID, RECIPIENT_NOT_REACHABLE, MEDIA_UPLOAD_FAILED. `details` names the slots (for example `body[2]`). |
| 401 | Authentication failed: the `Authorization` header is missing or invalid, or the workspace's plan does not include API access. |
| 403 | WhatsApp is not allowing the sending number to send (`code` SEND_BLOCKED, with Meta's reason). Or: The API key cannot access the requested chatbot. A chatbot-scoped key used with another chatbot's ID gets `Access denied to this chatbot`. A workspace key, or a chatbot-scoped key used with its own chatbot's ID, gets `Chatbot <id> was not found in this API key's workspace. It may have been deleted or moved to another workspace.` when the chatbot does not exist or belongs to another workspace. |
| 404 | The sending number is not connected (PHONE_NUMBER_NOT_FOUND), or `template.name` is missing or no approved template has this name (TEMPLATE_NOT_FOUND). |
| 409 | A request with the same `idempotencyKey` is still being processed, or it ended without knowing whether WhatsApp took the message (no answer from WhatsApp, or an error after WhatsApp accepted it), or the key could not be checked. Requests with that key are refused until the 5 minutes pass, so the message is not sent twice. |
| 429 | The workspace sent more than 600 API requests in the last minute. |
| 500 | Something went wrong on our side (`code` WHATSAPP_SEND_FAILED). If it happened after WhatsApp accepted the message, `details.mayHaveSent` is `true` and the message may already have been delivered: do not send it again with a new or missing `idempotencyKey`. |
| 502 | WhatsApp did not accept the message for another reason, or did not answer (`code` WHATSAPP_SEND_FAILED, with Meta's message and error code in `details` when it answered). When it did not answer, `details.mayHaveSent` is `true`: the message may already have been delivered, so do not send it again with a new or missing `idempotencyKey`. |
