Envío de plantilla
Envía una plantilla de mensaje aprobada a través de la API de WhatsApp Business. El servicio resuelve los componentes de la plantilla directamente desde Meta: el payload solo lleva la referencia de la plantilla y los valores de sus variables.
Endpoint: POST /v1/template/messages/{did}
Parámetros
Path
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
did | string | Sí | ID del destino. Debe coincidir con el did del body. |
Body
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
did | string | Sí | ID del destino. Igual al del path. |
type | string | Sí | Valor fijo template. |
channel | string | Sí | Valor fijo WHATSAPP. |
template | object | Sí | {name, language}: nombre e idioma de la plantilla aprobada. Si no existe esa combinación se devuelve 404. |
recipients | array | Sí | Lista de destinatarios {to, params}. |
campaignId | number | No | ID de campaña (va en camelCase). |
client_id | number | No | Cliente operador. Requiere permiso BSP_CN cuando difiere del cliente del token. |
attends | object | No | {waitTime, typification}. Ver Attends. |
message_send_ttl_seconds | number | No | Tiempo de validez del mensaje en segundos. |
component | object | No | Header de imagen, video, documento o ubicación. Obligatorio cuando la plantilla usa ese tipo de header; el type debe coincidir con el formato del header de la plantilla. |
params de cada recipient
Todos los arrays son posicionales: el primer elemento corresponde a {{1}}, el segundo a {{2}}, y así sucesivamente.
| Campo | Tipo | Descripción |
|---|---|---|
header | string[] | Valores del placeholder del HEADER TEXT. |
body | string[] | Valores de los placeholders del BODY. |
buttons | string[] | Valores de los botones que llevan variable (URL dinámica o COPY_CODE), en orden de aparición. Los botones sin variable (QUICK_REPLY, PHONE_NUMBER, URL estática) no se declaran. |
products | object[] | Productos para plantillas MPM/SPM. |
cards | object[] | Parámetros por tarjeta en carousel: {body, buttons}. |
Campos que no se envían
Estos datos los calcula el servicio y no forman parte del payload: namespace (se resuelve de la configuración BSP del DID), los componentes BODY, FOOTER y BUTTONS de la plantilla (se obtienen desde Meta) y el total de contactos (se deduce de recipients). El único componente que se declara en el payload es component.header, para plantillas con header de imagen, video, documento o ubicación. Enviar campos no reconocidos puede romper la request.
Attends
attends configura el comportamiento posterior al envío:
| Campo | Tipo | Descripción |
|---|---|---|
waitTime | number | Segundos de espera antes de derivar la atención. En QA se usa -1 para no abrir sesión de atención y 0 para atención inmediata. Si se omite se toma 0. |
typification | number | ID interno de tipificación con el que queda clasificada la interacción. 0 = sin tipificación. |
Ambos campos son opcionales y se pasan tal cual al motor de despacho: el servicio no los valida ni los calcula.
Request
Los ejemplos usan solo los campos obligatorios más los que cada caso necesita. Recordá que el envío es solo posicional: las plantillas creadas con parameter_format = "named" no pueden enviarse por esta API.
Ejemplo básico
Plantilla de texto con dos variables en el body:
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": "oferta_cliente",
"language": "es"
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["Juan", "30"]
}
}
]
}'Texto simple sin variables
Si la plantilla no tiene placeholders, params se omite:
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": "horarios_atencion",
"language": "es"
},
"recipients": [
{ "to": "521234567890" }
]
}'Header de texto + variables
El array header alimenta primero el placeholder del header; el array body, los del body:
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": "recordatorio_cita",
"language": "es"
},
"recipients": [
{
"to": "521234567890",
"params": {
"header": ["Confirmación de cita"],
"body": ["Juan", "mañana 10:00"]
}
}
]
}'Header de imagen, video o documento
Para plantillas con header media, component.header lleva el tipo (que debe coincidir con el formato de la plantilla), la URL pública del archivo y su nombre:
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": "catalogo_imagen",
"language": "es"
},
"component": {
"header": {
"type": "image_url",
"value": "https://cdn.tudominio.com/promo.jpg",
"filename": "promo.jpg"
}
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["Juan"]
}
}
]
}'Para video y documento el formato es igual, con "type": "video_url" o "document_url".
Header de ubicación
Para plantillas con header LOCATION, component.header lleva el objeto location. La ubicación se envía en cada request aunque sea la misma para todos los destinatarios:
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": "sucursal_cercana",
"language": "es"
},
"component": {
"header": {
"type": "location",
"location": {
"latitude": "-33.3925562",
"longitude": "-70.6261222",
"name": "Chattigo",
"address": "Av. El Salto 4001, piso 4, Huechuraba, Región Metropolitana"
}
}
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["Juan"]
}
}
]
}'Botón URL con variable
Si el botón URL de la plantilla usa una variable en el link, su valor viaja en 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": "seguimiento_pedido",
"language": "es"
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["Juan"],
"buttons": ["12345"]
}
}
]
}'Botón COPY_CODE (código de descuento)
El cupón viaja en buttons como 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": "cupon_bienvenida",
"language": "es"
},
"recipients": [
{
"to": "521234567890",
"params": {
"body": ["Juan"],
"buttons": ["BIENVENIDO20"]
}
}
]
}'Plantilla de catálogo (MPM)
Para multi-producto, products lleva la acción con el producto destacado y las secciones del catálogo. Los IDs son los product_retailer_id del catálogo de Meta:
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": "es"
},
"recipients": [
{
"to": "521234567890",
"params": {
"products": [
{
"type": "action",
"action": {
"thumbnailProductRetailerId": "0003",
"sections": [
{
"title": "Ropa y accesorios",
"product_items": [
{ "product_retailer_id": "0064" },
{ "product_retailer_id": "0042" }
]
},
{
"title": "Comida y bebida",
"product_items": [
{ "product_retailer_id": "0039" }
]
}
]
}
}
]
}
}
]
}'Para catálogo de producto único (SPM), action lleva solo thumbnailProductRetailerId.
Carousel
Cada tarjeta recibe sus parámetros en cards, en el mismo orden de las tarjetas de la plantilla:
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_opciones",
"language": "es"
},
"recipients": [
{
"to": "521234567890",
"params": {
"cards": [
{ "body": ["Tarjeta 1"], "buttons": ["opcion-a"] },
{ "body": ["Tarjeta 2"], "buttons": ["opcion-b"] }
]
}
}
]
}'Ejemplo completo con campos opcionales
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": "oferta_cliente",
"language": "es"
},
"recipients": [
{
"to": "521234567890",
"params": { "body": ["Juan", "30"] }
}
]
}'Response
Éxito (200)
{
"success": true
}Con warning (ej: campaña o idioma con warning):
{
"success": true,
"warning": "..."
}Errores
| Código | Caso |
|---|---|
400 | did is required o payload inválido |
403 | DID fuera de la jerarquía WABA o client_id sin permiso BSP_CN |
404 | La plantilla no existe para el name/language solicitados |
422 | El did del path no coincide con el del body, o la plantilla es inválida |
502 | Servicio externo inalcanzable (Meta o despacho interno) |
- Solo se pueden enviar plantillas en estado
APPROVED. - Solo posicional. Los parámetros (
header,body,buttons) son[]stringordenados y los placeholders deben ser posicionales ({{1}},{{2}}, …). No se admiteparameter_format = "named"; las plantillasnamedcreadas en Meta no pueden enviarse por api-bsp-chattigo.