Twilio Voice
Answer phone calls with a workflow: speak, listen for speech or keypad digits, play audio, record and transfer.
Twilio Voice runs a Session on every call to your Twilio number, on the TwilioVoice Channel. It is part of the Twilio family and is configured on its own: it has its own Environment configuration with its own Twilio credentials, so fill them here even if you already set them on the Twilio Module. To send SMS, WhatsApp or one-time codes during a call, add the Twilio Module to the Process as well. Not sure which Module you need? See Which Twilio module?.
How it works
| Channel | Started when | What happens |
|---|---|---|
TwilioVoice | A voice call reaches your Twilio number | A new Session starts on the TwilioVoice Channel, at the Process's call start, and replies are rendered as TwiML voice instructions |
Twilio expects the voice instructions back in the same HTTP round-trip, so a call hits POST /api/TwilioModule/Voice/start/{token} (where {token} is the Environment's token) and the engine answers each request directly with TwiML. The standard Tasks map to voice actions: an OutputTask speaks its text, an InputTask listens for speech or keypad digits, an EndTask hangs up (a farewell is an OutputTask right before it). The same OutputTask that sends "Hi there!" as a text on a messaging Channel is spoken on a call.
When the caller answers an InputTask (or a recording completes), Twilio calls POST /api/TwilioModule/Voice/next/{environmentId}, a URL the engine embeds in its own voice responses, and the Session continues.
Quick start (5 minutes)
- Create a Twilio account and note the Account SID (
AC...) and Auth Token on the Console dashboard. - Buy a Twilio number with voice capability: Console → Phone Numbers → Buy a Number.
- Find the number's SID: Console → Phone Numbers → Manage → Active Numbers → your number → Properties → "Phone Number SID" (
PN...). - Configure the Module. Open Environments, select your Environment, and open the Twilio Voice configuration:
- Top section: Account SID + Auth Token.
- Phone (Voice) Configuration: paste the SID into Phone Number SID, optionally set Default Voice and Default Language, and toggle Auto-Deploy Voice Webhook = on.
- Deploy a Process that depends on Twilio Voice, with
Call start → OutputTask("Welcome. Press 1 for sales, 2 for support.") → InputTask(Variable="digit") → OutputTask("You chose {digit}.") → EndTask("Goodbye!"). The Deployment log shows a row like:"Voice webhook updated on phone number PN… → https://…/api/TwilioModule/Voice/start/…"
- Call your Twilio number.
Webhook URLs are built from the platform's public engine address and registered on Twilio automatically by the Auto-Deploy toggle: you never have to construct them by hand.
Configuration
Configuration is per Environment: each Environment supplies its own Twilio credentials and phone number. Open Environments, select the Environment, and open the Twilio Voice configuration. The form has the credentials at the top followed by the Phone section.
Core Credentials
| Field | Type | Required | Description |
|---|---|---|---|
| Account SID | string (secret) | Yes | Twilio Account SID (AC...) |
| Auth Token | string (secret) | Yes | Twilio Auth Token, also used to verify the signature of Twilio's requests |
| Webhook Signing Secret | string (secret) | No | Optional override key for webhook signature checks |
| Validate Signatures | boolean | No (default: on) | Verify the signature on every inbound Twilio webhook |
The four fields are the same in every Module of the family; they are described on the Twilio Module page: Account SID, Auth Token, Webhook Signing Secret, Validate Signatures.
Phone (Voice) Configuration
| Field | Type | Required | Description |
|---|---|---|---|
| Phone Number SID | string | For voice auto-deploy | Twilio Incoming Phone Number SID (PN...) |
| Default Voice | string | No | Default text-to-speech voice |
| Default Language | string | No | Default language tag for spoken prompts |
| Speech Model | string | No | Speech-recognition model hint |
| Auto-Deploy Voice Webhook | boolean | No (default: off) | Register the voice webhook on every Deployment |
Phone Number SID
Twilio Incoming Phone Number SID, starts with PN. Example: PNxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Where to find it: Twilio Console → Phone Numbers → Manage → Active Numbers → click your number → Properties tab → "Phone Number SID".
Used by Auto-Deploy Voice Webhook to set this phone number's voice webhook.
Default Voice
Default text-to-speech voice for spoken prompts. Examples: alice, Polly.Joanna, Polly.Matthew, Google.en-US-Standard-A. Default: empty (Twilio's standard voice).
Reference: Twilio Voice TTS voices.
Default Language
Default IETF language tag (BCP-47) for spoken prompts and speech recognition. Examples: en-US, it-IT, es-ES. Default: empty (the Session's language, as set for example by a LanguageTask, otherwise Twilio's standard language).
Speech Model
Speech-recognition model hint used when a voice InputTask listens for spoken input. One of default, phone_call, phone_call_enhanced.
phone_call_enhanced is the most accurate but incurs an upgrade fee.
Auto-Deploy Voice Webhook
When on, every Deployment sets the phone number's voice webhook ("A call comes in") to this Environment's voice start URL (.../api/TwilioModule/Voice/start/{token}). Default: off.
Requires Phone Number SID to be set and start with PN.
Last-write-wins across Environments that share a phone number: the Environment deployed last receives the calls.
Tasks
The Module ships its call start, voice Tasks and the voice behavior of the standard Tasks, all bound to the TwilioVoice Channel: they only run in Sessions started by a call.
Several Tasks below have a Store variable output: a field where you type a variable name (no braces). The Task saves its result there and later Tasks can reference it as {name}.
TwilioCallStartTask (Channel: TwilioVoice)
Starts the Process when a call reaches your Twilio number, and puts the call in one variable, {call} by default. It binds the call like the voice behavior of every other step: the caller is also {execution.channelSender}, your number {execution.channelRecipient}.
| Property | Type | Required | Example | Description |
|---|---|---|---|---|
| Call variable | Store variable | Yes | {call} | Receives the call (fields below). Default: {call}. |
| Reference | Value |
|---|---|
{call.from} | The caller's number |
{call.to} | Your Twilio number they called |
{call.callId} | Twilio's CallSid |
{call.direction} | inbound (outbound for calls your account placed) |
{call.callerName} | The caller's name, when Caller ID Lookup is on for the number in Twilio Console (otherwise empty) |
{call.fromCountry} | The caller's country code (for example IT), when Twilio knows it |
{call.channel} | TwilioVoice (Chat in test mode) |
{call.isTest} | true when the start ran in the test chat |
Other voice providers' call starts write the same {call.from}, {call.to}, {call.callId} fields, so the steps after the start read the same variable whichever provider the call came through.
Test mode. In the portal's test chat the start writes {call} from the test data (the assistant's chat_start_session with testData, for example { "from": "+393331234567", "fromCountry": "IT" }; without one, from is a sample number) with {call.isTest} = true, and the rest of the flow runs on the chat: OutputTask texts appear as chat messages and InputTask waits for a typed answer. On any other Channel the start refuses to run (error 8025, StartWrongChannel).
Processes built before the call start, with the shared Start (Chat / API) event, keep working exactly as before (the call start answers Twilio the same way). Replace the start with the call start to get {call}.
TwilioVoicePlayTask (Channel: TwilioVoice)
Play a remote audio file to the caller on the active voice call.
Use it for: hold music, pre-recorded greetings, brand sounds.
Properties
| Property | Type | Required | Example | Description |
|---|---|---|---|---|
| MediaUrl | string | Yes | https://cdn.example.com/hold-music.mp3 | Publicly accessible audio URL. Supports {variable} placeholders. |
| Loop | number | No | 1 | How many times to play. 0 loops until the caller hangs up. Default: 1. |
TwilioVoiceRecordTask (Channel: TwilioVoice)
Record the caller's voice and store the recording's URL and ID in Session variables.
Use it for: voicemail, post-call surveys, claims intake. In the Process Editor it is placed as a Message Intermediate Catch Event: the Session waits until the recording completes, then continues.
Properties
| Property | Type | Required | Example | Description |
|---|---|---|---|---|
| MaxLengthSeconds | number | No | 60 | Maximum recording length in seconds. Twilio's maximum is 3600. Default: 30. |
| PlayBeep | boolean | No | true | Play a beep tone before recording. Default: true. |
| Trim | string | No | trim-silence | trim-silence or do-not-trim. Default: trim-silence. |
| Transcribe | boolean | No | false | Request Twilio transcription of the recording (extra cost). Default: false. |
| OutputUrlVariable | Store variable | No | recordingUrl | Variable name (no braces) that receives the recording's playback URL. Default: empty. |
| OutputSidVariable | Store variable | No | recordingSid | Variable name (no braces) that receives the recording's Twilio ID. Default: empty. |
TwilioVoiceDialTask (Channel: TwilioVoice)
Forward the active call to another phone number.
Use it for: "press 0 for an agent", overflow routing, ringing a desk-and-mobile pair.
Properties
| Property | Type | Required | Example | Description |
|---|---|---|---|---|
| Destination | string | Yes | +15550001111 | E.164 number to dial. Supports {variable} placeholders. |
| TimeoutSeconds | number | No | 30 | How long to ring before considering the call unanswered. Default: 30. |
| RecordCall | string | No | do-not-record | do-not-record, record-from-answer, or record-from-answer-dual. Default: do-not-record. |
| CallerId | string | No | +15551230000 | Optional caller ID presented to the dialed party. Must be a verified Twilio number. Default: empty (the caller's own number). |
Example
A voice IVR: OutputTask("Press 1 for sales, 2 for support") → InputTask(Variable="digit") (collects the keypress) → SwitchTask({digit}) → on 1, a TwilioVoiceDialTask with Destination = +15550001111 forwards the call to the sales line.
Channel override Tasks
On the TwilioVoice Channel, the standard Standard Module Tasks behave as voice actions. You don't pick anything special in the Process Editor; the right behavior is selected automatically from the Session's Channel:
- Start (Chat / API), the shared
StartTask(legacy): binds the Session to the call and records the caller ({execution.channelSender}) and your number ({execution.channelRecipient}), without{call}. Use the call start in new Processes. - InputTask speaks its prompt (if any) and listens for speech or keypad digits (5 seconds of silence ends the input). The speech transcript or the digits are written to the store variable. Store files in stays empty: a call carries no files.
- OutputTask speaks the text with the Default Voice and Default Language. Attachments are ignored on a call: only the text is spoken.
- EndTask hangs up. It says nothing: a farewell is an OutputTask right before the End Event.
Common recipes
Voicemail after hours
- Call start: the Session starts when someone calls your number; the caller is
{call.from}. - OutputTask: Message =
We're closed. Leave a message after the beep. - TwilioVoiceRecordTask: MaxLengthSeconds =
120, OutputUrlVariable =recordingUrl. - TwilioSendSmsTask (Twilio Module, add it to the Process too): To = your on-call number, Body =
New voicemail from {call.from}: {recordingUrl}. - EndTask: the call hangs up.
Troubleshooting
Calls don't start a Session
- Auto-Deploy Voice Webhook is on and the last Deployment log shows "Voice webhook updated on phone number PN…". If the log shows "Voice auto-deploy skipped: Phone Number SID must start with 'PN'", you pasted another SID (for example the Account SID).
- Another Environment that shares the number was deployed after yours: the last deploy wins.
- The webhook returns 403: see Webhook returns 403. Remember that Twilio Voice needs its own credentials in its own configuration.
The Deployment log shows nothing from Twilio Voice
Auto-Deploy Voice Webhook is off, so the deploy does not touch Twilio. Either turn it on, or set the number's "A call comes in" webhook by hand using the Webhook URLs table.
"Auto-configure skipped: Engine:PublicBaseUrl is not set"
The platform's public engine address is not configured, so no webhook URL can be built. Contact support.
Reference
Webhook URLs
These are the endpoints the Auto-Deploy toggle registers for you. You only need this table if you configure Twilio manually. {token} is the Environment's token, shown in the Deployment log.
| Inbound | Engine route | Where it's configured |
|---|---|---|
| Voice call started | POST /api/TwilioModule/Voice/start/{token} | The phone number's "A call comes in" webhook, set automatically by Auto-Deploy Voice Webhook. |
| Voice keypress / speech / recording callback | POST /api/TwilioModule/Voice/next/{environmentId} | Nothing to configure: the engine embeds this URL in its own voice responses. The Environment id in the URL selects the right Twilio Voice configuration; the call itself is identified by the CallSid Twilio sends in the signed request body. |
Channels
| Channel | Purpose |
|---|---|
TwilioVoice | Voice calls (spoken prompts, keypress and speech input) |
Best practices
- Keep Validate Signatures on: disable it only briefly for local debugging.
- Use one number per Environment: with a shared number, the last Environment deployed takes the calls.
- Keep prompts short: callers can't scroll back. Put the options first ("Press 1 for sales") and confirm what you heard ("You chose sales").
Error codes
See the full reference for resolutions:
| Code | Name | Description |
|---|---|---|
| 4008 | ModuleMissingConfiguration | Account SID or Auth Token is not set in the Twilio Voice configuration |
| 4009 | ModuleInputEmpty | An InputTask received neither speech nor digits |
| 4012 | ModuleInvalidData | An inbound webhook payload was malformed (missing call identifier) |
| 8025 | StartWrongChannel | The call start ran on another Channel: add that Channel's start |
| 4020 | WebhookSignatureInvalid | An inbound webhook failed the signature check |