> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://developers.zorvia.io/webhooks/events/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.zorvia.io/_mcp/server. # Webhook events > Event types and JSON payloads sent by Zorvia channel webhooks. Your webhook endpoint receives a JSON payload whenever a supported message event occurs on the channel. Use `event.type` to choose how your application handles the delivery. ## Event types | Event | When it is sent | | ------------------ | ------------------------------------------------------ | | `message.received` | New message activity is available for the channel. | | `message.edited` | The content of an existing message changes. | | `message.deleted` | A message is deleted from Zorvia. | | `message.removed` | A message is revoked or removed from the conversation. | | `message.failed` | Zorvia cannot deliver a message. | > **Note** > > Use the `message` object, including its sender and lifecycle timestamps, to determine the direction and current state of a `message.received` event. ## Example payload ```json { "event": { "type": "message.received", "source": null, "occurred_at": "2026-07-23T10:14:52+00:00" }, "workspace": { "id": "workspace_01JQ8XNZ2JQZ7J4HQYN7A5H6F3" }, "channel": { "id": "8aa25bf5-f24d-4f9f-b4ab-287d41a29aa3", "name": "Customer Support", "driver": "whatsapp" }, "connection": { "id": "01JQ8Z21R8VZ0N59S7E7R4GPH1", "driver": "webhook-server", "name": "Order status integration" }, "conversation": { "id": "01JQ8YVVTBVAJ7QEW49GB0N2H5", "type": "direct", "name": "Ada Okafor" }, "message": { "id": "01JQ8Z5E2V4PTHB63SF7F4CJA2", "conversation_id": "01JQ8YVVTBVAJ7QEW49GB0N2H5", "sender_id": "01JQ8YT9G39ZC9V91G7J71C49T", "sender_type": "contact", "content": "Hello, I need help with my order.", "type": "text", "is_template": false, "driver": "whatsapp", "is_reply": false, "is_comment": false, "parent_id": null, "meta": {}, "created_at": "2026-07-23T10:14:52+00:00", "updated_at": "2026-07-23T10:14:52+00:00", "deleted_at": null, "sent_at": null, "delivered_at": null, "edited_at": null, "removed_at": null, "received_at": "2026-07-23T10:14:52+00:00", "failed_at": null, "lifecycle_timestamp": "2026-07-23T10:14:52+00:00" } } ``` Fields such as `sender`, `media`, `quoted_message`, and `forwarded_message` are included when they apply to the message. ## Payload fields | Field | Type | Description | | ------------------- | ---------------- | ------------------------------------------------------------------------------------------- | | `event.type` | `string` | The event name used to route the delivery in your application. | | `event.occurred_at` | `string` | When the event occurred, formatted as an ISO 8601 timestamp. | | `event.source` | `object \| null` | Information about the originating connection, when available. | | `workspace.id` | `string` | The Zorvia workspace that owns the channel. | | `channel` | `object` | The channel where the message activity occurred. | | `connection` | `object` | The webhook configuration that sent the delivery. | | `conversation` | `object` | The affected conversation. Its values can be `null` when no conversation is available. | | `message` | `object` | The affected message, including its content, type, relationships, and lifecycle timestamps. | ### Message lifecycle fields The `message` object contains timestamps that help your application update its local state: | Field | Description | | -------------- | ---------------------------------------- | | `created_at` | When the message record was created. | | `sent_at` | When the message was sent successfully. | | `received_at` | When Zorvia received the message. | | `delivered_at` | When delivery was confirmed. | | `edited_at` | When the message was last edited. | | `removed_at` | When the message was removed or revoked. | | `failed_at` | When message delivery failed. | Timestamps are ISO 8601 strings or `null` when that lifecycle stage has not occurred. ## Handling events Webhook deliveries can arrive more than once or out of order. Store `message.id`, compare `event.occurred_at` with the state you have already processed, and make each handler idempotent. Use the signing instructions in [Set up a webhook](/webhooks/setup) to verify that deliveries came from Zorvia. > Event types and JSON payloads sent by Zorvia channel webhooks.