Streaming voice shares the realtime voice gate: contact your AI Reserve representative to have
realtimeVoiceEnabled turned on for your organization — until then, session mints return 403.- Streaming text-to-speech (
inworld-tts-2,inworld-tts-2-flash): send sentences, or individual LLM tokens, as your model produces them and receive audio chunks back as they are synthesized, with several independent contexts on one socket. - Streaming speech-to-text (
inworld-stt-1): send microphone audio as it is captured and receive interim and final transcripts with turn boundaries.
Models
The per-character rate is the same rate the Inworld HTTP passthrough
books, so a character costs the same whichever transport carried it.
How it works
- Mint a session credential:
POST /v1/realtime/sessionswith the model (and, for TTS, the voice). The gateway authenticates you, checks the org gate, reserves worst-case funds from your wallet, and returns a short-livedephemeral_keyand awss_urlon the relay’s/v1/audio/ttsor/v1/audio/sttpath. - Connect your WebSocket to
wss_urlwithephemeral_keyand speak Inworld’s frames. The relay opens Inworld’s socket on your behalf with the platform credential; neither your AI Reserve key nor the Inworld key ever reaches your code.
Step 1: Mint a session
voice on a TTS session is an Inworld voice id: any stock voice, or one of your organization’s
cloned or professionally cloned voices. It is pinned for the whole session — every create and
updateConfig you send has its voiceId replaced with it — so a ticket cannot be used to speak with
a voice the mint never authorized. Another organization’s voice answers 404 at mint, or closes
the socket with code 1008 if the relay’s own check refuses it. Defaults to Ashley. An STT session
takes no voice (sending one is a 400).
The response is the realtime mint’s: wss_url points at /v1/audio/tts or /v1/audio/stt,
ephemeral_key is a one-use HMAC ticket valid for five minutes, max_session_seconds is 3540. A
mint answers 503 with Retry-After when the deployment has no Inworld credential; nothing is
charged.
Step 2: Connect and stream
From a server, pass the key as a bearer header; from a browser, offer thebrowser_subprotocols the mint returned. Then speak Inworld’s protocol.
Text-to-speech
create, send_text, flush_context, close_context, cancel_context and
updateConfig, each with an optional contextId, exactly as Inworld documents them. voiceId and
modelId are set by the relay. enableCustomPronunciation is removed (it selects the shared
workspace dictionary, which is not available through AI Reserve); a frame selecting named
dictionaries (pronunciationDictionarySettings) closes the socket with 1008 — select dictionaries
on the HTTP synthesis endpoints instead. Any other frame, a non-JSON frame, or a send_text over
Inworld’s 2000-unit limit closes the socket.
Speech-to-text
transcribeConfig (the relay sets modelId); audioProtocol: "BINARY"
turns on raw binary audio frames, otherwise send base64 audioChunk frames. Then endTurn and
closeStream as Inworld documents. A binary frame before the config, or without BINARY selected,
closes the socket with 1008.
Billing
- TTS is billed on the characters of every
send_textthe relay forwards, UTF-16 code units as Inworld counts, at the model’s rate. Inworld does not count text acancel_contextdiscards before synthesis; AI Reserve does, so an interruption-heavy client is charged for the last unsynthesized sentence — the conservative side. The mint reserves 3,000 characters a minute for the maximum session; the settle clamps at that reserve. - STT is billed on connected seconds, like
grok-voice. Inworld counts audio for as long as it keeps arriving, which for a live microphone is the connected session; a socket held open and silent is charged for the silence. Mute by not sending, or close the stream. - The reserve is released and the actual charge booked by the settle sweep a few minutes after the
socket closes; the row appears in your Event Log under
inworld-tts-2,inworld-tts-2-flashorinworld-stt-1with providerinworld.
Limits
- Sessions last at most 3540 seconds; Inworld closes a TTS socket after 10 minutes of inactivity.
- Frames are capped at 1 MiB; a client that outruns the relay’s buffers is closed with
1013. - Concurrency is Inworld’s account tier, shared across every organization on the platform.
- Inworld’s speech-to-speech Realtime API is not served; use
grok-voiceoreleven-realtime-*on realtime voice sessions.