VoiceML / Text-to-speech

Speak text on a call with built-in voices or your own premium provider.

VoiceML turns text into spoken audio on a call using the Twilio-compatible <Say> verb. The same text-to-speech settings on your account also power agent speech in <Connect><ConversationRelay>. This guide covers how to use <Say>, the built-in voices included with every account, and how to connect your own premium voice provider for natural, studio-quality speech.

Free trial Compatibility matrix

Using <Say>

Quick start

<Say> reads text aloud. The simplest form uses the default voice:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Say>Thank you for calling. Please hold.</Say>
</Response>

To pick a different voice or language, use the voice and language attributes:

<Say voice="man">Press one for sales.</Say>
<Say language="es-ES">Gracias por llamar.</Say>
<Say voice="man" language="fr-FR">Appuyez sur le un.</Say>

Attributes

Attribute Purpose Default
voiceWhich voice speaks the text.Standard female
languageLanguage/locale as a BCP-47 code (e.g. en-US, es-ES).en-US
loopHow many times to repeat the text.1

Repeat a message three times:

<Say loop="3">This call is being recorded.</Say>

Voice names may only contain letters, digits, periods, underscores, and hyphens (A–Z a–z 0–9 . _ -). Other characters are rejected with a clear error.

Built-in voices

Every account includes built-in voices at no additional setup. Leave the TTS provider unset on your Account page (or choose default — built-in voices) to use them.

Voice name compatibility

You don't need to know internal voice ids. Use the same attributes Twilio documents:

voice value Result
womanStandard female voice
aliceStandard female voice
manStandard male voice
(omitted)Standard female voice (default)

Gender comes from voice: man / male select a male voice; woman, female, alice, empty, and most other values select a female voice.

Language comes from language: Spanish, French, and German tags select that language; English and any unsupported language select English.

<Say> attributes Voice used
(none)English, female
voice="man"English, male
voice="woman"English, female
language="es-ES"Spanish, female
voice="man" language="es-MX"Spanish, male
voice="Polly.Matthew" language="de-DE"German, male

Only the primary part of the language code matters — es, es-ES, and es-MX all select Spanish.

Languages supported

The built-in voices speak four languages, each with a male and a female option:

Language language value Female Male
English (US)en-US / enYesYes
Spanishes-ES / esYesYes
Frenchfr-FR / frYesYes
Germande-DE / deYesYes

Voice catalog (optional)

You can also select a voice directly by id or friendly name (either works, case-insensitive):

Voice id Name Language Gender
en-US-femaleLily (default)Englishfemale
en-US-maleMichaelEnglishmale
es-ES-femaleLuciaSpanishfemale
es-ES-maleCarlosSpanishmale
fr-FR-femaleChloé (or Chloe)Frenchfemale
fr-FR-malePierreFrenchmale
de-DE-femaleKerstinGermanfemale
de-DE-maleThorstenGermanmale
<Say voice="es-ES-male">Bienvenido.</Say>
<Say voice="de-DE-female">Willkommen.</Say>

Defaults and graceful fallback

  • Default voice: standard English female (Lily) when voice and language are omitted.
  • Unsupported language: the text is still spoken (in English) rather than failing, so a call never ends in silence.
  • Never silence: a valid <Say> always produces audio. If the requested voice can't be rendered, VoiceML automatically falls back so the caller always hears the prompt.

Migration-compatible voice names

VoiceML accepts Twilio-style voice names — for example Polly.Joanna, Polly.Matthew, or Google-prefixed names — and maps them to the closest matching built-in voice by gender. Your existing voice markup keeps working without edits. To reproduce a specific premium Twilio voice exactly, configure Bring Your Own Voice with the matching provider below.

Bring Your Own Voice

For studio-quality, natural-sounding speech and a much larger catalog of voices and languages, connect your own account with a supported text-to-speech provider. You bring the provider credentials; VoiceML uses them to synthesize your <Say> prompts and ConversationRelay agent speech.

Supported providers

Provider Service What you configure
Amazon PollyPollyAccess key, secret, region, voice, engine
Microsoft AzureCognitive Services SpeechAPI key, region, voice name
ElevenLabsText-to-SpeechAPI key, voice ID, model ID
DeepgramAuraAPI key, voice model
CartesiaSonicAPI key, voice ID, model, API version

How to enable a provider

Configure a premium provider from your Account page in the VoiceML portal (section Text-to-speech (TTS)):

  1. Open the Account page and find the Text-to-speech (TTS) section.
  2. Choose the provider you want from the dropdown, or leave it on default — built-in voices to use the standard voices above.
  3. Expand that provider's section and enter its credentials plus a default voice.
  4. Save. New calls immediately use the new voice — no restart or redeploy needed.

Credentials in the portal are write-only — leave a field blank to keep the value already saved.

Once a provider is configured, every <Say> on your account uses it automatically. You don't need to change your voice markup unless you want to override the voice on a specific prompt.

Voice resolution order

The voice that actually speaks is resolved in this order:

  1. Per-call — the voice attribute on the <Say> element, if set.
  2. Account default — the default voice you configured in the portal for your provider.
  3. Provider default — the provider's built-in default voice when you leave the portal voice field empty.

Cartesia has no built-in default voice, so always configure a default voice in the portal or pass voice on every <Say>.

Provider setup guides

Each guide walks through portal setup with concrete examples and popular voice names. After saving, test on a new call.

Amazon Polly

What you need: an AWS account with Polly enabled, an IAM access key and secret with permission to call Polly, and the AWS region where you created the key (for example us-east-1).

Portal fields (Account → Text-to-speech → AWS Polly):

FieldExample
Access key IDAKIA…
Secret access key(your secret — write-only)
Regionus-east-1
VoiceJoanna
Engineneural

Popular voices:

NameVoice valueNotes
JoannaJoannaDefault US English female; platform default if voice left blank
MatthewMatthewUS English male
RuthRuthUS English female (neural)
StephenStephenUS English male (neural)

We recommend the neural engine for the most natural Polly speech. Use standard for legacy voices or long-form for extended narration.

Example voice markup (with Polly configured as your provider):

<Response>
    <Say voice="Matthew">Your order has shipped.</Say>
    <Say voice="Joanna" language="es-ES">Su pedido ha sido enviado.</Say>
</Response>

Microsoft Azure

What you need: an Azure Speech resource and its subscription key, plus the region where the resource was created (for example eastus). The region must match your resource — a wrong region returns an authentication error.

Portal fields (Account → Text-to-speech → Azure Cognitive Services Speech):

FieldExample
API key(your subscription key — write-only)
Regioneastus
Voiceen-US-JennyNeural

Popular voices:

NameVoice valueLanguage
Jennyen-US-JennyNeuralUS English female; platform default if voice left blank
Guyen-US-GuyNeuralUS English male
Ariaen-US-AriaNeuralUS English female

The voice name encodes the language — pick a voice from the Azure voice gallery that matches the language of your text.

Example voice markup:

<Response>
    <Say voice="en-US-GuyNeural">Press one to confirm your appointment.</Say>
</Response>

ElevenLabs

What you need: an ElevenLabs API key and the voice ID of the voice you want as your default. You can find voice IDs in the ElevenLabs voice library or when creating a custom voice.

Portal fields (Account → Text-to-speech → ElevenLabs):

FieldExample
API key(your key — write-only)
Voice ID21m00Tcm4TlvDq8ikWAM
Model IDeleven_turbo_v2_5

Popular voices:

NameVoice IDNotes
Rachel21m00Tcm4TlvDq8ikWAMPlatform default if voice left blank
AdampNInz6obpgDQGcFmaJgBDeep male
BellaEXAVITQu4vr4xnSDxMaLSoft female

Popular models: eleven_turbo_v2_5 (fast, English-focused) or eleven_multilingual_v2 (broader language support). Leave Model ID empty to use ElevenLabs' default for your account.

Example voice markup:

<Response>
    <Say voice="pNInz6obpgDQGcFmaJgB">Hello, this is a reminder about your appointment tomorrow.</Say>
</Response>

Pass the ElevenLabs voice ID in the voice attribute, not the display name.

Deepgram Aura

What you need: a Deepgram API key with text-to-speech access. Aura voice models encode both the voice and its language in a single id (for example aura-2-thalia-en).

Portal fields (Account → Text-to-speech → Deepgram Aura):

FieldExample
API key(your key — write-only)
Voiceaura-2-thalia-en

Popular voices:

NameVoice valueLanguage
Thaliaaura-2-thalia-enUS English female; platform default if voice left blank
Asteriaaura-2-asteria-enUS English female
Helenaaura-2-helena-enUS English female

Example voice markup:

<Response>
    <Say voice="aura-2-asteria-en">Thanks for calling. One moment while we connect you.</Say>
</Response>

Cartesia Sonic

What you need: a Cartesia API key and a voice ID from the Cartesia voice catalog or playground. Cartesia voices are referenced by UUID — copy the ID from your Cartesia dashboard.

Portal fields (Account → Text-to-speech → Cartesia Sonic):

FieldExample
API key(your key — write-only)
Voice IDf786b574-daa5-4673-aa0c-cbe3e8534c02
Modelsonic-3
API version(leave blank unless Cartesia instructs otherwise)

Popular voices:

NameVoice IDStyle
Katief786b574-daa5-4673-aa0c-cbe3e8534c02Friendly, clear — great for support lines
Jamesona5136bf9-224c-4d76-b823-52bd5efcffccUS English male
Skylardb6b0ed5-d5d3-463d-ae85-518a07d3c2b4US English female

Cartesia requires a voice ID — configure one as your account default in the portal. If you leave Model empty, VoiceML uses the current Sonic model (sonic-3).

Example voice markup:

<Response>
    <Say voice="f786b574-daa5-4673-aa0c-cbe3e8534c02">Your verification code is 4 8 2 9.</Say>
</Response>

Choosing a voice per call

You can override the account default on any individual <Say> by setting the voice attribute to a value from your provider's catalog:

<!-- Polly: voice name -->
<Say voice="Matthew">Your order has shipped.</Say>

<!-- Azure: full neural voice name -->
<Say voice="en-US-GuyNeural">Press one to confirm.</Say>

<!-- ElevenLabs or Cartesia: voice ID -->
<Say voice="21m00Tcm4TlvDq8ikWAM">Hello from Rachel.</Say>

<!-- Deepgram: Aura model id -->
<Say voice="aura-2-helena-en">Thanks for holding.</Say>

The language attribute still applies where your provider uses it. With Azure, Polly, and Deepgram Aura, the voice identifier itself usually defines the language — pick a voice that natively speaks your target language.

Migrating from Twilio

VoiceML uses the same <Say> syntax as Twilio:

  • Existing markup with voice="woman", voice="man", or voice="alice" works unchanged.
  • Twilio-style names like Polly.Joanna map to the closest built-in voice so calls keep working during migration.
  • When you need the exact Polly, Azure, ElevenLabs, or other premium voice Twilio offered, configure the matching provider under Bring Your Own Voice and set the provider's voice identifier in voice.

Troubleshooting

Symptom What to check
Speech sounds like the basic built-in voice, not my providerConfirm the correct provider is selected on the Account page, credentials are saved, and the API key or region matches your provider account.
Wrong language spokenPick a voice from your provider that supports that language. Built-in voices only cover English, Spanish, French, and German.
Cartesia uses the wrong voice or no speechCartesia requires a voice ID — set a default in the portal or pass voice on every <Say>.
Azure returns an auth errorThe Region in the portal must match the region where your Azure Speech resource was created.
Polly voice sounds flatSwitch Engine to neural for supported voices.
A configuration change didn't seem to applyChanges take effect on the next call. Confirm the Account page save succeeded and place a fresh test call.
Empty <Say> does nothingThere must be text between the opening and closing tags.