Send a WhatsApp template
curl --request POST \
--url https://backend.botcadence.com/organizations/{organization_id}/projects/{project_id}/broadcasts/{broadcast_id}/messages \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"to": "<string>"
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({to: '<string>'})
};
fetch('https://backend.botcadence.com/organizations/{organization_id}/projects/{project_id}/broadcasts/{broadcast_id}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://backend.botcadence.com/organizations/{organization_id}/projects/{project_id}/broadcasts/{broadcast_id}/messages"
payload = { "to": "<string>" }
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)WhatsApp
Send a WhatsApp template
Send one approved WhatsApp template through a broadcast and track its recipient in Botcadence
POST
/
organizations
/
{organization_id}
/
projects
/
{project_id}
/
broadcasts
/
{broadcast_id}
/
messages
Send a WhatsApp template
curl --request POST \
--url https://backend.botcadence.com/organizations/{organization_id}/projects/{project_id}/broadcasts/{broadcast_id}/messages \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"to": "<string>"
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({to: '<string>'})
};
fetch('https://backend.botcadence.com/organizations/{organization_id}/projects/{project_id}/broadcasts/{broadcast_id}/messages', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://backend.botcadence.com/organizations/{organization_id}/projects/{project_id}/broadcasts/{broadcast_id}/messages"
payload = { "to": "<string>" }
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)Send an approved template to one recipient and record the send under an existing broadcast. This request does not start the broadcast or send to its saved contact list. The recipient and delivery status appear in that broadcast’s recipient history.
This API accepts template messages only. To reply with a free-form message during an open WhatsApp conversation, use Conversations in the dashboard.
Required scope:
Fields such as
Meta must be able to fetch the HTTPS media URL without signing in. This API does not upload files.
End-to-end setup
- Connect a WhatsApp number to the project.
- Create a WhatsApp broadcast, select its sender, attach an approved template, and save it. The broadcast can stay in draft; this API call does not launch it.
- Note the names of the variables in the attached template. Pass their values in
data. - Create a project API key with the
whatsapp:createscope. Keep the key on your server. - Copy the organization, project, and broadcast IDs into the request below.
Authentication
Send the project API key as a Bearer token. See API authentication.Authorization: Bearer bot_live_YOUR_KEY
whatsapp:create
Path parameters
string
required
Organization that owns the project and API key.
string
required
Project containing the broadcast and connected WhatsApp number.
string
required
Existing broadcast used to track this send. Its saved contact list is not sent.
Request body
string
required
Recipient phone number in international format, such as
+14155552671. Spaces, parentheses, periods, and hyphens are removed.object
Named values for variables in the broadcast’s attached template. Keys must match the template variables. Use
header_media_url for a dynamic image, video, or document header, and header_location for a location header. Omit data or pass an empty object if the template has no variables.type and payload are not accepted. The template must be attached to the broadcast; callers cannot select a different template in the request.
Example 1: send a template with named body variables
Suppose the broadcast’s approved template has the variablesfirst_name and order_id.
curl -X POST \
"https://backend.botcadence.com/organizations/ORG_ID/projects/PROJECT_ID/broadcasts/BROADCAST_ID/messages" \
-H "Authorization: Bearer $BOTCADENCE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1042-confirmation" \
-d '{
"to": "+14155552671",
"data": {
"first_name": "Alex",
"order_id": "ORD-1042"
}
}'
Example 2: send a template with a dynamic image header
For a template with an image header and afirst_name body variable, pass a public HTTPS URL in header_media_url.
curl -X POST \
"https://backend.botcadence.com/organizations/ORG_ID/projects/PROJECT_ID/broadcasts/BROADCAST_ID/messages" \
-H "Authorization: Bearer $BOTCADENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155552671",
"data": {
"first_name": "Alex",
"header_media_url": "https://cdn.example.com/products/item-1042.png"
}
}'
Example 3: send a template with no variables
curl -X POST \
"https://backend.botcadence.com/organizations/ORG_ID/projects/PROJECT_ID/broadcasts/BROADCAST_ID/messages" \
-H "Authorization: Bearer $BOTCADENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155552671"
}'
Idempotent retries
You can send anIdempotency-Key header of 1–255 characters. If the original request included the header, retry a timeout with the same key and request body. For 24 hours, repeating the same key and request returns the saved result instead of sending again. Reusing a key with a different request returns 409 Conflict. If the provider outcome is still being resolved, the API returns 202 Accepted while it waits for a delivery status update. Without an idempotency key on the original request, a timeout retry may send a duplicate.
Idempotency-Key: order-1042-confirmation
Response
When Meta accepts the request, the API returns the internal message ID, broadcast ID, recipient, status, and Meta message ID when available. Acceptance does not mean the recipient has received or read the message; delivery updates appear in the broadcast recipient history.{
"status": "success",
"message": "WhatsApp template message accepted by Meta",
"data": {
"message_id": "665f1a2b3c4d5e6f7a8b9c0d",
"broadcast_id": "665f1a2b3c4d5e6f7a8b9c0e",
"to": "+14155552671",
"type": "template",
"status": "sent",
"provider_message_id": "wamid.HBgLMTQxNTU1NTI2NzEVAgARGBI..."
},
"status_code": 200
}
Limits and errors
An active plan, available WhatsApp template-send quota, a connected sender, and recipient messaging eligibility are required. Meta acceptance consumes one WhatsApp template send. A definite Meta rejection releases the reserved send. An uncertain provider outcome remains reserved while the API resolves its status webhook. Retry uncertain requests with the same idempotency key.| Status | Meaning |
|---|---|
400 | Invalid request, unavailable sender, invalid or unapproved broadcast template, or recipient opted out. |
401 | API key is missing, invalid, or revoked. |
402 | Plan is inactive or WhatsApp template-send quota is exhausted. |
403 | API key belongs to another organization/project or lacks whatsapp:create. |
404 | Broadcast does not exist in the organization and project. |
409 | Idempotency key was already used with a different request. |
202 | A send using this idempotency key is processing or its provider outcome is being resolved. |
422 | Request contains unsupported fields such as type or payload. |
503 | Provider outcome is unknown. Repeating the same idempotency key returns 202 until the webhook resolves it. |

