Skip to content
Voicesaystable

Play prompt or audio

Plays a prompt to the caller — either text-to-speech (with voice + language) or any public mp3/wav URL. The flow advances when playback finishes. Set "Hea…

What it does

Plays a single prompt to one or more legs of the call. The prompt can be text (synthesized via Telnyx text-to-speech with a chosen voice and language) or an audio file (any public MP3 or WAV URL). The flow waits for the prompt to finish before moving on, so this is the standard way to say something to the caller and then continue.

By default the prompt is heard only by the caller. You can change that with the Heard by field — agent only whispers to the bridged agent without the caller hearing, and both plays it on every leg of an active bridge in parallel (useful for in-call announcements, timers, or beeps).

When to use it

  • Greet the caller at the start of a flow ("Thanks for calling Acme.")
  • Read back collected information ("You entered four-five-six-seven.")
  • Whisper context to an answering agent before the caller hears anything (Heard by: agent only, inside an On agent answered chain)
  • Announce something on a live call to both parties — a recording notice, a timer, a wrap-up warning
  • Play a static audio asset like an outage notice or hold message

If you need to collect digits after speaking, use Collect digits instead — it combines the prompt with a digit-collection window in one step. If you want background music on hold, use Play audio with Forever looping.

Configuration

Plays a prompt to the caller — either text-to-speech (with voice + language) or any public mp3/wav URL. The flow advances when playback finishes. Set "Heard by" to "Agent only" for a whisper, or "Both" to play in parallel on the caller leg and every bridged extension. To loop a specific audio file use "Play audio"; for hold music with start offset, play-time, resume, or press-a-key-to-skip use "Play music".

FieldLabelTypeRequiredDefaultNotes
promptPromptpromptRequired{"kind":"text","text":""}Choose Text (TTS, with voice + language) or Audio file (any public mp3/wav URL). Both support {{vars.x}} templating.
targetHeard byselectOptionalcallerOptions: caller, agent, both. Agent-only whisper requires an active bridged agent leg (from a dial / requestAgent). "Both" plays in parallel on the caller leg and every active bridged leg; the call advances when the caller leg finishes. Falls back to the caller leg only if no bridge is active.
loopsLoops (audio only)numberOptional1How many times to repeat an Audio file prompt. Ignored for Text (TTS) prompts. Use this to loop hold music for the duration of a ringback window — e.g. a 30-second clip with Loops 4 plays for 2 minutes. The flow advances when the last loop ends.

Outgoing events: call.speak.ended, call.hangup

Examples

Basic greeting

A single TTS prompt to the caller, then continue to the next step.

{
  "id": "greeting",
  "type": "say",
  "config": {
    "prompt": {
      "kind": "text",
      "text": "Thanks for calling. Please hold while we connect you.",
      "voice": "female",
      "language": "en-US"
    }
  },
  "on": { "call.speak.ended": "ring", "call.hangup": "end" }
}

Whisper to the answering agent

Inside an On agent answered chain, set target: "agent" so only the agent hears the prompt. The caller's audio is unaffected.

{
  "id": "agent-whisper",
  "type": "say",
  "config": {
    "prompt": { "kind": "text", "text": "Caller is a VIP. Be nice.", "voice": "male", "language": "en-US" },
    "target": "agent"
  },
  "on": { "call.speak.ended": "end" }
}

60-second timer announced to both sides

A minimal in-call timer that says the elapsed minute count to both the caller and the bridged agent every 60 seconds. The loop runs until either party hangs up.

[onCallAnswered] → [setVar counter=0] → [requestAgent]
                                              ↓ call.bridged
                                          [wait 60s] ←──────┐
                                              ↓             │
                                       [setVar counter, op:inc]
                                              ↓             │
                                  [say "{{vars.counter}}", target:both]
                                              ↓             │
                                           (loop edge ──────┘)

The say node fans out to every active leg in parallel. The flow advances when the caller leg's call.speak.ended fires; the bridge-leg copy of the event is silently dropped.

Gotchas

  • target: agent requires an active bridge. If no agent leg is in scope (no preceding dial / requestAgent, or the node runs outside an On agent answered chain), say falls back to the caller leg with a warning in the worker log. Pre-bridge agent-targeted prompts will be heard by the caller — not silently dropped.
  • target: both plays in parallel, not in sequence. Both legs hear the prompt at roughly the same time. Telnyx briefly mutes cross-bridge audio for the duration of each leg's playback, so the conversation pauses for the prompt's length on both sides.
  • Audio URLs must be publicly reachable. Telnyx fetches the file server-side; private URLs, signed S3 links that have expired, or anything behind auth will fail silently and the flow will stall on call.playback.ended.
  • Long TTS strings cost latency. Telnyx synthesizes the entire payload before playback starts. For prompts over a few sentences, prefer pre- rendered audio files for snappier perceived response.
  • Templating happens server-side. {{vars.x}}, {{event.from}}, and {{config.x}} resolve in the worker before the speak command is sent — so the values are stable for the duration of the playback even if the underlying var changes mid-prompt.