> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getdial.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getdial.ai/_mcp/server.

# call.ended

> Event emitted when a voice call finishes — inbound or outbound.

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`](/api-reference/events/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](/api-reference/events/overview#envelope) (`id`, `object`, `type`, `version`, `createdAt`, `relatedObject`). `relatedObject` is `{ id: <callId>, type: "call", url: "/api/v1/calls/<callId>" }`. The `data` payload:

| `data` field          | Type            | Description                                                                                                                                                                                                                                                                                  |
| --------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `callId`              | string          | Dial-issued ID for the call. Matches the `id` returned by `GET /api/v1/calls`.                                                                                                                                                                                                               |
| `from`                | string          | Calling phone number, E.164.                                                                                                                                                                                                                                                                 |
| `to`                  | string          | Called phone number, E.164.                                                                                                                                                                                                                                                                  |
| `direction`           | string          | `"inbound"` if someone called your Dial number; `"outbound"` if the call originated from a `dial call` / `POST /api/v1/calls`.                                                                                                                                                               |
| `durationSeconds`     | integer \| null | Call duration in seconds. `null` if the call never connected.                                                                                                                                                                                                                                |
| `status`              | string          | Final call status: `completed`, `busy`, `no-answer`, `failed`, or `canceled`. Reflects the call's terminal outcome.                                                                                                                                                                          |
| `canceled`            | boolean         | `true` 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. |
| `transcriptAvailable` | boolean         | Whether a transcript exists on the call record yet. When `true`, a separate [`call.transcribed`](/api-reference/events/call-transcribed) event follows once the transcript is processed.                                                                                                     |

## Example

```json
{
  "id": "evt_7c1b8a2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b",
  "object": "event",
  "type": "call.ended",
  "version": 1,
  "createdAt": "2026-05-28T14:35:21.108Z",
  "relatedObject": { "id": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3", "type": "call", "url": "/api/v1/calls/call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3" },
  "data": {
    "callId": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3",
    "from": "+14155550123",
    "to": "+14155559876",
    "direction": "inbound",
    "durationSeconds": 47,
    "status": "completed",
    "canceled": false,
    "transcriptAvailable": true
  }
}
```

## 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](/documentation/capabilities/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`](/api-reference/events/call-transcribed) event fires.