call.status_changed

View as Markdown

Emitted every time a voice call on one of your Dial numbers advances to a new lifecycle status. It’s the live, thin counterpart to call.ended: call.status_changed streams each transition as it happens (a call started ringing, was answered, terminated), while call.ended is a one-shot terminal snapshot carrying outcome details like durationSeconds. Wait on call.status_changed to react the moment a call starts or is answered; keep waiting on call.ended if you only care that it finished.

The status payload mirrors the status object returned by GET /api/v1/calls/{id} — the relatedObject.url — so what you see on the stream always matches what a fetch of the call record would show.

Lifecycle states

A call moves forward through these states, never backward:

QueuedRingingIn-ProgressTerminated

Not every call passes through every state, so don’t build a consumer that requires all four events: an outbound call that fails to connect can jump from Queued straight to Terminated, and some inbound calls first become visible to Dial once they’re already answered — their first event is In-Progress. Every call’s last event is always Terminated.

Schema

Shares the common event envelope (id, object, type, version, createdAt, relatedObject). relatedObject is { id: <callId>, type: "call", url: "/api/v1/calls/<callId>" }. The envelope’s createdAt is when the transition happened. The data payload:

data fieldTypeDescription
callIdstringDial-issued ID for the call. Matches the id returned by GET /api/v1/calls.
directionstring"inbound" if someone called your Dial number; "outbound" if the call originated from a dial call / POST /api/v1/calls.
fromstringCalling phone number, E.164.
tostringCalled phone number, E.164.
phoneNumberIdstringID of the Dial number this call is on — matches GET /api/v1/numbers. Use it to filter the stream to one number.
statusobjectThe status the call just entered: { state, label }. state is one of "Queued", "Ringing", "In-Progress", "Terminated"; label is the display string (e.g. "Ringing", "Completed", "Completed (Cancelled)").
previousStatestring | nullThe state the call left. null on the call’s first event (nothing preceded it).
terminationTypestring | nullOnly set when status.state is "Terminated": completed, busy, no-answer, failed, or canceled — the same value call.ended reports as status. null for all non-terminal transitions.

Example

An inbound call being answered:

1{
2 "id": "evt_5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b",
3 "object": "event",
4 "type": "call.status_changed",
5 "version": 1,
6 "createdAt": "2026-05-28T14:34:49.771Z",
7 "relatedObject": { "id": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3", "type": "call", "url": "/api/v1/calls/call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3" },
8 "data": {
9 "callId": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3",
10 "direction": "inbound",
11 "from": "+14155550123",
12 "to": "+14155559876",
13 "phoneNumberId": "clx8k2j9h0001mk08w3t5r7qz",
14 "status": { "state": "In-Progress", "label": "In-Progress" },
15 "previousState": "Ringing",
16 "terminationType": null
17 }
18}

When it fires

  • Once per state a call actually enters, inbound or outbound — at most four events per call, always ending with Terminated. Deduplicate on the envelope id; a given call emits each state at most once.
  • Requesting a cancel does not emit an event — cancellation is a request, not a state. When the cancelled call actually ends, the Terminated event carries terminationType: "canceled" (or, for an answered call you hung up, terminationType: "completed" with label: "Completed (Cancelled)").
  • The Terminated transition and call.ended describe the same moment and both fire. They’re intentionally redundant: call.status_changed keeps the lifecycle stream uniform, call.ended carries the terminal extras (durationSeconds, canceled, transcriptAvailable). Consume whichever fits, or both — they have distinct event ids.
  • To catch inbound calls the moment they arrive, filter on direction: "inbound" and treat the first event you see for a callId as the arrival — that’s Ringing when Dial observes the ring, otherwise In-Progress.