Saltar al contenido principal

El sobre

Todos los eventos tienen la misma forma exterior. Solo data cambia de un tipo a otro.

Todos los tipos de evento

Los eventos de contacto llevan el contacto completo, así que la mayoría de las integraciones nunca necesitan volver a llamar a la API. Los eventos de conversación y de mensaje llevan solo ids: lee la conversación o sus mensajes desde la API cuando necesites el contenido.
Con el tiempo se agregan nuevos tipos de evento. Un endpoint suscrito a todos los eventos empieza a recibirlos automáticamente. Responde 200 a cualquier type que no manejes.

El objeto contacto

Los eventos de contacto incluyen un objeto contact con los mismos campos que GET /v1/contacts/{id}:
Tres cosas que debes saber:
  • properties contiene tus propiedades personalizadas, indexadas por la clave de la propiedad. Lee kind para saber qué campo value_* contiene el valor.
  • Las propiedades de archivo se omiten. El enlace de descarga de un archivo es temporal y expiraría antes de que llegue una entrega reintentada. Lee el contacto desde la API para obtener un enlace nuevo.
  • El contacto es una foto tomada cuando Ciarem prepara el evento, un momento después del cambio. Si el contacto cambió dos veces seguidas, ambos eventos pueden mostrar el estado más reciente. Un reintento envía la misma foto otra vez, no una nueva.

Eventos de contacto

contact.created

Se agregó un contacto: lo hizo un compañero, una importación, la API, una integración como HubSpot, o una persona nueva escribió por un canal.

contact.updated

Cambiaron los campos propios de un contacto (nombre, correo, teléfono, ciudad, etc.) o una de sus propiedades personalizadas.
changed_fields lista qué cambió:
  • Un campo simple aparece por su nombre: "first_name", "email".
  • Una propiedad personalizada aparece como properties.<key>: "properties.custom_budget". Cada propiedad personalizada que cambia envía su propio evento contact.updated.
Los cambios de etapa del embudo y de propietario no se reportan aquí. Tienen sus propios eventos, más abajo. Una edición que cambia a la vez un nombre, la etapa y el propietario envía tres eventos: contact.updated, contact.funnel_stage.changed y contact.owner.changed.

contact.deleted

Se eliminó un contacto. El contacto ya no existe, así que solo se envía su id.

contact.merged

Se fusionaron dos contactos. contact es el que sobrevive, con el resultado de la fusión. merged_contact_id es el contacto que se integró en él y ya no existe por separado: actualiza los registros de tu lado que todavía apunten a él.

contact.funnel_stage.changed

Un contacto pasó a otra etapa del embudo, ya sea que lo movió un compañero o el agente de IA. La etapa nueva es contact.funnel_stage_id; la que dejó es previous_funnel_stage_id. Convierte los ids de etapa en nombres con GET /v1/funnel-stages.

contact.owner.changed

Cambió el propietario de un contacto. El propietario nuevo es contact.owner_id; el anterior es previous_owner_id. Cualquiera de los dos puede ser null, lo que significa que el contacto no tiene, o no tenía, propietario.

Eventos de conversación y de mensaje

Estos cuatro eventos comparten el mismo data base:

conversation.created

Empezó una conversación nueva.
Ciarem espera unos segundos a que el contacto quede vinculado antes de enviar este evento, así que contact_id casi siempre está presente. En el caso poco común de que siga en null, lee la conversación desde la API un poco después. Esta breve espera también significa que el primer messages.inbound de una conversación puede llegar antes que su conversation.created.

conversation.assigned

Se asignó una conversación: la tomó un compañero, la asignó un administrador, lo hicieron tus reglas de asignación automática, o el agente de IA la transfirió.
assignee_id es el compañero y siempre viene. team_id es el equipo de la conversación y puede ser null.

conversation.closed

Se resolvió una conversación, ya sea porque un compañero terminó el chat o porque el agente de IA la cerró. El cuerpo es el data base de arriba.

messages.inbound

Un cliente envió un mensaje. El evento te dice qué conversación tiene algo nuevo; no contiene el mensaje en sí.
Para leer lo que se dijo, trae los mensajes de la conversación:
Los mensajes que envían tu equipo o el agente de IA no disparan un evento.

Eventos de formularios de WhatsApp

whatsapp_flow.completed

Un cliente envió un formulario de WhatsApp. Se dispara una vez por envío, después de que Ciarem guardó las respuestas.
  • answers usa los nombres internos de los campos del formulario, no el texto de la pregunta. Para leer los valores por propiedad, usa outcome.saved (los campos y propiedades del contacto donde se escribieron las respuestas) y lee el contacto.
  • outcome.errors lista las respuestas que no se pudieron guardar, por ejemplo un email que pertenece a otro contacto.
  • Un formulario de reserva también trae booking_id, start_at, end_at, meeting_url y attendee_email en outcome.
  • La respuesta de una pregunta de fotos o documentos es una lista de {"file_name", "mime_type"}, y outcome.files da su estado: {"q3": {"status": "pending"}}. El evento se envía antes de que se guarden los archivos. Cuando la pregunta se guarda en una propiedad de archivo, los archivos guardados llegan con el evento contact.updated que sigue.
  • conversation_id puede ser null cuando el formulario se envió con una plantilla fuera de una conversación.

El evento de prueba

Una prueba enviada desde el panel o con POST /v1/webhook-endpoints/{id}/test se ve como un evento real, con dos diferencias:
  • Su id empieza con evt_test_, así que puedes distinguirlo y saltarte cualquier efecto real.
  • Si no eliges un tipo de evento, su type es test y su data está vacío:
Cuando sí eliges un tipo, la prueba lleva datos de ejemplo con exactamente la forma que tiene un evento real. GET /v1/webhook-event-samples devuelve el cuerpo de ejemplo de cada tipo, lo que resulta útil para escribir pruebas de tu propio handler.

Compatibilidad

Los cuerpos de los webhooks siguen la misma regla que el resto de la API: los cambios son aditivos. En cualquier momento pueden aparecer nuevos tipos de evento, nuevos campos dentro de data y nuevos valores en campos de texto. Lee los campos que necesitas, ignora el resto, y revisa el changelog cuando algo se vea distinto.