Skip to main content
The WebSocket API streams speech in real time over a single persistent connection. Unlike the HTTP endpoints, you can send text incrementally, as it is produced by an LLM or typed by a user, and receive audio as it is synthesized. This is the lowest-latency option and the right choice for voice agents and long-form speech.

Endpoint

For the full message schemas and an interactive connection playground, see the TTS WebSocket reference.

Authenticating

The WebSocket accepts your API key either as a header or as a query parameter (useful for browser clients that cannot set headers on a WebSocket handshake):
Prefer the chariotai-api-key header where your client allows it. If authentication fails, the server accepts the socket, sends an error frame, and closes with code 1008.

How a session works

The server buffers the text you send and does not synthesize it until you ask it to:
1

Send text

Send one or more input.text messages. Text accumulates in the server’s buffer. Nothing is generated yet.
2

Flush to generate

Send input.flush. The server synthesizes everything buffered so far and streams the audio back. The session stays open, so you can send more text and flush again.
3

Finish

Send input.done when no more text is coming. The server flushes any remainder and ends the session.
Flushing is what triggers generation. Send input.text as often as you like as fragments arrive, then input.flush at the point you want audio for. Flushing at natural boundaries, such as the end of a sentence or clause, gives the most natural speech.

Connection parameters

Pass these as query parameters on the connection URL:
string
required
UUID of the voice to synthesize with.
string
default:"pcm"
Audio encoding of the binary frames. One of pcm (raw signed 16-bit LE PCM) or wav (streaming WAV, a RIFF header followed by PCM).
number
default:"60"
Seconds the server waits for a client message before closing the session as idle. Must be greater than 0 and at most 300.
boolean
default:"false"
When true, each generated segment is archived to your TTS history and the audio is stored for later retrieval.

Message protocol

All control messages are JSON text frames. Audio is delivered as binary frames.

Client to server

message
Append text to the server’s buffer. This does not generate audio on its own.
message
Synthesize everything currently buffered and stream the audio back. The session stays open.
message
Signal that no more text is coming. The server flushes the remainder and finishes the session.

Server to client

message
A new audio segment is about to stream. Carries the segment index, the text being spoken, the format, and sample_rate (when known).
audio
One or more binary frames of audio for the current segment, in the negotiated response_format.
message
The current segment has finished streaming. Includes total_bytes and credits_utilized (the credits charged for this segment).
message
All segments are complete. The server will close the connection normally (1000).
message
An error occurred. Carries a message and, for terminal errors, a code matching the close code.

Audio format

Close codes

The connection closes with one of these codes. The close reason carries a short human-readable message.

Billing

Billing on the WebSocket is per segment, charged when each segment finishes (audio.done), at 1 credit per character of the synthesized text. The cost is reported in the credits_utilized field of each audio.done. If the workspace runs out of credits mid-session, the segment currently in flight is delivered (a one-segment grace), then the server sends an error frame with code 4402 and closes. You are not charged for the segment that could not be covered.

Limits

Example

Python