--- 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`