Mensajes de Plantilla
Cuando necesitas escribirle primero a un cliente — recuperar un carrito abandonado, avisar que un pedido está listo, entregar un PIN de retiro — el mensaje tiene que salir como una plantilla aprobada por Meta. Estos endpoints son la puerta pública para pedir ese envío y para consultar dónde quedó.Qué hace y qué no hace
Requisitos previos
Para saber qué plantillas puedes enviar, consulta el catálogo.
GET /v1/templates lista las que
tienes aprobadas, con el nombre y el idioma exactos que van en esta llamada. Una lista
vacía significa que todavía no hay ninguna aprobada, y hasta que la haya cada envío
se rechaza.
El campo sendable de cada plantilla dice si esta API puede enviarla: es false cuando el texto mezcla variables por posición y por nombre, las numera con huecos o lleva una variable en el encabezado (esta API rellena solo el cuerpo). Una plantilla con sendable: false responde 422 al enviar, y el arreglo está en Meta, no en tu request.Enviar un mensaje
Campos del request
El identificador de tu empresa no viaja en el request: se deriva de tu API key
(Autenticación). La plantilla sí viaja, por nombre e idioma, y se
valida contra las que tienes aprobadas.
Respuestas
Envío aceptado — 202
Validamos, reservamos el event_id y lo entregamos al servicio de envío. La respuesta
llega apenas eso ocurre y no trae el desenlace:
Sin envío nuevo — 200
Un 200 significa que esta petición no produjo un envío. Son dos casos:
- Un
event_idrepetido: devuelve el estado guardado de la primera petición (Idempotencia). - Un envío inviable de entrada — el aviso está vencido, la conversación del cliente está
en pausa, o el comercio apagó el envío desde el panel: responde
"status": "discarded"con el motivo enstatus_detail(stale,pausedodisabled). La petición funcionó; el envío está apagado a propósito.
Idempotencia
Mismoevent_id = mismo envío. Reenviarlo devuelve el estado de la primera petición y
nunca genera un segundo WhatsApp. Por eso es seguro reintentar ante un timeout de red.
La idempotencia corre antes de las validaciones de teléfono, plantilla y frescura: un
reenvío devuelve el estado guardado sin volver a juzgar esos datos. Lo que sí se evalúa
primero es la forma del cuerpo — el charset del event_id, los largos de
template.name y template.language, que occurred_at parsee. Un reenvío mal formado
recibe 422 y nunca llega a la idempotencia.
Hay un caso en que un event_id deja de servir: si del lado del envío ya quedó atado a otro
mensaje, o salió de la ventana de 30 días, la respuesta es 409 con
"type": "idempotency_conflict". Manda ese evento con un event_id nuevo — repetir el
mismo devuelve el mismo 409. A propósito no guardamos estado bajo la clave rechazada: si
lo hiciéramos, el siguiente intento recibiría un reenvío silencioso en vez del 409 que te
dice qué corregir.
Consultar el estado
“Enviado” no es “entregado”: Meta reporta la entrega al teléfono minutos u horas después — o nunca, si el teléfono está apagado. Ese ciclo se consulta por tuevent_id:
event_id que nunca se envió responde 404; uno que no respeta el charset responde
422.
Dos detalles útiles al integrar:
updated_ates cuándo cambió por última vez el registro, no cuándo consultaste. Consultar no lo mueve, pero una escritura de entrega que deja elstatusigual sí lo mueve, así que no lo uses como marca de agua: reconcilia porevent_id.- Sólo
failedydiscardedson definitivos.sent,deliveredyreadse vuelven a resolver en cada consulta, porque todavía puede llegar un recibo posterior — incluso uno de fallo después de unread.
Ventanas de tiempo
Errores
Los errores siguen el formato estándar de la API:Los dos
422 de cuenta se distinguen por detail[0].type, no por el campo: llegan
con "loc": ["body"] porque no hay un valor que corregir. Es el mismo formato de array
que cualquier otro 422 — ver Manejo de Errores. El 409, en cambio, usa el
formato estándar y trae su type en la raíz.Ni un aviso vencido, ni una conversación en pausa, ni el envío apagado son errores:
responden
200 con "status": "discarded" y "status_detail" en "stale", "paused" o
"disabled". Una pausa la pone un agente humano que tomó la conversación, o un corte por
facturación; el apagado lo pone el comercio desde el panel de carrito abandonado. Ninguno
de los dos se levanta desde el request.Receta: Shopify (Flow)
Shopify Flow hace este mismoPOST sin código y sin un servidor propio en medio: es el
ejemplo guiado del contrato de arriba, con el disparo del abandono ya resuelto.
¿Usas Shopify? Sigue la receta guiada →
Probar la integración
- Fase de prueba — envía a teléfonos de tu propio equipo, en una ventana acordada. El mensaje llega de verdad, con la plantilla real: esa es exactamente la prueba.
- Fase productiva — misma key, mismo contrato; solo cambia que los teléfonos son de clientes reales.

