This page describes the call event webhooks your system receives when WhatsApp voice calls are initiated, answered, rejected, missed, or ended.
Use these events to:
- Track inbound and outbound call lifecycle
- Update agent/customer UI state
- Store call history and recordings
- Measure call duration and outcomes
🔔 When are webhooks sent?
A webhook is sent every time the call state changes.
You may receive multiple events for the same callId as the call progresses.
📌 Event types
| Event | Description |
|---|---|
CALL_INCOMING_INITIATED | An incoming call from a customer has started ringing |
CALL_OUTGOING_INITIATED | An outgoing call to a customer was created successfully |
CALL_ACCEPTED | The call was answered (agent or customer) |
CALL_ENDED | The call ended after being connected |
CALL_REJECTED | The call was declined before being answered |
CALL_MISSED | An incoming call rang but was not answered |
🔁 Call direction
Each payload includes callDirection to distinguish inbound vs outbound calls.
| Value | Meaning |
|---|---|
INCOMING | Customer → Business |
OUTGOING | Business → Customer |
📊 Call status
Each payload also includes callStatus, which represents the current state of the call.
| Status | Meaning |
|---|---|
INITIATED | Call is ringing |
IN_PROGRESS | Call is connected |
END | Call ended after connection |
REJECT | Call declined before answer |
MISSED | Incoming call not answered |
FAILED | Call failed due to provider/network error |
Always use
event+callStatustogether to understand exactly what happened.
📦 Webhook payload
All call events follow the same base structure.
| Field | Type | Description |
|---|---|---|
event | string | Event type (e.g. CALL_ACCEPTED) |
callId | string | Unique provider call ID |
chatMessageId | string | Related chat message ID (may be empty) |
chatId | string | Related chat ID (may be empty) |
wabaNumber | string | WhatsApp Business number |
customerNumber | string | Customer phone number |
customerName | string | Customer display name |
customerId | string | Your internal customer ID |
callDirection | string | INCOMING or OUTGOING |
callStatus | string | Current call status |
failedReason | string | Failure reason (if any) |
durationInSeconds | number | Call duration |
callStartedAt | string | ISO timestamp when call was answered |
callEndedAt | string | ISO timestamp when call ended |
pickedBy | string | Phone number of user who answered |
rejectedBy | string | Phone number of user who rejected |
endedBy | string | Phone number of user who ended |
recordingUrl | string | Call recording URL (if available) |
deviceId | string | Client device identifier |
🧪 Sample payloads
Incoming call (ringing)
{
"event": "CALL_INCOMING_INITIATED",
"callId": "wacid.SAMPLE_CALL_ID_001",
"chatMessageId": "sample-chat-msg-001",
"chatId": "",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "INCOMING",
"callStatus": "INITIATED",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "",
"callEndedAt": "",
"pickedBy": "",
"rejectedBy": "",
"endedBy": "",
"recordingUrl": "",
"deviceId": ""
}
Incoming call missed (not answered)
{
"event": "CALL_MISSED",
"callId": "wacid.SAMPLE_CALL_ID_001",
"chatMessageId": "sample-chat-msg-001",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "INCOMING",
"callStatus": "MISSED",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "",
"callEndedAt": "2026-01-30T06:20:25.642Z",
"pickedBy": "",
"rejectedBy": "",
"endedBy": "",
"recordingUrl": "",
"deviceId": ""
}
Incoming call picked (accepted by agent)
{
"event": "CALL_ACCEPTED",
"callId": "wacid.SAMPLE_CALL_ID_002",
"chatMessageId": "sample-chat-msg-002",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "INCOMING",
"callStatus": "IN_PROGRESS",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "2026-01-30T06:20:52.485Z",
"callEndedAt": "",
"pickedBy": "agent_SAMPLE_001",
"rejectedBy": "",
"endedBy": "",
"recordingUrl": "",
"deviceId": "device_SAMPLE_001"
}
Incoming call ended by agent
{
"event": "CALL_ENDED",
"callId": "wacid.SAMPLE_CALL_ID_002",
"chatMessageId": "sample-chat-msg-002",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "INCOMING",
"callStatus": "END",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "2026-01-30T06:20:52.485Z",
"callEndedAt": "2026-01-30T06:21:40.000Z",
"pickedBy": "agent_SAMPLE_001",
"rejectedBy": "",
"endedBy": "agent_SAMPLE_001",
"recordingUrl": "",
"deviceId": "device_SAMPLE_001"
}
Incoming call rejected by agent
{
"event": "CALL_REJECTED",
"callId": "wacid.SAMPLE_CALL_ID_003",
"chatMessageId": "sample-chat-msg-003",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "INCOMING",
"callStatus": "REJECT",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "",
"callEndedAt": "2026-01-30T06:22:37.577Z",
"pickedBy": "",
"rejectedBy": "agent_SAMPLE_001",
"endedBy": "",
"recordingUrl": "",
"deviceId": ""
}
Outbound call initiated
{
"event": "CALL_OUTGOING_INITIATED",
"callId": "wacid.SAMPLE_CALL_ID_004",
"chatMessageId": "sample-chat-msg-004",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "OUTGOING",
"callStatus": "INITIATED",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "",
"callEndedAt": "",
"pickedBy": "agent_SAMPLE_001",
"rejectedBy": "",
"endedBy": "",
"recordingUrl": "",
"deviceId": "device_SAMPLE_001"
}
Outbound call ended by agent (e.g. hung up before customer answered)
When the agent ends an outbound call before the customer answers, you receive CALL_ENDED with callStatus END (or as determined by the system when the call is terminated).
{
"event": "CALL_ENDED",
"callId": "wacid.SAMPLE_CALL_ID_004",
"chatMessageId": "sample-chat-msg-004",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "OUTGOING",
"callStatus": "END",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "",
"callEndedAt": "2026-01-30T06:24:00.000Z",
"pickedBy": "agent_SAMPLE_001",
"rejectedBy": "",
"endedBy": "agent_SAMPLE_001",
"recordingUrl": "",
"deviceId": "device_SAMPLE_001"
}
Outbound call picked by customer
{
"event": "CALL_ACCEPTED",
"callId": "wacid.SAMPLE_CALL_ID_005",
"chatMessageId": "sample-chat-msg-005",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "OUTGOING",
"callStatus": "IN_PROGRESS",
"failedReason": "",
"durationInSeconds": 0,
"callStartedAt": "2026-01-30T06:24:48.221Z",
"callEndedAt": "",
"pickedBy": "agent_SAMPLE_001",
"rejectedBy": "",
"endedBy": "",
"recordingUrl": "",
"deviceId": "device_SAMPLE_001"
}
Outbound call ended by customer
{
"event": "CALL_ENDED",
"callId": "wacid.SAMPLE_CALL_ID_005",
"chatMessageId": "sample-chat-msg-005",
"chatId": "sample-chat-001",
"wabaNumber": "911111111111",
"customerNumber": "919999999999",
"customerName": "Sample Customer",
"customerId": "customer_SAMPLE_001",
"callDirection": "OUTGOING",
"callStatus": "END",
"failedReason": "",
"durationInSeconds": 19,
"callStartedAt": "2026-01-30T06:24:48.221Z",
"callEndedAt": "2026-01-30T06:25:06.409Z",
"pickedBy": "agent_SAMPLE_001",
"rejectedBy": "",
"endedBy": "customer_SAMPLE_001",
"recordingUrl": "https://example.com/sample-recordings/sample-call-005.mp3",
"deviceId": "device_SAMPLE_001"
}
