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

# Classical IVR

> Build deterministic keypad menus with WAV recordings, identifier collection, working hours and team transfers.

Classical IVR runs a saved workflow when an assigned number receives a call. Key presses select explicit branches; a phone agent does not interpret them or rewrite your recordings.

## Enable and create

1. Open **Settings → Voice & Telephony** and enable telephony.
2. Turn on **Enable Classical IVR** on the same settings page. This makes the IVR trigger and nodes available in Workflows.
3. Open **Channels → Phone**. The page contains **AI phone agents** followed by **Classical IVR**. Use the Classical IVR section to manage workflows, recordings and phone-number assignments. This section is hidden while Classical IVR is disabled.
4. Open the **WAV recordings** tab to upload recordings. In the **Workflows** tab, select **Create IVR**. The editor starts with the **IVR Incoming Call** trigger.
5. Build the flow, save a version and activate it.
6. Use **Test call** in the **Workflows** tab before assigning a phone number. After testing, use the searchable **Phone numbers** selector on the workflow row to assign one or more numbers. The selector shows each number’s name and phone number, and you can search by either. Deselect a number to remove its assignment. Numbers assigned to another IVR are labeled; selecting one moves it to this IVR.

Only verified phone numbers can be assigned. Each phone number can have only one inbound destination: an IVR or an AI phone agent. Numbers assigned to a phone agent cannot be selected for an IVR until you unassign them from that agent, and vice versa. **Settings → Phone Numbers → Inbound destination** shows the assigned IVR or agent name. Assignment changes display **Applying routing…** while they are saved and applied to incoming calls.

The **IVR Incoming Call** trigger runs only for calls to numbers assigned in the workflow row’s **Phone numbers** selector. It does not subscribe to other inbound calls, outbound calls or AI phone-agent calls. The workflow list shows each IVR’s assigned numbers in a scrollable table with 10 workflows per page. Use the page controls below the table to browse additional workflows.

You need workflow read permission to view flows and recordings, and workflow write permission to upload recordings, edit flows or start a test call. Assigning a number also requires voice-channel settings write permission.

<Warning>
  A browser test runs the active flow, including its lookup and session actions. Team transfers ring real available teammates. Use a test organization or test teams when you need isolation.
</Warning>

Turning Classical IVR off preserves workflows, recordings and number assignments. New calls use the number’s usual routing until Classical IVR is enabled again. Changing this setting requires Voice & Telephony write access.

## Classical IVR nodes

| Node | Purpose | Next step |
| - | - | - |
| Play WAV recording | Play an uploaded recording without changing its words | Branch on `completed` or `error` |
| Keypad Menu | Collect one allowed key | Branch on `outcome` and `digits` |
| Collect Digits | Collect an identifier or callback number | Confirm input before using it for a lookup |
| Speak Text | Read fixed text or repeat a workflow value | Select a language; enable digit-by-digit reading for identifiers |
| Transfer Call | Ring a team, transfer to an external phone-number destination, or connect a SIP destination | An answer ends the flow by default; team transfers can opt into post-call steps; SIP transfers always continue the flow |
| Save Keypad CSAT Rating | Save a collected 1–5 rating to native CSAT reporting | Reference a completed keypad step in this IVR run |
| Record Voicemail | Play a greeting and tone, then save caller audio and a callback number for a team | Branch on `completed`, `no_input` or `error`, then end the call |
| End Call | End the call | No later steps run |

Use existing workflow condition, working-hours, contact lookup and session-note actions alongside these nodes. For example: menu → collect VAT → repeat digits → confirmation menu → contact lookup → team transfer. A VAT match identifies a record; it does not prove the caller is authorized to access it.

## WAV recordings

Upload mono or stereo WAV files with 16-bit PCM, A-law or mu-law encoding. Supported sample rates are 8, 16, 24, 32, 44.1 and 48 kHz. Files must be at most **20 MB** and **five minutes** long. Unsupported or malformed files are rejected.

Uploads are automatically compressed for speech playback. Keep uploading WAV files; no conversion is needed on your side. Each recording is fully loaded before playback, and playback buffers are released when it finishes or is interrupted. Existing uploaded recordings remain playable.

Keypad Menu and Collect Digits have two recording selectors: **Menu WAV recording** plays the main prompt, while **Retry WAV recording (optional)** plays before a retry after missing or invalid keypad input. Leave the main recording empty to use menu text; leave the retry recording empty to repeat the menu without an extra recording.

You can also select **Upload WAV recording** beside a workflow node’s recording selector. The modal lets you preview a WAV before uploading; the new recording is selected automatically for that node.

The recordings table shows 10 recordings per page in a scrollable area. Use the page controls below the table to browse additional recordings. Uploading a recording returns you to the first page.

Select **Preview** to listen before using a recording. Each upload creates a new recording. To replace a recording, upload a new file and select it in a new workflow version. Existing calls keep the workflow version and recording references they started with.

For keypad menus, either select a WAV recording or enter fixed menu text and its two-letter language code. A WAV recording takes precedence when both are supplied. Speak Text reads exactly the supplied text; it does not compose a response.

## Input and retries

* Menus collect one key. Set **Allowed menu keys**, for example `1239`.
* Digit collection accepts 1–32 digits. Keep identifiers as text to preserve leading zeros.
* Input completes when its maximum length is reached or the caller presses the configured finish key. Fixed-length input can use **None** as its finish key.
* To accept variable-length input without requiring `#`, enable **Submit after a pause** and set **Inter-digit timeout (seconds)**. Once the minimum digit count is met, that pause submits the entered digits. This option is off by default; missing or shorter input still follows the timeout branch. Set the minimum length carefully to avoid treating an incomplete identifier as complete.
* No-input timeout defaults to 10 seconds; the pause allowed between digits defaults to 5 seconds.
* Maximum attempts defaults to 3 and can be set from 1 to 5. Use **Retry WAV recording** to select or upload the recording played after missing or invalid input.
* Keys may interrupt playback when **Allow keys during playback** is enabled, once the prompt starts playing. Keys pressed while a prompt is loading are ignored.
* With **Allow keys during playback** disabled, callers must wait for the entire prompt before entering input. Use this for instructions that must be heard before a selection, such as consent. The no-input timeout starts after playback finishes.
* Keys pressed between workflow steps are recorded as ignored; they are never carried into the next menu or identifier. Wait for the next prompt before entering the next value.

Branch explicitly for `input`, `no_input`, `invalid`, `inter_digit_timeout` and `error`. With **Submit after a pause** off, a pause before completion never produces successful input. Retrying collection starts with an empty digit buffer. Route missing or invalid identifiers to your chosen fallback; do not treat an input error as the caller declining consent or cancelling a callback.

## Voicemail for a team

**Record Voicemail** is available in IVR workflows after voicemail support has been enabled in your deployment. Existing callback menus require this action to record a message; saving a callback number alone does not start recording.

1. Upload your voicemail greeting under **WAV recordings**. Include the instructions for leaving a message; the action plays the tone automatically after the greeting.
2. Add **Record Voicemail** after your callback-number selection. Select the greeting and the receiving support team.
3. Set **Callback number** to a full international number beginning with `+`, such as `+35722123456`, and select **Number source**:
   * **Caller number**: map the incoming caller number. If caller ID is withheld or unusable, route to number collection first.
   * **Entered number**: use **Collect Digits**, validate and normalize the entered number, then pass the full international number to the action. Keypad entry cannot include `+`; add it after collecting a country code, or apply the correct country prefix for local input. This callback number does not replace the contact's saved phone number.
4. Set **Maximum message length (seconds)**, **Wait for speech (seconds)**, **Finish after silence (seconds)** and **Finish key**. Defaults are 180 seconds, 10 seconds, 5 seconds and `#` respectively. Maximum message length accepts 10–300 seconds.
5. Follow the action with **End Call**, optionally preceded by a confirmation on `completed` or a retry/fallback on `error`. Complete any required recording-consent steps before this action.

**Keep IVR unrecorded** controls the full-call recording; Record Voicemail explicitly records the message even when that setting is on. Use that setting when the greeting and menus should also be absent from the separate full-call recording.

Only the caller's incoming audio after the tone is saved. The greeting and other IVR playback are excluded. Recording finishes when the caller hangs up, presses the finish key, reaches the maximum length, or stops speaking for the configured period. Keys pressed during the greeting or tone do not finish the message.

The selected team receives an open session containing the callback number and a playable **Voicemail** card in the call history. Agents need session read permission to view it; calling back uses the usual outbound-call permissions. Ending the phone call leaves the session open for the team to handle. Delivery retries preserve later agent changes. Moving a voicemail session to a different team runs team-change workflows. If delivery reopens a closed session, its history records the system reopen and session-reopened workflows run. Deleting a team preserves its historical voicemail; if the selected team is removed or disabled before delivery, the session appears unassigned for follow-up.

An empty message returns `no_input`: callback details remain available and the card says no spoken message was recorded. Interrupted recordings show an incomplete or failed state and retain any recoverable audio. If the recording process disappears unexpectedly, recovery runs after ten minutes of inactivity. Temporary audio is cleaned up after completion; deleting the session also schedules its voicemail audio for deletion.

Configure country-to-team routing in the workflow before this action. The receiving team is explicit and does not depend on the callback number's country code.

## Business hours and holidays

Add **Get Custom Working Hours** to read a named schedule from **Settings → Office Hours**. Branch on `isHoliday` for holiday handling, then `isNowWithinHours` for regular open/closed handling. Use `exceptionName` in internal notes when useful. Keep dates, recurring holidays and opening periods in the schedule rather than duplicating them in workflow code. See [Office hours and holidays](/api-reference/office-hours/index).

## Transfers and version changes

Transfer Call uses an existing team, phone-number or SIP transfer destination. Team transfers use the team’s availability and ring settings. By default, an actual teammate joining ends the IVR and leaves the human call connected. When no eligible teammates exist, or nobody answers, the workflow continues with `no_eligible_agents` or `no_answer`. Add a callback-choice branch or a closing message for those outcomes.

For an external transfer, choose a **Phone Number** destination containing a full international number beginning with `+`. The incoming telephone carrier must support transferring the call. Browser preview calls and extensions are not supported by this IVR action; to keep the caller on the OpenCX call, use a SIP destination instead (see below). A successful carrier handoff returns `transferred` and ends the IVR; it does not confirm that a person answered. A rejected transfer returns `error`, so add a fallback branch. After handoff, OpenCX no longer controls the remote call’s recording, whisper or queue behavior. **Record human call** applies to OpenCX team and SIP transfers, not to external phone transfers.

For a team transfer, optionally select **Agent whisper recording**. The picker lists uploaded recordings of at most 15 seconds. After a teammate accepts, the dashboard plays it privately before joining the caller. It is not published into the call or included in the call recording. If the recording cannot be loaded, acceptance continues without an announcement. If browser playback is blocked or fails, the teammate sees a warning and the call connects without the announcement; a stalled playback is limited to 20 seconds. Use headphones and enable browser call audio before testing auto-answer. Switching organizations during the announcement ends the accepted call, so it cannot remain assigned without a teammate. Browser refresh/recovery after joining does not replay the whisper.

Activating a new version applies to new calls. Removing a number's call-flow assignment restores its other configured routing. Unassign a flow from its numbers before deactivating it.

Browser tests use your microphone, speakers and the on-screen keypad. They verify the call media and workflow behavior without changing number assignments. A successful browser test does not verify a carrier connection; test a real incoming call before rollout.

When an IVR-only call ends, its final status and duration are saved before Phone Call Finished workflows run. The session closes unless the call has entered a Record Voicemail action, which leaves it open for the receiving team. A successful team transfer keeps the human call open until it ends.

## Transfers to a SIP destination

Choose a **SIP** destination to connect the caller to an external SIP endpoint, such as an external virtual assistant or another contact center, without handing the call away. The caller stays on the OpenCX call while the destination talks to them, so the session keeps one call, one recording and one transcript, and the IVR decides what happens next:

| Outcome | When | What to add after it |
| - | - | - |
| `handed_back` | The destination returned the caller through [Hand back a call](/api-reference/phone/hand_back_call) | Usually a team Transfer Call. Its teammate sees the summary the destination sent |
| `completed` | The destination hung up | A closing message, a keypad survey, or End Call |
| `no_answer` | The destination did not answer, was busy or declined | A fallback transfer or a message |
| `error` | The call could not be placed, for example a rejected caller ID or a broken route | A fallback transfer or a message |

The destination is hung up as soon as its hand-back is accepted, before the next step runs, so it never hears the rest of the call; if it cannot be hung up, the call ends instead of continuing. A hand-back is accepted only after the destination answered. If the caller hangs up during the transfer, the destination is hung up too and the flow ends. A transfer lasts at most three hours.

Recording follows the same rules as a team transfer: with **Keep IVR unrecorded** enabled, the answered transfer is recorded only when **Record human call** is `true`, and the recording continues after a hand-back into the teammate's call. When the destination hangs up and the flow continues, the recording stops first, as it does before a post-call survey. When live transcripts are enabled for your organization, the destination's speech appears in session history under the destination's name.

### SIP headers from the workflow

Use **SIP headers (optional)** on Transfer Call to send values from earlier steps, such as the dialed number from the trigger or a customer tier from a lookup, as custom `X-` headers. Headers apply to external phone and SIP transfers.

* Every transfer carries the session ID as `X-OPENCX-SESSION-ID`, unless a SIP destination's allowed headers leave it out. Destinations that hand calls back need it, so add it to their list.
* A header whose value is empty when the step runs is not sent. Names must start with `X-` and cannot start with `X-OPENCX-`; values are up to 255 printable characters; a step can set up to 20 headers.
* A header the SIP destination already sends from its own settings cannot be set again by the workflow, and neither can `X-Zendesk-Ticket-Id`, which comes from the session.
* A SIP destination with **Send only allowed headers** receives only the names on its list, the session ID included. SIP transfers send no other headers: not the organization's internal identifiers, and not the headers that arrived on the caller's call.

Configure caller ID, encryption and allowed headers on the destination; see [SIP transfer destinations](/phone/sip-integration#sip-transfer-destinations).

## Post-call keypad surveys

For team transfers, enable **Continue IVR after the human call** on Transfer Call. The IVR stays silent while the teammate speaks with the caller. When the teammate clicks **End call**, the teammate leaves and begins their normal wrap-up; the caller stays connected to hear the following IVR steps. The human-call recording is stopped before the survey starts. Call duration includes the caller’s time in the survey; teammate wrap-up starts when the human call ends.

Build the survey in the same incoming-call workflow:

1. Optionally play your survey invitation before Transfer Call.
2. Enable **Continue IVR after the human call** on the team transfer.
3. Branch on the transfer outcome. Run the survey only for `completed`; keep your existing fallback for failed or unanswered transfers.
4. Add a Keypad Menu using your rating recording, allowed keys `12345`, and finish key **None**. Configure missing-input and invalid-input branches separately.
5. On `input`, add **Save Keypad CSAT Rating** and supply that menu’s step ID. It reads the accepted digits from this run; it cannot submit an arbitrary score or use another session’s input.
6. Play your acknowledgement recording, then End Call. End missing or invalid responses without creating a rating.

Enable **Phone** in your CSAT settings before saving keypad ratings. This action saves the rating in native CSAT reporting and session history, with the session’s assigned teammate and team at submission time. It does not send an SMS. Review any resolution-triggered **Send CSAT** workflows and exclude phone sessions if you only want keypad surveys; those message actions still use SMS for phone sessions.

Continuation requires an explicit **End call** from the teammate. If the caller hangs up first, the survey is cancelled. A browser disconnect allows a 30-second reconnection period; it does not immediately start the survey. If the teammate does not reconnect and no continuation arrives, the call ends. External-number transfers do not support continuation because the remote call is outside OpenCX.

If the survey cannot start safely, **End call** still ends the call and starts teammate wrap-up. If another End request is already processing, a conflicting request can report an error; retry after that request finishes.

Leave continuation off for calls that should end normally. Activate and test a new workflow version only after the post-call capability is available. Test teammate-end, caller-end, invalid input, missing input, recording behavior and saved scores before assigning live numbers.

## Companion and API

Companion can author the same `ivr-incoming-call` workflows and use the Classical IVR node definitions. It can list/upload recordings and assign an active flow to a number. Review the flow before activation and number assignment.

API access uses `workflows:read` for listing recordings, `workflows:write` for uploading, and both `phone:write` and `workflows:write` for number assignment. Use existing workflow endpoints to create versions, validate and activate them. A SIP destination returns callers with `phone-calls:write`.

* [List recordings](/api-reference/call-flows/list-assets)
* [Upload a WAV recording](/api-reference/call-flows/upload-asset)
* [Assign a number](/api-reference/call-flows/set-binding)
* [Hand back a transferred call](/api-reference/phone/hand_back_call)

## Session history and call recordings

Open the call's session in **Inbox** to review the IVR. By default, recording includes the IVR and continues if the caller reaches a teammate. Recording availability depends on recording being enabled and processing completing successfully.

To collect recording consent without recording the menu:

1. Enable **Keep IVR unrecorded** on the **IVR Incoming Call** trigger.
2. Collect consent with a keypad menu and branch explicitly on the caller’s choice. Use a recording that explains that declining recording still connects the call.
3. Continue both choices to **Transfer Call**. Set **Record human call** to `true` only for an explicit acceptance. Set it to `false` for declined, missing or invalid consent.

With this setting enabled, recording starts only after a teammate accepts an approved transfer. Declining recording does not prevent routing or disconnect the caller. Without **Record human call** enabled, the accepted transfer stays unrecorded. Later teammate transfers in that same call keep the original recording decision. The call keeps the settings of the workflow version it started with.

Leaving **Keep IVR unrecorded** off preserves recording from the beginning of the IVR; a consent menu or transfer setting alone cannot undo audio already captured. This setting controls audio recording, not separately configured live transcripts.

Each IVR run appears as one **IVR selection** event in session history, collapsed by default. Expand it to review the timestamped prompts, key presses, and outcomes together. Actions are emphasized and long details are truncated; hover over or focus a step to read its full details:

* Prompt playback starts show the exact text or the uploaded recording's name. A start does not mean the caller heard the entire prompt.
* Key presses show the key, the associated menu prompt, and the attempt number. The event identifies keys that interrupted the prompt or were ignored while keypad input was disabled, including loading and transitions. A transition key is associated with the preceding command; it is not input to the next step.
* Each attempt records its result, including invalid input, no input, or a timeout between digits. Retry prompts appear inside the same expandable event.

When IVR recording is enabled, play the session's call recording to hear the audio around a selection. With **Keep IVR unrecorded** enabled, use the IVR selection events to review that portion of the call. Keep session events visible when reviewing session history. IVR selections stay grouped even when **Group similar events** is turned off. These entries are internal and are not sent to the caller. History is captured for new calls; earlier calls cannot be reconstructed from final workflow results alone.

## Troubleshooting

If Classical IVR is missing, check both telephony and Classical IVR enablement and your workflow permissions. If a recording will not play, check its preview and the call's workflow run. If a transfer fails, check the destination's team, available membership, business hours and call capacity. For a SIP destination, run **Test connection** on the destination, and check that the endpoint accepts the caller ID and headers it is sent. A hand-back that returns `409` arrived after the transfer ended; check the transfer's outcome in the workflow run. Use the IVR selection event and workflow step results to distinguish invalid input, lookup results and transfer failures.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.