Payloads

Esta página documenta los payloads de los eventos normales de webhooks:

  • conversation.*
  • message.*
  • client.*
  • referral.received (anuncios de Meta)

WhatsApp Flows (whatsapp.flows.*) usa el mismo envelope, con resourceType: "flow_response", pero su data y la respuesta esperada están documentadas en WhatsApp Flows , porque esos eventos requieren que tu endpoint responda con datos para continuar el flow.

Envelope común

Todos estos eventos llegan a tu endpoint con un POST JSON usando esta estructura:

{
  "id": "9f8c...",
  "event": "conversation.created",
  "workspaceId": "ws_456",
  "timestamp": "2026-05-06T19:00:00.000Z",
  "source": "system.conversation.created",
  "resourceType": "conversation",
  "resourceId": "conv_123",
  "changes": null,
  "data": {}
}
CampoTipoDescripción
idstringIdentificador único del evento
eventstringNombre del evento que disparó el webhook
workspaceIdstringWorkspace donde ocurrió el evento
timestampstringFecha ISO-8601 del evento
sourcestringOrigen del evento — ver Campo source
resourceTypeconversation \| message \| client \| flow_responseTipo de recurso afectado
resourceIdstring \| nullIdentificador del recurso afectado
changesobject \| nullCambios detectados. Es null en eventos de creación / eliminación
dataobjectSnapshot normalizado del recurso

Campo source

Identifica el origen del evento. Para conversaciones, mensajes y clientes, su valor sigue el formato:

<origin>.<resource>.<action>[.<qualifier>]
  • origin: uno de api, dashboard, inbound, agent, system, scheduler, campaign.
  • resource: client, conversation, message, audience, scheduled_event, webhook, moderation, supervisor.
  • action: verbo / estado (created, updated, deleted, processed, dispatched, etc.).
  • qualifier (opcional): bulk, auto, campaign.

Para WhatsApp Flows, source es siempre whatsapp.flows.

Usa el source sólo para auditoría / debugging. La identidad lógica del evento (qué cambió y qué recursos afecta) está en event, resourceType, resourceId y changes. La plataforma del canal (whatsapp, instagram, …) se lee en data.conversation.platform para eventos de conversación/mensaje, no en source.

Ejemplos comunes por evento:

eventPosibles valores de source
client.createdapi.client.created, inbound.client.created, campaign.client.created
client.updatedapi.client.updated, dashboard.client.updated, inbound.client.profile_updated, inbound.client.refreshed, inbound.client.identifiers_updated, agent.supervisor.applied, system.moderation.applied
client.tags.updatedapi.client.tagged.bulk, api.audience.added, api.audience.removed, api.audience.cleared, dashboard.client.updated
client.customFields.updatedapi.client.custom_fields_updated, inbound.client.custom_fields_updated, agent.client.confirmation_saved, dashboard.client.updated
conversation.createdsystem.conversation.created, dashboard.conversation.created, campaign.conversation.created
conversation.status.updatedapi.conversation.updated, api.conversation.finished, api.conversation.marked_spam, api.conversation.archived, api.conversation.reactivated, dashboard.conversation.stopped, campaign.conversation.updated
conversation.expiredsystem.conversation.expired_by_inactivity, agent.conversation.expired, api.conversation.archived.auto, api.conversation.updated
conversation.owners.updatedapi.conversation.operator_assigned, api.conversation.operators_set, dashboard.conversation.assistance_accepted
conversation.tags.updatedapi.conversation.tagged, dashboard.conversation.assistance_requested
message.createdinbound.message.received, agent.message.generated, agent.message.processed, agent.message.dispatched, agent.message.service_sent, agent.message.summary_generated, campaign.message.received, dashboard.message.system_inserted, scheduler.scheduled_event.created
message.updatedinbound.message.delivery_updated, inbound.message.delivery_failed, inbound.message.delivery_updated.campaign, agent.message.processed, agent.message.status_updated, agent.message.dispatched, dashboard.message.resent, scheduler.scheduled_event.processing, scheduler.scheduled_event.sent, scheduler.scheduled_event.failed, api.scheduled_event.cancelled
whatsapp.flows.*whatsapp.flows

Conversaciones

Eventos:

Eventochanges
conversation.creatednull
conversation.status.updated{ "status": { "before", "after" } }
conversation.operation.updated{ "operation": { "before", "after" } }
conversation.owners.updated{ "owners": { "added": [], "removed": [] } }
conversation.tags.updated{ "tags": { "added": [], "removed": [] } }
conversation.expired{ "isFinished": { "before", "after": true } }

En eventos conversation.*, data siempre tiene:

{
  "client": {
    "id": "521234567890",
    "phoneNumber": "521234567890",
    "creationDate": "2026-05-06T19:00:00.000Z",
    "lastUpdate": "2026-05-06T19:00:00.000Z",
    "name": "Juan Pérez",
    "firstname": "Juan",
    "email": null
  },
  "conversation": {
    "id": "conv_123",
    "conversationId": "521234567890",
    "canSendDirectMessage": true,
    "workspaceId": "ws_456",
    "channelId": "521555000111",
    "contactName": "Juan Pérez",
    "phoneNumber": "521234567890",
    "topic": "",
    "platform": "whatsapp",
    "owners": [],
    "tags": [],
    "creationDate": "2026-05-06T19:00:00.000Z",
    "lastUpdate": "2026-05-06T19:00:00.000Z",
    "status": "open",
    "operation": "automatic",
    "messageCount": 1,
    "messages": []
  }
}
CampoTipoDescripción
idstring \| nullIdentificador interno
conversationIdstring \| nullIdentificador externo, normalmente el teléfono
canSendDirectMessagebooleanfalse si la conversación está cerrada, expirada, spam o fuera de la ventana de 24 h en WhatsApp
workspaceIdstring \| nullWorkspace propietario
channelIdstring \| nullCanal donde ocurrió
contactNamestring \| nullNombre del contacto
phoneNumberstring \| nullTeléfono del contacto
topicstringTema de la conversación
platformstring \| nullCanal del contacto: whatsapp, instagram, messenger, sms, etc.
ownersstring[]Propietarios asignados, identificados por email (no UID)
tagsstring[]Etiquetas asignadas
creationDatestring \| nullFecha ISO-8601
lastUpdatestring \| nullFecha ISO-8601
statusstring \| nullEstado actual: open, pending, finished, blocked, spam, expired
operationstring \| nullModo de la conversación: automatic (atendida por bot) o manual (atendida por operador)
messageCountnumberNúmero de mensajes
messagesunknown[]Mensajes serializados. Sólo aparece en eventos conversation.*

Mensajes

Eventos:

Eventochanges
message.creatednull
message.updatedCambios por campo: content, contentBlocks, contentType, direction, lastUpdate, role, status, files, images, owner
message.deletednull — declarado en el catálogo, pero no se emite todavía. Suscribirse no produce eventos hoy.

En eventos message.*, data tiene client, conversation y message. La conversación no incluye messages[]; el mensaje afectado va en data.message.

{
  "client": { "...": "WebhookClientSummary" },
  "conversation": { "...": "WebhookConversation sin messages[]" },
  "message": {
    "id": "msg_789",
    "content": "Hola, necesito ayuda con mi pedido",
    "contentBlocks": [
      { "type": "text", "text": "Hola, necesito ayuda con mi pedido" }
    ],
    "contentType": "text",
    "creationDate": "2026-05-06T19:00:00.000Z",
    "direction": "incoming",
    "files": [],
    "images": [],
    "owner": null,
    "lastUpdate": "2026-05-06T19:00:00.000Z",
    "role": "user",
    "status": "delivered"
  }
}
CampoTipoDescripción
idstring \| nullIdentificador del mensaje
contentstringTexto plano derivado del mensaje
contentBlocksunknown[]Bloques estructurados
contentTypestringtext por defecto
creationDatestring \| nullFecha ISO-8601
directionincoming \| outgoing \| string \| nullSiempre se normaliza a incoming u outgoing. Valores como received o sent se traducen antes de emitirse
filesunknown[]Archivos adjuntos
imagesunknown[]Imágenes adjuntas
owner{ "id": string } \| nullAutor del mensaje. id es el email del operador cuando aplica
lastUpdatestring \| nullFecha ISO-8601
rolestring \| nulluser, assistant, tool, etc.
statusstring \| nullEstado del mensaje. Valores comunes: received, sent, delivered, read, failed

Ejemplo de message.updated:

{
  "event": "message.updated",
  "resourceType": "message",
  "resourceId": "msg_789",
  "changes": {
    "status": {
      "before": "sent",
      "after": "read"
    }
  },
  "data": {
    "client": {},
    "conversation": {},
    "message": {}
  }
}

Clientes

Eventos:

Eventochanges
client.creatednull
client.updatedCambios por campo básico: phoneNumber, name, firstname, lastname, email, birthdate, gender, company, country, state, city, address, postalCode, creationDate, lastUpdate
client.owners.updated{ "owners": { "added": [], "removed": [] } }
client.tags.updated{ "tags": { "added": [], "removed": [] } }
client.customFields.updated{ "customFields": { "<campo>": { "before", "after" } } } o { "customFields": { "<campo>": { "added": [], "removed": [] } } }

En eventos client.*, data es directamente el cliente normalizado:

{
  "id": "521234567890",
  "workspaceId": "ws_456",
  "phoneNumber": "521234567890",
  "name": "Juan Pérez",
  "firstname": "Juan",
  "lastname": "Pérez",
  "email": "juan@empresa.com",
  "birthdate": null,
  "gender": null,
  "company": "Acme Inc.",
  "country": "MX",
  "state": null,
  "city": null,
  "address": null,
  "postalCode": null,
  "tags": ["vip"],
  "owners": ["agente1@empresa.com"],
  "customFields": {
    "placas": "ABC123"
  },
  "creationDate": "2026-05-06T19:00:00.000Z",
  "lastUpdate": "2026-05-06T19:00:00.000Z"
}

Ejemplo de client.customFields.updated:

{
  "event": "client.customFields.updated",
  "resourceType": "client",
  "resourceId": "521234567890",
  "changes": {
    "customFields": {
      "placas": {
        "before": "ABC123",
        "after": "XYZ789"
      },
      "visitas": {
        "added": [
          {
            "id": "visit_5",
            "creationDate": "2026-05-06T19:00:00.000Z",
            "lastUpdate": "2026-05-06T19:00:00.000Z",
            "content": "Visita de seguimiento"
          }
        ],
        "removed": []
      }
    }
  },
  "data": {
    "id": "521234567890",
    "customFields": {
      "placas": "XYZ789",
      "visitas": []
    }
  }
}

Anuncios de Meta

Evento:

EventochangesresourceType
referral.receivednullclient

Se emite cuando llega un mensaje entrante atribuido a un anuncio de Meta (Click-to-WhatsApp, Click-to-Messenger o anuncios de Instagram). A diferencia de los eventos client.*, su data no es el cliente normalizado: contiene client, conversation y un objeto referral con la atribución estructurada del anuncio.

{
  "event": "referral.received",
  "resourceType": "client",
  "resourceId": "client_sample_abc123",
  "changes": null,
  "data": {
    "client": {
      "id": "521234567890",
      "phoneNumber": "521234567890",
      "creationDate": "2026-05-06T19:00:00.000Z",
      "lastUpdate": "2026-05-06T19:00:00.000Z",
      "name": "Juan Pérez",
      "firstname": "Juan",
      "email": null
    },
    "conversation": {
      "id": "conv_123",
      "conversationId": "521234567890",
      "platform": "whatsapp",
      "channelId": "wb-123456789012345"
    },
    "referral": {
      "platform": "whatsapp",
      "source": "ad",
      "ad_id": "120211234567890123",
      "ctwa_clid": "ARAkLkA8rmlFeiCktEJQ-QTwRiyYHAFDLMNDBH0CD3qpjd0HR4irJ6LEkR7JwLzMDopn7vghDWqTXUYWmTzID29SrqLOgUSDRAsNH0_sample",
      "ref": null,
      "headline": "Anuncio de prueba",
      "body": "Texto principal del anuncio de prueba.",
      "media_type": "image",
      "image_url": "https://example.com/ad-image.jpg",
      "video_url": null,
      "thumbnail_url": null,
      "welcome_message": "Hola, quiero más información",
      "user_text": "Hola, quiero más información",
      "channelId": "wb-123456789012345",
      "messageId": "wamid.sample",
      "conversationId": "521234567890",
      "receivedAt": "2026-05-06T19:00:00.000Z"
    }
  }
}
CampoTipoDescripción
platformstringPlataforma del canal: whatsapp, messenger, instagram
sourcestring \| nullTipo de origen reportado por Meta, normalmente ad
ad_idstring \| nullIdentificador del anuncio de Meta
ctwa_clidstring \| nullClick ID de Click-to-WhatsApp, útil para la Conversions API
refstring \| nullParámetro ref del anuncio (Click-to-Messenger / m.me) cuando aplica
headlinestring \| nullTítulo del anuncio
bodystring \| nullTexto principal del anuncio
media_typestring \| nullTipo de medio del anuncio: image, video, etc.
image_urlstring \| nullURL de la imagen del anuncio
video_urlstring \| nullURL del video del anuncio
thumbnail_urlstring \| nullURL de la miniatura del anuncio
welcome_messagestring \| nullMensaje de bienvenida prellenado en el anuncio
user_textstring \| nullTexto que envió el cliente al iniciar la conversación
channelIdstring \| nullCanal donde llegó el mensaje
messageIdstring \| nullIdentificador del mensaje entrante que disparó el evento
conversationIdstring \| nullIdentificador de la conversación
receivedAtstring \| nullFecha ISO-8601 en que se recibió el mensaje atribuido