call.ended

View as Markdown

Emitted when a voice call on one of your Dial numbers wraps up. It’s the terminal snapshot: one event per call, carrying the outcome (status, durationSeconds). To follow a call while it’s happening — ringing, answered — listen for call.status_changed, which streams every lifecycle transition; its Terminated transition coincides with this event. The full call record (status, duration, transcript) is available via GET /api/v1/calls/{id} — the relatedObject.url.

Schema

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

data fieldTypeDescription
callIdstringDial-issued ID for the call. Matches the id returned by GET /api/v1/calls.
fromstringCalling phone number, E.164.
tostringCalled phone number, E.164.
directionstring"inbound" if someone called your Dial number; "outbound" if the call originated from a dial call / POST /api/v1/calls.
durationSecondsinteger | nullCall duration in seconds. null if the call never connected.
statusstringFinal call status: completed, busy, no-answer, failed, or canceled. Reflects the call’s terminal outcome.
canceledbooleantrue if the call was cancelled (via the dashboard’s terminate button or the cancel API) before it ended — even if the terminal status is completed (an in-progress call that you hang up reports completed). Lets you tell a user-initiated hang-up apart from a natural completion.
transcriptAvailablebooleanWhether a transcript exists on the call record yet. When true, a separate call.transcribed event follows once the transcript is processed.

Example

1{
2 "id": "evt_7c1b8a2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b",
3 "object": "event",
4 "type": "call.ended",
5 "version": 1,
6 "createdAt": "2026-05-28T14:35:21.108Z",
7 "relatedObject": { "id": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3", "type": "call", "url": "/api/v1/calls/call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3" },
8 "data": {
9 "callId": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3",
10 "from": "+14155550123",
11 "to": "+14155559876",
12 "direction": "inbound",
13 "durationSeconds": 47,
14 "status": "completed",
15 "canceled": false,
16 "transcriptAvailable": true
17 }
18}

When it fires

  • Every voice call on one of your Dial numbers, inbound or outbound, emits exactly one call.ended once the call reaches its terminal status.
  • Cancelling a call — via the dashboard’s terminate button or the cancel API — also produces a call.ended, carrying data.canceled: true. So a dial wait-for call.ended is always released when the call ends, however it ends.
  • Filter on direction: "inbound" if you only care about calls to your number — see Receive a voice call for the full flow.
  • The event tells you the call is done. To read the transcript or other details, fetch the call record after — data.transcriptAvailable may be false at the instant the event fires and finalize a moment later, at which point a call.transcribed event fires.