Todos los eventos llegan con la misma envoltura. Lo que cambia es data.

message.received

Un cliente te escribió. Llega por cada mensaje, de WhatsApp o de Instagram. Las reacciones (👍, ❤️) no lo disparan.
string
Id del mensaje en MINDO.
string
Id del mensaje en WhatsApp. No viene en Instagram.
string
Solo en Instagram: "instagram".
string
La conversación en el chat de MINDO.
string
Tu número de WhatsApp que recibió el mensaje (útil si tienes varios).
object
id, name (el nombre de perfil) y phone (WhatsApp) o instagram (usuario de Instagram).
string
El tipo de mensaje: text, image, video, audio, document, sticker, location, contacts, button (tocó un botón de una plantilla), interactive (eligió una opción), entre otros.
string | null
El texto del mensaje. En adjuntos, el pie de foto o una descripción (por ejemplo “📷 Imagen”); en botones, el texto del botón.
string
Cuándo lo mandó el cliente.
Cada mensaje entrante abre (o renueva) la ventana de 24 horas: durante ese tiempo puedes responder con text libre por la API.

message.status

Cambió el estado de un mensaje que mandaste, ya sea por la API, desde el chat o en una campaña.
string
El id de WhatsApp del mensaje: el mismo wamid que te devolvió POST /messages. Úsalo para encontrar el mensaje en tu sistema.
string
sent, delivered, read o failed.
string | null
Si el mensaje salió de una campaña, su id.
number | null
Con failed, el código de Meta. Por ejemplo 131026 (no se pudo entregar). Mira la tabla en Errores.
El estado solo avanza: sent → delivered → read. Si WhatsApp nos informa varios cambios juntos, te mandamos solo el más avanzado, así que puedes recibir read sin haber recibido delivered. Nunca vas a recibir un estado “hacia atrás”.
Si mandas campañas grandes, este evento llega una o más veces por cada destinatario. Suscríbete solo si lo vas a usar, y asegúrate de que tu servidor aguante el volumen.

contact.created

Se sumó un contacto nuevo a tu cuenta.
string
De dónde vino:
  • inbound: te escribió por WhatsApp por primera vez.
  • instagram: te escribió por Instagram por primera vez (en lugar de phone trae instagram, el usuario).
  • api: lo creaste con POST /contacts.
Los contactos que sumas desde la app (importando una planilla o a mano) y los que se crean al mandar un mensaje con POST /messages a un teléfono nuevo no disparan este evento.

contact.opted_out

Un contacto pidió no recibir más mensajes: tocó el botón de baja de una plantilla o escribió algo como “baja”, “stop”, “no recibir más” o “darme de baja”.
MINDO deja a ese contacto afuera de las campañas automáticamente. Si tienes otros sistemas que le mandan mensajes (tu CRM, tu tienda), usa este evento para marcarlo también ahí. Más en Bajas y consentimiento.
La API no bloquea los envíos a contactos dados de baja: POST /messages los manda igual. Antes de mandar mensajes de marketing por la API, revisa optedOut en el contacto o guarda estas bajas en tu sistema.

campaign.completed

Una campaña terminó de enviarse.
Los números son una foto del momento en que terminó el envío: las entregas y lecturas siguen subiendo durante las horas siguientes. Para los valores al día, consulta GET /campaigns.

automation.completed

Una ejecución de una automatización terminó: llegó al final del flujo o pasó la conversación a una persona.
string
Id de la ejecución. Es el runId que te devolvió el webhook entrante o POST /automations/{id}/runs.
string
La automatización.
string
La conversación en el chat de MINDO.
string
El contacto.
string
  • completed: llegó al final del flujo.
  • handed_off: llegó a un paso Pasar a una persona.
string | null
Siempre null en este evento.
object
Las variables de la ejecución: las respuestas guardadas, lo que devolvieron las solicitudes HTTP, webhook con el data que mandaste al arrancarla y, en los comentarios de Instagram, comentario. respuesta es siempre la última respuesta a una pregunta.
Es la forma más simple de traer a tu sistema lo que respondió el cliente: guarda cada respuesta en una variable con Guardar en la variable y léela de data.vars cuando llega este evento.

automation.failed

Una ejecución no pudo seguir. Tiene los mismos datos que automation.completed, con status: "failed" y el motivo en error.
Los errores más comunes y cómo resolverlos están en Probar y seguir las ejecuciones.
Las ejecuciones canceladas (porque alguien del equipo respondió, alguien la detuvo o se pausó la automatización) y las de prueba no mandan ninguno de los dos eventos.

agent.goal_reached

Un agente IA cumplió su objetivo con un cliente real. Las pruebas no lo mandan.
string
El agente.
string
Su nombre.
string
La conversación en el chat de MINDO.
string
El contacto.
string | null
El resumen que dejó el agente.
object
Los datos del objetivo que consiguió, con sus claves. Solo trae los que el cliente llegó a dar.

agent.handed_off

Un agente IA pasó una conversación a tu equipo: el cliente pidió una persona, tenía un reclamo o se dio uno de tus casos de derivación. Tiene los mismos datos que agent.goal_reached; en summary va el motivo y el resumen que quedó como nota interna en el chat.

agent.conversation_reviewed

Se terminó el análisis de una conversación de un agente avanzado: el resultado de cada criterio y los datos extraídos. Llega una vez por cada tramo del agente en la conversación, y otra vez si alguien toca Reanalizar.
string | null
La versión del agente que atendió.
string
Por qué se dio por terminado el tramo: goal (cumplió el objetivo), handoff (derivó) o idle (una hora sin mensajes).
string | null
Una o dos frases con lo que pasó.
object[]
Un elemento por criterio. result es success, failure o unknown en los criterios de bien o mal (y null en los de puntaje); score es de 1 a 5 en los de puntaje (o null).
object
Los datos extraídos, con sus claves. Los que no aparecieron vienen en null.

case.opened, case.classified, case.closed, case.outcome y case.stage_changed

Los casos: cada consulta de un cliente, con su motivo, su puntaje comercial y su resultado. Los cinco eventos traen el caso entero en data:
  • case.opened: un cliente escribió y se abrió un caso nuevo.
  • case.classified: Jev le puso motivo o calculó el puntaje.
  • case.closed: se cerró (pasaron sus horas sin mensajes, alguien lo cerró, se cerró la conversación, el agente IA cumplió su objetivo o pasó a una etapa final de su pipeline).
  • case.outcome: se marcó la venta o que se perdió, desde el chat o por la API.
  • case.stage_changed: el caso entró a un pipeline o cambió de etapa: lo movió una persona, una regla de la etapa, la falta de respuesta del cliente, una automatización o la API.
object | null
El motivo y el submotivo, con su id y su nombre.
string | null
Quién puso el motivo: jev o person (alguien del equipo).
string
Quién respondió: none, automation, ai, human o mixed (agente IA y equipo).
string | null
El anuncio de Meta que trajo al cliente, si vino de uno en los 7 días anteriores.
number | null
El puntaje comercial de 0 a 100, si el motivo lo lleva.
string | null
inactivity, manual, agent_goal, conversation_closed, stage (pasó a una etapa final de su pipeline) o stale (pasó solo a perdido por días sin respuesta del cliente).
object | null
El resultado: result (won o lost), el monto y la moneda, la nota, tu externalId y si lo marcó una persona (person) o llegó por la API (api).
object | null
La etapa del caso, si su motivo está en un pipeline: el pipeline (id, name), la etapa (stage con id, name y kind: open, won o lost), cuándo entró (enteredAt), el monto estimado (amount, solo ventas) y los valores de sus campos (fields). null si no está en ninguno.

Evento de prueba

El botón Probar de Ajustes › API y webhooks manda este message.received, con "test": true y datos de ejemplo:
Verifica la firma igual que siempre, pero no lo proceses como un mensaje real.