Call control (verbs)
When a call needs instructions we POST to your webhook, and your server replies with a call-control document: a <Response> element containing the verbs below. We execute them in order, top to bottom.
<Response> <Say voice="woman">Karibu SautiPBX.</Say> <Hangup/></Response>Speak text to the caller using text-to-speech.
Control flow. Blocking. The next verb waits until this one finishes.
Text content. The words to speak, as plain text.
| Attribute | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
voice |
enum | No | woman |
woman, man |
The text-to-speech voice. An unknown value uses the default. |
language |
string | No | en-US |
- | BCP-47 language tag, e.g. en-US. Speech is English only today: the tag is accepted, and any other language is spoken in English. |
loop |
integer | No | 1 |
- | How many times to repeat the text. A value below 1 plays it once. |
<Say voice="woman" language="en-US">Karibu SautiPBX. Please hold.</Say><Play>
Section titled “<Play>”Play an audio file to the caller, from an uploaded asset or a URL.
Control flow. Blocking. The next verb waits until this one finishes.
Text content. A publicly reachable URL to an audio file (e.g. a WAV) to play. Leave it empty when you use the asset attribute.
| Attribute | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
asset |
string | No | - | - | The slug of an audio asset you uploaded in the portal, e.g. reminder-english. When set it wins over any URL in the element. A slug that is missing, switched off or has no playable audio skips the verb and emits PLAY.0404. |
loop |
integer | No | 1 |
- | How many times to repeat the file. A value below 1 plays it once. |
<Play asset="reminder-english" loop="2"/><Play>https://example.com/hold-music.wav</Play><Dial>
Section titled “<Dial>”Bridge the caller to a phone number. The destination goes in a child <Number>. A destination outside the countries enabled for outbound calls is not dialled: the call carries on with the next verb and DIAL.0403 is emitted.
Control flow. Blocking. The next verb waits until the far end hangs up.
| Attribute | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
timeout |
integer | No | 30 |
- | Seconds to wait for the destination to answer. |
callerId |
string | No | the call’s own number |
- | Caller ID to present to the callee. Must be a number you own and that is active. Otherwise it falls back to the call’s own number. |
record |
enum | No | false |
true, false |
Reserved. Whole-bridge recording is not active yet; to record a dialled conversation, wrap the <Dial> in <RecordSession>. |
action |
URL | No | - | - | When set, after the dial ends we POST the result (DialCallStatus, DialCallDuration) to this URL and continue with the verbs it returns. |
Allowed children. <Number>
<Dial timeout="30" callerId="+254709080010"> <Number>+254700000000</Number></Dial><Record>
Section titled “<Record>”Record the caller and post the audio to your webhook.
Control flow. Blocking. Stops at maxLength, the finish key, or hangup. Put prompts BEFORE it.
| Attribute | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
maxLength |
integer | No | 3600 |
- | Maximum recording length in seconds. This is also the hard ceiling. |
playBeep |
enum | No | true |
true, false |
Play a beep before recording starts. |
finishOnKey |
string | No | # |
- | Keypad key (0-9, * or #) the caller presses to stop early. An empty or invalid value uses #; the key-stop cannot be turned off. |
action |
URL | No | - | - | When set, after recording we POST the result (RecordingDuration, RecordingPath) to this URL and continue with the verbs it returns. |
<Record maxLength="60" playBeep="true" finishOnKey="#"/><RecordSession>
Section titled “<RecordSession>”Record the whole conversation, both directions, while the verbs inside it run.
Control flow. Non-blocking. The enclosed verbs run normally; recording stops at the closing tag. Put the verbs you want captured INSIDE it.
This verb takes no attributes.
Allowed children. <Say>, <Play>, <Dial>, <Record>, <Pause>, <Redirect>, <Hangup>
<RecordSession> <Say>This call is recorded for quality.</Say> <Dial><Number>+254700000000</Number></Dial></RecordSession><Redirect>
Section titled “<Redirect>”Hand control to another verb document at the given URL.
Control flow. Ends this document. Any verbs after it are ignored.
Text content. A URL. We fetch the next verb document from it and continue there.
This verb takes no attributes.
<Redirect>https://example.com/next.xml</Redirect><Pause>
Section titled “<Pause>”Wait silently before the next verb.
Control flow. Blocking. It waits for the given time, then continues.
| Attribute | Type | Required | Default | Values | Description |
|---|---|---|---|---|---|
length |
integer | No | 1 |
- | Seconds to pause. |
<Pause length="2"/><Hangup>
Section titled “<Hangup>”End the call immediately.
Control flow. Ends the call. Any verbs after it never run.
This verb takes no attributes.
<Hangup/>Child elements
Section titled “Child elements”These appear only inside another verb, never directly under the root.
<Number>
Section titled “<Number>”A destination phone number, used inside <Dial>.
Control flow. Only valid as a child of <Dial>. Only the first non-empty <Number> is dialled; the others are ignored.
Text content. One phone number, ideally in E.164 format, e.g. +254700000000.
This verb takes no attributes.
<Number>+254700000000</Number>