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

# IVR flows

> The graph that answers a call: greetings, menus, time checks, actions and destinations.

A flow is a graph. A call enters at the entry node and follows an edge out of
each node until it reaches one that ends the call.

<img src="https://mintlify.s3.us-west-1.amazonaws.com/firetone/images/ivr-designer.png" alt="The flow designer" />

## Direction

A flow is **inbound** or **outbound**, and the distinction is enforced where it
is attached, not at runtime.

* An **inbound** flow answers a number, through a process or directly.
* An **outbound** flow runs after a campaign's contact picks up. Its entry node
  is labelled *Contact answered* rather than *Incoming call*, because that is
  when it starts.

A process refuses an outbound flow and a campaign refuses an inbound one. A
graph drawn for one direction meets entry assumptions it was not drawn for.

An outbound flow can also be marked for one **campaign kind**. Left unmarked it
suits both; marked, a campaign of the other kind refuses it by name.

## Publishing

A flow has a draft you edit and a published revision that answers calls. **A
flow with no published revision takes no traffic.**

<Warning>
  A campaign whose workflow has never been published refuses to start, rather
  than playing *"your call cannot be completed as dialled"* to somebody who has
  just heard your message.
</Warning>

## The nodes

| Node                                      | What it does                                                                                                  | Leaves by                         |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| **Entry**                                 | Where the call arrives                                                                                        | `next`                            |
| **Play**                                  | Plays a prompt                                                                                                | `next`                            |
| **Menu**                                  | Collects one digit                                                                                            | the digits you wire, or `timeout` |
| **Collect digits**                        | Asks for a number (an account, a PIN) and saves it as a variable; with nothing to save it as, works as a menu | `next` / `timeout`                |
| **Time condition**                        | Checks the clock                                                                                              | `match` / `nomatch`               |
| **Hold**                                  | Waits, with music                                                                                             | `next`                            |
| **App action**                            | Runs an app — a ticket, an appointment                                                                        | the action's own outcomes         |
| **Fetch data**                            | Looks the caller up in your own system and keeps parts of the answer as variables                             | `ok` / `error`                    |
| **Send email**                            | Emails someone the call's details, from a template or text you write                                          | `sent` / `error`                  |
| **Send SMS**                              | Texts the caller, or any number, through your FireFlo account                                                 | `sent` / `error`                  |
| **Condition**                             | Tests one thing — the caller, a customer field, a flow variable                                               | `match` / `nomatch`               |
| **Voicemail**                             | Takes a message                                                                                               | `left` / `none`                   |
| **Virtual agent**                         | Hands the call to an AI                                                                                       | ends the call                     |
| **Route to extension / queue / external** | Sends the call on                                                                                             | ends the call                     |
| **Hangup**                                | Ends it                                                                                                       | —                                 |

<Note>
  **A menu takes a single digit.** "Press 1 to confirm" is a menu, and the
  digits you wire *are* the valid keys, with no separate list to keep in step.
  For "enter your six-digit reference", use **Collect digits** with a name to
  save it as.
</Note>

## Unwired outlets

An outlet with no edge is not a silent dead end: the caller is told the entry
was invalid and the call ends cleanly, and the flow's trace records which outlet
was never taken. The publish check warns about them before they cost you a call.

## Variables

A flow can remember things about the caller while the call lasts:

* **Collect digits** saves what the caller keys, under the name you give it
  (`acct`). The caller ends with <kbd>#</kbd>, or stops when they reach the
  most digits you allowed.
* **Fetch data** saves parts of your system's answer, one variable per JSON
  path: `tier ← customer.tier`, `first_id ← items.0.id`.
* Always there: `{{caller_number}}`, `{{did}}` (the number they rang),
  `{{call_uuid}}`.

Use a variable by writing `{{name}}`:

| Where                | Example                                                                                                   |
| -------------------- | --------------------------------------------------------------------------------------------------------- |
| Spoken text          | *"Your balance is {{balance}} dollars."* Rendered for this call only, never stored in your audio library. |
| Ring extension       | `{{ext}}`: rings the extension your system named                                                          |
| Send to queue        | `{{queue}}`: a queue name or id in this organisation                                                      |
| Call external number | `{{mobile}}`: read like any dialled number, and refused if it is not a real one                           |
| Fetch data           | `/customers?phone={{caller_number}}`, or a POST body `{"account": "{{acct}}"}`                            |
| Condition            | test **A flow variable** — `tier` equals `vip`                                                            |

A variable nobody set is empty. The publish check warns you when a
`{{placeholder}}` isn't set by any step of the flow.

## Fetch data

The step calls one of your **HTTP connections** (Settings → Integrations): a
base URL plus the headers your system needs. The step adds a path, and a body
for POST.

* The caller hears nothing while it waits, so keep the timeout short. The
  default is 4 seconds and the most is 10.
* If the server answers with anything but a 2xx, doesn't answer in time, or
  answers with something other than JSON when there's something to keep, the
  step leaves by **`error`**. It sets `{{http_status}}`, plus `{{http_error}}`
  saying why. Wire `error` to something the caller can hear.
* Use **Test this request** in the step's settings to run it with sample
  values and see the answer, and what each variable would hold.

See [Integrations](/tenant/phone-system/integrations) for setting up
connections and checking signed requests.

## Send email

**Send email** emails someone while the call carries on: a sales inbox, the
caller's account manager, whoever should know.

* **To**: up to 5 addresses, separated by commas. A variable works, e.g.
  `{{agent_email}}` from a Fetch data step.
* **Email**: one of the IVR email templates the platform keeps for your
  organisation, or **Write it here** with a subject and a plain-text message.
  Ask your provider for a named template if you want the same email from
  several flows.
* Everything takes the call's variables: `{{caller}}`, `{{did}}`, `{{call_uuid}}`
  and anything a Collect or Fetch data step saved.

The email is queued, so the caller never waits for it, and the step leaves by
**sent**. It leaves by **error**, with `{{email_error}}` saying why, when an
address is not valid once filled in, the platform's email is not set up, or
your flows have sent 200 emails in the last hour. Publishing refuses a fixed
address that is not valid, a template that does not exist, and a step with
neither a template nor a subject.

## Send SMS

**Send SMS** texts somebody while the call carries on, usually the caller:
a booking link, a confirmation, the address. It needs your organisation's
FireFlo account ([SMS](/tenant/phone-system/sms)).

* **To**: blank texts the caller. A number the caller gave is read in your
  organisation's country, so `0412345678` works; a variable or a number in
  international form works too.
* **Message**: one of your IVR SMS templates, or text written on the step. The
  count of characters and SMS parts is shown as you type.
* **Send from**: an approved sender ID, or leave it to the template's or the
  default.

It leaves by **sent** once the SMS is queued, and by **error** when the number
is not a mobile number (an extension, an anonymous caller), no SMS account is
connected, the sender ID is not approved, or your organisation has sent 500 SMS
in the last hour. `{{sms_error}}` says which. It texts **at most once per call**,
even if the flow comes back through it.

## Testing a flow

You don't need a phone number to try a flow. Press **Test** in the editor:

* **Ring me now:** FireTone rings your phone, or any extension you pick.
  Every device on that extension rings. Answer and you're in the flow.
* **Test number:** give the flow a short number, like `7001`. Anyone can
  dial it from a phone of your organisation, as often as needed, until you
  remove it. It can't be reached from outside, and it can't be a number an
  extension or call park already uses.

Both run the **draft** by default, so you hear a change before publishing.
Choose **Published** to hear what callers get. A test runs the *saved* draft,
so save first.

**Pretend to be calling from** makes the flow see another caller, e.g. a
customer's mobile, so Conditions and Fetch-data lookups that depend on who is
calling can be tried. The trace still shows who really rang.

Test calls appear in the call trace and logs. Webhooks mark them
`"test": true`. They aren't counted in the flow's status figures.
