> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wave.sa/llms.txt
> Use this file to discover all available pages before exploring further.

# How voice works

> The shape of a Wave voice call — numbers, call flows, and events.

A voice interaction on Wave has three moving parts:

<CardGroup cols={3}>
  <Card title="Numbers" icon="hashtag">
    A phone number (or SIP user) is the entry point — someone dials it, or you
    place a call from it.
  </Card>

  <Card title="Call flows" icon="diagram-project">
    A **call flow** decides what the call does, expressed in [WaveML](/voice/waveml)
    — play a prompt, gather a digit, bridge, record, hand off to an AI agent.
  </Card>

  <Card title="Events" icon="bell">
    Every state change (ringing, answered, ended, a digit pressed) is delivered to
    your [webhook](/webhooks) endpoint.
  </Card>
</CardGroup>

## The lifecycle of a call

<Steps>
  <Step title="A call starts">
    Either a caller dials your number (**inbound**), or you place one with the
    [Callbacks API](/quickstart) (**outbound**). Every call gets a stable
    `wave_call_id` (a UUID) that appears on all its events and in the
    [call logs](/web-callback#call-lifecycle).
  </Step>

  <Step title="The engine runs your call flow">
    Wave's voice engine fetches your call flow and executes it verb by verb. If the
    flow needs input (a keypad digit, an AI-agent outcome), the engine pauses,
    collects it, and continues — see the loop below.
  </Step>

  <Step title="Events reach your webhook">
    As the call progresses, Wave POSTs signed events to your endpoint:
    `call.initiated`, `call.answered`, `call.ended`, and — when a caller makes a
    menu choice — `call.input`.
  </Step>

  <Step title="The call appears in your logs">
    When it ends, the call (with duration, status, and any recording pointer) is in
    `GET /v1/calls`.
  </Step>
</Steps>

## The call-flow loop

Call flows run as a **chunked loop**. When the engine needs instructions it sends
your flow a JSON request; you reply with a [WaveML](/voice/waveml) document. The
`node_id` on each verb is a cursor the engine echoes back, so your flow always
knows where the call is.

```json theme={null}
// what the engine sends your flow
{
  "wave_call_id": "27d6dd39-f9e8-4fed-b378-a830b23bacd3",
  "src_number": "0115209300",
  "dst_number": "9001",
  "direction": "inbound",
  "node_id": "",              // cursor — empty on the first request
  "dtmf": "",                 // digits collected by the previous <Gather>
  "aiagent_result": ""        // outcome word from the previous <AIAgent>
}
```

You answer with WaveML. On a `<Gather>`, the caller's digits come back on the next
request as `dtmf`; on an `<AIAgent>`, the outcome comes back as `aiagent_result`.
Branch on the `node_id` + the input to drive the call.

<Note>
  **Where flows live today.** The engine executes WaveML, but call flows are
  currently provisioned for your account (dashboard + your Wave contact) rather
  than authored through a public API. A call-flow authoring API is on the roadmap.
  You can build against everything else — placing calls, receiving events, reading
  logs, allocating numbers, managing queues — today.
</Note>

## Events you can subscribe to

Register an endpoint under [Webhooks](/webhooks) and subscribe to the voice events:

| Event                                                             | When                                                              |
| ----------------------------------------------------------------- | ----------------------------------------------------------------- |
| `call.initiated`                                                  | The call was placed / arrived.                                    |
| `call.answered`                                                   | The far end answered.                                             |
| `call.ended`                                                      | The call completed.                                               |
| `call.missed` · `call.timeout` · `call.failed` · `call.cancelled` | The call didn't connect.                                          |
| `call.input`                                                      | A caller pressed a key in a `<Gather>` — carries `{ digits, … }`. |

## What you can build today

<CardGroup cols={2}>
  <Card title="WaveML reference" icon="code" href="/voice/waveml">
    Every verb a call flow can use.
  </Card>

  <Card title="Virtual numbers" icon="user-tag" href="/voice/virtual-numbers">
    Give each of your end-users their own Saudi number.
  </Card>

  <Card title="Queues" icon="users-line" href="/voice/queues">
    Route callers to agents and manage who's logged in.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks">
    Receive call events at your endpoint.
  </Card>
</CardGroup>
