Webhooks
Subscribe to call lifecycle events instead of polling. We POST signed JSON to your endpoint at each state transition. Failed deliveries retry with exponential backoff, and every payload includes an HMAC SHA-256 signature for verification.
Configure your webhook endpoint URL on the portal.
Events
| Event | Description |
|---|---|
call.initiated |
Party A is being dialed. Call has not yet connected. |
call.ringing |
Party A's phone is ringing. |
call.answered |
Party A answered. We are now dialing Party B to bridge. |
call.bridged |
Both parties are connected and talking. |
call.completed |
Call ended normally. Includes duration and recording URL. |
call.failed |
Call failed. Includes hangup_cause for diagnostics. |
call.no-answer |
Party A did not answer within the timeout window. |
recording.ready |
Recording is processed and available for download. |
Sample payload (call.completed)
{
"event": "call.completed",
"call_sid": "d28be7cd-9840-4b23-9627-199f1ef81fc6",
"data": {
"caller_number": "917969002802",
"target_number": "9876543210",
"masked_number": "917969002802",
"direction": "click_to_call",
"status": "completed",
"started_at": "2026-05-11T08:30:00Z",
"answered_at": "2026-05-11T08:30:08Z",
"ended_at": "2026-05-11T08:31:42Z",
"duration_sec": 94,
"bill_duration_sec": 120,
"price": 3.0,
"recording_url": "recordings/2026/05/11/d28be7cd.wav"
}
}
Verifying signatures
Each request includes an HMAC SHA-256 signature computed over the raw request body using your webhook signing secret (from the portal). Recompute the HMAC on your side and compare it to the signature header before trusting the payload. Always respond with a 2xx status quickly; do any heavy processing asynchronously so deliveries are not retried unnecessarily.