Un webhook de WhatsApp permite que su sistema reciba mensajes de clientes y novedades sobre los mensajes enviados. Para configurarlo necesita un receptor accesible, seleccionar los eventos adecuados y comprobar qué ocurre con los datos recibidos. Esta guía recorre dos caminos: la conexión directa con Meta Cloud API y los callbacks de EngageLab. También muestra cómo relacionar un evento con una incidencia de atención al cliente y qué probar antes de ampliar la integración.
Qué es un webhook de WhatsApp y qué eventos permite recibir
Un webhook es una petición HTTP que una plataforma envía a una dirección de su servidor cuando ocurre un evento. El cuerpo contiene datos en JSON, también llamados payload. Su aplicación los recibe y decide qué hacer con ellos.
- Mensajes entrantes: una consulta, una respuesta o una interacción del cliente que puede incorporarse a una conversación.
- Estados de mensajes enviados: información de entrega, lectura o fallo, según el evento y la plataforma.
La respuesta de una API de envío y un estado de entrega responden a preguntas distintas: que la API acepte una petición no demuestra que el cliente haya recibido el mensaje. Además, una entrega o lectura tampoco acredita una compra. Aquí hablamos de estados de entrega de los mensajes, no de los contenidos que se publican en la pestaña «Estados» de WhatsApp.
Antes de configurar: Meta Cloud API o un proveedor
Identifique quién envía los callbacks a su sistema. Esa elección determina dónde configurar la dirección y cómo interpretar los datos.
| Conexión | Dónde configurar | Qué recibe | Responsabilidad propia |
|---|---|---|---|
| Directa con Meta | Aplicación de Meta y suscripción de la cuenta | Webhooks de Cloud API | Receptor, validación y relación con el negocio |
| A través de EngageLab | Configuración de callbacks de EngageLab | Formato documentado por EngageLab | Receptor y procesamiento de sus registros |
| Otro proveedor | El panel y la documentación de ese proveedor | Su propio contrato de eventos | Confirmar formato, autenticación y recuperación |
Los formatos no son intercambiables. Si necesita contexto sobre el servicio antes de configurar el receptor, consulte la guía de la API de WhatsApp Business.
Cómo configurar un webhook de WhatsApp paso a paso
Preparar el endpoint y separar prueba y producción
El endpoint es la ruta que recibirá las peticiones, por ejemplo, https://su-dominio.example/webhooks/whatsapp. Prepare una dirección HTTPS accesible desde Internet, el almacenamiento de eventos y registros de diagnóstico. Para Meta, el certificado debe ser válido; no se admiten certificados autofirmados.
Anote qué aplicación, cuenta y número de empresa pertenecen a cada entorno. Compruebe desde fuera de su red que la ruta responde al método previsto. Si falla, revise DNS, certificado, proxy y restricciones del servidor antes de cambiar la configuración de WhatsApp.
Mantenga separadas estas credenciales:
| Ruta | Credencial | Uso | Límite |
|---|---|---|---|
| Meta | Access token | Llamadas a Graph API con los permisos correspondientes | No sustituye al verify token |
| Meta | Verify token | Comparar el valor recibido al verificar la dirección | No autentica los POST posteriores |
| Meta | App Secret | Comprobar la firma de los eventos | Debe permanecer en el servidor |
| EngageLab | DevKey y DevSecret | Autenticación HTTP Basic de la API de envío | No acreditan por sí solos el origen del callback |
Si la conexión es directa con Meta
1. Verificar la dirección. Según la documentación de Meta para crear el receptor, la configuración está en App Dashboard → WhatsApp → Configuration. Para aplicaciones creadas con el caso de uso «Connect with customers through WhatsApp», la ruta es Use cases → Customize → Configuration. Introduzca la URL en Callback URL y una cadena propia en Verify token; guarde la misma cadena en el servidor.
Meta enviará una petición GET. Este ejemplo ilustra el intercambio; sustituya la ruta y el token:
GET /webhooks/whatsapp?hub.mode=subscribe&hub.verify_token=TOKEN_DE_VERIFICACION&hub.challenge=123456 HTTP/1.1
Host: su-dominio.example
Compruebe el modo de suscripción y que el token coincide. Si la petición es válida, devuelva el challenge como cuerpo, sin envolverlo en JSON:
HTTP/1.1 200 OK
Content-Type: text/plain
123456
Una petición inválida debe rechazarse. La señal de éxito es que la configuración se guarde tras el intercambio. Si no ocurre, examine el GET recibido, el token comparado y el cuerpo de respuesta.
2. Suscribir el campo de mensajes. En la configuración de webhooks de esa aplicación, suscriba messages. Este campo incluye mensajes entrantes y estados de los enviados. Compruebe que aparece suscrito: enviar una muestra con el botón de prueba no sustituye esta acción. La referencia de Meta indica el permiso whatsapp_business_messaging para estos eventos.
3. Comprobar la suscripción a la WABA. La cuenta de WhatsApp Business debe estar vinculada a la aplicación receptora mediante su suscripción. Si aún no lo está, utilice el endpoint de aplicaciones suscritas. Para esta operación, la colección oficial de Meta especifica un token de usuario del sistema con whatsapp_business_management.
POST /{VERSION}/{WABA_ID}/subscribed_apps HTTP/1.1
Host: graph.facebook.com
Authorization: Bearer {ACCESS_TOKEN}
Sustituya los valores entre llaves por la versión admitida por su integración, el ID de la WABA y el token de la aplicación correspondiente. Tras la respuesta de éxito, consulte la misma ruta con GET:
GET /{VERSION}/{WABA_ID}/subscribed_apps HTTP/1.1
Host: graph.facebook.com
Authorization: Bearer {ACCESS_TOKEN}
Compruebe que la lista contiene la aplicación esperada. Si no aparece o se devuelve un error, revise la cuenta, el token y sus permisos. No utilice el ID del número de teléfono en lugar del ID de la WABA.
4. Preparar la recepción de POST. Valide la firma como se explica en la sección de seguridad, conserve el evento y responda con HTTP 200. Para interpretar los datos, recorra todas las entradas y cambios: los mensajes están en entry[].changes[].value.messages[] y los estados en entry[].changes[].value.statuses[], según la referencia del campo messages. El procesamiento no debe limitarse al primer elemento.
Si la conexión utiliza EngageLab
1. Abrir la configuración. La guía de callbacks sitúa la opción en Configuration Management → Callback Settings, con la acción Set Now. Localice esa configuración en la organización correcta; los nombres pueden variar con la versión de la consola.
2. Guardar la dirección y los eventos. Añada una descripción, la URL receptora y las categorías que necesita: message status para estados y message response para mensajes del cliente. Tras guardar, revise la dirección y las categorías habilitadas. Si falta un tipo de evento, compruebe primero esa selección.
3. Confirmar la recepción. EngageLab envía JSON mediante POST y puede incluir varios registros en rows. Su documentación exige responder con HTTP 200 en un máximo de 3 segundos; no requiere cuerpo de respuesta:
HTTP/1.1 200 OK
Content-Length: 0
Diseñe el receptor para guardar de forma duradera la petición completa o todos sus registros antes de confirmar, y procese después las operaciones del CRM. Si no cumple el tiempo, compruebe almacenamiento, proxy y llamadas síncronas al sistema de negocio. El siguiente apartado incluye ejemplos del JSON recibido.
Comprobar la recepción con mensajes reales
Use un contacto de prueba autorizado y el número de empresa de la integración. Envíe un mensaje permitido para ese contexto, por ejemplo una plantilla de WhatsApp Business aprobada. Conserve el ID devuelto por la API y busque sus eventos posteriores. Después, pida al contacto que responda y compruebe el registro entrante.
Para EngageLab, la documentación de envío detalla el POST a https://wa.api.engagelab.cc/v1/messages, la cabecera Authorization: Basic calculada con DevKey y DevSecret, y la respuesta message_id.
Registre por separado dirección verificada, suscripciones comprobadas, callback recibido y actualización del negocio. No exija que todas las pruebas produzcan un evento de lectura. Si una muestra del panel llega pero el mensaje real no, revise número, cuenta, aplicación, entorno y suscripciones.
Cómo interpretar los eventos y conectarlos con su sistema
Relacionar mensajes, destinatarios y registros de negocio
Supongamos que su empresa envía una actualización sobre la incidencia ticket_demo_042. Su base de datos guarda ese identificador junto con el message_id devuelto por EngageLab, la cuenta y el destinatario. Esa relación la construye su aplicación.
Los dos ejemplos siguientes son extractos ficticios de callbacks de EngageLab: omiten otros campos y no constituyen cuerpos completos para una prueba de contrato. En el envío se habría añadido custom_args.ticket_id como dato propio de asociación. Una notificación de entrega podría contener:
{
"total": 1,
"rows": [{
"message_id": "msg_demo_042",
"custom_args": {"ticket_id": "ticket_demo_042"},
"status": {
"message_status": "delivered",
"status_data": {
"channel_message_id": "wamid.demo_salida_042",
"whatsapp_business_account_id": "waba_demo",
"recipient_user_id": "ES.CLIENTE42"
}
}
}]
}
Busque el mensaje por su ID dentro de la cuenta correcta, registre el evento de entrega y conserve el ID del canal. Compruebe que el valor de asociación concuerda con su registro de envío; no cierre la incidencia solo porque el mensaje se haya entregado.
Ahora el cliente utiliza la función de responder a ese mensaje. La referencia de callbacks documenta un contexto que identifica el mensaje original:
{
"total": 1,
"rows": [{
"response": {
"event": "reply",
"response_data": {
"channel_message_id": "wamid.demo_entrada_043",
"whatsapp_business_account_id": "waba_demo",
"contact": {"wa_id": "", "user_id": "ES.CLIENTE42"},
"message": {
"type": "text",
"text": {"body": "¿Pueden confirmar la fecha?"}
},
"message_context": {
"origin_message_id": "msg_demo_042",
"origin_channel_message_id": "wamid.demo_salida_042"
}
}
}
}]
}
Use origin_message_id, si está presente, para encontrar el envío original; como alternativa, consulte su correspondencia por origin_channel_message_id. Así llega a ticket_demo_042 y añade la respuesta una sola vez. El ID wamid.demo_entrada_043 identifica el nuevo mensaje, no el mensaje al que responde.
No espere custom_args en la respuesta del cliente. La API de envío promete devolverlo en los callbacks de estado. Un mensaje directo sin contexto necesita una relación previa de conversación y cliente. Si hay varias incidencias posibles, guárdelo como pendiente de asignación en vez de elegir automáticamente la más reciente.
En el ejemplo falta el teléfono, pero existe un BSUID, el identificador de usuario asociado al negocio. Conserve contact.user_id y su ámbito de negocio; contact.wa_id sigue siendo el campo telefónico. Si falta el BSUID, utilice una correspondencia telefónica ya validada cuando exista. Si no puede identificar al cliente, retenga el evento para resolverlo. Un nombre visible o un username no deben convertirse en la clave estable del cliente.
Separar estados, respuestas y notificaciones
| Dato recibido | Registro que localizar | Acción propuesta | Qué no concluir |
|---|---|---|---|
| Estado delivered o read | Mensaje enviado y destinatario | Guardar el historial y actualizar la vista | Que se haya resuelto la incidencia |
| Respuesta con contexto | Mensaje original y su incidencia | Añadir el nuevo mensaje | Que el ID entrante sea el original |
| Mensaje sin asociación inequívoca | Cliente y conversación, si se conocen | Dejar pendiente de asignación | Que pertenezca al último pedido |
| Notificación de cuenta o plantilla | Cuenta o recurso afectado | Derivar al flujo operativo correspondiente | Que sea un mensaje del cliente |
Procese cada registro de rows y trate los campos opcionales como tales. Una prueba de asociación debe permitir recorrer el nuevo mensaje, el envío original, la incidencia y la operación realizada.
Cómo procesar los eventos con seguridad y sin duplicados
Valide el origen según la ruta. Meta documenta la cabecera X-Hub-Signature-256: calcule HMAC-SHA256 con el cuerpo original de la petición y el App Secret, y compruébelo contra el valor que sigue a sha256=. Como medida de implementación, conserve los bytes recibidos antes de transformar el JSON y use una comparación segura. El verify token del GET no sustituye esa comprobación.
La documentación pública de EngageLab, consultada el 15 de octubre de 2026, sigue indicando «próximamente» en los apartados de autenticación del callback y reintentos. Confirme las capacidades de su cuenta antes de diseñar esas garantías. Si su empresa exige un origen verificable, ese requisito debe quedar resuelto en el piloto; una URL difícil de adivinar no lo acredita.
Guarde antes de confirmar. Una cola duradera o una bandeja de entrada persistente permite separar la recepción del trabajo posterior. Una lista en memoria no ofrece esa protección. Si confirma con HTTP 200 antes de guardar y el proceso falla, no puede considerar recibido el evento de forma fiable.
| Situación | Qué conserva | Recuperación posible | Límite |
|---|---|---|---|
| Evento guardado; falla el CRM | El evento y el error de procesamiento | Reintento o reprocesamiento interno | Debe mantener la protección contra duplicados |
| Receptor caído; evento nunca recibido | Puede no existir copia propia | Reentrega del proveedor, si está disponible | Una cola propia no recupera datos que nunca recibió |
| HTTP 200 sin almacenamiento | Tal vez solo el registro HTTP | Investigar copias disponibles y corregir el receptor | No presuponer una nueva entrega |
Para la conexión directa, Meta documenta reintentos de entrega durante un máximo de siete días cuando la petición falla o no recibe HTTP 200. También indica que no existe una API para recuperar el historial de webhooks. Estas reglas no deben trasladarse automáticamente al tramo entre un proveedor y su servidor.
Distinga mensaje, evento y acción. Una deduplicación basada únicamente en el ID del mensaje puede descartar su estado de lectura después de haber guardado la entrega. Diseñe la identificación según el tipo de evento y su ámbito de cuenta; reserve además una operación única para añadir una respuesta o generar un envío automático, incluso con varios procesos concurrentes.
Conserve el historial y aplique reglas explícitas a la vista actual: un delivered recibido después de read no debería hacer retroceder la vista a «entregado». Los fallos y tiempos de espera necesitan sus propias reglas; no basta con ordenar todos los estados como una secuencia numérica.
El piloto puede comprobar estos resultados. El equipo técnico conserva la evidencia, el responsable de atención valida la incidencia y el proveedor aclara su capacidad de autenticación y recuperación.
| Prueba | Resultado esperado | Evidencia | Error que detecta |
|---|---|---|---|
| Varias entradas en una petición | Todas se procesan o quedan retenidas para revisión | Resultado por registro | Leer solo el primer elemento |
| Distintos estados del mismo mensaje | Se conservan los estados válidos | Historial del mensaje | Deduplicar solo por message_id |
| Lectura antes que entrega | La vista no retrocede | Eventos y estado mostrado | Usar solo el orden de llegada |
| La misma respuesta se reprocesa | Una incorporación y una acción prevista | Incidencia y registro de operaciones | Duplicar incidencias o respuestas automáticas |
| Falta teléfono o contexto | Se conserva la identidad disponible o queda pendiente | Correspondencia o cola de revisión | Asignar al cliente o pedido equivocado |
| El CRM tarda o falla | El evento guardado se puede reprocesar | Persistencia, respuesta HTTP y recuperación | Bloquear la recepción con el trabajo posterior |
| Falla el almacenamiento | Se detecta y no se registra una recepción fiable | Alerta y respuesta emitida | Confirmar antes de guardar |
| El receptor está fuera de servicio | Se comprueba la recuperación real y sus límites | Eventos generados y reentregados | Confundir reintento interno con reentrega |
| Origen inválido o contenido desconocido | No desencadena una acción de negocio sin validar | Rechazo o aislamiento controlado | Confiar en cualquier POST recibido |
Observe retrasos de confirmación, fallos de almacenamiento, acumulación de trabajo y errores de procesamiento, con acceso restringido y datos sensibles ocultos en los registros. Superar estas pruebas respalda el piloto; la capacidad, la seguridad y la operación en producción requieren su propia validación.
Qué revisar cuando el webhook no funciona
Localice primero dónde se interrumpe el recorrido: plataforma, receptor, almacenamiento o aplicación de negocio.
| Síntoma | Evidencia que revisar | Siguiente acción | Paso relacionado |
|---|---|---|---|
| Meta rechaza la URL | GET, token comparado y respuesta | Revisar TLS, ruta y devolución del challenge | Verificación de la dirección |
| La muestra llega, el mensaje real no | Número, cuenta, campo messages y aplicaciones suscritas | Revisar suscripciones y entorno; en Meta, comprobar también el modo de la aplicación | Configuración y prueba real |
| Solo llega un tipo de evento | Categorías seleccionadas y JSON recibido | Revisar selección y ramas del parser | Suscripción y lectura de eventos |
| Hay HTTP 200 pero la incidencia no cambia | Evento persistido y operación posterior | Separar pérdida de almacenamiento y fallo del CRM | Recepción fiable |
| Aparecen duplicados o retrocede el estado | IDs, estados e historial de operaciones | Corregir deduplicación y reglas de actualización | Seguridad y procesamiento |
| Quedan eventos sin asignar | Cuenta, cliente y contexto del mensaje original | Revisar las correspondencias sin adivinar el pedido | Asociación con el sistema |
Si necesita soporte, aporte hora, entorno, identificadores relevantes y un ejemplo anonimizado. Evite enviar tokens, secretos o conversaciones completas cuando un extracto baste para reproducir el problema.
Preguntas frecuentes sobre los webhooks de WhatsApp
¿Hace falta programar para utilizar un webhook de WhatsApp?
Depende del receptor. Una herramienta con un conector compatible puede encargarse de parte del trabajo. Si desarrolla su propio endpoint, deberá implementar validación, almacenamiento y procesamiento. Incluso con una herramienta visual, conviene comprobar cómo resuelve los duplicados y relaciona los mensajes con sus registros.
¿Se puede probar el webhook en un entorno local?
Sí, si una dirección HTTPS pública puede dirigir las peticiones al entorno de prueba. Una URL de localhost no es accesible desde los servidores de la plataforma. Separe credenciales y datos de producción, y recuerde que la disponibilidad de una conexión temporal no prueba la del servicio definitivo.
¿Se pueden conectar varios sistemas al mismo flujo de eventos?
Sí: una opción de diseño consiste en recibir y guardar el evento una vez, y distribuirlo al CRM, al sistema de atención o a otros consumidores. Cada consumidor necesita su propio control de errores y duplicados. Las opciones para registrar varios destinos directamente en la plataforma dependen del proveedor.
Defina qué eventos necesita, a qué sistema deben llegar y qué requisitos de autenticación y recuperación debe cumplir su proyecto. La solución WhatsApp Business API de EngageLab y su documentación permiten concretar la evaluación.







