Webhooks — Introducción

Qué son, cómo se configuran y cómo se entregan los webhooks salientes de Wasapi.

Un webhook es un aviso que Wasapi envía a un servidor suyo cada vez que ocurre algo en su
cuenta: llega un mensaje, se crea un contacto, cambia el estado de un envío. En vez de que su
sistema pregunte cada tanto si hay novedades, Wasapi se las manda en el momento.

📘

Esta sección documenta los webhooks salientes: los que Wasapi envía a su

integración. No cubre los webhooks entrantes de Meta hacia Wasapi.

Cómo se configura

  1. Entre a Configuración → Desarrolladores → Webhooks en la plataforma.
  2. Elija el evento que quiere recibir.
  3. Ponga la URL pública de su servidor.
  4. En los eventos que dependen de una línea, marque de qué números quiere recibirlos.

Puede tener varias URLs para un mismo evento: cada una recibe una copia.

El filtro por línea

De los 16 eventos, 13 se filtran por número de WhatsApp y 3 no:

Se filtran por líneaNo se filtran (aplican a toda la cuenta)
receive_message, send_message, send_bot_message, status_message, status_bot_contact, wa_flow_sent, wa_flow_response_received, message_facebook_advertising, los cinco survey_*create_contact, update_contact, delete_contact

⚠️ Si conecta una línea nueva, no queda suscrita automáticamente. Los webhooks
existentes siguen apuntando a las líneas que usted marcó cuando los creó. Es la causa más
común de «configuré el webhook y no llega»: revise que la línea nueva esté marcada.

Cómo se entrega

MétodoPOST
Content-Typeapplication/json
CuerpoEl envoltorio {event, data} que se describe abajo
Timeout4 segundos
Intentos3
Espera entre intentos10 s después del 1.º, 100 s después del 2.º
FirmaNo se firma. No hay cabecera de firma que validar

Su endpoint tiene 4 segundos

Wasapi corta la conexión a los 4 segundos y lo cuenta como fallo. Si su endpoint hace
trabajo pesado —consultar otra API, escribir en varias tablas, generar un PDF— no lo haga
dentro del request
: guarde el payload, responda de inmediato y procese después, en
segundo plano.

Qué se considera entrega exitosa

Cualquier código 2xx. Cualquier otra cosa (4xx, 5xx, timeout, error de conexión) se
reintenta hasta 3 veces en total y después se descarta: no hay bandeja de reenvío ni
notificación de fallo.

Consecuencia práctica: si su servidor estuvo caído más de ~2 minutos, esos eventos se
perdieron. Para datos que no puede perder, complemente el webhook con una lectura periódica
de la API REST.

Reintentos ⇒ su endpoint debe ser idempotente

Un reintento envía el mismo evento otra vez. Si su servidor recibió el aviso pero
respondió tarde o con un 500 después de haber guardado, va a recibirlo repetido.

Use una llave natural para descartar duplicados:

FamiliaLlave sugerida
Mensajesdata.wam_id (el id del mensaje en Meta), o data.id
Contactosdata.uuid + event
Encuestasdata.session_id + event

Tampoco hay garantía de orden. Dos eventos disparados con milisegundos de diferencia
pueden llegar al revés. No asuma que receive_message llega antes que el
update_contact que provocó.

Seguridad del endpoint

Como los webhooks no van firmados, cualquiera que descubra su URL puede enviarle datos
falsos. Recomendaciones:

  • Use una URL larga y no adivinable, o agregue un token en el query string
    (https://suservidor.com/wasapi?token=…) y valídelo.
  • Sirva el endpoint por HTTPS, con un certificado válido.
  • Trate el contenido como dato no confiable: valide antes de insertar.

El envoltorio

Todos los eventos llegan con la misma forma:

{
  "event": "receive_message",
  "data": {
    "...": "los campos del evento",
    "version": 1
  }
}
  • event — el nombre del evento, igual al que activó en la plataforma.
  • data — el contenido, distinto según la familia de evento.
  • data.version — la versión del contrato. Hoy siempre 1.

Los 16 eventos

EventoCuándo se disparaFamilia
receive_messageEntra un mensaje de un contactoMensaje
send_messageSale un mensaje desde la plataforma o la APIMensaje
send_bot_messageUn chatbot respondeMensaje
status_messageCambia el estado de un mensaje enviado (entregado, leído, fallido)Mensaje
wa_flow_sentSe envía un WhatsApp FlowMensaje
wa_flow_response_receivedEl contacto responde un FlowMensaje
create_contactSe crea un contactoContacto
update_contactSe modifica un contactoContacto
delete_contactSe borra un contactoContacto
status_bot_contactSe activa o desactiva el bot para un contactoContacto
message_facebook_advertisingLlega un mensaje desde un anuncio Click to WhatsAppPublicidad
survey_sentSe envía una encuesta de satisfacciónEncuesta
survey_startedEl contacto empieza a responderlaEncuesta
survey_response_receivedLlega una respuestaEncuesta
survey_completedLa encuesta se completaEncuesta
survey_expiredLa encuesta vence sin completarseEncuesta

Compatibilidad: qué podemos cambiar y qué no

🚧

La promesa: solo agregamos campos.

Dentro de la v1 del contrato, un campo documentado no se quita ni cambia de significado.
Lo que sí puede pasar es que aparezcan campos nuevos.

Si alguna vez hay que quitar o renombrar algo, habrá una v2 del payload y aviso
previo
a las cuentas con integración activa, con las dos versiones conviviendo durante
la transición.

Qué significa esto para su integración: debe tolerar campos que no conoce. Es la única
condición para que un cambio aditivo no la rompa.

// ✅ Tome lo que necesita
$telefono = $data['phone'] ?? null;

// ❌ No inserte el payload completo a ciegas:
// un campo nuevo rompe el INSERT
$db->insert('mensajes', $data);

Qué leer ahora

La página más importante es Identidad del contacto:
explica cómo saber a qué persona corresponde cada evento, incluido el caso de los contactos
que ocultan su número de teléfono.


Did this page help you?