---
name: vobiz-voice-xml
description: Build declarative call flows with VobizXML - Vobiz's TwiML-equivalent for play, speak, gather, dial, record, stream, conference, redirect, and hangup verbs.
license: MIT
compatibility: VobizXML 1.0, served from any HTTPS endpoint as application/xml.
metadata:
author: vobiz
version: "1.0"
---
# Vobiz Voice XML skill
Use this when the user wants to **script a call flow declaratively** - IVR menus, voicemail, queues, conferences, agent transfers. Anything beyond just "make a call and stream audio" usually involves VobizXML.
## How Vobiz fetches XML
1. Call is created via `POST /Call/` with `answer_url` (or an inbound call hits a number attached to an Application with an `answer_url`).
2. When the call is answered, Vobiz requests `answer_url` with the call context and `Event=StartApp`.
3. Your server returns `...verbs...` as `application/xml`.
4. Verbs execute top-to-bottom.
## Core verbs
| Verb | Purpose |
|---|---|
| `` | TTS - speak text to the caller |
| `` | Play an audio file (HTTPS URL) |
| `` | Collect DTMF or speech input |
| `` | Bridge to another party - nest `` (PSTN) or `` (SIP URI / registered WebRTC or SIP user) |
| `` | Record the call (optionally stream-while-recording) |
| `` | Open a WebSocket for bidirectional audio (AI voice agents) |
| `` | Add caller to a conference room |
| `` | Fetch new XML from a different URL |
| `` | Pause for N seconds |
| `` | End the call |
| `` | Run `Speak`/`Play`/`Wait` before answering (early media, no billsec) |
| `` | Send tones onto the live call |
## Request payload - what your `answer_url` receives
Standard `application/x-www-form-urlencoded` POST (GET sends them as query params). Common parameters: `CallUUID`, `From`, `To`, `Direction`, `CallStatus`, `Event`, `CallerName`, `ForwardedFrom`, plus `ALegUUID`/`ALegRequestUUID` for outbound calls and any custom `X-VH-` SIP headers. `HangupCause`, `Duration`, `BillDuration` are present only after the call ends. See `xml/request` for the full list.
## Standard callback params by verb
Action/callback URLs receive the standard call params **plus** verb-specific ones:
- ``: `InputType` (dtmf|speech), `Digits`, `Speech`, `SpeechConfidenceScore`, `BilledAmount`. Empty `Digits`/`Speech` on timeout.
- `` (one final request, `Event=DialAction`): `DialStatus` (completed|busy|failed|cancel|timeout|no-answer), `DialRingStatus`, `DialHangupCause`, `DialALegUUID`, `DialBLegUUID` (empty if unanswered).
- `` (real-time): `Event=DialAnswer|DialConnected|DialDigitsMatch|DialHangup` with `DialAction=answer|connected|digits|hangup`, plus `DialBLegUUID`, `DialBLegFrom`, `DialBLegTo`, `DialBLegPosition`; hangup events add `DialBLegDuration`, `DialBLegBillDuration`, `DialBLegHangupCause`.
- `` (initial event, `Event=Record`): `RecordingID` only - do not treat it as "file ready".
- `` (`Event=RecordStop`): `RecordingID`, `RecordFile`/`RecordUrl`, `RecordingDuration`, `RecordingDurationMs`, `RecordingStartMs`, `RecordingEndMs`, `RecordingEndReason` (RecordingTimeout|maxLength|FinishedOnKey|HungUp).
- ``: `ConferenceAction` (enter|exit) with `Event=ConferenceEnter|ConferenceExit`, `ConferenceUUID`, `ConferenceName`, `ConferenceMemberID`, `ConferenceFirstMember` (on enter), `ConferenceLastMember` (on exit). Derive room start/end from first enter and last exit.
- ``: `Event=StartStream|PlayedStream|ClearedAudio|DegradedStream|DroppedStream|StopStream` with `StreamID`, `CallUUID`, `Error`.
- ``: standard params + `Event=Redirect`.
## Per-verb quick recipes
- **IVR menu**: `` wrapping a ``; put fallback ``+`` after it.
- **Variable-length input**: ``.
- **Speech intent**: ``; threshold `SpeechConfidenceScore`. `inputType="dtmf speech"` accepts either.
- **Blind transfer**: `...` then fallback after.
- **Confirmation prompt to the answering agent**: `` - `confirmSound` returns `Speak`/`Play`/`Wait` XML; check `xml/dial/confirm-to-answer-call` before relying on `confirmKey` as an acceptance gate.
- **Voicemail**: `` prompt + ``; read the file URL from the `RecordStop` callback.
- **Record whole call**: self-closing `` as the first element, before ``/``/``.
- **Hold music**: `...` or ``.
- **AMD voicemail drop**: `` then ``.
- **Reject without billing**: `` (or `rejected`) as the first element.
- **Branch/loop**: `https://.../next` (last runnable element).
- **Send tones to a remote IVR**: `1WW2#`.
- **AI voice agent**: `wss://...`.
- **Conference**: `RoomName`; set `startConferenceOnEnter="false"` + `waitSound` for participants who wait for a moderator.
## Pitfalls
- Response must be `application/xml` (or `text/xml`), not `text/html`/`text/plain`, served over HTTPS, and under 100 KB. Return within 1-2 s or callers hear dead air.
- **`` uses `executionTimeout` (5-60 s, default 15), NOT `timeout`.** The timer starts after nested `Play`/`Speak` finish. `timeout` on `` is the ring timeout (effective default 120 s when omitted - set it explicitly); `timeout` on `` is the silence timeout. `` (default 14400) caps the connected bridge only - don't confuse the two.
- Verbs execute strictly top-to-bottom. `` ends the current document. `Gather` and `Dial` default to `redirect="true"`, so the XML returned by `action` replaces the flow; elements after them run only when no handoff happens (no input, no bridge). `Record` defaults to `redirect="false"`: its `action` handler must return an empty ``. Set `redirect="false"` on `Dial`/`Gather` when you only want the result delivered and the current flow to continue.
- All URLs in ``, ``, ``, `` (action/callbackUrl/confirmSound/dialMusic) must be fully qualified HTTPS. `dialMusic` and `confirmSound` must return XML (`Play`/`Speak`/`Wait`), not an audio file.
- **`` must be a Vobiz number your account owns or is authorized for** (E.164). If omitted on an inbound call, Vobiz derives it from the A-leg (the caller's number) and B-leg creation fails with no Dial callbacks - execution falls through to the next element.
- DTMF: `finishOnKey` (default `#`) is excluded from `Digits`; set `finishOnKey=""`/`none` to rely on `numDigits`/timeout. On no input, Vobiz still posts with empty `Digits`/`Speech` - check for empty.
- `Dial`: always branch on every `DialStatus` (busy/no-answer/timeout/failed/cancel/completed). `DialBLegUUID` is empty when nobody answers. Sibling `` elements dial simultaneously; losing legs report `DialBLegHangupCause=LOSE_RACE`.
- `Dial sipHeaders`/`User sipHeaders`: each key must **end** with `X-VH` (`RefX-VH=abc`); it arrives as `X-VH-Ref`. A key without the suffix drops the whole header set silently.
- `Record`: `timeout` is *silence* timeout (default 60 s, not total length); `maxLength` is the hard cap (default 60 s). `finishOnKey` defaults to every key (`1234567890*#`) - narrow it to `#` for voicemails. Set `maxLength` high enough for voicemails.
- `Conference`: room names are case-sensitive and the room is created on first join. `stayAlone` defaults to `false`, so a lone first arrival is disconnected - set `stayAlone="true"` on legs that may arrive first. `endConferenceOnExit="true"` removes every remaining member. Record conferences with a per-leg `` placed before ``.
- `Stream`: without `keepCallAlive="true"` (requires `bidirectional="true"`) the call reaches end-of-XML and hangs up right after the stream starts. `contentType` sets the **inbound** format only (`audio/x-l16;rate=8000|16000` or `audio/x-mulaw;rate=8000`); 24 kHz L16 is for outbound `playAudio` only. Vobiz sends no inbound `stop` event - treat the WebSocket `close` plus the `hangup_url` `Event=Hangup` webhook as end-of-call.
- Escape `&`, `<`, `>` in ``/`` text or the document fails to parse.
- `` defaults to `voice="WOMAN"`, `language="en-US"`; not every language has both MAN and WOMAN voices - Vobiz falls back to the available one.
- `` early media depends on the carrier and number type, and WebRTC (Browser SDK) calls have none - the flow must work whether or not it is honored. Only `Speak`/`Play`/`Wait` nest inside it.
- `loop="0"` means infinite (`Play`, `Speak`) - it stops only on hangup or a parallel event, never on its own.
- `` needs a following element (`Speak`/`Play`/`Wait`) or the call ends immediately.
## When to search docs
- "How do I build an IVR?" → `xml/gather`, `examples/vobiz-ivr-xml-python`
- "Voicemail" → `xml/record/record-a-voicemail`, `examples/vobiz-voicemail-xml-python`
- "Conference call" → `xml/conference`, `xml/conference/attributes`, `solutions/conference-calling`
- "AI voice agent" → `xml/stream`, `xml/stream/audio-formats`, `integrations/pipecat`
- "DTMF input" → `xml/dtmf`, `xml/gather/detecting-speech-inputs`
- "Transfer a live call" → `xml/dial/transferred-calls`, `call/transfer-call`