{"asyncapi":"2.6.0","info":{"title":"Models API","version":"1.0.0"},"channels":{"/waves/v1/tts/live":{"description":"# Live TTS WebSocket — `/waves/v1/tts/live`\n\nReal-time text-to-speech over a persistent WebSocket connection. The\n`model` field in the request payload selects which Lightning pool serves\nthe synthesis: `lightning_v3.1`, `lightning_v3.1_pro`, or the preview\nPro checkpoint `lightning_v3.1_pro_10_26` for English, Spanish and Hindi\n(see [Checkpoints](/model-cards/text-to-speech/lightning-v-3-1-pro#checkpoints)).\n\n## When to use this\n\n- **Use this** when text arrives incrementally (LLM token streams, live\n  captioning, conversational pipelines where playback should start as\n  soon as the first chunk is ready).\n- POST to `/waves/v1/tts/live` (SSE) when you have the full text up\n  front but still want chunked playback. (Same URL, different\n  protocol — HTTP POST gets you SSE; WSS connect gets you WebSocket.)\n- Use `/waves/v1/tts` (sync) when total latency doesn't matter.\n\n## Selecting the model\n\nPass `\"model\": \"lightning_v3.1\"` (default), `\"model\": \"lightning_v3.1_pro\"`\nor `\"model\": \"lightning_v3.1_pro_10_26\"` (the preview Pro checkpoint for\nEnglish, Spanish and Hindi; see [Checkpoints](/model-cards/text-to-speech/lightning-v-3-1-pro#checkpoints))\non each request. Concurrency and latency are identical across all three.\nVoice catalogs differ — see the\n[Lightning v3.1](/model-cards/text-to-speech/lightning-v-3-1) and\n[Lightning v3.1 Pro](/model-cards/text-to-speech/lightning-v-3-1-pro)\nmodel cards for the per-model catalog.\n\n## Language behaviour\n\n**`auto` (recommended for cross-language use cases):** routes internally\nbased on the input text. Any English or Hindi voice can be used across\nall supported languages when `auto` is set.\n\nOn `lightning_v3.1` — 20 accepted language codes (10 European + 10\nIndic). The trained voice catalog covers 12 of these directly; the\nother 8 route through English or Hindi voices.\n\nOn `lightning_v3.1_pro` — 31 languages with dedicated voices (10\nIndic, 8 Asian & Middle Eastern, 13 European including Dutch and\nSwedish):\n- Pass `language: en` → UK + American accented English.\n- Pass `language: hi` → Indian accented English + Hindi (code-switching).\n- Pass the ISO 639-1 code of any other Pro language (e.g. `ta`, `de`,\n  `ja`) with a matching Pro voice. See the\n  [Lightning v3.1 Pro model card](/model-cards/text-to-speech/lightning-v-3-1-pro#supported-languages)\n  for the full list.\n- Omit `language` → defaults to `en + hi` (mixed Indian + Western\n  English coverage).\n\nOn `lightning_v3.1_pro_10_26` (preview), pass `language: en` (English),\n`es` (Spanish with English code-switching) or `hi` (Hindi with English\ncode-switching); see [Checkpoints](/model-cards/text-to-speech/lightning-v-3-1-pro#checkpoints).\n\n## Optional features\n\nSet `word_timestamps: true` to receive per-word timing events\ninterleaved with the audio chunks (`status: \"word_timestamp\"`).\nSupported on English + Hindi base-queue voices. See\n[Word-level timestamps](/models/text-to-speech/word-timestamps).\n\nSend the same `context_id` on a sequence of text fragments to have\nthem buffered, joined at natural sentence boundaries, and spoken as\none continuous generation instead of one reset-per-fragment. See\n[Continuations](/models/text-to-speech/continuations).\n\n## Connection timeout\n\nThe server closes idle WebSocket connections to free resources. The\ndefault idle timeout is **60 seconds** — if your client does not send\na message within that window the server closes the connection with:\n\n```json\n{\"status\": \"error\", \"message\": \"Connection timed out after 60 seconds of inactivity\"}\n```\n\nOverride the value with the `timeout` query parameter on the URL:\n\n```\nwss://api.smallest.ai/waves/v1/tts/live?timeout=120\n```\n\nPass a positive integer (seconds). Smaller values are honored\nverbatim (e.g. `?timeout=5` closes after 5 s of silence); larger\nvalues are clamped to the maximum of **180 seconds**. Use a larger\nvalue when your application has known pauses between turns — voice\nagents with long human-thinking windows, agentic pipelines waiting on\nan LLM round-trip, etc.\n\nThe timeout is reset on every message you send (binary audio in, JSON\ncontrol in).\n\n## Keep-alive\n\nTo hold a connection open past the timeout without sending audio,\nsend a JSON keep-alive frame:\n\n```json\n{\"type\": \"ping\"}\n```\n\nThe server replies `{\"type\": \"pong\"}` and resets the inactivity timer.\n`keepalive`, `keep_alive`, and `keep-alive` are accepted as aliases.\nThe frame is handled at the API edge — it never reaches the model and\ndoes not affect synthesis. Prefer this over a raised `timeout`: the\n`pong` also tells you the connection is still live, and it is the only\nway to stay open past the 180-second cap.\n\n## Migrating from `/waves/v1/lightning-v3.1/get_speech/stream`\n\nSame protocol, same payload shape — only the URL changes. Existing\nclients should:\n\n1. Update the WebSocket URL to `wss://api.smallest.ai/waves/v1/tts/live`.\n2. Add `\"model\": \"lightning_v3.1_pro\"` and a Pro `voice_id`.\n\nVoice IDs, sample rates, auth, and the response/streaming format are\nunchanged, so downstream audio handling, jitter buffers, and barge-in\nlogic stay the same.\n","publish":{"operationId":"subpackage_tts.TTS-publish","summary":"TtsResponse","description":"Receive audio data chunks and completion status from the server.","message":{"name":"TtsResponse","title":"TtsResponse","description":"Receive audio data chunks and completion status from the server.","payload":{"$ref":"#/components/schemas/ttsStream_ttsResponse.message"}}},"subscribe":{"operationId":"subpackage_tts.TTS-subscribe","summary":"TtsRequest","description":"Send a JSON message with `voice_id`, `text`, and optional parameters (including `model`) to generate speech audio.","message":{"name":"TtsRequest","title":"TtsRequest","description":"Send a JSON message with `voice_id`, `text`, and optional parameters (including `model`) to generate speech audio.","payload":{"$ref":"#/components/schemas/ttsStream_ttsRequest.message"}}}},"/waves/v1/stt/live":{"description":"Real-time speech-to-text over a persistent WebSocket. The fit-for-purpose path for live captioning, voice agents, and any flow where you need partial transcripts as the user is still speaking.\n\n## When to use this\n\n- **Use this** for live audio: microphone input, voice-agent turns, simultaneous interpretation, low-latency captioning. Partial results stream back while audio is still arriving.\n- **Use `POST /waves/v1/stt/`** when you have a complete file. Single request, single response, less plumbing.\n\n## Model selection\n\n- **`?model=pulse`** — multilingual.\n- **`?model=pulse-2`** — English-only (`language=en` or omitted). Adds built-in end-of-turn detection (finals close on turn boundaries instead of a fixed silence/word-count window — `eou_timeout_ms`, `finalize_on_words`, and `max_words` are ignored by default - don't send them; if you do, they still take effect and compete with end-of-turn detection), plus per-utterance `emotion` and `gender` on every final (on by default, opt out with `emotion_detection=false` / `gender_detection=false`).\n- **`?model=pulse-pro`** is rejected with `400` because Pulse Pro has no streaming worker; use `POST /waves/v1/stt/?model=pulse-pro` (HTTP) instead.\n\n## How it works\n\n1. Open a WebSocket to `wss://api.smallest.ai/waves/v1/stt/live` with `Authorization: Bearer <key>` and the session params (`model`, `language`, `sample_rate`, `encoding`, etc.) as query string.\n2. Stream raw PCM (or your chosen `encoding`) over the socket as binary frames.\n3. The server pushes back JSON `transcription` messages with `is_final: false` partial results as audio streams and `is_final: true` when an utterance closes.\n4. Send a control message when the user pauses or the session ends:\n   - **`{\"type\":\"finalize\"}`** — *turn-boundary signal*. Flushes the current audio buffer, emits one `is_final: true` transcript for that turn, and **keeps the WebSocket open** for the next user turn. Use this once per turn in a multi-turn voice agent.\n   - **`{\"type\":\"close_stream\"}`** — *session-end signal*. Flushes remaining audio, emits the terminal `is_final: true` + `is_last: true` transcript, then closes the WebSocket. Use this once, at the actual end of the session (call end, app shutdown, or after a single-shot transcription buffer is fully streamed).\n\nA multi-turn voice agent typically fires many `finalize` messages and exactly one `close_stream`. A one-off transcription of a fixed audio buffer fires only `close_stream`.\n\n## Examples\n\n**Python — multi-turn voice agent (recommended for Voice AI)**\n\nSend `finalize` per user turn so the WebSocket stays open across the whole call — you pay the connection cost once, not per turn:\n\n```python\nimport asyncio, json, websockets\n\nURL = \"wss://api.smallest.ai/waves/v1/stt/live?model=pulse&language=en&sample_rate=16000&encoding=linear16&itn_normalize=true&eou_timeout_ms=1000\"\nHEADERS = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nasync def run_voice_agent(audio_source, llm_reply, stop_event):\n    async with websockets.connect(URL, additional_headers=HEADERS) as ws:\n        async def stream_audio():\n            async for frame in audio_source:\n                if stop_event.is_set(): return\n                await ws.send(frame)\n\n        # Call this when your VAD detects end-of-turn (user paused)\n        async def end_of_turn():\n            await ws.send(json.dumps({\"type\": \"finalize\"}))\n\n        async def consume():\n            async for msg in ws:\n                data = json.loads(msg)\n                if data.get(\"is_final\"):\n                    await llm_reply(data[\"transcript\"])  # ITN-normalized full turn\n                if data.get(\"is_last\"): break          # only fires after close_stream\n\n        producer = asyncio.create_task(stream_audio())\n        consumer = asyncio.create_task(consume())\n        await stop_event.wait()                          # end of call\n\n        await ws.send(json.dumps({\"type\": \"close_stream\"}))\n        await consumer\n        producer.cancel()\n```\n\n**Python — single-shot transcription**\n\nFor one-off transcription of a complete audio buffer (file, single utterance) where no further audio is coming, send `close_stream` directly after the last chunk:\n\n```python\nimport asyncio, json, websockets\n\nURL = \"wss://api.smallest.ai/waves/v1/stt/live?model=pulse&language=en&sample_rate=16000&encoding=linear16\"\nHEADERS = {\"Authorization\": f\"Bearer {API_KEY}\"}\n\nasync def transcribe_once(audio_bytes):\n    async with websockets.connect(URL, additional_headers=HEADERS) as ws:\n        for i in range(0, len(audio_bytes), 4096):\n            await ws.send(audio_bytes[i:i+4096])\n        await ws.send(json.dumps({\"type\": \"close_stream\"}))\n        async for msg in ws:\n            data = json.loads(msg)\n            if data.get(\"is_final\"):\n                print(data[\"transcript\"])\n            if data.get(\"is_last\"):\n                break\n\nasyncio.run(transcribe_once(open(\"audio.pcm\", \"rb\").read()))\n```\n\n## Common gotchas\n\n- **`model` is required.** Missing or invalid values return `400` during the WebSocket handshake.\n- **Match `sample_rate` to your audio.** The server does not resample; mismatched rates produce garbage transcripts.\n- **Existing clients** on `wss://api.smallest.ai/waves/v1/pulse/get_text` continue to work alongside this unified path.\n","bindings":{"ws":{"headers":{"type":"object","properties":{"x-expire-content":{"type":"string"},"model":{"description":"Reference to transcription_model"},"language":{"description":"Reference to transcription_language"},"sample_rate":{"description":"Reference to transcription_sample_rate","default":"16000"},"encoding":{"description":"Reference to transcription_encoding","default":"linear16"},"word_timestamps":{"description":"Reference to transcription_word_timestamps","default":"false"},"diarize":{"description":"Reference to transcription_diarize","default":"false"},"vad_events":{"description":"Reference to transcription_vad_events","default":"false"},"vad":{"description":"Reference to transcription_vad"},"endpointing":{"description":"Reference to transcription_endpointing","default":"true"},"eou_timeout_ms":{"type":"string"},"format":{"description":"Reference to transcription_format","default":"true"},"punctuate":{"description":"Reference to transcription_punctuate","default":"true"},"capitalize":{"description":"Reference to transcription_capitalize","default":"true"},"itn_normalize":{"description":"Reference to transcription_itn_normalize","default":"false"},"no_format_delay":{"description":"Reference to transcription_no_format_delay","default":"false"},"finalize_on_words":{"description":"Reference to transcription_finalize_on_words","default":"true"},"max_words":{"type":"string"},"redact_pii":{"description":"Reference to transcription_redact_pii","default":"false"},"redact_pci":{"description":"Reference to transcription_redact_pci","default":"false"},"sentence_timestamps":{"description":"Reference to transcription_sentence_timestamps","default":"false"},"keywords":{"type":"string"},"emotion_detection":{"description":"Reference to transcription_emotion_detection"},"gender_detection":{"description":"Reference to transcription_gender_detection"}}}}},"publish":{"operationId":"subpackage_speechToText.Speech to Text-publish","summary":"Server messages","message":{"oneOf":[{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-server-0-receiveTranscription"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-server-1-receiveTranscription"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-server-2-receiveTranscription"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-server-3-receiveTranscription"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-server-4-receiveTranscription"}]}},"subscribe":{"operationId":"subpackage_speechToText.Speech to Text-subscribe","summary":"Client messages","message":{"oneOf":[{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-client-0-sendAudio"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-client-1-sendFinalize"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-client-2-sendClose"},{"$ref":"#/components/messages/subpackage_speechToText.Speech to Text-client-3-sendKeepAlive"}]}}},"/waves/v1/s2s":{"description":"# Hydra Speech-to-Speech WebSocket\n\nHydra is Smallest AI's full-duplex speech-to-speech model. A single WebSocket carries microphone audio from your client to the model and streams synthesised response audio back. **Audio in, audio out**. Hydra does not emit a transcript stream. If your application needs text, transcribe the PCM you sent or received using the Pulse STT API.\n\n## When to use this\n\n- **Use Hydra** when latency-to-voice matters above all else (phone agents, kiosks, in-car assistants, real-time tutors).\n- **Use the Pulse → Electron → Lightning v3.1 stack** when you need explicit text in the middle (analytics, custom RAG, regulated content moderation, BYOM).\n- **Use just Lightning v3.1** when you already have text and only need TTS.\n\n## Model versions\n\nThree Hydra tags are served on this endpoint; select one with `?model=`. Everything else in this reference (event catalog, `session.configure` shape, tool calling, interruption handling) is identical across them, so switching versions is a one-parameter change on the query string.\n\n| Version | Query string | Status |\n|---|---|---|\n| **`hydra-v1.1`** (current release) | `?model=hydra-v1.1` | Latest speech-to-speech model. Recommended for all new integrations. |\n| `hydra-v1.0` | `?model=hydra-v1.0` | Served, not deprecated. The server's deprecation message for `?model=hydra` names this tag as the migration target. |\n| `hydra` (original release) | `?model=hydra` | **Deprecated** 2026-08-20. Sessions still open, but the server emits a `warning` frame with `code: \"model_deprecated\"` immediately before `session.created`. |\n\nSee the [Deprecation Notices](/api-reference/deprecations/models) page and the [Hydra model card](/model-cards/speech-to-speech/hydra) for the per-version reference.\n\n## How it works\n\n1. Connect: `wss://api.smallest.ai/waves/v1/s2s?model=hydra-v1.1&api_key=<SMALLEST_API_KEY>`.\n2. Receive `session.created` → send `session.configure` with persona, voice, optional tools. On the deprecated `?model=hydra`, a `warning` frame with `code: \"model_deprecated\"` arrives immediately before `session.created`.\n3. Stream `input_audio_buffer.append` continuously while the mic is open, even while the model is speaking. Hydra detects turn boundaries on its own.\n4. Read `session.configured.session.output_audio_sample_rate` and initialize your audio pipeline at that rate. Then receive `response.output_audio.delta` chunks (base64 PCM16) and queue them for playback.\n5. Handle barge-in: if `response.created` arrives before the previous response's `response.output_audio.done`, drop any still-scheduled audio buffers from the previous response.\n\n## Audio formats\n\n- **Input** (client → server): PCM16, signed little-endian, mono, **16 kHz**, base64 inside `input_audio_buffer.append`. Recommended chunk size 20–40 ms (640–1280 samples).\n- **Output** (server → client): PCM16, signed little-endian, mono. Sample rate is per-model and echoed on `session.configured.session.output_audio_sample_rate`:\n  - `hydra-v1.0` outputs **48000 Hz**, fixed.\n  - `hydra-v1.1` outputs **24000 Hz by default**, and is configurable via `session.configure.session.output_audio_sample_rate` (`8000`, `16000`, `22050`, `24000`, `32000`, `44100`, or `48000`). Unsupported values are rejected with `error` (`code: \"invalid_request_error\"`, `param: \"session.configure.session.output_audio_sample_rate\"`).\n\n  Each chunk arrives base64-encoded inside `response.output_audio.delta`.\n\n## Voices\n\nSet on `session.configure.session.voice` and frozen at handshake. Rosters are **per version and do not overlap**. When you switch versions, also pick a voice from the new roster.\n\n- **`hydra-v1.1`** (current release), nineteen voices: `zoe`, `maya`, `elena`, `ivy`, `grace`, `alex`, `aria`, `leo`, `sam`, `kai`, plus nine British English voices - `arabella`, `cressida`, `elowen`, `sophie` (female) and `callum`, `caspian`, `cormac`, `everett`, `rupert` (male).\n- **`hydra-v1.0`**, fourteen voices: `vaughn`, `brooks`, `cole`, `hayes`, `pierce`, `sterling`, `ellis`, `lane`, `quinn`, `arden`, `rowan`, `blair`, `emery`, `sawyer`.\n- **`hydra`** (original release, deprecated): migrate to one of the tags above and pick a voice from its roster.\n\nOmit `voice` to use the server default voice. An unrecognised voice is rejected with an `error` frame (`code: \"invalid_request_error\"`, `param: \"session.configure.session.voice\"`) rather than silently defaulted. Validate client-side. The [Hydra model card](/model-cards/speech-to-speech/hydra) carries the per-version table.\n\n## Idle timeout\n\n~30 seconds of no traffic from either side. Reconnect to resume.\n\n## Connection rejection and close codes\n\n- Bad `api_key` is rejected during the WebSocket *handshake* with **HTTP 401**. The upgrade never completes, so no `error` event or close code lands on the wire.\n- `1000`. Normal close (including the ~30 s server-side idle timeout).\n- `1013`. Server at capacity. An `error` event with `code: \"server_full\"` precedes the close frame; back off with jitter and retry.\n\nSee the [Hydra realtime guide](/models/speech-to-speech/overview) for the full protocol reference, tool-calling pattern, interruption handling, and complete Python + browser examples.\n","publish":{"operationId":"subpackage_speechToSpeech.Speech to Speech-publish","summary":"Server messages","message":{"oneOf":[{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-0-SessionCreated"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-1-SessionConfigured"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-2-SessionUpdated"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-3-InputAudioBufferSpeechStarted"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-4-InputAudioBufferSpeechStopped"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-5-ConversationItemAdded"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-6-ConversationItemDone"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-7-ResponseCreated"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-8-ResponseOutputAudioDelta"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-9-ResponseOutputAudioDone"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-10-ResponseFunctionCallArgumentsDelta"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-11-ResponseFunctionCallArgumentsDone"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-12-ResponseDone"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-server-13-ErrorEvent"}]}},"subscribe":{"operationId":"subpackage_speechToSpeech.Speech to Speech-subscribe","summary":"Client messages","message":{"oneOf":[{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-client-0-SessionConfigure"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-client-1-SessionUpdate"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-client-2-InputAudioBufferAppend"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-client-3-ConversationItemCreate"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-client-4-ResponseCreate"},{"$ref":"#/components/messages/subpackage_speechToSpeech.Speech to Speech-client-5-ResponseCancel"}]}}}},"servers":{"waves":{"url":"wss://api.smallest.ai/","protocol":"wss"}},"components":{"messages":{"subpackage_speechToText.Speech to Text-server-0-receiveTranscription":{"name":"receiveTranscription","title":"receiveTranscription","payload":{"$ref":"#/components/schemas/transcription_transcriptionEvent"}},"subpackage_speechToText.Speech to Text-server-1-receiveTranscription":{"name":"receiveTranscription","title":"receiveTranscription","payload":{"$ref":"#/components/schemas/transcription_errorEvent"}},"subpackage_speechToText.Speech to Text-server-2-receiveTranscription":{"name":"receiveTranscription","title":"receiveTranscription","payload":{"$ref":"#/components/schemas/transcription_pongEvent"}},"subpackage_speechToText.Speech to Text-server-3-receiveTranscription":{"name":"receiveTranscription","title":"receiveTranscription","payload":{"$ref":"#/components/schemas/transcription_speechStarted"}},"subpackage_speechToText.Speech to Text-server-4-receiveTranscription":{"name":"receiveTranscription","title":"receiveTranscription","payload":{"$ref":"#/components/schemas/transcription_speechEnded"}},"subpackage_speechToText.Speech to Text-client-0-sendAudio":{"name":"sendAudio","title":"sendAudio","payload":{"$ref":"#/components/schemas/transcription_audioChunkOut"}},"subpackage_speechToText.Speech to Text-client-1-sendFinalize":{"name":"sendFinalize","title":"sendFinalize","description":"Flush the current audio buffer, run ITN over the accumulated utterance, and emit one `is_final` transcript. The WebSocket stays open and accepts audio for the next user turn. Send this once per turn in any multi-turn flow (voice agents, conversational STT).","payload":{"$ref":"#/components/schemas/transcription_finalizeSignal"}},"subpackage_speechToText.Speech to Text-client-2-sendClose":{"name":"sendClose","title":"sendClose","description":"Flush any remaining buffered audio, emit the terminal `is_final` + `is_last` transcript, then close the WebSocket. Send this once at the end of the session — end of call, app shutdown, or after the entire buffer of a single-shot transcription is streamed.","payload":{"$ref":"#/components/schemas/transcription_closeStream"}},"subpackage_speechToText.Speech to Text-client-3-sendKeepAlive":{"name":"sendKeepAlive","title":"sendKeepAlive","description":"Reset the connection inactivity timer without sending audio. The server replies with `{\"type\":\"pong\"}`. The frame is discarded before model processing. It does not affect the transcript, contains no audio data, and is not billed. It does not extend the 20-minute model-session idle window. For pauses longer than that, close the session and open a new one when audio resumes.","payload":{"$ref":"#/components/schemas/transcription_keepAliveSignal"}},"subpackage_speechToSpeech.Speech to Speech-server-0-SessionCreated":{"name":"SessionCreated","title":"SessionCreated","description":"First message after the WebSocket opens.","payload":{"$ref":"#/components/schemas/hydraSession_sessionCreated"}},"subpackage_speechToSpeech.Speech to Speech-server-1-SessionConfigured":{"name":"SessionConfigured","title":"SessionConfigured","description":"Server echoes the effective configuration the server applied.","payload":{"$ref":"#/components/schemas/hydraSession_sessionConfigured"}},"subpackage_speechToSpeech.Speech to Speech-server-2-SessionUpdated":{"name":"SessionUpdated","title":"SessionUpdated","payload":{"$ref":"#/components/schemas/hydraSession_sessionUpdated"}},"subpackage_speechToSpeech.Speech to Speech-server-3-InputAudioBufferSpeechStarted":{"name":"InputAudioBufferSpeechStarted","title":"InputAudioBufferSpeechStarted","payload":{"$ref":"#/components/schemas/hydraSession_inputAudioBufferSpeechStarted"}},"subpackage_speechToSpeech.Speech to Speech-server-4-InputAudioBufferSpeechStopped":{"name":"InputAudioBufferSpeechStopped","title":"InputAudioBufferSpeechStopped","payload":{"$ref":"#/components/schemas/hydraSession_inputAudioBufferSpeechStopped"}},"subpackage_speechToSpeech.Speech to Speech-server-5-ConversationItemAdded":{"name":"ConversationItemAdded","title":"ConversationItemAdded","payload":{"$ref":"#/components/schemas/hydraSession_conversationItemAdded"}},"subpackage_speechToSpeech.Speech to Speech-server-6-ConversationItemDone":{"name":"ConversationItemDone","title":"ConversationItemDone","payload":{"$ref":"#/components/schemas/hydraSession_conversationItemDone"}},"subpackage_speechToSpeech.Speech to Speech-server-7-ResponseCreated":{"name":"ResponseCreated","title":"ResponseCreated","payload":{"$ref":"#/components/schemas/hydraSession_responseCreated"}},"subpackage_speechToSpeech.Speech to Speech-server-8-ResponseOutputAudioDelta":{"name":"ResponseOutputAudioDelta","title":"ResponseOutputAudioDelta","description":"Decode the base64 `delta` and play at the negotiated output sample rate. If `response.created` arrives before the previous response's `response.output_audio.done`, drop any still-scheduled audio from the previous response, because the user has barged in.","payload":{"$ref":"#/components/schemas/hydraSession_responseOutputAudioDelta"}},"subpackage_speechToSpeech.Speech to Speech-server-9-ResponseOutputAudioDone":{"name":"ResponseOutputAudioDone","title":"ResponseOutputAudioDone","payload":{"$ref":"#/components/schemas/hydraSession_responseOutputAudioDone"}},"subpackage_speechToSpeech.Speech to Speech-server-10-ResponseFunctionCallArgumentsDelta":{"name":"ResponseFunctionCallArgumentsDelta","title":"ResponseFunctionCallArgumentsDelta","payload":{"$ref":"#/components/schemas/hydraSession_responseFunctionCallArgumentsDelta"}},"subpackage_speechToSpeech.Speech to Speech-server-11-ResponseFunctionCallArgumentsDone":{"name":"ResponseFunctionCallArgumentsDone","title":"ResponseFunctionCallArgumentsDone","description":"The client is responsible for executing the tool and posting the result back via `conversation.item.create`.","payload":{"$ref":"#/components/schemas/hydraSession_responseFunctionCallArgumentsDone"}},"subpackage_speechToSpeech.Speech to Speech-server-12-ResponseDone":{"name":"ResponseDone","title":"ResponseDone","payload":{"$ref":"#/components/schemas/hydraSession_responseDone"}},"subpackage_speechToSpeech.Speech to Speech-server-13-ErrorEvent":{"name":"ErrorEvent","title":"ErrorEvent","description":"Errors are non-fatal unless followed by a close frame. Treat them as diagnostics.","payload":{"$ref":"#/components/schemas/hydraSession_errorEvent"}},"subpackage_speechToSpeech.Speech to Speech-client-0-SessionConfigure":{"name":"SessionConfigure","title":"SessionConfigure","description":"Sent exactly once, immediately after receiving `session.created`. The server will not accept audio until this frame is processed.","payload":{"$ref":"#/components/schemas/hydraSession_sessionConfigure"}},"subpackage_speechToSpeech.Speech to Speech-client-1-SessionUpdate":{"name":"SessionUpdate","title":"SessionUpdate","description":"Apply a mid-session change. Today, only `tools` is honoured.","payload":{"$ref":"#/components/schemas/hydraSession_sessionUpdate"}},"subpackage_speechToSpeech.Speech to Speech-client-2-InputAudioBufferAppend":{"name":"InputAudioBufferAppend","title":"InputAudioBufferAppend","description":"Continuously while the microphone is open. No manual `commit` or `end-of-turn` event. Hydra decides when a turn ends.","payload":{"$ref":"#/components/schemas/hydraSession_inputAudioBufferAppend"}},"subpackage_speechToSpeech.Speech to Speech-client-3-ConversationItemCreate":{"name":"ConversationItemCreate","title":"ConversationItemCreate","payload":{"$ref":"#/components/schemas/hydraSession_conversationItemCreate"}},"subpackage_speechToSpeech.Speech to Speech-client-4-ResponseCreate":{"name":"ResponseCreate","title":"ResponseCreate","payload":{"$ref":"#/components/schemas/hydraSession_responseCreate"}},"subpackage_speechToSpeech.Speech to Speech-client-5-ResponseCancel":{"name":"ResponseCancel","title":"ResponseCancel","payload":{"$ref":"#/components/schemas/hydraSession_responseCancel"}}},"schemas":{"ChannelsTtsStreamMessagesTtsResponseMessageStatus":{"type":"string","enum":["chunk","word_timestamp","complete"],"description":"Frame type discriminator:\n- `chunk` — base64-encoded audio chunk in `data.audio`.\n- `word_timestamp` — per-word timing event in `data.{id,word,start,end}`. Only emitted when the request set `word_timestamps: true` and the voice family supports it.\n- `complete` — terminal frame; the server closes the WebSocket after this. **Exception:** inside a `context_id` continuation, `complete` marks one released segment as done, not the end of the connection — the socket stays open and more segments (each with its own `complete`) can follow. See [Continuations](/models/text-to-speech/continuations).\n","title":"ChannelsTtsStreamMessagesTtsResponseMessageStatus"},"ChannelsTtsStreamMessagesTtsResponseMessageData":{"type":"object","properties":{"audio":{"type":"string","description":"Base64-encoded audio chunk (present on `status: \"chunk\"` frames)."},"id":{"type":"integer","description":"0-indexed position of the word within the input text (present on `status: \"word_timestamp\"` frames)."},"word":{"type":"string","description":"Exact substring from the input text, un-normalized — `\"$100\"` stays `\"$100\"`, `\"25th\"` stays `\"25th\"` (present on `status: \"word_timestamp\"` frames)."},"start":{"type":"number","format":"double","description":"Start of the word in seconds, relative to the start of the audio stream (present on `status: \"word_timestamp\"` frames)."},"end":{"type":"number","format":"double","description":"End of the word in seconds, relative to the start of the audio stream (present on `status: \"word_timestamp\"` frames)."}},"description":"Frame-specific payload. Shape depends on `status` — see the per-frame examples below.","title":"ChannelsTtsStreamMessagesTtsResponseMessageData"},"ttsStream_ttsResponse.message":{"type":"object","properties":{"session_id":{"type":"string","description":"Internal session identifier (system-generated, stable for the WebSocket connection lifetime)."},"request_id":{"type":"string","description":"Internal request identifier (system-generated UUID, unique per TTS synthesis)."},"external_session_id":{"type":"string","description":"Echoed client-provided session_id (omitted if not provided)."},"external_request_id":{"type":"string","description":"Echoed client-provided request_id (omitted if not provided)."},"status":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsResponseMessageStatus","description":"Frame type discriminator:\n- `chunk` — base64-encoded audio chunk in `data.audio`.\n- `word_timestamp` — per-word timing event in `data.{id,word,start,end}`. Only emitted when the request set `word_timestamps: true` and the voice family supports it.\n- `complete` — terminal frame; the server closes the WebSocket after this. **Exception:** inside a `context_id` continuation, `complete` marks one released segment as done, not the end of the connection — the socket stays open and more segments (each with its own `complete`) can follow. See [Continuations](/models/text-to-speech/continuations).\n"},"data":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsResponseMessageData","description":"Frame-specific payload. Shape depends on `status` — see the per-frame examples below."}},"title":"ttsStream_ttsResponse.message"},"ChannelsTtsStreamMessagesTtsRequestMessageModel":{"type":"string","enum":["lightning_v3.1","lightning_v3.1_pro","lightning_v3.1_pro_10_26"],"default":"lightning_v3.1","description":"TTS model to route the request to. Controls which model pool\nserves this synthesis.\n\n- `lightning_v3.1` (default): standard Lightning v3.1. Retiring on Nov\n  30, 2026; use `lightning_v3.1_pro`.\n- `lightning_v3.1_pro` — Lightning v3.1 Pro pool with a\n  curated voice catalog. See the\n  [Pro model card](/model-cards/text-to-speech/lightning-v-3-1-pro).\n- `lightning_v3.1_pro_10_26` — [preview] New Lightning v3.1\n  Pro checkpoint for English, Spanish and Hindi. Accepts every\n  Pro voice. On 2026-11-28, it becomes the stable\n  `lightning_v3.1_pro` for these three languages only; all\n  other languages are unchanged. `lightning_v3.1_pro_10_26`\n  remains available until 2026-12-28. See\n  [Checkpoints](/model-cards/text-to-speech/lightning-v-3-1-pro#checkpoints).\n\nSame concurrency and latency profile across all three. Other\nrequest fields behave identically.\n","title":"ChannelsTtsStreamMessagesTtsRequestMessageModel"},"ChannelsTtsStreamMessagesTtsRequestMessageLanguage":{"type":"string","enum":["auto","en","hi","mr","kn","ta","bn","gu","te","ml","pa","or","es","de","fr","it","nl","sv","pt","ru","el","fi","no","pl","ar","zh","id","ja","ko","ms","tr","vi"],"description":"Language code for synthesis. Influences pronunciation,\nnumber/date normalization, and phoneme selection.\n\nEach voice has its own `tags.language` set in the voice catalog —\nquery `GET /waves/v1/lightning-v3.1/get_voices`. Pass a language\nthe voice was trained on; passing other codes is accepted by the\nAPI but produces English-pronounced output.\n\n**`auto`:** routes internally based on the input text. Any\nEnglish or Hindi voice can be used across all supported\nlanguages when `auto` is set; the platform handles\nlanguage-appropriate routing without needing a code per call.\n\n**On `lightning_v3.1`** — 20 supported languages:\n- 10 European: English, Spanish, French, German, Italian, Dutch, Swedish, Portuguese, Polish, Russian\n- 10 Indic: Hindi, Marathi, Gujarati, Punjabi, Bengali, Odia, Tamil, Telugu, Kannada, Malayalam\n\n**On `lightning_v3.1_pro`** — 31 supported languages (adds 11 over base):\n- 13 European: base 10 plus Greek, Finnish, Norwegian\n- 8 Asian & Middle Eastern: Chinese, Japanese, Korean, Indonesian, Malay, Vietnamese, Turkish, Arabic\n- 10 Indic: same as base\n- Pass `en` → UK + American accented English.\n- Pass `hi` → Indian accented English + Hindi (code-switching).\n- Omit `language` → defaults to `en + hi` (mixed Indian + Western English coverage).\n\nOn `lightning_v3.1_pro_10_26`, use `en` (English), `es` (Spanish with English code-switching) or `hi` (Hindi with English code-switching).\n","title":"ChannelsTtsStreamMessagesTtsRequestMessageLanguage"},"ChannelsTtsStreamMessagesTtsRequestMessageNumberPronunciationLanguage":{"type":"string","enum":["auto","en","hi","mr","kn","ta","bn","gu","te","ml","pa","or","es","de","fr","it","nl","sv","pt","ru","el","fi","no","pl","ar","zh","id","ja","ko","ms","tr","vi"],"description":"Optional. Sets the language used to read out numeric content\n— numbers, currency amounts, times, and the numeric parts of\ndates and years — independently of the synthesis voice.\nOrdinary words are not translated.\n\n- If you **omit `language`**, this value also becomes the\n  synthesis language: model selection and voice routing\n  follow it.\n- If you **set `language` explicitly**, `language` always wins\n  for synthesis and `number_pronunciation_language` only\n  changes how numeric content is normalized. It works both\n  ways — read numbers in Hindi under an English voice, or in\n  English under a Hindi voice (tuned for Indian, often\n  mixed-script, use cases).\n- Omit this field to keep the existing behaviour —\n  normalization follows `language`.\n\nNote: only numeric tokens are re-spoken; the words around them\nstay in the text language. On a cross-language request names\nmay also render in the target script (e.g. \"Smith\" →\n\"स्मिथ\"), which is generally the desired reading for\nnative-language voices.\n\nAccepts the same language codes as `language` (including\n`auto`, `nl`, `sv`).\n","title":"ChannelsTtsStreamMessagesTtsRequestMessageNumberPronunciationLanguage"},"ChannelsTtsStreamMessagesTtsRequestMessageDateFormat":{"type":"string","enum":["EU","US"],"description":"Optional. Controls how all-numeric dates (e.g. `05/03/2024`)\nare read out, independent of the synthesis voice:\n\n- `EU` — day/month order (`DD/MM`): `05/03/2024` → \"fifth\n  March, twenty twenty four\".\n- `US` — month/day order (`MM/DD`): `05/03/2024` → \"May\n  third, twenty twenty four\".\n\nOmit this field to keep the existing behaviour: English dates\ndefault to `US` (`MM/DD`). Applies across all languages, so you\ncan force day-first (`DD/MM`) reading — e.g. the Indian\nconvention — on any voice.\n","title":"ChannelsTtsStreamMessagesTtsRequestMessageDateFormat"},"ChannelsTtsStreamMessagesTtsRequestMessageContentFilterAction":{"type":"string","enum":["reject","flag","redact"],"default":"reject","description":"What happens on a match. `reject` fails the request with a `CONTENT_FILTER_BLOCKED` error frame; `flag` synthesizes normally and records the match; `redact` removes the matched term and synthesizes the rest.","title":"ChannelsTtsStreamMessagesTtsRequestMessageContentFilterAction"},"ChannelsTtsStreamMessagesTtsRequestMessageContentFilter":{"type":"object","properties":{"enabled":{"type":"boolean","default":false,"description":"Must be the literal `true` to enable the filter. Any other value leaves it off."},"action":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsRequestMessageContentFilterAction","default":"reject","description":"What happens on a match. `reject` fails the request with a `CONTENT_FILTER_BLOCKED` error frame; `flag` synthesizes normally and records the match; `redact` removes the matched term and synthesizes the rest."}},"description":"Opt-in profanity filter for the submitted text. Off by\ndefault; sending this object is the only way to turn it on,\nand `enabled` must be the literal `true`.\n\nThe filter rewrites your text only with `action: redact`; otherwise it either lets the\nmessage through or rejects it before synthesis.\n\n`action: \"reject\"` returns an error frame carrying\n`error_code: \"CONTENT_FILTER_BLOCKED\"`, the `language`\nchecked and a `match_count`, alongside the usual\n`session_id` and `request_id`; no audio frames are sent and\nthe request never reaches the worker. `action: \"flag\"`\nsynthesizes normally and records the match.\n\nMatching is whole-word rather than substring. The lists\nconsulted are the one for the request's locale plus English.\nMatched terms are never returned or logged. If no verdict is\navailable the request fails open and the audio is\nsynthesized unfiltered.\n\nSee [Content filter](/models/text-to-speech/content-filter).\n","title":"ChannelsTtsStreamMessagesTtsRequestMessageContentFilter"},"ttsStream_ttsRequest.message":{"type":"object","properties":{"voice_id":{"type":"string","description":"The ID of the voice to use. See the model card for available voices per model."},"text":{"type":"string","description":"The text to convert to speech."},"model":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsRequestMessageModel","default":"lightning_v3.1","description":"TTS model to route the request to. Controls which model pool\nserves this synthesis.\n\n- `lightning_v3.1` (default): standard Lightning v3.1. Retiring on Nov\n  30, 2026; use `lightning_v3.1_pro`.\n- `lightning_v3.1_pro` — Lightning v3.1 Pro pool with a\n  curated voice catalog. See the\n  [Pro model card](/model-cards/text-to-speech/lightning-v-3-1-pro).\n- `lightning_v3.1_pro_10_26` — [preview] New Lightning v3.1\n  Pro checkpoint for English, Spanish and Hindi. Accepts every\n  Pro voice. On 2026-11-28, it becomes the stable\n  `lightning_v3.1_pro` for these three languages only; all\n  other languages are unchanged. `lightning_v3.1_pro_10_26`\n  remains available until 2026-12-28. See\n  [Checkpoints](/model-cards/text-to-speech/lightning-v-3-1-pro#checkpoints).\n\nSame concurrency and latency profile across all three. Other\nrequest fields behave identically.\n"},"max_buffer_flush_ms":{"type":"integer","minimum":0,"maximum":1000,"default":0,"description":"The maximum time (in ms) to wait for more input before generating output. It flushes when either this time is reached or enough input is received for optimal output—whichever comes first. This is useful for input streams. Defaults to 0"},"continue":{"type":"boolean","default":false,"description":"Buffering control. Meaning depends on whether `context_id`\nis also set:\n\n- **Without `context_id`** (legacy buffer): `true` holds\n  this text and waits for a later request with\n  `flush: true` before generating any audio.\n- **With `context_id`** (continuations): `true` means\n  \"more text for this context is coming\" — the fragment\n  is buffered only until it reaches a natural sentence\n  boundary or `max_buffer_delay_ms` elapses, whichever is\n  first. Send `continue: false` to close out the context\n  and speak whatever is left buffered — this frame may\n  omit `text`. See\n  [Continuations](/models/text-to-speech/continuations).\n\nIf not set, assumes no more input is coming.\n"},"flush":{"type":"boolean","default":false,"description":"This setting controls whether the system should flush the\ncurrent buffer. Legacy buffering only — cannot be combined\nwith `context_id` (end a context with `continue: false` or\n`context_close: true` instead).\n"},"complete_backoff_ms":{"type":"number","format":"double","minimum":0,"maximum":10000,"default":4000,"description":"The time in ms to wait after the last chunk is sent before sending the complete response. Default is 4000ms. Maximum is 10000ms."},"context_id":{"type":"string","pattern":"^[a-zA-Z0-9_\\-.]+$","maxLength":128,"description":"Groups a sequence of text fragments into one continuous\nsynthesis (\"continuations\"). Send the same `context_id` on\nevery fragment belonging to one utterance — fragments are\nbuffered and joined at natural sentence boundaries, and\neach new generation in the context is primed with the\naudio from the previous one so prosody carries across\nfragments instead of resetting per-chunk.\n\nFragments sharing a `context_id` on the same connection\ncount as a single concurrency slot, not one per fragment.\n\nCannot be combined with `flush` or `max_buffer_flush_ms` —\nthose are the legacy buffering contract. End a context\nwith `continue: false` or `context_close: true` instead.\nSee [Continuations](/models/text-to-speech/continuations).\n"},"max_buffer_delay_ms":{"type":"integer","minimum":0,"maximum":5000,"default":3000,"description":"Only meaningful together with `context_id`. Upper bound\n(ms) on how long a fragment may wait for a clean sentence\nboundary before it's spoken anyway. The deadline starts on\nthe first still-buffered fragment and does not reset as\nmore fragments arrive, so a chatty client can't hold\nplayback in silence indefinitely.\n"},"context_close":{"type":"boolean","default":false,"description":"Ends a `context_id` immediately: releases any buffered\ntext and drops that context's carried audio state right\naway instead of waiting out its idle timeout. May be sent\nwithout `text` / `voice_id`.\n"},"language":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsRequestMessageLanguage","description":"Language code for synthesis. Influences pronunciation,\nnumber/date normalization, and phoneme selection.\n\nEach voice has its own `tags.language` set in the voice catalog —\nquery `GET /waves/v1/lightning-v3.1/get_voices`. Pass a language\nthe voice was trained on; passing other codes is accepted by the\nAPI but produces English-pronounced output.\n\n**`auto`:** routes internally based on the input text. Any\nEnglish or Hindi voice can be used across all supported\nlanguages when `auto` is set; the platform handles\nlanguage-appropriate routing without needing a code per call.\n\n**On `lightning_v3.1`** — 20 supported languages:\n- 10 European: English, Spanish, French, German, Italian, Dutch, Swedish, Portuguese, Polish, Russian\n- 10 Indic: Hindi, Marathi, Gujarati, Punjabi, Bengali, Odia, Tamil, Telugu, Kannada, Malayalam\n\n**On `lightning_v3.1_pro`** — 31 supported languages (adds 11 over base):\n- 13 European: base 10 plus Greek, Finnish, Norwegian\n- 8 Asian & Middle Eastern: Chinese, Japanese, Korean, Indonesian, Malay, Vietnamese, Turkish, Arabic\n- 10 Indic: same as base\n- Pass `en` → UK + American accented English.\n- Pass `hi` → Indian accented English + Hindi (code-switching).\n- Omit `language` → defaults to `en + hi` (mixed Indian + Western English coverage).\n\nOn `lightning_v3.1_pro_10_26`, use `en` (English), `es` (Spanish with English code-switching) or `hi` (Hindi with English code-switching).\n"},"number_pronunciation_language":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsRequestMessageNumberPronunciationLanguage","description":"Optional. Sets the language used to read out numeric content\n— numbers, currency amounts, times, and the numeric parts of\ndates and years — independently of the synthesis voice.\nOrdinary words are not translated.\n\n- If you **omit `language`**, this value also becomes the\n  synthesis language: model selection and voice routing\n  follow it.\n- If you **set `language` explicitly**, `language` always wins\n  for synthesis and `number_pronunciation_language` only\n  changes how numeric content is normalized. It works both\n  ways — read numbers in Hindi under an English voice, or in\n  English under a Hindi voice (tuned for Indian, often\n  mixed-script, use cases).\n- Omit this field to keep the existing behaviour —\n  normalization follows `language`.\n\nNote: only numeric tokens are re-spoken; the words around them\nstay in the text language. On a cross-language request names\nmay also render in the target script (e.g. \"Smith\" →\n\"स्मिथ\"), which is generally the desired reading for\nnative-language voices.\n\nAccepts the same language codes as `language` (including\n`auto`, `nl`, `sv`).\n"},"date_format":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsRequestMessageDateFormat","description":"Optional. Controls how all-numeric dates (e.g. `05/03/2024`)\nare read out, independent of the synthesis voice:\n\n- `EU` — day/month order (`DD/MM`): `05/03/2024` → \"fifth\n  March, twenty twenty four\".\n- `US` — month/day order (`MM/DD`): `05/03/2024` → \"May\n  third, twenty twenty four\".\n\nOmit this field to keep the existing behaviour: English dates\ndefault to `US` (`MM/DD`). Applies across all languages, so you\ncan force day-first (`DD/MM`) reading — e.g. the Indian\nconvention — on any voice.\n"},"math_notation":{"type":"boolean","default":false,"description":"Opt-in flag that reads digit-flanked math operators\n(`5 x 3`, `2 ^ 10`, `6 ÷ 2`) as words instead of leaving\nthem for the default number reader. Off by default\nbecause in real traffic digit-flanked `NxN` is more\noften a product dimension, the `24x7` idiom, or a\nvehicle-registration code than an actual multiplication.\n\nWhen `true`, the normalizer replaces the operator with\nthe spoken word matched to\n`number_pronunciation_language`:\n\n| Glyphs | en (default / fallback) | hi | mr |\n|---|---|---|---|\n| `×` `x` `X` `*` | times | गुणा | गुणिले |\n| `÷` and spaced `/` | divided by | बटा | भागिले |\n| `+` | plus | प्लस | अधिक |\n| spaced `-` `–` `−` | minus | माइनस | वजा |\n| `=` | equals | बराबर | बरोबर |\n| `^` `**` | to the power of | की घात | ची घात |\n\nLocalized only for `hi` and `mr`; every other language\nfalls back to the English words. The operator word\nfollows `number_pronunciation_language`, not the\nsynthesis `language`, so\n`language=en, number_pronunciation_language=hi` reads\n`6 x 7` as \"छः गुणा सात\".\n\nMatching rules: unambiguous glyphs (`× ÷ * ^ ** = +` and\nthe wrong-glyph `x`/`X`) fire glued or spaced (`5x3`,\n`5 x 3`). The ambiguous `-` `–` `−` and `/` fire only\nwhen space-padded, so `5-3` stays a range and `1/2`\nstays a fraction. See [Math notation](/models/text-to-speech/math-notation)\nfor the full lexicon, known limitations (product\ndimensions, `24x7` idiom, vehicle-reg codes), and\nEU-language localizations.\n"},"sample_rate":{"type":"integer","default":44100,"description":"Audio sample rate in Hz. Supported values: 8000, 16000, 24000, 44100"},"speed":{"type":"number","format":"double","minimum":0.5,"maximum":2,"default":1,"description":"Speaking speed multiplier"},"session_id":{"type":"string","pattern":"^[a-zA-Z0-9_\\-.]+$","maxLength":128,"description":"Optional client-provided session identifier for correlation. Only alphanumeric characters, hyphens, underscores, and dots allowed. Max 128 characters. Echoed back in responses as `external_session_id`."},"request_id":{"type":"string","pattern":"^[a-zA-Z0-9_\\-.]+$","maxLength":128,"description":"Optional client-provided request identifier for correlation. Only alphanumeric characters, hyphens, underscores, and dots allowed. Max 128 characters. Echoed back in responses as `external_request_id`."},"content_filter":{"$ref":"#/components/schemas/ChannelsTtsStreamMessagesTtsRequestMessageContentFilter","description":"Opt-in profanity filter for the submitted text. Off by\ndefault; sending this object is the only way to turn it on,\nand `enabled` must be the literal `true`.\n\nThe filter rewrites your text only with `action: redact`; otherwise it either lets the\nmessage through or rejects it before synthesis.\n\n`action: \"reject\"` returns an error frame carrying\n`error_code: \"CONTENT_FILTER_BLOCKED\"`, the `language`\nchecked and a `match_count`, alongside the usual\n`session_id` and `request_id`; no audio frames are sent and\nthe request never reaches the worker. `action: \"flag\"`\nsynthesizes normally and records the match.\n\nMatching is whole-word rather than substring. The lists\nconsulted are the one for the request's locale plus English.\nMatched terms are never returned or logged. If no verdict is\navailable the request fails open and the audio is\nsynthesized unfiltered.\n\nSee [Content filter](/models/text-to-speech/content-filter).\n"},"word_timestamps":{"type":"boolean","default":false,"description":"Opt in to per-word timing events for the synthesized audio. When `true`, the server interleaves `status: \"word_timestamp\"` frames with the audio `chunk` frames; each carries `data: { id, word, start, end }` where `start`/`end` are floats in seconds relative to the start of the audio stream, and `word` is verbatim from the input text (un-normalized — `\"$100\"` stays `\"$100\"`, not `\"one hundred dollars\"`). Supported on base-queue English + Hindi voices (`meher`, `devansh`, `kartik`, `maithili`, `liam`, `avery`); other voice families silently emit no word events (audio still works). Defaults to `false` so existing integrations see no change.\n"}},"required":["voice_id","text"],"title":"ttsStream_ttsRequest.message"},"ChannelsTranscriptionMessagesTranscriptionEventType":{"type":"string","enum":["transcription"],"title":"ChannelsTranscriptionMessagesTranscriptionEventType"},"ChannelsTranscriptionMessagesTranscriptionEventWordsItems":{"type":"object","properties":{"word":{"type":"string"},"start":{"type":"number","format":"double"},"end":{"type":"number","format":"double"},"confidence":{"type":"number","format":"double","description":"Per-word confidence score, from 0.0 to 1.0."},"speaker":{"type":"integer","description":"Zero-indexed speaker label (0, 1, 2, ...). Present when `diarize=true`."},"speaker_confidence":{"type":"number","format":"double","description":"Confidence of the speaker assignment, from 0.0 to 1.0. Present when `diarize=true`."}},"title":"ChannelsTranscriptionMessagesTranscriptionEventWordsItems"},"ChannelsTranscriptionMessagesTranscriptionEventUtterancesItems":{"type":"object","properties":{"text":{"type":"string","description":"The sentence text."},"start":{"type":"number","format":"double","description":"Start time in seconds."},"end":{"type":"number","format":"double","description":"End time in seconds."},"speaker":{"type":"integer","description":"Zero-indexed speaker label. Present when `diarize=true`."}},"title":"ChannelsTranscriptionMessagesTranscriptionEventUtterancesItems"},"ChannelsTranscriptionMessagesTranscriptionEventEmotionLabel":{"type":"string","enum":["neutral","happy","angry","sad","fear","disgust"],"description":"Highest-scoring emotion class.","title":"ChannelsTranscriptionMessagesTranscriptionEventEmotionLabel"},"ChannelsTranscriptionMessagesTranscriptionEventEmotionScores":{"type":"object","properties":{"neutral":{"type":"number","format":"double"},"happy":{"type":"number","format":"double"},"angry":{"type":"number","format":"double"},"sad":{"type":"number","format":"double"},"fear":{"type":"number","format":"double"},"disgust":{"type":"number","format":"double"}},"description":"Full score distribution across all six classes.","title":"ChannelsTranscriptionMessagesTranscriptionEventEmotionScores"},"ChannelsTranscriptionMessagesTranscriptionEventEmotion":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventEmotionLabel","description":"Highest-scoring emotion class."},"confidence":{"type":"number","format":"double","description":"Confidence of `label`, from 0.0 to 1.0."},"scores":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventEmotionScores","description":"Full score distribution across all six classes."}},"description":"`model=pulse-2` only, on finals when `emotion_detection` is on (default). Six-class per-utterance emotion; scores sum to 1.","title":"ChannelsTranscriptionMessagesTranscriptionEventEmotion"},"ChannelsTranscriptionMessagesTranscriptionEventGenderLabel":{"type":"string","enum":["male","female"],"description":"Higher-scoring gender class.","title":"ChannelsTranscriptionMessagesTranscriptionEventGenderLabel"},"ChannelsTranscriptionMessagesTranscriptionEventGenderScores":{"type":"object","properties":{"male":{"type":"number","format":"double"},"female":{"type":"number","format":"double"}},"description":"Score distribution across both classes.","title":"ChannelsTranscriptionMessagesTranscriptionEventGenderScores"},"ChannelsTranscriptionMessagesTranscriptionEventGender":{"type":"object","properties":{"label":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventGenderLabel","description":"Higher-scoring gender class."},"confidence":{"type":"number","format":"double","description":"Confidence of `label`, from 0.0 to 1.0."},"scores":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventGenderScores","description":"Score distribution across both classes."}},"description":"`model=pulse-2` only, on finals when `gender_detection` is on (default). Acoustic gender estimate of the speaker's voice, not an identity attribute.","title":"ChannelsTranscriptionMessagesTranscriptionEventGender"},"transcription_transcriptionEvent":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventType"},"status":{"type":"string"},"transcription":{"type":"string"},"transcript":{"type":"string","description":"Same content as `transcription`; the WebSocket DTO emits both fields for SDK compatibility."},"is_final":{"type":"boolean","description":"True when this segment will not be revised."},"is_last":{"type":"boolean","description":"True on the terminal segment, fires only after the client sends `{\"type\":\"close_stream\"}`."},"from_finalize":{"type":"boolean","description":"True on the final that a manual `{\"type\":\"finalize\"}` message produced. Each `finalize` produces exactly one such final, with `itn_normalize` on or off. Its transcript is empty if no audio was pending."},"session_id":{"type":"string","description":"Server-generated session identifier, stable for the connection lifetime. The client-provided `external_session_id` query param is not echoed back — keep your own mapping if you need it."},"language":{"type":["string","null"],"description":"The language code Pulse detected or was pinned to for this segment."},"languages":{"type":["array","null"],"items":{"type":"string"},"description":"Populated when language detection emits multiple candidates."},"words":{"type":"array","items":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventWordsItems"}},"utterances":{"type":"array","items":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventUtterancesItems"},"description":"Sentence-level timestamps. Present when `sentence_timestamps=true` is set on connect."},"eot_finalized":{"type":"boolean","description":"`model=pulse-2` only. True when this final was closed by built-in end-of-turn detection. Absent on finals flushed by `finalize` or `close_stream`: a `finalize` final is marked `from_finalize: true`, and the terminal `close_stream` final is marked `is_last: true`."},"emotion":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventEmotion","description":"`model=pulse-2` only, on finals when `emotion_detection` is on (default). Six-class per-utterance emotion; scores sum to 1."},"gender":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesTranscriptionEventGender","description":"`model=pulse-2` only, on finals when `gender_detection` is on (default). Acoustic gender estimate of the speaker's voice, not an identity attribute."}},"title":"transcription_transcriptionEvent"},"TranscriptionErrorEventType":{"type":"string","enum":["error"],"title":"TranscriptionErrorEventType"},"transcription_errorEvent":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/TranscriptionErrorEventType"},"error_code":{"type":"string","description":"Machine-readable error code. Branch on this rather than on `message`. Not every error frame carries one. Values:\n\n- `LANGUAGE_NOT_ENABLED_IN_REGION`: the requested `language` is not enabled in the region you connected to. The frame also carries `language` and `region`, and the socket closes.\n- `LANGUAGE_NOT_SUPPORTED_BY_MODEL`: `model=pulse-2` with a `language` other than `en`. The frame also carries `model` and `language`, and the socket closes.\n- `SERVICE_UNAVAILABLE`: the transcription service could not be reached. Try again. When the frame carries `retryable: true`, the socket closes with code `1013`.\n- `UPSTREAM_UNAVAILABLE`: the transcription service dropped the session mid-stream. The frame carries `retryable: true` and the socket closes with code `1012`. Reconnect to continue.\n- `SERVICE_RESTART`: the server is restarting. Reconnect to continue.\n"},"error":{"type":"string","description":"Human-readable message. Present on some frames, such as validation errors and errors from the model; may appear alongside `error_code`."},"message":{"type":"string"},"retryable":{"type":"boolean","description":"Present and `true` on `UPSTREAM_UNAVAILABLE` and on most `SERVICE_UNAVAILABLE` frames. Reconnect to retry."},"session_id":{"type":"string","description":"Server-generated session identifier. Present on some frames, such as `UPSTREAM_UNAVAILABLE`, `SERVICE_RESTART`, and errors from the model."},"region":{"type":"string","description":"The region you connected to. Present with `LANGUAGE_NOT_ENABLED_IN_REGION`."},"model":{"type":"string","description":"Echoes the `?model=` value that triggered the error, when applicable."},"language":{"type":"string","description":"Echoes the `language` value that triggered the error, when applicable."}},"title":"transcription_errorEvent"},"ChannelsTranscriptionMessagesPongEventType":{"type":"string","enum":["pong"],"title":"ChannelsTranscriptionMessagesPongEventType"},"transcription_pongEvent":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesPongEventType"}},"title":"transcription_pongEvent"},"SpeechStartedEventType":{"type":"string","enum":["speech_started"],"description":"Discriminator. Always `speech_started` for this event.","title":"SpeechStartedEventType"},"transcription_speechStarted":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/SpeechStartedEventType","description":"Discriminator. Always `speech_started` for this event."},"session_id":{"type":"string","description":"Matches the `session_id` on `transcription` messages from the same connection; use it to correlate VAD events with transcript turns."},"timestamp":{"type":"number","format":"double","description":"Acoustic onset of speech, in seconds from the first audio frame sent on this connection."}},"required":["type","session_id","timestamp"],"title":"transcription_speechStarted"},"SpeechEndedEventType":{"type":"string","enum":["speech_ended"],"description":"Discriminator. Always `speech_ended` for this event.","title":"SpeechEndedEventType"},"transcription_speechEnded":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/SpeechEndedEventType","description":"Discriminator. Always `speech_ended` for this event."},"session_id":{"type":"string","description":"Same session identifier returned on the `transcription` messages."},"timestamp":{"type":"number","format":"double","description":"Acoustic offset of speech (end of a continuous voiced region), in seconds from the first audio frame."}},"required":["type","session_id","timestamp"],"title":"transcription_speechEnded"},"transcription_audioChunkOut":{"type":"string","format":"binary","title":"transcription_audioChunkOut"},"ChannelsTranscriptionMessagesFinalizeSignalType":{"type":"string","enum":["finalize"],"description":"Flush the current audio buffer and emit one `is_final: true` transcript. The WebSocket stays open and accepts audio for the next user turn.","title":"ChannelsTranscriptionMessagesFinalizeSignalType"},"transcription_finalizeSignal":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesFinalizeSignalType","description":"Flush the current audio buffer and emit one `is_final: true` transcript. The WebSocket stays open and accepts audio for the next user turn."}},"required":["type"],"title":"transcription_finalizeSignal"},"ChannelsTranscriptionMessagesCloseStreamType":{"type":"string","enum":["close_stream"],"description":"Flush remaining buffered audio, emit the terminal `is_final` + `is_last` transcript, then close the WebSocket. Send exactly once at the end of the session.","title":"ChannelsTranscriptionMessagesCloseStreamType"},"transcription_closeStream":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesCloseStreamType","description":"Flush remaining buffered audio, emit the terminal `is_final` + `is_last` transcript, then close the WebSocket. Send exactly once at the end of the session."}},"required":["type"],"title":"transcription_closeStream"},"ChannelsTranscriptionMessagesKeepAliveSignalType":{"type":"string","enum":["ping","keepalive","keep_alive","keep-alive"],"description":"Reset the connection inactivity timer. All four values behave identically. The server acknowledges with a `pong` message.","title":"ChannelsTranscriptionMessagesKeepAliveSignalType"},"transcription_keepAliveSignal":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsTranscriptionMessagesKeepAliveSignalType","description":"Reset the connection inactivity timer. All four values behave identically. The server acknowledges with a `pong` message."}},"required":["type"],"title":"transcription_keepAliveSignal"},"ChannelsHydraSessionMessagesSessionCreatedType":{"type":"string","enum":["session.created"],"title":"ChannelsHydraSessionMessagesSessionCreatedType"},"hydraSession_sessionCreated":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionCreatedType"},"event_id":{"type":"string","description":"Server-minted event identifier."},"session_id":{"type":"string","description":"Server-minted session identifier, stable for the lifetime of the WebSocket."}},"title":"hydraSession_sessionCreated"},"ChannelsHydraSessionMessagesSessionConfiguredType":{"type":"string","enum":["session.configured"],"title":"ChannelsHydraSessionMessagesSessionConfiguredType"},"ToolType":{"type":"string","enum":["function"],"title":"ToolType"},"ToolParameters":{"type":"object","properties":{},"description":"JSON Schema for the tool's parameters.","title":"ToolParameters"},"Tool":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ToolType"},"name":{"type":"string"},"description":{"type":"string"},"parameters":{"$ref":"#/components/schemas/ToolParameters","description":"JSON Schema for the tool's parameters."}},"required":["type","name"],"title":"Tool"},"ChannelsHydraSessionMessagesSessionConfiguredSession":{"type":"object","properties":{"instructions":{"type":"string"},"voice":{"type":"string"},"tools":{"type":"array","items":{"$ref":"#/components/schemas/Tool"}},"generate_initial_response":{"type":"boolean"},"output_audio_sample_rate":{"type":"integer","description":"The output sample rate actually applied. Always present on `hydra-v1.1`; `48000` on `hydra-v1.0`."}},"description":"Effective session configuration as accepted by the server. Echoes the fields the server applied:\n`instructions`, `voice`, `tools`, `generate_initial_response`, `output_audio_sample_rate`.\n","title":"ChannelsHydraSessionMessagesSessionConfiguredSession"},"hydraSession_sessionConfigured":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionConfiguredType"},"event_id":{"type":"string"},"session":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionConfiguredSession","description":"Effective session configuration as accepted by the server. Echoes the fields the server applied:\n`instructions`, `voice`, `tools`, `generate_initial_response`, `output_audio_sample_rate`.\n"}},"title":"hydraSession_sessionConfigured"},"ChannelsHydraSessionMessagesSessionUpdatedType":{"type":"string","enum":["session.updated"],"title":"ChannelsHydraSessionMessagesSessionUpdatedType"},"ChannelsHydraSessionMessagesSessionUpdatedSession":{"type":"object","properties":{},"description":"Echo containing only the fields that were applied. A no-op patch produces no echo.","title":"ChannelsHydraSessionMessagesSessionUpdatedSession"},"hydraSession_sessionUpdated":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionUpdatedType"},"event_id":{"type":"string"},"session":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionUpdatedSession","description":"Echo containing only the fields that were applied. A no-op patch produces no echo."}},"title":"hydraSession_sessionUpdated"},"ChannelsHydraSessionMessagesInputAudioBufferSpeechStartedType":{"type":"string","enum":["input_audio_buffer.speech_started"],"title":"ChannelsHydraSessionMessagesInputAudioBufferSpeechStartedType"},"hydraSession_inputAudioBufferSpeechStarted":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesInputAudioBufferSpeechStartedType"},"event_id":{"type":"string"},"audio_start_ms":{"type":"integer","description":"Offset (in ms) from session start when speech was detected."},"item_id":{"type":"string","description":"ID of the user message item that will be created when the turn ends."}},"title":"hydraSession_inputAudioBufferSpeechStarted"},"ChannelsHydraSessionMessagesInputAudioBufferSpeechStoppedType":{"type":"string","enum":["input_audio_buffer.speech_stopped"],"title":"ChannelsHydraSessionMessagesInputAudioBufferSpeechStoppedType"},"hydraSession_inputAudioBufferSpeechStopped":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesInputAudioBufferSpeechStoppedType"},"event_id":{"type":"string"},"audio_end_ms":{"type":"integer"},"item_id":{"type":"string"}},"title":"hydraSession_inputAudioBufferSpeechStopped"},"ChannelsHydraSessionMessagesConversationItemAddedType":{"type":"string","enum":["conversation.item.added"],"title":"ChannelsHydraSessionMessagesConversationItemAddedType"},"ConversationItemType":{"type":"string","enum":["message","function_call","function_call_output"],"title":"ConversationItemType"},"ConversationItemRole":{"type":"string","enum":["user","assistant","system"],"title":"ConversationItemRole"},"ConversationItemStatus":{"type":"string","enum":["in_progress","completed","incomplete"],"title":"ConversationItemStatus"},"ConversationItemContentItemsType":{"type":"string","enum":["input_audio","input_text","output_audio","output_text"],"title":"ConversationItemContentItemsType"},"ConversationItemContentItems":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ConversationItemContentItemsType"},"text":{"type":"string","description":"For audio message items, `text` is always `null`. Audio bytes are the payload. The field exists for `function_call_output` and other text-bearing items."}},"title":"ConversationItemContentItems"},"ConversationItem":{"type":"object","properties":{"id":{"type":"string"},"type":{"$ref":"#/components/schemas/ConversationItemType"},"role":{"$ref":"#/components/schemas/ConversationItemRole"},"status":{"$ref":"#/components/schemas/ConversationItemStatus"},"content":{"type":"array","items":{"$ref":"#/components/schemas/ConversationItemContentItems"}},"call_id":{"type":"string","description":"`function_call` / `function_call_output` only."},"name":{"type":"string","description":"`function_call` only."},"arguments":{"type":"string","description":"`function_call` only. JSON-encoded argument string."},"output":{"type":"string","description":"`function_call_output` only. Your tool result."}},"description":"Carried by most conversation events. The shape is intentionally flat. Every field is optional; presence is dictated by `type`.","title":"ConversationItem"},"hydraSession_conversationItemAdded":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesConversationItemAddedType"},"event_id":{"type":"string"},"previous_item_id":{"type":"string","description":"ID of the item immediately preceding this one in the conversation log."},"item":{"$ref":"#/components/schemas/ConversationItem"}},"title":"hydraSession_conversationItemAdded"},"ChannelsHydraSessionMessagesConversationItemDoneType":{"type":"string","enum":["conversation.item.done"],"title":"ChannelsHydraSessionMessagesConversationItemDoneType"},"hydraSession_conversationItemDone":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesConversationItemDoneType"},"event_id":{"type":"string"},"previous_item_id":{"type":"string"},"item":{"$ref":"#/components/schemas/ConversationItem"}},"title":"hydraSession_conversationItemDone"},"ChannelsHydraSessionMessagesResponseCreatedType":{"type":"string","enum":["response.created"],"title":"ChannelsHydraSessionMessagesResponseCreatedType"},"ChannelsHydraSessionMessagesResponseCreatedResponse":{"type":"object","properties":{"id":{"type":"string"}},"title":"ChannelsHydraSessionMessagesResponseCreatedResponse"},"hydraSession_responseCreated":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseCreatedType"},"event_id":{"type":"string"},"response":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseCreatedResponse"}},"title":"hydraSession_responseCreated"},"ChannelsHydraSessionMessagesResponseOutputAudioDeltaType":{"type":"string","enum":["response.output_audio.delta"],"title":"ChannelsHydraSessionMessagesResponseOutputAudioDeltaType"},"hydraSession_responseOutputAudioDelta":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseOutputAudioDeltaType"},"event_id":{"type":"string"},"response_id":{"type":"string"},"item_id":{"type":"string"},"output_index":{"type":"integer"},"content_index":{"type":"integer"},"delta":{"type":"string","description":"Base64-encoded PCM16 audio chunk at the negotiated output sample rate."}},"title":"hydraSession_responseOutputAudioDelta"},"ChannelsHydraSessionMessagesResponseOutputAudioDoneType":{"type":"string","enum":["response.output_audio.done"],"title":"ChannelsHydraSessionMessagesResponseOutputAudioDoneType"},"hydraSession_responseOutputAudioDone":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseOutputAudioDoneType"},"event_id":{"type":"string"},"response_id":{"type":"string"},"item_id":{"type":"string"},"output_index":{"type":"integer"},"content_index":{"type":"integer"}},"title":"hydraSession_responseOutputAudioDone"},"ChannelsHydraSessionMessagesResponseFunctionCallArgumentsDeltaType":{"type":"string","enum":["response.function_call_arguments.delta"],"title":"ChannelsHydraSessionMessagesResponseFunctionCallArgumentsDeltaType"},"hydraSession_responseFunctionCallArgumentsDelta":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseFunctionCallArgumentsDeltaType"},"event_id":{"type":"string"},"response_id":{"type":"string"},"call_id":{"type":"string"},"name":{"type":"string","description":"Tool name (present on first delta)."},"delta":{"type":"string","description":"Streaming JSON fragment of the arguments. Concatenate per `call_id`."}},"title":"hydraSession_responseFunctionCallArgumentsDelta"},"ChannelsHydraSessionMessagesResponseFunctionCallArgumentsDoneType":{"type":"string","enum":["response.function_call_arguments.done"],"title":"ChannelsHydraSessionMessagesResponseFunctionCallArgumentsDoneType"},"hydraSession_responseFunctionCallArgumentsDone":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseFunctionCallArgumentsDoneType"},"event_id":{"type":"string"},"response_id":{"type":"string"},"call_id":{"type":"string"},"name":{"type":"string"},"arguments":{"type":"string","description":"Full arguments JSON. Parse with `JSON.parse` / `json.loads` before passing to your tool."}},"title":"hydraSession_responseFunctionCallArgumentsDone"},"ChannelsHydraSessionMessagesResponseDoneType":{"type":"string","enum":["response.done"],"title":"ChannelsHydraSessionMessagesResponseDoneType"},"ChannelsHydraSessionMessagesResponseDoneResponseStatus":{"type":"string","enum":["completed","cancelled","incomplete","failed"],"title":"ChannelsHydraSessionMessagesResponseDoneResponseStatus"},"ChannelsHydraSessionMessagesResponseDoneResponseStatusDetailsReason":{"type":"string","enum":["interrupted","client_cancelled","max_output_tokens","content_filter"],"title":"ChannelsHydraSessionMessagesResponseDoneResponseStatusDetailsReason"},"ChannelsHydraSessionMessagesResponseDoneResponseStatusDetailsError":{"type":"object","properties":{"code":{"type":"string"},"type":{"type":"string"}},"title":"ChannelsHydraSessionMessagesResponseDoneResponseStatusDetailsError"},"ChannelsHydraSessionMessagesResponseDoneResponseStatusDetails":{"type":"object","properties":{"reason":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneResponseStatusDetailsReason"},"type":{"type":"string"},"error":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneResponseStatusDetailsError"}},"title":"ChannelsHydraSessionMessagesResponseDoneResponseStatusDetails"},"ChannelsHydraSessionMessagesResponseDoneResponseUsage":{"type":"object","properties":{"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}},"title":"ChannelsHydraSessionMessagesResponseDoneResponseUsage"},"ChannelsHydraSessionMessagesResponseDoneResponse":{"type":"object","properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneResponseStatus"},"status_details":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneResponseStatusDetails"},"output":{"type":"array","items":{"$ref":"#/components/schemas/ConversationItem"}},"usage":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneResponseUsage"}},"title":"ChannelsHydraSessionMessagesResponseDoneResponse"},"hydraSession_responseDone":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneType"},"event_id":{"type":"string"},"response":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseDoneResponse"}},"title":"hydraSession_responseDone"},"ChannelsHydraSessionMessagesErrorEventType":{"type":"string","enum":["error"],"title":"ChannelsHydraSessionMessagesErrorEventType"},"ChannelsHydraSessionMessagesErrorEventErrorCode":{"type":"string","enum":["invalid_request_error","invalid_audio","tool_response_timeout","server_full","internal_error"],"title":"ChannelsHydraSessionMessagesErrorEventErrorCode"},"ChannelsHydraSessionMessagesErrorEventError":{"type":"object","properties":{"type":{"type":"string"},"code":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesErrorEventErrorCode"},"message":{"type":"string"},"param":{"type":"string"},"event_id":{"type":"string","description":"When present, the `event_id` of the client frame that triggered the error."}},"title":"ChannelsHydraSessionMessagesErrorEventError"},"hydraSession_errorEvent":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesErrorEventType"},"event_id":{"type":"string"},"error":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesErrorEventError"}},"title":"hydraSession_errorEvent"},"ChannelsHydraSessionMessagesSessionConfigureType":{"type":"string","enum":["session.configure"],"title":"ChannelsHydraSessionMessagesSessionConfigureType"},"SessionConfigVoice":{"type":"string","enum":["zoe","maya","elena","ivy","grace","alex","aria","leo","sam","kai","arabella","cressida","elowen","sophie","callum","caspian","cormac","everett","rupert","vaughn","brooks","cole","hayes","pierce","sterling","ellis","lane","quinn","arden","rowan","blair","emery","sawyer"],"description":"Voice identifier. The roster is per model version and the rosters do not overlap:\n\n- `?model=hydra-v1.1` (current release), nineteen voices: `zoe`, `maya`, `elena`, `ivy`, `grace`, `alex`, `aria`, `leo`, `sam`, `kai`, plus nine British English voices - `arabella`, `cressida`, `elowen`, `sophie` (female) and `callum`, `caspian`, `cormac`, `everett`, `rupert` (male).\n- `?model=hydra-v1.0`, fourteen voices: `vaughn`, `brooks`, `cole`, `hayes`, `pierce`, `sterling`, `ellis`, `lane`, `quinn`, `arden`, `rowan`, `blair`, `emery`, `sawyer`.\n- `?model=hydra` (original release, deprecated): migrate to one of the tags above and pick a voice from its roster.\n\nOmit the field to use the server default voice. An unrecognised voice is **rejected, not defaulted**. The server replies with an `error` frame carrying `code: \"invalid_request_error\"` and `param: \"session.configure.session.voice\"`, so validate client-side. The enum above is the union of the two supported rosters; AsyncAPI cannot express a constraint conditioned on a server query parameter. See the [Hydra model card](/model-cards/speech-to-speech/hydra) for the per-version table.\n","title":"SessionConfigVoice"},"SessionConfigOutputAudioSampleRate":{"type":"string","enum":["8000","16000","22050","24000","32000","44100","48000"],"description":"`hydra-v1.1` only. Sample rate, in Hz, for `response.output_audio.delta` chunks. Defaults to `24000` if omitted. Frozen at handshake, like `voice`.\n\nThe rate actually applied is echoed on `session.configured.session.output_audio_sample_rate` - read it from there rather than assuming the requested value was honored. An unsupported value is rejected with an `error` frame (`code: \"invalid_request_error\"`, `param: \"session.configure.session.output_audio_sample_rate\"`). `hydra-v1.0` does not support this field; its output stays fixed at `48000`.\n","title":"SessionConfigOutputAudioSampleRate"},"SessionConfig":{"type":"object","properties":{"instructions":{"type":"string","description":"Persona / system prompt that defines the assistant's behaviour."},"voice":{"$ref":"#/components/schemas/SessionConfigVoice","description":"Voice identifier. The roster is per model version and the rosters do not overlap:\n\n- `?model=hydra-v1.1` (current release), nineteen voices: `zoe`, `maya`, `elena`, `ivy`, `grace`, `alex`, `aria`, `leo`, `sam`, `kai`, plus nine British English voices - `arabella`, `cressida`, `elowen`, `sophie` (female) and `callum`, `caspian`, `cormac`, `everett`, `rupert` (male).\n- `?model=hydra-v1.0`, fourteen voices: `vaughn`, `brooks`, `cole`, `hayes`, `pierce`, `sterling`, `ellis`, `lane`, `quinn`, `arden`, `rowan`, `blair`, `emery`, `sawyer`.\n- `?model=hydra` (original release, deprecated): migrate to one of the tags above and pick a voice from its roster.\n\nOmit the field to use the server default voice. An unrecognised voice is **rejected, not defaulted**. The server replies with an `error` frame carrying `code: \"invalid_request_error\"` and `param: \"session.configure.session.voice\"`, so validate client-side. The enum above is the union of the two supported rosters; AsyncAPI cannot express a constraint conditioned on a server query parameter. See the [Hydra model card](/model-cards/speech-to-speech/hydra) for the per-version table.\n"},"tools":{"type":"array","items":{"$ref":"#/components/schemas/Tool"},"description":"Function-calling tool schemas the model may invoke."},"generate_initial_response":{"type":"boolean","description":"When `true`, the model speaks first instead of waiting for user input. Honoured only at handshake."},"output_audio_sample_rate":{"$ref":"#/components/schemas/SessionConfigOutputAudioSampleRate","description":"`hydra-v1.1` only. Sample rate, in Hz, for `response.output_audio.delta` chunks. Defaults to `24000` if omitted. Frozen at handshake, like `voice`.\n\nThe rate actually applied is echoed on `session.configured.session.output_audio_sample_rate` - read it from there rather than assuming the requested value was honored. An unsupported value is rejected with an `error` frame (`code: \"invalid_request_error\"`, `param: \"session.configure.session.output_audio_sample_rate\"`). `hydra-v1.0` does not support this field; its output stays fixed at `48000`.\n"}},"description":"Sent inside the client's `session.configure` frame and echoed inside the server's `session.configured` frame. All fields optional. Omitted fields fall back to the server default.","title":"SessionConfig"},"hydraSession_sessionConfigure":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionConfigureType"},"event_id":{"type":"string","description":"Optional client-generated event identifier. UUIDs recommended so server errors can reference the originating frame."},"session":{"$ref":"#/components/schemas/SessionConfig"}},"required":["type","session"],"title":"hydraSession_sessionConfigure"},"ChannelsHydraSessionMessagesSessionUpdateType":{"type":"string","enum":["session.update"],"title":"ChannelsHydraSessionMessagesSessionUpdateType"},"ChannelsHydraSessionMessagesSessionUpdateSession":{"type":"object","properties":{"tools":{"type":"array","items":{"$ref":"#/components/schemas/Tool"}}},"description":"Mid-session live patch. Only `tools` is honoured today; persona, voice, and audio formats are frozen at handshake.","title":"ChannelsHydraSessionMessagesSessionUpdateSession"},"hydraSession_sessionUpdate":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionUpdateType"},"session":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesSessionUpdateSession","description":"Mid-session live patch. Only `tools` is honoured today; persona, voice, and audio formats are frozen at handshake."}},"required":["type","session"],"title":"hydraSession_sessionUpdate"},"ChannelsHydraSessionMessagesInputAudioBufferAppendType":{"type":"string","enum":["input_audio_buffer.append"],"title":"ChannelsHydraSessionMessagesInputAudioBufferAppendType"},"hydraSession_inputAudioBufferAppend":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesInputAudioBufferAppendType"},"audio":{"type":"string","description":"Base64-encoded PCM16 audio chunk. Signed little-endian, mono, 16 kHz. Recommended chunk size: 20–40 ms (640–1280 samples)."}},"required":["type","audio"],"title":"hydraSession_inputAudioBufferAppend"},"ChannelsHydraSessionMessagesConversationItemCreateType":{"type":"string","enum":["conversation.item.create"],"title":"ChannelsHydraSessionMessagesConversationItemCreateType"},"hydraSession_conversationItemCreate":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesConversationItemCreateType"},"item":{"$ref":"#/components/schemas/ConversationItem"}},"required":["type","item"],"title":"hydraSession_conversationItemCreate"},"ChannelsHydraSessionMessagesResponseCreateType":{"type":"string","enum":["response.create"],"title":"ChannelsHydraSessionMessagesResponseCreateType"},"ChannelsHydraSessionMessagesResponseCreateResponse":{"type":"object","properties":{},"description":"Optional response shaping. Body is optional. Send an empty `response.create` after posting all tool outputs to request narration.","title":"ChannelsHydraSessionMessagesResponseCreateResponse"},"hydraSession_responseCreate":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseCreateType"},"response":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseCreateResponse","description":"Optional response shaping. Body is optional. Send an empty `response.create` after posting all tool outputs to request narration."}},"required":["type"],"title":"hydraSession_responseCreate"},"ChannelsHydraSessionMessagesResponseCancelType":{"type":"string","enum":["response.cancel"],"title":"ChannelsHydraSessionMessagesResponseCancelType"},"hydraSession_responseCancel":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ChannelsHydraSessionMessagesResponseCancelType"},"response_id":{"type":"string","description":"Optional. Target a specific in-flight response. No-op if no response is in flight."}},"required":["type"],"title":"hydraSession_responseCancel"}}}}