Template sending
Sends an approved message template through the WhatsApp Business API. The service resolves the template components directly from Meta: the payload only carries the template reference and its variable values.
Endpoint: POST /v1/template/messages/{did}
Parameters
Path
| Parameter | Type | Required | Description |
|---|---|---|---|
did | string | Yes | Destination ID. Must match the body did. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
did | string | Yes | Destination ID. Same as path. |
type | string | Yes | Fixed value template. |
channel | string | Yes | Fixed value WHATSAPP. |
template | object | Yes | {name, language}: name and language of the approved template. Returns 404 if that combination does not exist. |
recipients | array | Yes | List of recipients {to, params}. |
campaignId | number | No | Campaign ID (camelCase). |
client_id | number | No | Operating client. Requires BSP_CN permission when it differs from the token’s client. |
attends | object | No | {waitTime, typification}. See Attends. |
message_send_ttl_seconds | number | No | Message time-to-live in seconds. |
component | object | No | Image, video, document or location header. Required when the template uses that kind of header; type must match the template header format. |
Recipient params
All arrays are positional: the first element maps to {{1}}, the second to {{2}}, and so on.
| Field | Type | Description |
|---|---|---|
header | string[] | Values for the HEADER TEXT placeholder. |
body | string[] | Values for the BODY placeholders. |
buttons | string[] | Values for buttons carrying a variable (dynamic URL or COPY_CODE), in order of appearance. Buttons without variables (QUICK_REPLY, PHONE_NUMBER, static URL) are not declared. |
products | object[] | Products for MPM/SPM templates. |
cards | object[] | Per-card parameters in carousels: {body, buttons}. |
Fields you do not send
The service calculates these and they are not part of the payload: namespace (resolved from the DID’s BSP configuration), the template’s BODY, FOOTER and BUTTONS components (fetched from Meta) and the contact total (derived from recipients). The only component declared in the payload is component.header, for templates with an image, video, document or location header. Sending unrecognized fields can break the request.
Attends
attends configures post-send behavior:
| Field | Type | Description |
|---|---|---|
waitTime | number | Seconds to wait before handing over attention. QA usage: -1 keeps no attention session open, 0 starts immediately. Defaults to 0 when omitted. |
typification | number | Internal typification ID used to classify the interaction. 0 = untyped. |
Both fields are optional and passed as-is to the dispatch engine: the service neither validates nor calculates them.
Request
Examples use only required fields plus whatever each case needs. Remember sending is positional-only: templates created with parameter_format = "named" cannot be sent through this API.
Basic example
Text template with two body variables:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "customer_offer",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["John", "30"]
}
}
]
}'Plain text without variables
If the template has no placeholders, omit params:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "business_hours",
"language": "en"
},
"recipients": [
{ "to": "521234567890" }
]
}'Text header + variables
The header array feeds the header placeholder first; the body array, the body ones:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "appointment_reminder",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": {
"header": ["Appointment confirmation"],
"body": ["John", "tomorrow 10:00"]
}
}
]
}'Image, video or document header
For templates with a media header, component.header carries the type (which must match the template format), the file’s public URL and its name:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "product_catalog",
"language": "en"
},
"component": {
"header": {
"type": "image_url",
"value": "https://cdn.yourdomain.com/promo.jpg",
"filename": "promo.jpg"
}
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["John"]
}
}
]
}'Video and documents follow the same shape with "type": "video_url" or "document_url".
Location header
For templates with a LOCATION header, component.header carries the location object. The location is sent on every request even if identical for all recipients:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "nearest_store",
"language": "en"
},
"component": {
"header": {
"type": "location",
"location": {
"latitude": "-33.3925562",
"longitude": "-70.6261222",
"name": "Chattigo",
"address": "Av. El Salto 4001, floor 4, Huechuraba, Santiago"
}
}
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["John"]
}
}
]
}'URL button with variable
If the template’s URL button uses a variable in the link, its value travels in buttons:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "order_tracking",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["John"],
"buttons": ["12345"]
}
}
]
}'COPY_CODE button (discount code)
The coupon travels in buttons as a string:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "welcome_coupon",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["John"],
"buttons": ["WELCOME20"]
}
}
]
}'Catalog template (MPM)
For multi-product, products carries the action with the featured product and the catalog sections. IDs are the Meta catalog’s product_retailer_id values:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "hsm_multiproducto",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": {
"products": [
{
"type": "action",
"action": {
"thumbnailProductRetailerId": "0003",
"sections": [
{
"title": "Clothing and accessories",
"product_items": [
{ "product_retailer_id": "0064" },
{ "product_retailer_id": "0042" }
]
},
{
"title": "Food and drinks",
"product_items": [
{ "product_retailer_id": "0039" }
]
}
]
}
}
]
}
}
]
}'For single-product catalogs (SPM), action carries only thumbnailProductRetailerId.
Carousel
Each card receives its parameters in cards, in the same order as the template cards:
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"template": {
"name": "carousel_options",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": {
"cards": [
{ "body": ["Card 1"], "buttons": ["option-a"] },
{ "body": ["Card 2"], "buttons": ["option-b"] }
]
}
}
]
}'Full example with optional fields
curl --request POST \
--url 'https://api.chattigo.com/v1/template/messages/{did}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"did": "5731000000000",
"type": "template",
"channel": "WHATSAPP",
"campaignId": 3612,
"client_id": 42,
"attends": { "waitTime": 5, "typification": 383393 },
"message_send_ttl_seconds": 3600,
"template": {
"name": "customer_offer",
"language": "en"
},
"recipients": [
{
"to": "521234567890",
"params": { "body": ["John", "30"] }
}
]
}'Response
Success (200)
{
"success": true
}With warning (e.g.: campaign or language warning):
{
"success": true,
"warning": "..."
}Errors
| Code | Case |
|---|---|
400 | did is required or invalid payload |
403 | DID outside the WABA hierarchy or client_id without BSP_CN permission |
404 | Template does not exist for the requested name/language |
422 | Path did does not match body did, or invalid template |
502 | External service unreachable (Meta or internal dispatch) |
- Only templates in
APPROVEDstatus can be sent. - Positional only. Parameters (
header,body,buttons) are ordered[]stringand placeholders must be positional ({{1}},{{2}}, …).parameter_format = "named"is not supported; templates created asnamedin Meta cannot be sent through api-bsp-chattigo.