---
title: "Voice sequence node reference"
description: "Look up the generally available steps for an inline voice sequence definition, with each type, its fields, allowed values, and outcomes."
---

# Voice sequence node reference

> **Warning:** Voice sequences are in preview. Steps, entry data, and the sequence definition format can change in ways that break existing sequences and API requests.

Use this reference to write the `sequence.definition` you send with [Create Call](/docs/guides/voice/create-calls#run-an-inline-sequence). Bird runs an inline definition once and does not save it. To keep a sequence, build it in the [dashboard editor](/docs/guides/voice/sequences/editor).

## Definition

| Field                    | Value                                                                                                                                    |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `schema_version`         | `1`.                                                                                                                                     |
| `expression_environment` | `"bird.cel.v1"`.                                                                                                                         |
| `nodes`                  | Array of node objects. Array order has no effect on execution.                                                                           |
| `settings`               | Omit it or send `{}`. A non-empty object fails with `unsupported_contract`; a value that is not an object fails with `invalid_envelope`. |
| `presentation`           | Optional editor layout and labels. It does not affect execution but counts toward size limits.                                           |

Each node has these fields:

| Field          | Value                                                                                                                  |
| -------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `id`           | Unique in the definition. Starts with a lowercase letter, then lowercase letters, digits, or `_`, up to 64 characters. |
| `type`         | A node type from this page, such as `voice.say`.                                                                       |
| `type_version` | `1` for every node type on this page.                                                                                  |
| `config`       | Setup that fixes the node's shape, such as declared outcomes. Use `{}` when the node has none.                         |
| `input`        | Values the node uses when it runs. Use `{}` when the node has none.                                                    |
| `connections`  | Map from an outcome name to `{ "node_id": "<target>", "port": "input" }`.                                              |

Connections must not form a loop, and every node must be reachable from an entry. An outcome left out of `connections` is unconnected. Unconnected outcomes end the run normally, except where a node says otherwise.

## Values and expressions

Most fields take literal JSON. Fields marked **binds** also accept `$expr` or `$template`; fields marked **expr** also accept `$expr` only:

- `{"$expr": "trigger.data.customer_name"}` returns a typed value.
- `{"$template": ["Hello ", {"$expr": "trigger.data.customer_name"}, "."]}` returns text. Templates are arrays; `{{name}}` stays literal text.

Expressions use CEL and can read these values:

| Value                                  | Contents                                                                                            |
| -------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `trigger.data`                         | The entry data, matching the entry's `data_schema`.                                                 |
| `trigger.node_id`                      | The ID of the entry that started this visit.                                                        |
| `trigger.type`                         | The type of the entry that started this visit, such as `trigger.start_call`.                        |
| `steps.<id>.output`                    | Output of an earlier completed node in this visit.                                                  |
| `variables.<key>`                      | Values saved by a `data.set` node in this visit.                                                    |
| `execution.id`, `execution.started_at` | The run ID and its start time. Use `string(execution.started_at)` in speech.                        |
| `execution.call`                       | The call's `id`, `session_id`, and original parties `orig` and `dest`, each of which can be `null`. |

Guard optional values before reading them, for example `has(trigger.data.name) ? trigger.data.name : 'caller'`. The `has` macro is available; `map`, `filter`, `all`, `exists`, and `exists_one` are not.

## Entry

### `trigger.start_call`

Where a call starts. `entry_node_id` in the Create Call request names this node.

| Field                | Value                                                                                                                                           |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `config.data_schema` | Optional JSON Schema (draft 2020-12) object schema for `trigger_data`. Only local `$ref` is supported. Without it, the entry accepts only `{}`. |
| Outcome              | `event`.                                                                                                                                        |

Entry data is limited to 16 KiB.

## Speech and audio

### `voice.say`

| Field            | Value                                                  |
| ---------------- | ------------------------------------------------------ |
| `input.text`     | Required, **binds**. Text to speak, at most 160 bytes. |
| `input.language` | Required. Speech language code, such as `en`.          |
| Outcome          | `next`.                                                |

### `voice.play`

| Field            | Value                                                                                                                  |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `input.asset_id` | Required. ID of an audio asset available in this workspace. An unavailable asset can fail the call when the step runs. |
| Outcome          | `next`.                                                                                                                |

### `voice.tone`

| Field                | Value                      |
| -------------------- | -------------------------- |
| `input.frequency_hz` | Required. `100` to `3000`. |
| `input.duration_ms`  | Required. `1` to `10000`.  |
| Outcome              | `next`.                    |

### `logic.pause`

Waits with the call connected.

| Field               | Value                     |
| ------------------- | ------------------------- |
| `input.duration_ms` | Required. `1` to `60000`. |
| Outcome             | `next`.                   |

## Keypad input

### `voice.gather`

Plays prompts, which a key press interrupts, and collects keypad digits.

| Field                               | Value                                                                                                                                                                                                                                                                                                                           |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `input.prompts`                     | Required. Up to 4 prompts. Each is `{"type": "say", "text", "language"}`, `{"type": "play", "asset_id"}`, `{"type": "tone", "frequency_hz", "duration_ms"}`, or `{"type": "pause", "duration_ms"}`, with the same limits as the matching node. Tone and pause durations together are at most 60000 ms. Prompt `text` **binds**. |
| `input.max_digits`                  | Required. `1` to `32`.                                                                                                                                                                                                                                                                                                          |
| `input.timeout_seconds`             | Required. Seconds to wait for the first key, `1` to `10`.                                                                                                                                                                                                                                                                       |
| `input.inter_digit_timeout_seconds` | Required. Seconds to wait between keys, `1` to `5`.                                                                                                                                                                                                                                                                             |
| `input.finish_on_key`               | Required. One of `0`–`9`, `*`, `#`, `A`–`D` that ends input, or `null`.                                                                                                                                                                                                                                                         |
| `input.matches`                     | Required. Map from an outcome name to the exact digits that select it, such as `{"hours": "1"}`. Names and digits must be unique. A name cannot be `input`, `timeout`, or `fallback`. Digits are at most `max_digits` long and cannot contain `finish_on_key`.                                                                  |
| `input.private`                     | Optional, default `false`. When `true`, later steps cannot read the digits, and they are left out of the trace.                                                                                                                                                                                                                 |
| Outcomes                            | Each name in `matches`, `timeout` when no key is pressed, and `fallback` for any other input.                                                                                                                                                                                                                                   |
| Output                              | `digits` and `reason`: `initial_timeout`, `max_digits`, `finish_key`, or `inter_digit_timeout`.                                                                                                                                                                                                                                 |

## Logic and data

### `logic.branch`

Checks conditions in order and follows the first that is true.

| Field                 | Value                                                                        |
| --------------------- | ---------------------------------------------------------------------------- |
| `config.cases`        | Required. At least one `{"port": "<name>", "when": {"$expr": "<boolean>"}}`. |
| `config.default_port` | Required. Outcome name when no case is true.                                 |
| Outcomes              | Each `port` in `cases`, and `default_port`.                                  |
| Output                | `branch`: the selected outcome name.                                         |

### `data.set`

Saves values for later steps in the same visit.

| Field   | Value                                                                                                                                                    |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `input` | Object of values, each of which **binds**. Each key becomes `variables.<key>`. Every value is computed from the variables as they were before this node. |
| Outcome | `next`.                                                                                                                                                  |
| Output  | The saved object.                                                                                                                                        |

## Calls and transfers

### `voice.dial`

Calls another number and connects it to the current call.

| Field                   | Value                                                                                                                                                                                                               |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `input.to`              | Required, **binds**. E.164 number, such as `+12025550123`.                                                                                                                                                          |
| `input.timeout_seconds` | Required, **expr**. Seconds to ring, `1` to `120`.                                                                                                                                                                  |
| Outcomes                | `success`, `busy`, `no_answer`, and `failure`. `success` follows after the connected call ends and the original call's audio is restored, not when the destination answers. An unconnected `failure` fails the run. |

### `logic.voice_goto`

Starts another entry in the same definition. The new visit gets fresh `trigger.data` and clears earlier step outputs and variables; the call continues.

| Field                 | Value                                                                |
| --------------------- | -------------------------------------------------------------------- |
| `input.entry_node_id` | Required. ID of a `trigger.start_call` node in this definition.      |
| `input.data`          | Optional, **expr**, default `{}`. Entry data for that node's schema. |
| Outcomes              | None.                                                                |

## Ending the call

### `logic.exit`

Ends the call with a result.

| Field           | Value                                                                                                                                                            |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config.status` | Required. `succeeded` or `failed`.                                                                                                                               |
| `config.reason` | Optional, **expr**. Stable code of lowercase letters, digits, and `_`, starting with a letter or digit, up to 64 characters. Omit it rather than sending `null`. |
| `input.output`  | Required object, which can be `{}`. Its top-level values **bind**.                                                                                               |
| Outcomes        | None.                                                                                                                                                            |

### `voice.hangup`

Ends the call without an authored result. It has no fields and no outcomes.

## Early access steps

`voice.webhook`, `voice.record_start`, `voice.record_stop`, and `logic.voice_goto` with `dependency_id` for managed voicemail or call recording are in early access and are not documented here. Using them requires access for your workspace.

## Example: transfer to a person

This definition greets the recipient, dials a support number, and records whether the transfer connected:

```json
{
  "schema_version": 1,
  "expression_environment": "bird.cel.v1",
  "nodes": [
    {
      "id": "start",
      "type": "trigger.start_call",
      "type_version": 1,
      "config": {},
      "input": {},
      "connections": { "event": { "node_id": "greeting", "port": "input" } }
    },
    {
      "id": "greeting",
      "type": "voice.say",
      "type_version": 1,
      "config": {},
      "input": { "text": "Connecting you to our support team.", "language": "en" },
      "connections": { "next": { "node_id": "support", "port": "input" } }
    },
    {
      "id": "support",
      "type": "voice.dial",
      "type_version": 1,
      "config": {},
      "input": { "to": "+12025550123", "timeout_seconds": 30 },
      "connections": {
        "success": { "node_id": "connected", "port": "input" },
        "busy": { "node_id": "unavailable", "port": "input" },
        "no_answer": { "node_id": "unavailable", "port": "input" },
        "failure": { "node_id": "unavailable", "port": "input" }
      }
    },
    {
      "id": "connected",
      "type": "logic.exit",
      "type_version": 1,
      "config": { "status": "succeeded", "reason": "transferred" },
      "input": { "output": {} }
    },
    {
      "id": "unavailable",
      "type": "logic.exit",
      "type_version": 1,
      "config": { "status": "failed", "reason": "support_unavailable" },
      "input": { "output": {} }
    }
  ]
}
```

Send it as `sequence.definition` with `"entry_node_id": "start"` and `"trigger_data": {}`.

## Related resources

- [Voice sequences](/docs/guides/voice/sequence-builder) (docs)
