Payloads

This page documents the payloads of regular webhook events:

  • conversation.*
  • message.*
  • client.*
  • referral.received (Meta ads)

WhatsApp Flows (whatsapp.flows.*) use the same envelope, with resourceType: "flow_response", but their data and expected response are documented in WhatsApp Flows , since those events require your endpoint to respond with data to keep the flow going.

Common envelope

All these events reach your endpoint via a JSON POST with this structure:

{
  "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": {}
}
FieldTypeDescription
idstringUnique event identifier
eventstringName of the event that triggered the webhook
workspaceIdstringWorkspace where the event happened
timestampstringISO-8601 date of the event
sourcestringOrigin of the event — see the source field
resourceTypeconversation \| message \| client \| flow_responseType of resource affected
resourceIdstring \| nullIdentifier of the affected resource
changesobject \| nullDetected changes. null for creation/deletion events
dataobjectNormalized snapshot of the resource

The source field

Identifies the origin of the event. For conversation, message, and customer events, its value follows the format:

<origin>.<resource>.<action>[.<qualifier>]
  • origin: one of api, dashboard, inbound, agent, system, scheduler, campaign.
  • resource: client, conversation, message, audience, scheduled_event, webhook, moderation, supervisor.
  • action: verb / state (created, updated, deleted, processed, dispatched, etc.).
  • qualifier (optional): bulk, auto, campaign.

For WhatsApp Flows, source is always whatsapp.flows.

Use source only for auditing / debugging. The logical identity of the event (what changed and which resources it affects) lives in event, resourceType, resourceId, and changes. The channel platform (whatsapp, instagram, …) is read from data.conversation.platform for conversation/message events, not from source.

Common examples by event:

eventPossible source values
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

Conversations

Events:

Eventchanges
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 } }

For conversation.* events, data always has:

{
  "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": []
  }
}
FieldTypeDescription
idstring \| nullInternal identifier
conversationIdstring \| nullExternal identifier, usually the phone number
canSendDirectMessagebooleanfalse if the conversation is closed, expired, spam, or outside the 24-hour window on WhatsApp
workspaceIdstring \| nullOwning workspace
channelIdstring \| nullChannel where it happened
contactNamestring \| nullContact name
phoneNumberstring \| nullContact phone number
topicstringConversation topic
platformstring \| nullContact channel: whatsapp, instagram, messenger, sms, etc.
ownersstring[]Assigned owners, identified by email (not UID)
tagsstring[]Assigned tags
creationDatestring \| nullISO-8601 date
lastUpdatestring \| nullISO-8601 date
statusstring \| nullCurrent state: open, pending, finished, blocked, spam, expired
operationstring \| nullConversation mode: automatic (bot-handled) or manual (operator-handled)
messageCountnumberNumber of messages
messagesunknown[]Serialized messages. Only present in conversation.* events

Messages

Events:

Eventchanges
message.creatednull
message.updatedPer-field changes: content, contentBlocks, contentType, direction, lastUpdate, role, status, files, images, owner
message.deletednull — declared in the catalog, but not emitted yet. Subscribing produces no events today.

For message.* events, data contains client, conversation, and message. The conversation does not include messages[]; the affected message is in 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"
  }
}
FieldTypeDescription
idstring \| nullMessage identifier
contentstringPlain-text version of the message
contentBlocksunknown[]Structured blocks
contentTypestringtext by default
creationDatestring \| nullISO-8601 date
directionincoming \| outgoing \| string \| nullAlways normalized to incoming or outgoing. Values like received or sent are translated before being emitted
filesunknown[]Attached files
imagesunknown[]Attached images
owner{ "id": string } \| nullMessage author. id is the operator's email when applicable
lastUpdatestring \| nullISO-8601 date
rolestring \| nulluser, assistant, tool, etc.
statusstring \| nullMessage status. Common values: received, sent, delivered, read, failed

Example of message.updated:

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

Customers

Events:

Eventchanges
client.creatednull
client.updatedPer basic-field changes: 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": { "<field>": { "before", "after" } } } or { "customFields": { "<field>": { "added": [], "removed": [] } } }

For client.* events, data is the normalized customer directly:

{
  "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"
}

Example of 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": []
    }
  }
}

Meta Ads

Event:

EventchangesresourceType
referral.receivednullclient

Emitted when an inbound message arrives attributed to a Meta ad (Click-to-WhatsApp, Click-to-Messenger, or Instagram ads). Unlike client.* events, its data is not the normalized customer: it contains client, conversation, and a referral object with the structured ad attribution.

{
  "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"
    }
  }
}
FieldTypeDescription
platformstringChannel platform: whatsapp, messenger, instagram
sourcestring \| nullSource type reported by Meta, usually ad
ad_idstring \| nullMeta ad identifier
ctwa_clidstring \| nullClick-to-WhatsApp click ID, useful for the Conversions API
refstring \| nullAd ref parameter (Click-to-Messenger / m.me) when present
headlinestring \| nullAd headline
bodystring \| nullAd primary text
media_typestring \| nullAd media type: image, video, etc.
image_urlstring \| nullAd image URL
video_urlstring \| nullAd video URL
thumbnail_urlstring \| nullAd thumbnail URL
welcome_messagestring \| nullWelcome message prefilled in the ad
user_textstring \| nullText the customer sent when starting the conversation
channelIdstring \| nullChannel where the message arrived
messageIdstring \| nullIdentifier of the inbound message that triggered the event
conversationIdstring \| nullConversation identifier
receivedAtstring \| nullISO-8601 date when the attributed message was received