Call Webhooks (Voice Calls)

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

EventDescription
CALL_INCOMING_INITIATEDAn incoming call from a customer has started ringing
CALL_OUTGOING_INITIATEDAn outgoing call to a customer was created successfully
CALL_ACCEPTEDThe call was answered (agent or customer)
CALL_ENDEDThe call ended after being connected
CALL_REJECTEDThe call was declined before being answered
CALL_MISSEDAn incoming call rang but was not answered

🔁 Call direction

Each payload includes callDirection to distinguish inbound vs outbound calls.

ValueMeaning
INCOMINGCustomer → Business
OUTGOINGBusiness → Customer

📊 Call status

Each payload also includes callStatus, which represents the current state of the call.

StatusMeaning
INITIATEDCall is ringing
IN_PROGRESSCall is connected
ENDCall ended after connection
REJECTCall declined before answer
MISSEDIncoming call not answered
FAILEDCall failed due to provider/network error

💡

Always use event + callStatus together to understand exactly what happened.


📦 Webhook payload

All call events follow the same base structure.

FieldTypeDescription
eventstringEvent type (e.g. CALL_ACCEPTED)
callIdstringUnique provider call ID
chatMessageIdstringRelated chat message ID (may be empty)
chatIdstringRelated chat ID (may be empty)
wabaNumberstringWhatsApp Business number
customerNumberstringCustomer phone number
customerNamestringCustomer display name
customerIdstringYour internal customer ID
callDirectionstringINCOMING or OUTGOING
callStatusstringCurrent call status
failedReasonstringFailure reason (if any)
durationInSecondsnumberCall duration
callStartedAtstringISO timestamp when call was answered
callEndedAtstringISO timestamp when call ended
pickedBystringPhone number of user who answered
rejectedBystringPhone number of user who rejected
endedBystringPhone number of user who ended
recordingUrlstringCall recording URL (if available)
deviceIdstringClient 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"
}