Voice actions
The verbs you return from your voice callback to drive a live call — speak, play audio, collect digits, record, bridge, or hang up.
AIAgentAIAgentAction hands the answered call to a Sautikit AI agent, expanding inline so a Say or Play prologue may precede it in the same response. It must be the final action: nothing runs after the legConferenceConferenceAction places the caller into a named conference room. The field set tracks the live PBX conference webhook contract and the canonical JSON schema at docs/voice-actions.schema.json.DialDialAction connects the caller to one or more numbers/SIP endpoints. Number/SIP URIs are subject to the same destination authorisation as POST /v1/calls. URL must be on the allow-list when diallingGetDigitsGetDigitsAction collects DTMF from the caller, optionally with a nested `<Say>` / `<Play>` prompt. Mirrors the PBX `<GetDigits>` verb.HangupHangupAction ends the call immediately. It carries no parameters; an empty struct is a valid action.PlayPlayAction streams an audio file to the caller. URL must resolve to an allow-listed CDN host (see URLAllowFunc).RecordRecordAction records the caller's audio and posts the recording URL to the Action callback when finished.RedirectRedirectAction transfers the call flow to another Sautikit URL. The URL should point to a Sautikit-owned endpoint that returns a new VoiceAction response; the PBX rejects unsupported URL targets.RejectRejectAction rejects the inbound call with an optional reason.SaySayAction speaks synthesised text to the caller.StreamStreamAction forks call audio to a WebSocket endpoint. The socket must advertise the audio.drachtio.org subprotocol or the PBX handshake fails.
Chaining actions
Return an array and the actions run in order. Here a greeting is followed by a menu that collects one digit, then hands the call back to your app to route on the caller’s choice.
import { sauti, say } from "@sautikit/node";
res.json(
sauti
.say("Welcome to Acme Insurance.", { voice: "alice" })
.getDigits({ numDigits: 1, timeout: 5, finishOnKey: "#" }, [
say("Press 1 to pay your premium, 2 to speak to an agent."),
])
.redirect("https://your-app.example.com/voice/menu", { method: "POST" }),
);{
"actions": [
{
"say": {
"text": "Welcome to Acme Insurance.",
"voice": "alice"
}
},
{
"getDigits": {
"numDigits": 1,
"timeout": 5,
"finishOnKey": "#",
"nested": [
{
"say": {
"text": "Press 1 to pay your premium, 2 to speak to an agent."
}
}
]
}
},
{
"redirect": {
"url": "https://your-app.example.com/voice/menu",
"method": "POST"
}
}
]
}<Response>
<Say voice="alice">Welcome to Acme Insurance.</Say>
<GetDigits numDigits="1" timeout="5" finishOnKey="#">
<Say>Press 1 to pay your premium, 2 to speak to an agent.</Say>
</GetDigits>
<Redirect method="POST">https://your-app.example.com/voice/menu</Redirect>
</Response>