The Voice API pushes events to your server in two ways. A status callback is a URL you set per call (or per application) and it receives every state change of that call. A webhook subscription is a workspace-level endpoint that receives signed events such as call.completed, recording.ready, disposition.submitted and call.missed, with a delivery log, retries and replay.
Which one to use#
| Status callback | Webhook subscription | |
|---|---|---|
| Set where | status_callback on POST/v1/calls, or on an application or number |
POST/v1/webhooks/subscriptions |
| Covers | One call, any kind | Agent-dialer campaign calls and missed-call numbers, across the workspace |
| Payload | Twilio-style PascalCase (CallSid, CallStatus, ...) |
JSON envelope {event, timestamp, data} with snake_case fields |
| Signature | X-Webhook-Signature + X-Webhook-Timestamp |
X-Edesy-Signature, keyed with your own secret |
| Docs | Status Callbacks | Subscriptions |
Event list#
Status callback events (labelled this way in the delivery log; the payload carries CallStatus):
| Event | CallStatus |
|---|---|
call.initiated |
initiated |
call.ringing |
ringing |
call.answered |
in-progress |
call.completed |
completed, busy, no-answer, failed or canceled |
A call that does not connect is reported as call.completed with a failing CallStatus, and its timeline at GET/v1/calls/{CallSid}/events shows call.failed.
Subscription events:
| Event | Fires when | Scope |
|---|---|---|
call.answered |
A lead picks up | Agent-dialer campaigns |
call.completed |
The call ends, whatever the outcome | Agent-dialer campaigns |
recording.ready |
The call's recording is stored and playable | Agent-dialer campaigns |
disposition.submitted |
An agent submits a wrap-up code | Agent-dialer campaigns |
call.missed |
A number routed to the missed-call target declines a call | Missed-call numbers |
webhook.test |
You press Test, or call POST/v1/webhooks/subscriptions/{id}/test |
Test only |
call.missed example#
{
"event": "call.missed",
"timestamp": "2026-10-28T09:42:18Z",
"data": {
"call_sid": "CA_8f3c1e0b-0000-4000-8000-000000000000",
"from": "+9198XXXXXXXX",
"to": "+9180XXXXXXXX",
"direction": "inbound",
"status": "missed",
"sip_status": 486,
"phone_number_id": "5e229f03-0000-4000-8000-000000000000",
"phone_number_name": "Campaign line"
}
}
from is the caller and to is your number. call_sid is safe to de-duplicate on. Each delivered call.missed event costs Rs 0.30 (excluding GST); nothing is charged while no endpoint is subscribed.
Next#
- Subscriptions: create, filter, test.
- Verify Signatures: Node.js and Python.
- Retries and Replay: delivery log and re-sending.