{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-docs/voice-2.0/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"product":"Voice v2 (preview)","type":"markdown"},"seo":{"title":"Text-to-Speech & Available Voices","siteUrl":"https://developers.sinch.com","llmstxt":{"title":"Sinch Developer Documentation","description":"LLMs.txt containing a map of all the documentation files for Sinch.","sections":[{"title":"Numbers API","description":"The Numbers API enables you to search for, view, and activate numbers. It's considered a precursor to other APIs in the Sinch product family. The numbers API can be used in tandem with any of our APIs that perform messaging or calling.","includeFiles":["docs/numbers/**/*.md","docs/numbers/**/*.yaml"],"excludeFiles":["docs/numbers/index.md"]},{"title":"Conversation API","description":"Send and receive messages globally on many popular channels with ease and confidence when using Sinch's Conversation API. Conversation API is the preferred API for sending mobile messages on SMS and other social channels with Sinch. It is a simple API with unified error messages, consistent request payloads, and common webhook payloads that are channel-agnostic.","includeFiles":["docs/conversation/**/*.md","docs/conversation/**/*.yaml"],"excludeFiles":["docs/conversation/index.md"]},{"title":"Voice API","description":"The Voice API works as a big telephony switch. The Voice API handles incoming phone calls (also known as incoming call “legs”), sets up outgoing phone calls (or outgoing call “legs”), and bridges the two. The incoming call leg may come in over a data connection (from a smartphone or web application using the Sinch SDKs) or through a local phone number (from the PSTN network). Similarly, the outgoing call leg can be over data (to another smartphone or web application using the Sinch SDKs) or the PSTN network.","includeFiles":["docs/voice/**/*.md","docs/voice/**/*.yaml"],"excludeFiles":["docs/voice/index.md"]},{"title":"Voice API v2","description":"The Voice API works as a big telephony switch. The Voice API handles incoming phone calls (also known as incoming call “legs”), sets up outgoing phone calls (or outgoing call “legs”), and bridges the two. The incoming call leg may come in over a data connection (from a smartphone or web application using the Sinch SDKs) or through a local phone number (from the PSTN network). Similarly, the outgoing call leg can be over data (to another smartphone or web application using the Sinch SDKs) or the PSTN network.","includeFiles":["docs/voice-2.0/**/*.md","docs/voice-2.0/**/*.yaml"],"excludeFiles":["docs/voice-2.0/index.md"]},{"title":"Verification API","description":"The Verification API is a platform for phone number verification. It consists of the API and different software development kits (the Sinch SDKs) that you integrate with your smartphone or web application and cloud based back-end services. Together they enable SMS, Flashcall, Phone Call and Data verification in your application.","includeFiles":["docs/verification/**/*.md","docs/verification/**/*.yaml"],"excludeFiles":["docs/verification/index.md"]},{"title":"Provisioning API","description":"Provisioning API allows you to programmatically set up your senders, accounts and templates on your favorite messaging platforms on the Conversation API. For now, you can create your first WhatsApp channel through Meta's Embedded sign up, you can configure your first SMS App and configure your webhooks. As development continues, we will be adding the most commonly used channels.","includeFiles":["docs/provisioning-api/**/*.md","docs/provisioning-api/**/*.json"],"excludeFiles":["docs/provisioning-api/index.md"]},{"title":"Elastic SIP Trunking API","description":"With Elastic SIP Trunking you can create and manage your SIP trunks and phone numbers programmatically.","includeFiles":["docs/est/**/*.md","docs/est/**/*.yaml"],"excludeFiles":["docs/est/index.md"]},{"title":"Fax API","description":"Send and receive HIPAA compliant faxes on our modern fax platform using our developer-friendly API.","includeFiles":["docs/fax/**/*.md","docs/fax/**/*.yaml"],"excludeFiles":["docs/fax/index.md"]},{"title":"In-app Voice and Video SDK","description":"The In-app Voice and Video SDK enables you to add voice and video calling capabilities directly into your mobile or web application using the Sinch SDKs.","includeFiles":["docs/in-app-calling/**/*.md"],"excludeFiles":["docs/in-app-calling/index.md"]},{"title":"Number Lookup API","description":"The Number Lookup API is designed to provide in-depth information about phone numbers, helping enterprises enhance their communication strategies and prevent fraud. By identifying the type of phone line (for example, mobile, landline, VoIP) and the associated carrier, the API allows businesses to optimize routing, reduce unnecessary costs, and improve customer engagement.","includeFiles":["docs/number-lookup-api-v2/**/*.md","docs/number-lookup-api-v2/**/*.yaml"],"excludeFiles":["docs/number-lookup-api-v2/index.md"]},{"title":"Functions","description":"Serverless compute for voice and messaging. Deploy your code and Sinch routes live calls and messages to it — no infrastructure to run.","includeFiles":["docs/functions/functions/**/*.md","docs/functions/concepts/**/*.md","docs/functions/reference/**/*.md"],"excludeFiles":["docs/functions/functions/index.md"]},{"title":"CLI","description":"One command line for every Sinch API and the full Functions lifecycle — scaffold, run locally, deploy, and manage.","includeFiles":["docs/functions/cli/**/*.md"],"excludeFiles":["docs/functions/cli/index.md"]}]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"text-to-speech--available-voices","__idx":0},"children":["Text-to-Speech & Available Voices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Sinch Voice API v2 can synthesize speech on the fly inside any call. You don't need to host audio files or run a separate TTS service -- drop a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]}," item inside a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," command and Sinch generates the audio using one of its neural voices."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Three things to know about TTS in v2:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," is non-blocking."]}," The call continues executing the next SVAML command while the message plays; use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["events.onFinish"]}," if you need to act after playback completes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PLAY"]}," mix freely."]}," A single ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," array can interleave TTS (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]},") items with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PLAY"]}," items that point at pre-recorded MP3/WAV URLs."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["TEXT vs SSML."]}," The default ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["format"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TEXT"]},". Set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["format: \"SSML\""]}," to use prosody, breaks, emphasis, character spelling, and the rest of the SSML feature set."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"setup","__idx":2},"children":["Setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You'll need credentials and numbers from the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://dashboard.sinch.com"},"children":["Sinch dashboard"]},". Authentication is ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HTTP Basic"]}," (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["KEY_ID:KEY_SECRET"]},")."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Export these variables before running any example:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"export PROJECT_ID='your-project-id'\nexport KEY_ID='your-access-key-id'\nexport KEY_SECRET='your-access-key-secret'   # required for Basic auth -- must be present\nexport SINCH_NUMBER='+1...'                   # your Sinch virtual number, E.164\nexport DESTINATION_NUMBER='+1...'             # number you want to call, E.164\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Note: every example in this tutorial authenticates with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["KEY_ID:KEY_SECRET"]},". If your environment only contains a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SERVICE_ID"]}," and no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["KEY_SECRET"]},", the requests will fail -- add the access key secret before running."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"first-success----one-say-call-you-can-run-now","__idx":3},"children":["First success -- one SAY call you can run now"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This single request dials ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DESTINATION_NUMBER"]}," and, when answered, speaks one line of TTS in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Emma"]}," voice, then hangs up."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"bash","__idx":4},"children":["Bash"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"curl -s -X POST \\\n  -u \"${KEY_ID}:${KEY_SECRET}\" \\\n  \"https://voice.api.sinch.com/v2/projects/${PROJECT_ID}/calls\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -d '{\n    \"commands\": [\n      {\n        \"command\": \"dial\",\n        \"callName\": \"tts-hello\",\n        \"from\": { \"type\": \"PHONE\", \"phone\": { \"number\": \"'\"${SINCH_NUMBER}\"'\" } },\n        \"to\":   { \"type\": \"PHONE\", \"phone\": { \"number\": \"'\"${DESTINATION_NUMBER}\"'\" } },\n        \"dialTimeoutDurationSeconds\": 30,\n        \"maxCallDurationSeconds\": 120,\n        \"events\": {\n          \"onAnswer\": [\n            {\n              \"command\": \"messages\",\n              \"messagesName\": \"hello\",\n              \"messages\": [\n                {\n                  \"type\": \"SAY\",\n                  \"say\": {\n                    \"text\": \"Hello. This is text to speech from the Sinch Voice API.\",\n                    \"voiceName\": \"Emma\"\n                  }\n                }\n              ],\n              \"events\": { \"onFinish\": [ { \"command\": \"hangup\" } ] }\n            }\n          ],\n          \"onHangup\": [ { \"command\": \"hangup\" } ]\n        }\n      }\n    ]\n  }'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"python","__idx":5},"children":["Python"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import os, uuid, requests\n\nproject_id = os.environ[\"PROJECT_ID\"]\nkey_id     = os.environ[\"KEY_ID\"]\nkey_secret = os.environ[\"KEY_SECRET\"]\n\nbody = {\n    \"commands\": [\n        {\n            \"command\": \"dial\",\n            \"callName\": \"tts-hello\",\n            \"from\": {\"type\": \"PHONE\", \"phone\": {\"number\": os.environ[\"SINCH_NUMBER\"]}},\n            \"to\":   {\"type\": \"PHONE\", \"phone\": {\"number\": os.environ[\"DESTINATION_NUMBER\"]}},\n            \"dialTimeoutDurationSeconds\": 30,\n            \"maxCallDurationSeconds\": 120,\n            \"events\": {\n                \"onAnswer\": [\n                    {\n                        \"command\": \"messages\",\n                        \"messagesName\": \"hello\",\n                        \"messages\": [\n                            {\n                                \"type\": \"SAY\",\n                                \"say\": {\n                                    \"text\": \"Hello. This is text to speech from the Sinch Voice API.\",\n                                    \"voiceName\": \"Emma\",\n                                },\n                            }\n                        ],\n                        \"events\": {\"onFinish\": [{\"command\": \"hangup\"}]},\n                    }\n                ],\n                \"onHangup\": [{\"command\": \"hangup\"}],\n            },\n        }\n    ]\n}\n\nresp = requests.post(\n    f\"https://voice.api.sinch.com/v2/projects/{project_id}/calls\",\n    json=body,\n    auth=(key_id, key_secret),\n    headers={\"Idempotency-Key\": str(uuid.uuid4())},\n)\n\nprint(resp.status_code, resp.json())\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"nodejs","__idx":6},"children":["Node.js"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const https = require(\"https\");\n\nconst projectId = process.env.PROJECT_ID;\nconst keyId     = process.env.KEY_ID;\nconst keySecret = process.env.KEY_SECRET;\n\nconst body = JSON.stringify({\n  commands: [\n    {\n      command: \"dial\",\n      callName: \"tts-hello\",\n      from: { type: \"PHONE\", phone: { number: process.env.SINCH_NUMBER } },\n      to:   { type: \"PHONE\", phone: { number: process.env.DESTINATION_NUMBER } },\n      dialTimeoutDurationSeconds: 30,\n      maxCallDurationSeconds: 120,\n      events: {\n        onAnswer: [\n          {\n            command: \"messages\",\n            messagesName: \"hello\",\n            messages: [\n              {\n                type: \"SAY\",\n                say: {\n                  text: \"Hello. This is text to speech from the Sinch Voice API.\",\n                  voiceName: \"Emma\",\n                },\n              },\n            ],\n            events: { onFinish: [{ command: \"hangup\" }] },\n          },\n        ],\n        onHangup: [{ command: \"hangup\" }],\n      },\n    },\n  ],\n});\n\nconst auth = Buffer.from(`${keyId}:${keySecret}`).toString(\"base64\");\n\nconst req = https.request(\n  `https://voice.api.sinch.com/v2/projects/${projectId}/calls`,\n  {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Authorization: `Basic ${auth}`,\n      \"Idempotency-Key\": crypto.randomUUID(),\n    },\n  },\n  (res) => {\n    let data = \"\";\n    res.on(\"data\", (chunk) => (data += chunk));\n    res.on(\"end\", () => console.log(res.statusCode, JSON.parse(data)));\n  }\n);\n\nreq.write(body);\nreq.end();\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["What success looks like:"]}," the API returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["201"]}," with a JSON body containing a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["callId"]}," (and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["callResourceUrl"]},"). Your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DESTINATION_NUMBER"]}," rings; on answer you hear \"Hello. This is text to speech from the Sinch Voice API.\" spoken by the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Emma"]}," voice, then the call hangs up."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"real-life-examples","__idx":7},"children":["Real-life examples"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Verification codes"]},": read a code character-by-character -- ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Your verification code is <say-as interpret-as='characters'>4837</say-as>. Do not share this code."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Multi-language alerts"]},": send the same notification with locale-appropriate voices based on the customer's locale. (Pick the matching ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["voiceName"]}," from the live voice list -- see below.)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Brand voice"]},": choose a voice that matches your brand -- calm and slow for healthcare, upbeat for retail."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Dynamic pacing"]},": use SSML ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<break time=\"500ms\"/>"]}," to insert deliberate pauses between key facts."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"where-tts-appears-in-svaml","__idx":8},"children":["Where TTS appears in SVAML"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]}," is one of the two message item types in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," array (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PLAY"]}," is the other). Schema (from the spec, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messageSay"]},"):"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"messageSay:\n  required: [type, say]\n  additionalProperties: false\n  properties:\n    type: { const: SAY }\n    say:\n      required: [text, voiceName]\n      additionalProperties: false\n      properties:\n        text:      { type: string }\n        format:    { enum: [TEXT, SSML], default: TEXT }\n        voiceName: { type: string, example: Emma }\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The enclosing ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," command requires ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["command"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]},"; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messagesName"]}," is optional but you need it if you later want to target the sequence with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stopMessages"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A minimal ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," block:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"command\": \"messages\",\n  \"messagesName\": \"verification\",\n  \"messages\": [\n    {\n      \"type\": \"SAY\",\n      \"say\": {\n        \"text\": \"Your verification code is 4 8 3 7.\",\n        \"voiceName\": \"Emma\"\n      }\n    }\n  ],\n  \"events\": { \"onFinish\": [ { \"command\": \"hangup\" } ] }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"picking-a-voice","__idx":9},"children":["Picking a voice"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["voiceName"]}," is the only required style knob. Sinch offers neural voices across many languages and locales."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For the complete, current list (including non-English voices and their characteristics), see the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://developers.sinch.com/docs/voice/api-reference/text-to-speech-voices"},"children":["Text-to-Speech Voices page in the Voice API docs"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"ssml----for-everything-beyond-plain-text","__idx":10},"children":["SSML -- for everything beyond plain text"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["format: \"SSML\""]}," and wrap your text in a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<speak>"]}," document. Commonly supported elements include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<break>"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<prosody>"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<emphasis>"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<say-as>"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<phoneme>"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<sub>"]},". (Element support can vary by voice -- verify against the voice list / SSML reference when in doubt.)"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"verification-code-with-character-by-character-spelling","__idx":11},"children":["Verification code with character-by-character spelling"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"type\": \"SAY\",\n  \"say\": {\n    \"format\": \"SSML\",\n    \"voiceName\": \"Emma\",\n    \"text\": \"<speak>Your verification code is <say-as interpret-as='characters'>4837</say-as>. <break time='500ms'/> Do not share this code with anyone.</speak>\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"slow-calm-delivery-for-a-healthcare-reminder","__idx":12},"children":["Slow, calm delivery for a healthcare reminder"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"type\": \"SAY\",\n  \"say\": {\n    \"format\": \"SSML\",\n    \"voiceName\": \"Emma\",\n    \"text\": \"<speak><prosody rate='slow' pitch='-1st'>Hello. This is a reminder that your appointment with Dr. Patel is on <break time='200ms'/> Tuesday, the third of March, at <emphasis level='moderate'>two p.m.</emphasis></prosody></speak>\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"quieter-audible-signature-at-the-start","__idx":13},"children":["Quieter audible signature at the start"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"type\": \"SAY\",\n  \"say\": {\n    \"format\": \"SSML\",\n    \"voiceName\": \"Brian\",\n    \"text\": \"<speak><prosody volume='-6dB'>Welcome to Acme.</prosody> How can I help you today?</speak>\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"mixing-say-and-play","__idx":14},"children":["Mixing ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PLAY"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages"]}," is an ordered array. Combine recorded audio (a music sting, a brand jingle) with dynamic TTS. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PLAY"]}," requires only a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["url"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"command\": \"messages\",\n  \"messagesName\": \"intro\",\n  \"messages\": [\n    { \"type\": \"PLAY\", \"play\": { \"url\": \"https://example.com/audio/sting.mp3\" } },\n    { \"type\": \"SAY\",  \"say\":  { \"text\": \"Welcome back. Please hold.\", \"voiceName\": \"Emma\" } },\n    { \"type\": \"PLAY\", \"play\": { \"url\": \"https://example.com/audio/hold-music.mp3\" } }\n  ]\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"stopping-tts-mid-playback","__idx":15},"children":["Stopping TTS mid-playback"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stopMessages"]}," to interrupt a sequence -- useful when a downstream event lets you skip a hold prompt. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messagesName"]}," targets a specific sequence (if omitted, all active sequences on the call are stopped):"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{ \"command\": \"stopMessages\", \"messagesName\": \"hold\", \"flags\": \"ALL_FROM_NOW_ON\" }\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["flags"]}," choices (default is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ALL_FROM_NOW_ON"]},"):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ALL_FROM_NOW_ON"]}," -- stop the currently playing message and cancel all queued items."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ONLY_PLAYING"]}," -- stop only the currently playing item; queued items continue to play."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"events-you-can-hook","__idx":16},"children":["Events you can hook"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messages.events"]}," (schema ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["messageEvents"]},") supports:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Event"},"children":["Event"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"When it fires"},"children":["When it fires"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFinish"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["All items in the sequence have finished playing."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Common pattern -- hang up after the message:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"command\": \"messages\",\n  \"messagesName\": \"vm\",\n  \"messages\": [\n    { \"type\": \"SAY\", \"say\": { \"text\": \"We could not reach an agent. Goodbye.\", \"voiceName\": \"Emma\" } }\n  ],\n  \"events\": { \"onFinish\": [ { \"command\": \"hangup\" } ] }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"full-sampler----plain-text-play-and-ssml-in-one-call","__idx":17},"children":["Full sampler -- plain TEXT, PLAY, and SSML in one call"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example dials ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DESTINATION_NUMBER"]}," and, on answer, plays three items in sequence: a plain-text ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]},", a short ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PLAY"]}," clip, and an SSML ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SAY"]},". Then it hangs up. Voices default to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Emma"]}," (plain) and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Brian"]}," (SSML); override them with environment variables if you want to compare options."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"bash-1","__idx":18},"children":["Bash"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"bash","header":{"controls":{"copy":{}}},"source":"# Override voices:  export VOICE_PLAIN=Emma  VOICE_SSML=Brian\n\nVOICE1=\"${VOICE_PLAIN:-Emma}\"\nVOICE2=\"${VOICE_SSML:-Brian}\"\n\ncurl -s -X POST \\\n  -u \"${KEY_ID}:${KEY_SECRET}\" \\\n  \"https://voice.api.sinch.com/v2/projects/${PROJECT_ID}/calls\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $(uuidgen || date +%s%N)\" \\\n  -d '{\n    \"commands\": [\n      {\n        \"command\": \"dial\",\n        \"callName\": \"tts-sampler\",\n        \"from\": { \"type\": \"PHONE\", \"phone\": { \"number\": \"'\"${SINCH_NUMBER}\"'\" } },\n        \"to\":   { \"type\": \"PHONE\", \"phone\": { \"number\": \"'\"${DESTINATION_NUMBER}\"'\" } },\n        \"dialTimeoutDurationSeconds\": 30,\n        \"maxCallDurationSeconds\": 120,\n        \"events\": {\n          \"onAnswer\": [\n            {\n              \"command\": \"messages\",\n              \"messagesName\": \"sampler\",\n              \"messages\": [\n                {\n                  \"type\": \"SAY\",\n                  \"say\": {\n                    \"text\": \"Hello, this is a plain text message with the '\"${VOICE1}\"' voice.\",\n                    \"voiceName\": \"'\"${VOICE1}\"'\"\n                  }\n                },\n                {\n                  \"type\": \"PLAY\",\n                  \"play\": { \"url\": \"https://samplelib.com/mp3/sample-3s.mp3\" }\n                },\n                {\n                  \"type\": \"SAY\",\n                  \"say\": {\n                    \"format\": \"SSML\",\n                    \"voiceName\": \"'\"${VOICE2}\"'\",\n                    \"text\": \"<speak><prosody rate='\"'\"'slow'\"'\"'>Now hear an S S M L example. Your code is <say-as interpret-as='\"'\"'characters'\"'\"'>4837</say-as>.</prosody><break time='\"'\"'400ms'\"'\"'/>Goodbye.</speak>\"\n                  }\n                }\n              ],\n              \"events\": { \"onFinish\": [ { \"command\": \"hangup\" } ] }\n            }\n          ],\n          \"onHangup\": [ { \"command\": \"hangup\" } ]\n        }\n      }\n    ]\n  }'\n","lang":"bash"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"python-1","__idx":19},"children":["Python"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import os, uuid, requests\n\nproject_id = os.environ[\"PROJECT_ID\"]\nkey_id     = os.environ[\"KEY_ID\"]\nkey_secret = os.environ[\"KEY_SECRET\"]\n\n# Override voices:  export VOICE_PLAIN=Emma  VOICE_SSML=Brian\nvoice_plain = os.environ.get(\"VOICE_PLAIN\", \"Emma\")\nvoice_ssml  = os.environ.get(\"VOICE_SSML\", \"Brian\")\n\nbody = {\n    \"commands\": [\n        {\n            \"command\": \"dial\",\n            \"callName\": \"tts-sampler\",\n            \"from\": {\"type\": \"PHONE\", \"phone\": {\"number\": os.environ[\"SINCH_NUMBER\"]}},\n            \"to\":   {\"type\": \"PHONE\", \"phone\": {\"number\": os.environ[\"DESTINATION_NUMBER\"]}},\n            \"dialTimeoutDurationSeconds\": 30,\n            \"maxCallDurationSeconds\": 120,\n            \"events\": {\n                \"onAnswer\": [\n                    {\n                        \"command\": \"messages\",\n                        \"messagesName\": \"sampler\",\n                        \"messages\": [\n                            {\n                                \"type\": \"SAY\",\n                                \"say\": {\n                                    \"text\": f\"Hello, this is a plain text message with the {voice_plain} voice.\",\n                                    \"voiceName\": voice_plain,\n                                },\n                            },\n                            {\n                                \"type\": \"PLAY\",\n                                \"play\": {\"url\": \"https://samplelib.com/mp3/sample-3s.mp3\"},\n                            },\n                            {\n                                \"type\": \"SAY\",\n                                \"say\": {\n                                    \"format\": \"SSML\",\n                                    \"voiceName\": voice_ssml,\n                                    \"text\": (\n                                        \"<speak>\"\n                                        \"<prosody rate='slow'>\"\n                                        \"Now hear an S S M L example. \"\n                                        \"Your code is <say-as interpret-as='characters'>4837</say-as>.\"\n                                        \"</prosody>\"\n                                        \"<break time='400ms'/>\"\n                                        \"Goodbye.\"\n                                        \"</speak>\"\n                                    ),\n                                },\n                            },\n                        ],\n                        \"events\": {\"onFinish\": [{\"command\": \"hangup\"}]},\n                    }\n                ],\n                \"onHangup\": [{\"command\": \"hangup\"}],\n            },\n        }\n    ]\n}\n\nresp = requests.post(\n    f\"https://voice.api.sinch.com/v2/projects/{project_id}/calls\",\n    json=body,\n    auth=(key_id, key_secret),\n    headers={\"Idempotency-Key\": str(uuid.uuid4())},\n)\n\nprint(resp.status_code, resp.json())\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"nodejs-1","__idx":20},"children":["Node.js"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const https = require(\"https\");\n\nconst projectId = process.env.PROJECT_ID;\nconst keyId     = process.env.KEY_ID;\nconst keySecret = process.env.KEY_SECRET;\n\n// Override voices:  export VOICE_PLAIN=Emma  VOICE_SSML=Brian\nconst voicePlain = process.env.VOICE_PLAIN || \"Emma\";\nconst voiceSsml  = process.env.VOICE_SSML  || \"Brian\";\n\nconst body = JSON.stringify({\n  commands: [\n    {\n      command: \"dial\",\n      callName: \"tts-sampler\",\n      from: { type: \"PHONE\", phone: { number: process.env.SINCH_NUMBER } },\n      to:   { type: \"PHONE\", phone: { number: process.env.DESTINATION_NUMBER } },\n      dialTimeoutDurationSeconds: 30,\n      maxCallDurationSeconds: 120,\n      events: {\n        onAnswer: [\n          {\n            command: \"messages\",\n            messagesName: \"sampler\",\n            messages: [\n              {\n                type: \"SAY\",\n                say: {\n                  text: `Hello, this is a plain text message with the ${voicePlain} voice.`,\n                  voiceName: voicePlain,\n                },\n              },\n              {\n                type: \"PLAY\",\n                play: { url: \"https://samplelib.com/mp3/sample-3s.mp3\" },\n              },\n              {\n                type: \"SAY\",\n                say: {\n                  format: \"SSML\",\n                  voiceName: voiceSsml,\n                  text:\n                    \"<speak>\" +\n                    \"<prosody rate='slow'>\" +\n                    \"Now hear an S S M L example. \" +\n                    \"Your code is <say-as interpret-as='characters'>4837</say-as>.\" +\n                    \"</prosody>\" +\n                    \"<break time='400ms'/>\" +\n                    \"Goodbye.\" +\n                    \"</speak>\",\n                },\n              },\n            ],\n            events: { onFinish: [{ command: \"hangup\" }] },\n          },\n        ],\n        onHangup: [{ command: \"hangup\" }],\n      },\n    },\n  ],\n});\n\nconst auth = Buffer.from(`${keyId}:${keySecret}`).toString(\"base64\");\n\nconst req = https.request(\n  `https://voice.api.sinch.com/v2/projects/${projectId}/calls`,\n  {\n    method: \"POST\",\n    headers: {\n      \"Content-Type\": \"application/json\",\n      Authorization: `Basic ${auth}`,\n      \"Idempotency-Key\": crypto.randomUUID(),\n    },\n  },\n  (res) => {\n    let data = \"\";\n    res.on(\"data\", (chunk) => (data += chunk));\n    res.on(\"end\", () => console.log(res.statusCode, JSON.parse(data)));\n  }\n);\n\nreq.write(body);\nreq.end();\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["What success looks like:"]}," the API returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["201"]},". Your phone rings; on answer you hear the plain-text message in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VOICE_PLAIN"]}," voice, then a short audio clip, then the SSML message in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VOICE_SSML"]}," voice, followed by an automatic hangup."]}]},"headings":[{"value":"Text-to-Speech & Available Voices","id":"text-to-speech--available-voices","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Setup","id":"setup","depth":2},{"value":"First success -- one SAY call you can run now","id":"first-success----one-say-call-you-can-run-now","depth":2},{"value":"Bash","id":"bash","depth":3},{"value":"Python","id":"python","depth":3},{"value":"Node.js","id":"nodejs","depth":3},{"value":"Real-life examples","id":"real-life-examples","depth":2},{"value":"Where TTS appears in SVAML","id":"where-tts-appears-in-svaml","depth":2},{"value":"Picking a voice","id":"picking-a-voice","depth":2},{"value":"SSML -- for everything beyond plain text","id":"ssml----for-everything-beyond-plain-text","depth":2},{"value":"Verification code with character-by-character spelling","id":"verification-code-with-character-by-character-spelling","depth":3},{"value":"Slow, calm delivery for a healthcare reminder","id":"slow-calm-delivery-for-a-healthcare-reminder","depth":3},{"value":"Quieter audible signature at the start","id":"quieter-audible-signature-at-the-start","depth":3},{"value":"Mixing SAY and PLAY","id":"mixing-say-and-play","depth":2},{"value":"Stopping TTS mid-playback","id":"stopping-tts-mid-playback","depth":2},{"value":"Events you can hook","id":"events-you-can-hook","depth":2},{"value":"Full sampler -- plain TEXT, PLAY, and SSML in one call","id":"full-sampler----plain-text-play-and-ssml-in-one-call","depth":2},{"value":"Bash","id":"bash-1","depth":3},{"value":"Python","id":"python-1","depth":3},{"value":"Node.js","id":"nodejs-1","depth":3}],"frontmatter":{"seo":{"title":"Text-to-Speech & Available Voices"}},"lastModified":"2026-09-01T08:14:37.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/voice-2.0/tutorials/tts-voices","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}