Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

Realtime WebSocket

The WebSocket endpoint streams synthesis one sentence at a time. It is ideal when text is produced incrementally — for example, sentences coming out of an LLM — and you want each one spoken as soon as it is ready.
wss://api.vakyam.ai/v1/tts/websocket
Send one complete sentence or utterance per text message. Input streaming (partial or word-by-word text) is not supported in v1.

Connection lifecycle

  1. Connect with your API key in the Authorization header. The server authenticates on the handshake; a bad key closes the socket with code 4001.
  2. The server sends {"type":"connected"}.
  3. Send one config message to set model_id, voice, language, output_format, and speed for the session. The server replies with {"type":"configured", ...}.
  4. For each sentence, send a text message. The server streams binary audio chunks, then a end_of_utterance message.
  5. Wait for end_of_utterance before sending the next sentence.
  6. Send disconnect (or close) when done.
Client Server |-- connect (Authorization) ----------->| |<-- {"type":"connected"} --------------| |-- {"type":"config", ...} ------------>| |<-- {"type":"configured", ...} --------| |-- {"type":"text","text":"..."} ------>| |<-- [binary audio chunk] --------------| |<-- [binary audio chunk] --------------| |<-- {"type":"end_of_utterance", ...} --| |-- {"type":"disconnect"} ------------->| |<-- closed 1000 -----------------------|

Client message types

The server accepts five client message types:
TypePurpose
configSet or replace the session synthesis config.
textSynthesize one complete sentence with current config.
cancelInterrupt (barge-in) the current utterance.
pingReceive a JSON pong and reset the idle timer.
disconnectClose the connection normally.

Messages you send

Sets the session voice, language, model, output format, and speed. Must be the first message sent after connecting.
{ "type": "config", "model_id": "raaga-v1", "voice": "Archana", "language": "ta-IN", "output_format": "pcm", "speed": 1.0 }
Fields
  • type — always "config".
  • model_id — the TTS model. Use raaga-v1.
  • voice — the preset voice name or a custom voice ID beginning with vc_ (see Voices).
  • language — BCP 47 language code; must form a valid pair with a preset voice.
  • output_format — pcm (default), mp3, wav, or mulaw.
  • sample_rate — output sample rate in Hz: 8000, 16000, 24000 (default), or 48000.
  • speed — playback speed multiplier, 0.5–2.0 (default 1.0).

Messages you receive

Sent once after the connection is authenticated.
{ "type": "connected", "user_id": "f1e2d3c4-..." }
Fields
  • type — always "connected".
  • user_id — the authenticated account's ID.

Binary audio chunks

Audio chunks arrive as raw binary WebSocket frames (not base64). The default output_format for WebSocket is pcm to avoid encoding overhead. Reassemble chunks in arrival order for playback.

Interrupting playback (barge-in)

Send a cancel message to stop the current utterance before it finishes — for example, when the user starts talking over the audio or the upstream text changes:
{ "type": "cancel" }
The benefit of interrupting this way is that cancel clears the worker's internal text buffer: instead of finishing the queued utterance, the worker immediately drops the remaining text and stops generating audio for it.
What happens next:
  1. The server stops sending further audio for the current turn and forwards the cancel upstream, which clears the worker's internal text buffer so no more audio is generated for the discarded text.
  2. Keep reading from the socket until the cancellation frame arrives. Any audio frames still in flight may be delivered first, and stopping reads early can stall on WebSocket backpressure.
  3. The server sends a cancellation message instead of end_of_utterance:
    { "type": "cancellation", "characters_used": 12, "duration_seconds": 0.86 }
  4. The connection stays open — send the next text whenever you're ready.
You are billed only for the audio produced before the cancel (characters_used on the cancellation frame), not for the full input text. A cancel sent while nothing is being synthesized is acknowledged with characters_used: 0 and is not billed.

Idle timeout

The server closes idle connections after 60 seconds without an incoming message. Any message you send — including a ping — resets the idle timer, so send a periodic ping to keep a session open between sentences.
Both SDKs send a keepalive ping for you by default, so you rarely need to do this manually:
# The Python SDK sends keepalive pings while the session is open. # You can also ping explicitly between utterances: ws.ping()

Using the SDKs

Both SDKs handle the handshake, config, chunk reassembly, and end_of_utterance for you. Each call to send a sentence resolves with the full audio for that utterance.
with client.tts.websocket( model_id="raaga-v1", voice="Archana", language="ta-IN", output_format="pcm", ) as ws: result = ws.synthesize("நான் சரியாக இருக்கிறேன்.") result.save("sentence.pcm") print(result.characters_used, result.duration_seconds)
Send only one sentence at a time and wait for it to finish. The JavaScript SDK throws if you call sendText again before the current utterance resolves.

Per-message errors

Rate limit, concurrency limit, credit, and validation problems are returned as JSON error messages and the connection stays open:
{ "type": "error", "error": { "code": "rate_limit_exceeded", "message": "Too many requests. Retry after 12 seconds.", "retry_after_seconds": 12 } }
Possible codes include rate_limit_exceeded, concurrency_limit_exceeded, insufficient_credits, voice_language_not_found, text_too_long, missing_websocket_config, validation_error, and internal_error.

Close codes

CodeReason
1000Normal closure
1011Session lost (concurrency or worker capacity revoked mid-session) — reconnect
4001Authentication failed
4002Internal server error