Overview
Send text as your LLM produces it and get audio frames back as they render, over one WebSocket connection. Use this when you do not have the full text up front. If you do, use Synthesize Speech — same voices, same controls.Use a
BTTS_V3 or newer voice. expressiveness and stability are calibrated for
it. BTTS_V2 voices synthesize, but the controls are not tuned for them.Authentication
Credentials are checked in this order:?token=<JWT>query parameter (recommended for browsers). Mint via Mint Stream Input Token.Authorization: Bearer <api_key>header (server-side).Sec-WebSocket-Protocol: bland.api_key.<key>subprotocol.?api_key=<key>query (deprecated, logged).
Protocol
Control frames are JSON text. Audio frames are binary, so tell them apart by WebSocket frame type. There is nocontainer here — you always get bare frames in the encoding you asked for.
Client → Server messages
initis required as the first message.voiceis a UUID (names are rejected).audio.encodingdefaults topcm_s16le.mulawis 8 kHz only, for telephony.audio.sample_ratedefaults to48000, the rate BTTS V3 renders natively. Allowed:8000,16000,24000,44100,48000.controls.expressivenessandcontrols.stabilityare optional0.0–1.0.auto_flush(defaulttrue) triggers synthesis on sentence boundaries or when the buffer reachesauto_flush_char_threshold.
speakappends text. Settingflush: truerenders the buffer immediately.flushrenders whatever is buffered.closerenders any remaining text, sendsdone, then closes.
Server → Client messages
Limits and guardrails
Error codes
Example
Node (ws)
Docs for agents: llms.txt