Skip to main content
Manage up to 20 independent audio streams over a single WebSocket connection. Useful for multi-speaker conversations, pre-buffering, and interleaved audio. The conceptual guide is Multi-context streaming.

Connection

Prepare a voice before sending text

Once connected, you can send the selected voice and model before the LLM produces text:
Omit context_id for this configuration-only message. It starts optional reference preparation without creating an audio context or charging for synthesis. There is no preparation acknowledgement to wait for; send text normally when it becomes available. Each generation still checks current voice permissions, and preparation does not create a missing voice encoding ahead of an admitted generation. This also works on /ws/tts/stream. The top-level voice_id only warms preparation: it does not reach contexts. Each context must still receive voice_settings: {"voice_id": ...} on its first message, otherwise its first text fails with MISSING_VOICE_ID.

Client → Server Messages

Server → Client Messages

The optional usage object on context_closed is present for organization- backed requests:

Voice Settings

When creating a context, pass voice settings as a nested object:

Session-Level Config

These options can be set on any message and apply to the entire session: Reuse the same context_id across turns to keep one context alive (recommended for a single conversation), or open new ids for parallel speakers:

Updating Settings

Change the session’s generation parameters mid-connection with an update_settings message (no context_id — it is session-scoped). The server replies with settings_updated:
Only these generation parameters are updatable; every field is optional. Identity, project, dictionary, and audio-format fields (voice_id, model_id, sample_rate, output_format, project_id, dictionary_ids) are rejected inside update_settings with a VALIDATION_ERROR frame. Ordinary context messages use the session-level fields in the table above.
Applies to contexts started after the update. A context’s generation parameters are bound when its backend session opens, so an already-streaming context keeps its settings; the update affects contexts created after it. With the common one-context-per-turn pattern that means it takes effect on the next turn. (Per-context cfg_scale / max_new_tokens set in a context’s voice_settings still win for that context.)

Example

Limits

  • Maximum 20 concurrent contexts per connection
  • Contexts auto-close after 20 seconds of inactivity (send the empty-text keep-alive to reset)
  • Opening a context beyond the limit returns a per-context error (error_code: "TOO_MANY_CONTEXTS", code: 429) without closing the connection — close an existing context, or wait for an idle one to be released, then retry.

Errors

See Error Codes for the full TTS error lookup table. A refused connection is an HTTP status on the upgrade, not a close code (Refused WebSocket upgrades).
Last modified on September 28, 2026