Documentation Index Fetch the complete documentation index at: https://docs.kapso.ai/llms.txt
Use this file to discover all available pages before exploring further.
All webhook payloads use v2 format with phone_number_id at the top level.
Payload structure
Webhook payloads separate message data from conversation data:
message.kapso - Message-scoped only: direction, status, processing_status, statuses (raw status history), origin, has_media, content (text representation), transcript (for audio), media helpers (media_data, media_url, message_type_data)
conversation - Top-level identifiers such as id, phone_number, phone_number_id, and, when available, business_scoped_user_id, parent_business_scoped_user_id, and username. Optional conversation.kapso contains summary metrics (counts, last-message metadata, timestamps)
phone_number_id - Included at top level for routing
Do not assume phone_number, from, to, or wa_id are always present.
WhatsApp webhook events
Sent only to phone-number webhooks (/whatsapp/phone_numbers/{phone_number_id}/webhooks).
Message received whatsapp.message.receivedFired when a new WhatsApp message is received from a customer. Supports message buffering for batch delivery.
Message sent whatsapp.message.sentFired when a message is successfully sent to WhatsApp
Message delivered whatsapp.message.deliveredFired when a message is successfully delivered to the recipient’s device
Message read whatsapp.message.readFired when the recipient reads your message
Message failed whatsapp.message.failedFired when a message fails to deliver
Conversation created whatsapp.conversation.createdFired when a new WhatsApp conversation is initiated
Conversation ended whatsapp.conversation.endedFired when a WhatsApp conversation ends (agent action, manual closure, or 24-hour inactivity)
Conversation inactive whatsapp.conversation.inactiveFired when no messages (inbound/outbound) for configured minutes (1-1440, default 60)
Payload structures
whatsapp.message.received
{
"message" : {
"id" : "wamid.123" ,
"timestamp" : "1730092800" ,
"type" : "text" ,
"from" : "16315551181" ,
"from_user_id" : "US.13491208655302741918" ,
"from_parent_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"text" : { "body" : "Hello" },
"kapso" : {
"direction" : "inbound" ,
"status" : "received" ,
"processing_status" : "pending" ,
"origin" : "cloud_api" ,
"has_media" : false ,
"content" : "Hello"
}
},
"conversation" : {
"id" : "conv_123" ,
"phone_number" : "16315551181" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "active" ,
"last_active_at" : "2025-10-28T14:25:01Z" ,
"created_at" : "2025-10-28T13:40:00Z" ,
"updated_at" : "2025-10-28T14:25:01Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345" ,
"kapso" : {
"contact_name" : "John Doe" ,
"messages_count" : 1 ,
"last_message_id" : "wamid.123" ,
"last_message_type" : "text" ,
"last_message_timestamp" : "2025-10-28T14:25:01Z" ,
"last_message_text" : "Hello" ,
"last_inbound_at" : "2025-10-28T14:25:01Z" ,
"last_outbound_at" : null
}
},
"is_new_conversation" : true ,
"phone_number_id" : "123456789012345"
}
whatsapp.message.sent
{
"message" : {
"id" : "wamid.456" ,
"timestamp" : "1730092860" ,
"type" : "text" ,
"to" : "15551234567" ,
"text" : { "body" : "On my way" },
"kapso" : {
"direction" : "outbound" ,
"status" : "sent" ,
"processing_status" : "completed" ,
"origin" : "cloud_api" ,
"has_media" : false ,
"statuses" : [
{
"id" : "wamid.456" ,
"status" : "sent" ,
"timestamp" : "1730092860" ,
"recipient_id" : "15551234567"
}
]
}
},
"conversation" : {
"id" : "conv_123" ,
"phone_number" : "15551234567" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "active" ,
"last_active_at" : "2025-10-28T14:31:00Z" ,
"created_at" : "2025-10-28T13:40:00Z" ,
"updated_at" : "2025-10-28T14:31:00Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345" ,
"kapso" : {
"contact_name" : "John Doe" ,
"messages_count" : 2 ,
"last_message_id" : "wamid.456" ,
"last_message_type" : "text" ,
"last_message_timestamp" : "2025-10-28T14:31:00Z" ,
"last_message_text" : "On my way" ,
"last_inbound_at" : "2025-10-28T14:25:01Z" ,
"last_outbound_at" : "2025-10-28T14:31:00Z"
}
},
"is_new_conversation" : false ,
"phone_number_id" : "123456789012345"
}
whatsapp.message.delivered
{
"message" : {
"id" : "wamid.456" ,
"timestamp" : "1730092888" ,
"type" : "text" ,
"to" : "15551234567" ,
"text" : { "body" : "On my way" },
"kapso" : {
"direction" : "outbound" ,
"status" : "delivered" ,
"processing_status" : "completed" ,
"origin" : "cloud_api" ,
"has_media" : false ,
"statuses" : [
{
"id" : "wamid.456" ,
"status" : "sent" ,
"timestamp" : "1730092860" ,
"recipient_id" : "15551234567"
},
{
"id" : "wamid.456" ,
"status" : "delivered" ,
"timestamp" : "1730092888" ,
"recipient_id" : "15551234567"
}
]
}
},
"conversation" : {
"id" : "conv_123" ,
"phone_number" : "15551234567" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "active" ,
"last_active_at" : "2025-10-28T14:31:28Z" ,
"created_at" : "2025-10-28T13:40:00Z" ,
"updated_at" : "2025-10-28T14:31:28Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345"
},
"is_new_conversation" : false ,
"phone_number_id" : "123456789012345"
}
whatsapp.message.failed
{
"message" : {
"id" : "wamid.789" ,
"timestamp" : "1730093200" ,
"type" : "text" ,
"to" : "15551234567" ,
"text" : { "body" : "This message failed" },
"kapso" : {
"direction" : "outbound" ,
"status" : "failed" ,
"processing_status" : "completed" ,
"origin" : "cloud_api" ,
"has_media" : false ,
"statuses" : [
{
"id" : "wamid.789" ,
"status" : "sent" ,
"timestamp" : "1730093100" ,
"recipient_id" : "15551234567"
},
{
"id" : "wamid.789" ,
"status" : "failed" ,
"timestamp" : "1730093200" ,
"recipient_id" : "15551234567" ,
"errors" : [
{
"code" : 131047 ,
"title" : "Re-engagement message" ,
"message" : "More than 24 hours have passed since the recipient last replied"
}
]
}
]
}
},
"conversation" : {
"id" : "conv_123" ,
"phone_number" : "15551234567" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "active" ,
"last_active_at" : "2025-10-28T15:00:00Z" ,
"created_at" : "2025-10-28T13:40:00Z" ,
"updated_at" : "2025-10-28T15:00:00Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345"
},
"is_new_conversation" : false ,
"phone_number_id" : "123456789012345"
}
whatsapp.conversation.created
{
"conversation" : {
"id" : "conv_789" ,
"phone_number" : "15551234567" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "active" ,
"last_active_at" : "2025-10-28T14:00:00Z" ,
"created_at" : "2025-10-28T14:00:00Z" ,
"updated_at" : "2025-10-28T14:00:00Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345" ,
"kapso" : {
"contact_name" : "John Doe" ,
"messages_count" : 0 ,
"last_message_id" : null ,
"last_message_type" : null ,
"last_message_timestamp" : null ,
"last_message_text" : null ,
"last_inbound_at" : null ,
"last_outbound_at" : null
}
},
"phone_number_id" : "123456789012345"
}
whatsapp.conversation.ended
{
"conversation" : {
"id" : "conv_789" ,
"phone_number" : "15551234567" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "ended" ,
"last_active_at" : "2025-10-28T15:10:45Z" ,
"created_at" : "2025-10-28T14:00:00Z" ,
"updated_at" : "2025-10-28T15:10:45Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345" ,
"kapso" : {
"contact_name" : "John Doe" ,
"messages_count" : 15 ,
"last_message_id" : "wamid.999" ,
"last_message_type" : "text" ,
"last_message_timestamp" : "2025-10-28T15:10:45Z" ,
"last_message_text" : "Thanks!" ,
"last_inbound_at" : "2025-10-28T15:10:45Z" ,
"last_outbound_at" : "2025-10-28T15:10:30Z"
}
},
"phone_number_id" : "123456789012345"
}
whatsapp.conversation.inactive
{
"conversation" : {
"id" : "conv_789" ,
"phone_number" : "15551234567" ,
"business_scoped_user_id" : "US.13491208655302741918" ,
"parent_business_scoped_user_id" : "US.ENT.506847293015824" ,
"username" : "@testusername" ,
"status" : "active" ,
"last_active_at" : "2025-10-28T13:00:00Z" ,
"created_at" : "2025-10-28T12:00:00Z" ,
"updated_at" : "2025-10-28T13:00:00Z" ,
"metadata" : {},
"phone_number_id" : "123456789012345"
},
"since_message" : {
"id" : "msg_anchor" ,
"whatsapp_message_id" : "wamid.ANCHOR" ,
"direction" : "inbound" ,
"created_at" : "2025-10-28T13:00:00Z"
},
"inactivity" : {
"minutes" : 60
},
"phone_number_id" : "123456789012345"
}
Multiple inactivity timeouts
Create separate webhooks for different timeout thresholds:
// First webhook: 5 minute warning
{
"events" : [ "whatsapp.conversation.inactive" ],
"inactive_after_minutes" : 5
}
// Second webhook: 30 minute escalation
{
"events" : [ "whatsapp.conversation.inactive" ],
"inactive_after_minutes" : 30
}
Each webhook fires independently when its threshold is reached.
Project webhook events
Sent only to project webhooks. These do not include message or conversation events.
whatsapp.phone_number.created
Fires when a customer successfully connects their WhatsApp through a setup link.
See Connection detection for implementation guide.
Payload :
{
"phone_number_id" : "123456789012345" ,
"project" : {
"id" : "990e8400-e29b-41d4-a716-446655440004"
},
"customer" : {
"id" : "880e8400-e29b-41d4-a716-446655440003"
}
}
whatsapp.phone_number.deleted
Fires when a WhatsApp phone number is removed from your project. This event triggers at the start of the teardown process, before the number is fully deleted.
Payload :
{
"phone_number_id" : "123456789012345" ,
"project" : {
"id" : "990e8400-e29b-41d4-a716-446655440004"
},
"customer" : {
"id" : "880e8400-e29b-41d4-a716-446655440003"
}
}
workflow.execution.handoff
Fires when a workflow execution is handed off to a human agent.
Payload :
{
"event" : "workflow.execution.handoff" ,
"occurred_at" : "2025-12-08T12:00:00Z" ,
"project_id" : "990e8400-e29b-41d4-a716-446655440004" ,
"workflow_id" : "880e8400-e29b-41d4-a716-446655440001" ,
"workflow_execution_id" : "770e8400-e29b-41d4-a716-446655440002" ,
"status" : "handoff" ,
"tracking_id" : "track-abc123" ,
"channel" : "whatsapp" ,
"whatsapp_conversation_id" : "conv_789" ,
"handoff" : {
"reason" : "User requested human assistance" ,
"source" : "agent_tool"
}
}
Field Description handoff.reasonOptional reason provided during handoff handoff.sourceagent_tool (from agent step) or action_step (from workflow action)
workflow.execution.failed
Fires when a workflow execution fails due to an error.
Payload :
{
"event" : "workflow.execution.failed" ,
"occurred_at" : "2025-12-08T12:00:00Z" ,
"project_id" : "990e8400-e29b-41d4-a716-446655440004" ,
"workflow_id" : "880e8400-e29b-41d4-a716-446655440001" ,
"workflow_execution_id" : "770e8400-e29b-41d4-a716-446655440002" ,
"status" : "failed" ,
"tracking_id" : "track-abc123" ,
"channel" : "whatsapp" ,
"whatsapp_conversation_id" : "conv_789" ,
"error" : {
"message" : "Workflow execution timed out"
}
}
Message origin
The message.kapso.origin field indicates how the message entered the system:
cloud_api - Sent via Kapso API (outbound jobs, flow actions, API calls)
business_app - Echoed from WhatsApp Business App (when using the Business App)
history_sync - Backfilled during message history imports (only if project ran sync)
Status history
The message.kapso.statuses array contains the complete history of raw Meta status events for a message, ordered chronologically. Each entry is the unmodified payload from Meta’s webhook.
Status object structure
Each status object in the array follows Meta’s webhook format:
{
"id" : "<WHATSAPP_MESSAGE_ID>" ,
"status" : "<STATUS>" ,
"timestamp" : "<UNIX_TIMESTAMP>" ,
"recipient_id" : "<PHONE_NUMBER>" ,
"pricing" : {
"billable" : true ,
"pricing_model" : "<PRICING_MODEL>" ,
"category" : "<PRICING_CATEGORY>"
},
"errors" : [
{
"code" : 131031 ,
"title" : "<ERROR_TITLE>" ,
"message" : "<ERROR_MESSAGE>" ,
"error_data" : {
"details" : "<ERROR_DETAILS>"
},
"href" : "<ERROR_CODES_URL>"
}
],
...
}
Field Included when pricingSent status, plus delivered or read errorsFailed to send or deliver
See Meta’s status webhook reference for the complete schema.
Use this field to track the full lifecycle of outbound messages and understand failure causes. The array only appears when status events have been recorded.
Message types
The message.type field can be one of:
text - Plain text message
image - Image attachment
video - Video attachment
audio - Audio/voice message
document - Document attachment
location - Location sharing
template - WhatsApp template message
interactive - Interactive message (buttons, lists)
reaction - Message reaction
contacts - Contact card sharing
Message type-specific data
{
"message" : {
"id" : "wamid.789" ,
"timestamp" : "1730093000" ,
"type" : "image" ,
"image" : {
"caption" : "Photo description" ,
"id" : "media_id_123"
},
"kapso" : {
"direction" : "inbound" ,
"status" : "received" ,
"processing_status" : "pending" ,
"origin" : "cloud_api" ,
"has_media" : true ,
"content" : "Photo description Image attached (photo.jpg) [Size: 200 KB | Type: image/jpeg] URL: https://api.kapso.ai/media/..." ,
"media_url" : "https://api.kapso.ai/media/..." ,
"media_data" : {
"url" : "https://api.kapso.ai/media/..." ,
"filename" : "photo.jpg" ,
"content_type" : "image/jpeg" ,
"byte_size" : 204800
},
"message_type_data" : {
"caption" : "Photo description"
}
}
}
}
Audio messages
{
"message" : {
"id" : "wamid.790" ,
"timestamp" : "1730093100" ,
"type" : "audio" ,
"audio" : {
"id" : "media_id_456"
},
"kapso" : {
"direction" : "inbound" ,
"status" : "received" ,
"processing_status" : "pending" ,
"origin" : "cloud_api" ,
"has_media" : true ,
"content" : "[Audio attached] (voice.ogg) [Size: 50 KB | Type: audio/ogg] URL: https://api.kapso.ai/media/... \n Transcript: Hello, I need help with my order" ,
"transcript" : {
"text" : "Hello, I need help with my order"
},
"media_url" : "https://api.kapso.ai/media/..." ,
"media_data" : {
"url" : "https://api.kapso.ai/media/..." ,
"filename" : "voice.ogg" ,
"content_type" : "audio/ogg" ,
"byte_size" : 51200
}
}
}
}
Location messages
{
"message" : {
"type" : "location" ,
"location" : {
"latitude" : 37.7749 ,
"longitude" : -122.4194 ,
"name" : "San Francisco" ,
"address" : "San Francisco, CA, USA"
}
}
}
Template messages
{
"message" : {
"type" : "template" ,
"template" : {
"name" : "order_confirmation" ,
"language" : {
"code" : "en_US"
},
"components" : [ ... ]
}
}
}
Interactive messages
{
"message" : {
"type" : "interactive" ,
"interactive" : {
"type" : "button_reply" ,
"button_reply" : {
"id" : "btn_1" ,
"title" : "Confirm"
}
}
}
}
Reaction messages
{
"message" : {
"type" : "reaction" ,
"reaction" : {
"message_id" : "wamid.HBgNNTU0MTIzNDU2Nzg5MA" ,
"emoji" : "👍"
}
}
}