> 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.status_changed

> Event emitted each time a call moves through its lifecycle — queued, ringing, in-progress, terminated.

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`](/api-reference/events/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:

`Queued` → `Ringing` → `In-Progress` → `Terminated`

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](/api-reference/events/overview#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` field      | Type           | Description                                                                                                                                                                                                                   |
| ----------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `callId`          | string         | Dial-issued ID for the call. Matches the `id` returned by `GET /api/v1/calls`.                                                                                                                                                |
| `direction`       | string         | `"inbound"` if someone called your Dial number; `"outbound"` if the call originated from a `dial call` / `POST /api/v1/calls`.                                                                                                |
| `from`            | string         | Calling phone number, E.164.                                                                                                                                                                                                  |
| `to`              | string         | Called phone number, E.164.                                                                                                                                                                                                   |
| `phoneNumberId`   | string         | ID of the Dial number this call is on — matches `GET /api/v1/numbers`. Use it to filter the stream to one number.                                                                                                             |
| `status`          | object         | The 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)"`). |
| `previousState`   | string \| null | The state the call left. `null` on the call's first event (nothing preceded it).                                                                                                                                              |
| `terminationType` | string \| null | Only 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:

```json
{
  "id": "evt_5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b",
  "object": "event",
  "type": "call.status_changed",
  "version": 1,
  "createdAt": "2026-05-28T14:34:49.771Z",
  "relatedObject": { "id": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3", "type": "call", "url": "/api/v1/calls/call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3" },
  "data": {
    "callId": "call_01HW3X7P5QF6K2YQ9YJ7Q8R5N3",
    "direction": "inbound",
    "from": "+14155550123",
    "to": "+14155559876",
    "phoneNumberId": "clx8k2j9h0001mk08w3t5r7qz",
    "status": { "state": "In-Progress", "label": "In-Progress" },
    "previousState": "Ringing",
    "terminationType": null
  }
}
```

## 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`](/api-reference/events/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 `id`s.
* 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`.