Events & Payloads
Payload envelope
Every webhook delivery — regardless of the event type — shares the same envelope structure:
{
"event": "contact.created",
"delivery_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"timestamp": 1741093200,
"data": { ... }
}
| Field | Type | Description |
|---|---|---|
event | string | Event name (see below) |
delivery_id | string | UUID unique to this delivery attempt |
timestamp | integer | Unix timestamp of the delivery |
data | object | Event-specific payload (flat structure; see per-event schemas below) |
Contact events
contact.created
Fired when a new contact is created.
{
"event": "contact.created",
"delivery_id": "uuid",
"timestamp": 1741093200,
"data": {
"id": 42,
"name": "Noura Al-Otaibi",
"email": "noura@example.com",
"phone": "+966501234567",
"type": "whatsapp",
"status": "active",
"is_blacklist": false,
"source": "api",
"company": null,
"address": null,
"country_id": 194,
"created_at": "2026-03-04T12:00:00.000000Z",
"updated_at": "2026-03-04T12:00:00.000000Z"
}
}
contact.updated
Fired when a contact's fields are changed. Same payload structure as contact.created.
contact.deleted
Fired when a contact is permanently deleted.
{
"event": "contact.deleted",
"delivery_id": "uuid",
"timestamp": 1741100400,
"data": {
"id": 42,
"name": "Noura Al-Otaibi",
"phone": "+966501234567",
"email": "noura@example.com",
"type": "whatsapp",
"deleted_at": "2026-03-04T14:00:00.000000Z"
}
}
Message events
message.received
Fired when an inbound message arrives from a contact.
{
"event": "message.received",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"id": 201,
"contact_id": 42,
"value": "Hi, I need help with my order.",
"message_type": "text",
"message_by": "contact",
"status": "received",
"source": "whatsapp",
"header_image": null,
"header_video": null,
"header_document": null,
"header_audio": null,
"campaign_id": null,
"created_at": "2026-03-04T13:00:00.000000Z"
}
}
message.sent
Fired when an outbound message is successfully sent. Same payload structure as message.received with message_by: "client".
Channel events
Fired when a connected messaging channel (WhatsApp, Telegram, Instagram, Messenger, LinkedIn) changes state. Use these to monitor channel health and trigger reconnection flows.
channel.connected
Fired the first time a channel connects or successfully reconnects after being disconnected.
{
"event": "channel.connected",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"channel": "whatsapp",
"channel_id": 3,
"username": "+14155550000",
"status": "OK",
"connected_at": "2026-03-04T13:00:00.000000Z"
}
}
| Field | Values |
|---|---|
channel | whatsapp, telegram, instagram, messenger, linkedin |
status | OK, CREATION_SUCCESS, RECONNECTED, SYNC_SUCCESS |
channel.disconnected
Fired when a previously connected channel goes offline.
{
"event": "channel.disconnected",
"delivery_id": "uuid",
"timestamp": 1741200000,
"data": {
"channel": "whatsapp",
"channel_id": 3,
"username": "+14155550000",
"status": "CREDENTIALS",
"reason": "Session expired. Please reconnect your account.",
"disconnected_at": "2026-03-05T08:00:00.000000Z"
}
}
status | Meaning |
|---|---|
CREDENTIALS | Credentials invalid or session expired |
ERROR | General connection error |
STOPPED | Account was stopped |
DELETED | Account was deleted from the provider |
channel.error
Fired when an initial connection attempt fails (before the channel ever connects).
{
"event": "channel.error",
"delivery_id": "uuid",
"timestamp": 1741200000,
"data": {
"channel": "instagram",
"channel_id": 7,
"status": "CREATION_FAIL",
"error": "Channel creation failed.",
"occurred_at": "2026-03-05T08:01:00.000000Z"
}
}
Campaign events
Fired when an outreach campaign transitions between lifecycle states.
campaign.started
{
"event": "campaign.started",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"id": 18,
"name": "March Promo",
"status": "running",
"total_contacts": 500,
"success_count": 0,
"failed_count": 0,
"started_at": "2026-03-04T10:00:00.000000Z",
"completed_at": null,
"updated_at": "2026-03-04T10:00:00.000000Z"
}
}
campaign.completed
Fired when all messages have been processed.
{
"event": "campaign.completed",
"delivery_id": "uuid",
"timestamp": 1741130000,
"data": {
"id": 18,
"name": "March Promo",
"status": "completed",
"total_contacts": 500,
"success_count": 487,
"failed_count": 13,
"started_at": "2026-03-04T10:00:00.000000Z",
"completed_at": "2026-03-04T19:00:00.000000Z",
"updated_at": "2026-03-04T19:00:00.000000Z"
}
}
campaign.paused
Same payload structure as campaign.started with status: "paused".
campaign.cancelled
Same payload structure as campaign.started with status: "cancelled".
campaign.failed
Same payload structure as campaign.completed with status: "failed".
Knowledge base events
knowledge_base.created
Fired when a new knowledge base entry is created (any type).
{
"event": "knowledge_base.created",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"id": 91,
"title": "Product Manual",
"type": "document",
"status": "active",
"description": "Full product manual for Model X",
"business_description": "Used for product-related questions",
"created_at": "2026-03-04T13:00:00.000000Z",
"updated_at": "2026-03-04T13:00:00.000000Z"
}
}
knowledge_base.updated
Same payload as knowledge_base.created. Fired on any field change including status.
knowledge_base.deleted
{
"event": "knowledge_base.deleted",
"delivery_id": "uuid",
"timestamp": 1741200000,
"data": {
"id": 91,
"title": "Product Manual",
"type": "document",
"deleted_at": "2026-03-05T08:00:00.000000Z"
}
}
knowledge_base.processing.completed
Fired when a document finishes AI extraction, a voice note finishes transcription, or a website crawl completes. This is especially useful for website type (async crawl) — subscribe to this to know when crawled content is ready for the AI to use.
{
"event": "knowledge_base.processing.completed",
"delivery_id": "uuid",
"timestamp": 1741097400,
"data": {
"knowledge_base_id": 94,
"title": "مركز مساعدة نخيل",
"type": "website",
"item_id": 8,
"website_url": "https://help.nakheel.sa",
"crawl_status": "completed",
"pages_crawled": 47,
"error": null,
"occurred_at": "2026-03-04T13:10:00.000000Z"
}
}
Document example:
{
"event": "knowledge_base.processing.completed",
"data": {
"knowledge_base_id": 91,
"title": "Product Manual",
"type": "document",
"item_id": 12,
"original_name": "manual.pdf",
"status": "completed",
"error": null,
"occurred_at": "2026-03-04T13:00:30.000000Z"
}
}
knowledge_base.processing.failed
Same structure as knowledge_base.processing.completed with an error message explaining the failure.
Ticket events
ticket.created
Fired when a new support ticket is opened.
{
"event": "ticket.created",
"delivery_id": "uuid",
"timestamp": 1741099800,
"data": {
"id": 55,
"subject": "Issue with booking confirmation",
"status": "open",
"priority": "normal",
"department_id": 1,
"ticket_id": "TKT-55",
"created_at": "2026-03-04T15:00:00.000000Z",
"updated_at": "2026-03-04T15:00:00.000000Z"
}
}
ticket.updated
Fired when a ticket's status, priority, or assignment changes (and it is not a close/resolve transition).
Same payload structure as ticket.created.
ticket.closed
Fired when a ticket's status transitions to closed or resolved.
{
"event": "ticket.closed",
"delivery_id": "uuid",
"timestamp": 1741104000,
"data": {
"id": 55,
"subject": "Issue with booking confirmation",
"status": "closed",
"priority": "normal",
"department_id": 1,
"ticket_id": "TKT-55",
"created_at": "2026-03-04T15:00:00.000000Z",
"updated_at": "2026-03-04T16:10:00.000000Z"
}
}
ticket.replied
Fired when a reply is added to a support ticket.
{
"event": "ticket.replied",
"delivery_id": "uuid",
"timestamp": 1741100100,
"data": {
"ticket_id": 55,
"ticket_subject": "Issue with booking confirmation",
"reply_id": 12,
"reply": "We've updated your booking. Please check your email.",
"type": "staff",
"user_id": 3,
"created_at": "2026-03-04T15:05:00.000000Z"
}
}
AI agent events
ai_agent.created
Fired when a new AI agent persona is created.
{
"event": "ai_agent.created",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"id": 5,
"name": "Sales Assistant",
"is_active": true,
"is_default": false,
"created_at": "2026-03-04T13:00:00.000000Z",
"updated_at": "2026-03-04T13:00:00.000000Z"
}
}
ai_agent.updated
Fired when an AI agent persona is modified (name, prompt, active status, or set as default). Same payload as ai_agent.created.
ai_agent.deleted
{
"event": "ai_agent.deleted",
"delivery_id": "uuid",
"timestamp": 1741200000,
"data": {
"id": 5,
"name": "Sales Assistant",
"deleted_at": "2026-03-05T08:00:00.000000Z"
}
}
Booking events
booking.created
{
"event": "booking.created",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"id": 101,
"status": "pending",
"customer_name": "Noura Al-Otaibi",
"customer_phone": "+966501234567",
"customer_email": null,
"booking_date": "2026-03-10",
"start_time": "14:00",
"end_time": "15:00",
"guest_count": null,
"notes": null,
"booking_type_id": 5,
"booking_resource_id": 2,
"contact_id": 42,
"cancelled_at": null,
"cancellation_reason": null,
"created_at": "2026-03-04T14:00:00.000000Z",
"updated_at": "2026-03-04T14:00:00.000000Z"
}
}
booking.updated
Fired when a booking is modified (e.g., rescheduled). Same payload structure as booking.created.
booking.cancelled
{
"event": "booking.cancelled",
"delivery_id": "uuid",
"timestamp": 1741158000,
"data": {
"id": 101,
"status": "cancelled",
"customer_name": "Noura Al-Otaibi",
"customer_phone": "+966501234567",
"booking_date": "2026-03-10",
"start_time": "14:00",
"cancelled_at": "2026-03-05T09:00:00.000000Z",
"cancellation_reason": "Customer requested cancellation",
"created_at": "2026-03-04T14:00:00.000000Z",
"updated_at": "2026-03-05T09:00:00.000000Z"
}
}
booking.completed
Fired when a booking is marked as completed. Same payload structure as booking.created with status: "completed".
Order events
order.created
Fired when a new order is placed.
{
"event": "order.created",
"delivery_id": "uuid",
"timestamp": 1741096800,
"data": {
"id": 42,
"status": "pending",
"customer_name": "Ahmed Al-Rashid",
"customer_phone": "+966501234567",
"customer_email": "ahmed@example.com",
"subtotal": 450.00,
"total": 450.00,
"currency": "SAR",
"shipping_address": "123 King Fahd Road, Riyadh",
"notes": "Please call before delivery",
"contact_id": 15,
"created_by": "api",
"cancelled_at": null,
"cancellation_reason": null,
"created_at": "2026-04-05T10:30:00.000000Z",
"updated_at": "2026-04-05T10:30:00.000000Z",
"items": [
{
"id": 101,
"product_id": 5,
"product_name": "Premium T-Shirt",
"product_sku": "TSH-001",
"quantity": 3,
"unit_price": 150.00,
"total_price": 450.00
}
]
}
}
order.updated
Fired when an order is modified (status change, notes updated, etc.). Same payload structure as order.created.
order.cancelled
Fired when an order is cancelled.
{
"event": "order.cancelled",
"delivery_id": "uuid",
"timestamp": 1741158000,
"data": {
"id": 42,
"status": "cancelled",
"customer_name": "Ahmed Al-Rashid",
"customer_phone": "+966501234567",
"total": 450.00,
"currency": "SAR",
"cancelled_at": "2026-04-05T14:00:00.000000Z",
"cancellation_reason": "Customer requested cancellation",
"items": [...],
"created_at": "2026-04-05T10:30:00.000000Z",
"updated_at": "2026-04-05T14:00:00.000000Z"
}
}
order.delivered
Fired when an order is marked as delivered. Same payload structure as order.created with status: "delivered".
Test event
webhook.test
Sent when you trigger a test delivery from the dashboard or via POST /api/v1/webhooks/{id}/test.
{
"event": "webhook.test",
"delivery_id": "uuid",
"timestamp": 1741093200,
"data": {
"message": "This is a test delivery from SkyLight Chat to verify your webhook endpoint.",
"webhook_id": 7,
"webhook_name": "Production Webhook"
}
}
All events reference
| Event | Trigger |
|---|---|
contact.created | A contact is created |
contact.updated | A contact is updated |
contact.deleted | A contact is deleted |
message.received | An inbound message arrives |
message.sent | An outbound message is sent |
channel.connected | A channel connects or reconnects |
channel.disconnected | A channel goes offline |
channel.error | A channel fails to connect |
campaign.started | A campaign starts sending |
campaign.completed | A campaign finishes sending |
campaign.paused | A campaign is paused |
campaign.cancelled | A campaign is cancelled |
campaign.failed | A campaign encounters a critical failure |
knowledge_base.created | A KB entry is created |
knowledge_base.updated | A KB entry is updated |
knowledge_base.deleted | A KB entry is deleted |
knowledge_base.processing.completed | Document / voice / website processing finishes |
knowledge_base.processing.failed | Document / voice / website processing fails |
ticket.created | A support ticket is opened |
ticket.updated | A ticket is updated |
ticket.closed | A ticket is closed or resolved |
ticket.replied | A reply is added to a ticket |
ai_agent.created | An AI agent persona is created |
ai_agent.updated | An AI agent persona is updated |
ai_agent.deleted | An AI agent persona is deleted |
booking.created | A booking is created |
booking.updated | A booking is updated |
booking.cancelled | A booking is cancelled |
booking.completed | A booking is marked as completed |
order.created | An order is placed |
order.updated | An order is updated |
order.cancelled | An order is cancelled |
order.delivered | An order is marked as delivered |
webhook.test | Manual test delivery |
