Un solo endpoint funciona sin importar por qué canal está la conversación:
- WhatsApp Business (Cloud API): se envía como plantilla real aprobada por Meta. La conexión WABA en el producto llegará pronto; hoy el listado puede estar vacío.
- WhatsApp Web, Instagram, Facebook o Widget Web: Yolani envía el mismo contenido como texto libre con variables reemplazadas (
delivery_mode: "text_fallback").
WhatsApp Business API:
La conexión por Cloud API en Yolani está próximamente. Mientras tanto, usa el endpoint con fallback de texto en conversaciones de WhatsApp Web u otros canales.
Tip:
La respuesta indica qué pasó realmente con delivery_mode: "template" (se envió como plantilla de Meta) o "text_fallback" (se envió como texto libre).
Listar plantillas aprobadas
GET /api/v1/templates
Scope: messages:send_template
Devuelve solo las plantillas con status APPROVED en tu WABA. Si tu cuenta no tiene WhatsApp Business (Cloud API) conectado, devuelve una lista vacía (puedes seguir usando el envío por fallback de texto libre si conoces el nombre y variables de tu plantilla).
curl https://api.yolani.co/api/v1/templates \
-H "Authorization: Bearer yol_TU_TOKEN"
Respuesta:
{
"success": true,
"data": [
{
"name": "pedido_en_camino",
"language": "es_MX",
"category": "UTILITY",
"body": "Hola {{1}}, tu pedido #{{2}} va en camino y llega hoy.",
"header_format": null,
"header_text": null,
"footer": null,
"buttons": []
}
]
}
Enviar una plantilla
POST /api/v1/conversations/:id/messages/template
Scope: messages:send_template
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
template_name | string | Sí | Nombre exacto de la plantilla aprobada |
language | string | No | Código de idioma (ej. es_MX). Si la omites, se usa la primera plantilla aprobada que coincida con el nombre |
body_params | string[] | Sí si la plantilla tiene variables | Valores para las variables del cuerpo, en orden ({{1}}, {{2}}, ...) |
header_param | string | No | Valor de la variable del encabezado, o URL pública del archivo si el encabezado es multimedia. Solo aplica cuando se envía como plantilla real (WhatsApp Business Cloud API) |
button_params | string[] | No | Valores para botones dinámicos (URL con variable, código de cupón). Solo aplica cuando se envía como plantilla real |
client_request_id | string | No | ID propio para idempotencia |
curl -X POST https://api.yolani.co/api/v1/conversations/913/messages/template \
-H "Authorization: Bearer yol_TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template_name": "pedido_en_camino",
"body_params": ["Andrea", "1042"]
}'
Respuesta (enviada como plantilla real):
{
"success": true,
"data": {
"message_id": 15300,
"conversation_id": 913,
"channel": "whatsapp",
"delivery_mode": "template",
"status": "sent"
}
}
Respuesta cuando el canal no soporta plantillas (se manda como texto):
{
"success": true,
"data": {
"message_id": 15301,
"conversation_id": 927,
"channel": "instagram",
"delivery_mode": "text_fallback",
"status": "sent"
}
}
Comportamiento por canal:
| Canal | ¿Cómo se envía? |
|---|---|
| WhatsApp Business (Cloud API) | Plantilla real aprobada por Meta. Soporta header_param y button_params |
| WhatsApp Web (sin Cloud API) | Texto libre con las variables ya reemplazadas. header_param y button_params se ignoran |
| Instagram / Facebook / Widget Web | Texto libre con las variables ya reemplazadas. header_param y button_params se ignoran |
Ejemplo: notificar pedido en camino
async function notificarPedidoEnCamino(conversationId, nombreCliente, numeroPedido) {
const response = await fetch(
`https://api.yolani.co/api/v1/conversations/${conversationId}/messages/template`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.YOLANI_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
template_name: 'pedido_en_camino',
body_params: [nombreCliente, numeroPedido],
client_request_id: `pedido-${numeroPedido}-en-camino`,
}),
},
);
return response.json();
}
import requests
def notificar_pedido_entregado(conversation_id, nombre_cliente, numero_pedido):
response = requests.post(
f"https://api.yolani.co/api/v1/conversations/{conversation_id}/messages/template",
headers={"Authorization": f"Bearer {YOLANI_API_KEY}"},
json={
"template_name": "pedido_entregado",
"body_params": [nombre_cliente, numero_pedido],
},
)
return response.json()
Errores propios de plantillas
| HTTP | Código | Descripción |
|---|---|---|
| 404 | TEMPLATE_NOT_FOUND | No existe una plantilla aprobada con ese template_name (y language, si lo enviaste) |
| 400 | TEMPLATE_NOT_APPROVED | La plantilla existe pero Meta aún no la aprueba |
| 400 | TEMPLATE_PARAMS_MISMATCH | La cantidad de body_params no coincide con las variables de la plantilla |
Ver también Errores y límites para los códigos generales de la API.