# Soniox docs Documentation from the [docs.soniox.com](https://docs.soniox.com) website. ## Links to docs content pages: - [AI engineering](https://docs.soniox.com/ai-engineering) - [Create temporary API key](https://docs.soniox.com/api-reference/auth/create_temporary_api_key) - [Errors](https://docs.soniox.com/api-reference/errors) - [Soniox API reference](https://docs.soniox.com/api-reference) - [Create a project API key](https://docs.soniox.com/api-reference/organization/create_organization_project_api_key) - [Delete a project API key](https://docs.soniox.com/api-reference/organization/delete_organization_project_api_key) - [Get the organization](https://docs.soniox.com/api-reference/organization/get_organization) - [Get the organization balance](https://docs.soniox.com/api-reference/organization/get_organization_balance) - [Get the organization limits](https://docs.soniox.com/api-reference/organization/get_organization_limits) - [Get the organization's usage for a month](https://docs.soniox.com/api-reference/organization/get_organization_monthly_usage) - [List a project's API keys](https://docs.soniox.com/api-reference/organization/get_organization_project_api_keys) - [List the organization's projects](https://docs.soniox.com/api-reference/organization/get_organization_projects) - [Get the organization's usage summary](https://docs.soniox.com/api-reference/organization/get_organization_usage_summary) - [Get concurrency limits](https://docs.soniox.com/api-reference/other/get_concurrency_limits) - [Get concurrent streams history](https://docs.soniox.com/api-reference/other/get_concurrent_streams_history) - [Get usage logs](https://docs.soniox.com/api-reference/other/get_usage_logs) - [Get usage summary](https://docs.soniox.com/api-reference/other/get_usage_summary) - [Delete file](https://docs.soniox.com/api-reference/stt/files/delete_file) - [Get file](https://docs.soniox.com/api-reference/stt/files/get_file) - [Get files](https://docs.soniox.com/api-reference/stt/files/get_files) - [Get files count](https://docs.soniox.com/api-reference/stt/files/get_files_count) - [Upload file](https://docs.soniox.com/api-reference/stt/files/upload_file) - [Get models](https://docs.soniox.com/api-reference/stt/get_models) - [Create transcription](https://docs.soniox.com/api-reference/stt/transcriptions/create_transcription) - [Delete transcription](https://docs.soniox.com/api-reference/stt/transcriptions/delete_transcription) - [Get transcription](https://docs.soniox.com/api-reference/stt/transcriptions/get_transcription) - [Get transcription transcript](https://docs.soniox.com/api-reference/stt/transcriptions/get_transcription_transcript) - [Get transcriptions](https://docs.soniox.com/api-reference/stt/transcriptions/get_transcriptions) - [Get transcriptions count](https://docs.soniox.com/api-reference/stt/transcriptions/get_transcriptions_count) - [WebSocket API](https://docs.soniox.com/api-reference/stt/websocket-api) - [Generate speech](https://docs.soniox.com/api-reference/tts/generate_tts) - [Get shared voices](https://docs.soniox.com/api-reference/tts/get_shared_voices) - [Get TTS models](https://docs.soniox.com/api-reference/tts/get_tts_models) - [Create voice](https://docs.soniox.com/api-reference/tts/voices/create_voice) - [Delete voice](https://docs.soniox.com/api-reference/tts/voices/delete_voice) - [Get voice](https://docs.soniox.com/api-reference/tts/voices/get_voice) - [Get voices](https://docs.soniox.com/api-reference/tts/voices/get_voices) - [Get voices count](https://docs.soniox.com/api-reference/tts/voices/get_voices_count) - [Recompute voice](https://docs.soniox.com/api-reference/tts/voices/recompute_voice) - [WebSocket API](https://docs.soniox.com/api-reference/tts/websocket-api) - [Community and support](https://docs.soniox.com/community-and-support) - [Account and organization deletion](https://docs.soniox.com/console/account-deletion) - [Console](https://docs.soniox.com/console) - [Limits](https://docs.soniox.com/console/limits) - [Members and roles](https://docs.soniox.com/console/members-and-roles) - [Projects and regions](https://docs.soniox.com/console/projects) - [Data residency](https://docs.soniox.com/data-residency) - [Soniox Live](https://docs.soniox.com/demo-apps/soniox-live) - [Speech-to-speech translation](https://docs.soniox.com/demo-apps/soniox-speech-to-speech-translation) - [Soniox Voice Agent](https://docs.soniox.com/demo-apps/soniox-voice-agent) - [FAQ](https://docs.soniox.com/faq) - [API key permissions](https://docs.soniox.com/guides/api-key-permissions) - [Concurrency limits](https://docs.soniox.com/guides/concurrency-limits) - [Direct stream](https://docs.soniox.com/guides/direct-stream) - [Guides](https://docs.soniox.com/guides) - [Migrate WebSocket authentication](https://docs.soniox.com/guides/migrate-websocket-authentication) - [Organization API](https://docs.soniox.com/guides/organization-api) - [Proxy stream](https://docs.soniox.com/guides/proxy-stream) - [Temporary API keys](https://docs.soniox.com/guides/temporary-api-keys) - [Usage logs](https://docs.soniox.com/guides/usage-logs) - [Usage summary](https://docs.soniox.com/guides/usage-summary) - [WebSocket authentication](https://docs.soniox.com/guides/websocket-authentication) - [Overview](https://docs.soniox.com/) - [Community integrations](https://docs.soniox.com/integrations/community-integrations) - [Integrations](https://docs.soniox.com/integrations) - [LangChain.js (JavaScript)](https://docs.soniox.com/integrations/langchain/langchain-js) - [LangChain (Python)](https://docs.soniox.com/integrations/langchain/langchain) - [LiveKit](https://docs.soniox.com/integrations/livekit) - [Switch your LiveKit STT or TTS provider to Soniox](https://docs.soniox.com/integrations/livekit/migrate) - [Speech-to-Text](https://docs.soniox.com/integrations/livekit/stt) - [Text-to-Speech](https://docs.soniox.com/integrations/livekit/tts) - [Build a voice agent with LiveKit and Soniox](https://docs.soniox.com/integrations/livekit/voice-agent) - [n8n](https://docs.soniox.com/integrations/n8n) - [Pipecat](https://docs.soniox.com/integrations/pipecat) - [Switch your Pipecat STT or TTS provider to Soniox](https://docs.soniox.com/integrations/pipecat/migrate) - [Speech-to-Text](https://docs.soniox.com/integrations/pipecat/stt) - [Text-to-Speech](https://docs.soniox.com/integrations/pipecat/tts) - [Build a voice agent with Pipecat and Soniox](https://docs.soniox.com/integrations/pipecat/voice-agent) - [Retell AI](https://docs.soniox.com/integrations/retell) - [TanStack AI SDK](https://docs.soniox.com/integrations/tanstack-ai-sdk) - [Telnyx](https://docs.soniox.com/integrations/telnyx) - [Speech-to-Text](https://docs.soniox.com/integrations/telnyx/stt) - [Text-to-Speech](https://docs.soniox.com/integrations/telnyx/tts) - [Twilio](https://docs.soniox.com/integrations/twilio) - [Vapi](https://docs.soniox.com/integrations/vapi) - [Vercel AI SDK](https://docs.soniox.com/integrations/vercel-ai-sdk) - [SDKs](https://docs.soniox.com/sdk) - [Node SDK](https://docs.soniox.com/sdk/node-SDK) - [Classes](https://docs.soniox.com/sdk/node-SDK/reference/classes) - [Full Node SDK reference](https://docs.soniox.com/sdk/node-SDK/reference) - [Types](https://docs.soniox.com/sdk/node-SDK/reference/types) - [Async transcription with Node SDK](https://docs.soniox.com/sdk/node-SDK/stt/async-transcription) - [Async translation with Node SDK](https://docs.soniox.com/sdk/node-SDK/stt/async-translation) - [Handling files with Node SDK](https://docs.soniox.com/sdk/node-SDK/stt/files) - [Real-time transcription with Node SDK](https://docs.soniox.com/sdk/node-SDK/stt/realtime-transcription) - [Handling webhooks with Node SDK](https://docs.soniox.com/sdk/node-SDK/stt/webhooks) - [Real-time speech generation with Node SDK](https://docs.soniox.com/sdk/node-SDK/tts/realtime-speech-generation) - [REST speech generation with Node SDK](https://docs.soniox.com/sdk/node-SDK/tts/rest-speech-generation) - [Async Client](https://docs.soniox.com/sdk/python-SDK/Full-SDK-reference/async_client) - [Errors](https://docs.soniox.com/sdk/python-SDK/Full-SDK-reference/errors) - [Realtime Client](https://docs.soniox.com/sdk/python-SDK/Full-SDK-reference/realtime_client) - [Types](https://docs.soniox.com/sdk/python-SDK/Full-SDK-reference/types) - [Helpers](https://docs.soniox.com/sdk/python-SDK/Full-SDK-reference/utils) - [Python SDK](https://docs.soniox.com/sdk/python-SDK) - [Async transcription with Python SDK](https://docs.soniox.com/sdk/python-SDK/stt/async-transcription) - [Handling files with Python SDK](https://docs.soniox.com/sdk/python-SDK/stt/files) - [Real-time transcription with Python SDK](https://docs.soniox.com/sdk/python-SDK/stt/realtime-transcription) - [Handling webhooks with Python SDK](https://docs.soniox.com/sdk/python-SDK/stt/webhooks) - [Sync vs async clients](https://docs.soniox.com/sdk/python-SDK/sync-vs-async-clients) - [Real-time speech generation with Python SDK](https://docs.soniox.com/sdk/python-SDK/tts/realtime-speech-generation) - [REST speech generation with Python SDK](https://docs.soniox.com/sdk/python-SDK/tts/rest-speech-generation) - [React SDK](https://docs.soniox.com/sdk/react-SDK) - [Full React SDK reference](https://docs.soniox.com/sdk/react-SDK/reference) - [Types](https://docs.soniox.com/sdk/react-SDK/reference/types) - [Real-time transcription with React SDK](https://docs.soniox.com/sdk/react-SDK/stt/realtime-transcription) - [Real-time speech generation with React SDK](https://docs.soniox.com/sdk/react-SDK/tts/realtime-speech-generation) - [React Native SDK](https://docs.soniox.com/sdk/react-native-SDK) - [Web SDK](https://docs.soniox.com/sdk/web-SDK) - [Classes](https://docs.soniox.com/sdk/web-SDK/reference/classes) - [Full Web SDK reference](https://docs.soniox.com/sdk/web-SDK/reference) - [Types](https://docs.soniox.com/sdk/web-SDK/reference/types) - [Real-time transcription with Web SDK](https://docs.soniox.com/sdk/web-SDK/stt/realtime-transcription) - [Real-time speech generation with Web SDK](https://docs.soniox.com/sdk/web-SDK/tts/realtime-speech-generation) - [REST speech generation with Web SDK](https://docs.soniox.com/sdk/web-SDK/tts/rest-speech-generation) - [Security and privacy](https://docs.soniox.com/security-and-privacy) - [Async transcription](https://docs.soniox.com/stt/async/async-transcription) - [Error handling](https://docs.soniox.com/stt/async/error-handling) - [Limits & quotas](https://docs.soniox.com/stt/async/limits-and-quotas) - [Webhooks](https://docs.soniox.com/stt/async/webhooks) - [Confidence scores](https://docs.soniox.com/stt/concepts/confidence-scores) - [Context](https://docs.soniox.com/stt/concepts/context) - [Language hints](https://docs.soniox.com/stt/concepts/language-hints) - [Language identification](https://docs.soniox.com/stt/concepts/language-identification) - [Language restrictions](https://docs.soniox.com/stt/concepts/language-restrictions) - [Speaker diarization](https://docs.soniox.com/stt/concepts/speaker-diarization) - [Supported languages](https://docs.soniox.com/stt/concepts/supported-languages) - [Timestamps](https://docs.soniox.com/stt/concepts/timestamps) - [Get started](https://docs.soniox.com/stt/get-started) - [Models](https://docs.soniox.com/stt/models) - [Connection keepalive](https://docs.soniox.com/stt/rt/connection-keepalive) - [Endpoint detection](https://docs.soniox.com/stt/rt/endpoint-detection) - [Error handling](https://docs.soniox.com/stt/rt/error-handling) - [Limits & quotas](https://docs.soniox.com/stt/rt/limits-and-quotas) - [Manual finalization](https://docs.soniox.com/stt/rt/manual-finalization) - [Real-time transcription](https://docs.soniox.com/stt/rt/real-time-transcription) - [Get started](https://docs.soniox.com/translation/get-started) - [Real-time speech-to-speech translation](https://docs.soniox.com/translation/sts-translation) - [Async speech-to-text translation](https://docs.soniox.com/translation/stt-translation/async-translation) - [Speech-to-text translation](https://docs.soniox.com/translation/stt-translation) - [Real-time speech-to-text translation](https://docs.soniox.com/translation/stt-translation/rt-translation) - [Supported languages](https://docs.soniox.com/translation/supported-languages) - [Audio formats](https://docs.soniox.com/tts/concepts/audio-formats) - [Emotion & tone](https://docs.soniox.com/tts/concepts/emotion-and-tone) - [Language mixing](https://docs.soniox.com/tts/concepts/language-mixing) - [Reduce silence](https://docs.soniox.com/tts/concepts/reduce-silence) - [Speech speed](https://docs.soniox.com/tts/concepts/speech-speed) - [Supported languages](https://docs.soniox.com/tts/concepts/supported-languages) - [Voice cloning](https://docs.soniox.com/tts/concepts/voice-cloning) - [Voices](https://docs.soniox.com/tts/concepts/voices) - [Get started](https://docs.soniox.com/tts/get-started) - [Models](https://docs.soniox.com/tts/models) - [Generate speech](https://docs.soniox.com/tts/rest-api/generate-speech) - [Limits & quotas](https://docs.soniox.com/tts/rest-api/limits-and-quotas) - [Connection keepalive](https://docs.soniox.com/tts/rt/connection-keepalive) - [Limits & quotas](https://docs.soniox.com/tts/rt/limits-and-quotas) - [Real-time generation](https://docs.soniox.com/tts/rt/real-time-generation) - [Streams](https://docs.soniox.com/tts/rt/streams) - [Stream termination](https://docs.soniox.com/tts/rt/termination) - [Timestamps](https://docs.soniox.com/tts/rt/timestamps) # AI engineering URL: /ai-engineering Using MCP, AI assistant, and LLMs with Soniox for AI-powered development import Image from "next/image"; Soniox provides easy-to-use AI tools that help you explore documentation, generate code, and get guidance, even if you're new to programming. These tools work directly with your coding environment, so you can focus on building instead of searching for answers. With Soniox AI engineering, you can: * Browse documentation via the **MCP server** without leaving your coding tools * Ask the **AI assistant** for explanations, examples, or code help * Use **LLM context files** so AI models understand Soniox APIs and examples * Copy page content or open it directly in your preferred AI tool These features reduce friction, help you learn faster, and make working with Soniox APIs simple and efficient. *** ## MCP server The **MCP server** lets you access Soniox documentation right from tools like Cursor, Windsurf, or Claude Code. You can search guides, view examples, and explore APIs without switching windows. ### Available tools The Soniox MCP server exposes the following tools to your AI assistant: Search Soniox documentation by natural-language query. Use this first to find focused pages and headings before reading a page or section. **Inputs** * `query` (string, required) – natural-language search query. * `limit` (integer, optional) – maximum number of results to return (1–10). Read a specific Soniox documentation page by URL. Accepts relative URLs (e.g. `/stt/get-started`) and absolute URLs (e.g. `https://docs.soniox.com/stt/get-started`). Use `soniox_search_docs` first unless the URL is already known. **Inputs** * `url` (string, required) – page URL to read. Read one section from a Soniox documentation page by URL plus heading or anchor. Use `soniox_search_docs` first when the URL or heading is unknown. **Inputs** * `url` (string, required) – page URL to read from. * `heading` (string, optional) – heading text within the page. * `anchor` (string, optional) – anchor identifier within the page. Get the table of contents for broad Soniox documentation navigation. Use `soniox_search_docs` for natural-language search instead. Get a concise overview of Soniox documentation (`llms.txt`) for background on features, APIs, and concepts. Use `soniox_search_docs` when looking for a specific answer. Last resort: get the full content of all Soniox documentation pages (\~100k tokens). This is very large — prefer `soniox_search_docs`, then `soniox_read_section` or `soniox_read_page`.
### How to set it up Pick your AI tool below and follow the steps to connect the Soniox MCP server. Open **Cursor settings → Tools & MCPs** and click **New MCP Server**, or edit `~/.cursor/mcp.json` directly and add the following entry: ```json title="~/.cursor/mcp.json" { "mcpServers": { "soniox-docs": { "url": "https://docs.soniox.com/api/mcp/mcp" } } } ``` Prefer a one-click install? Use the button below:
[![Install MCP Server](https://cursor.com/deeplink/mcp-install-light.svg)](https://cursor.com/en/install-mcp?name=soniox-docs\&config=eyJjb21tYW5kIjoibnB4IC15IG1jcC1yZW1vdGUgaHR0cHM6Ly9zb25pb3guY29tL2RvY3MvYXBpL21jcC9tY3AifQ%3D%3D)
[![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=soniox-docs\&config=eyJjb21tYW5kIjoibnB4IC15IG1jcC1yZW1vdGUgaHR0cHM6Ly9zb25pb3guY29tL2RvY3MvYXBpL21jcC9tY3AifQ%3D%3D)
Open Claude Desktop and click **Customize** in the left sidebar. In the Customize panel, select **Connectors**. Click the **+** button and choose **Add custom connector**. Give it a name (for example, `Soniox docs`) and paste the server URL below: ```text title="Server URL" https://docs.soniox.com/api/mcp/mcp ``` Open [ChatGPT](https://chatgpt.com/) and go to **Settings**. Navigate to **Connectors** → **Developer mode**. Click **Add MCP server**. Paste the server URL below and click **Add**: ```text title="Server URL" https://docs.soniox.com/api/mcp/mcp ``` Codex accepts a remote MCP server through a built-in form — no config file to edit. Go to **Settings → MCP Servers**. Click **Add server**. Select **Streamable HTTP**. Paste the URL below into the **URL** field and save: ```text title="Server URL" https://docs.soniox.com/api/mcp/mcp ``` In Windsurf, open **Settings → Cascade → MCP Servers**. Click the gear icon — `mcp_config.json` opens automatically. Paste the snippet below into the file and save: ```json title="mcp_config.json" { "mcpServers": { "soniox-docs": { "serverUrl": "https://docs.soniox.com/api/mcp/mcp" } } } ``` Open Zed's agent panel. Click the **…** button at the top-right of the panel, then **Add MCP Server**. In the new window, click **Remote**. Paste the snippet below and save: ```json title="settings.json" { "soniox-docs": { "url": "https://docs.soniox.com/api/mcp/mcp" } } ``` In Antigravity, open the MCP store via the **…** dropdown at the top of the editor's agent panel. Click **Manage MCP Servers → View raw config**. Paste the snippet below into `mcp_config.json` and save: ```json title="mcp_config.json" { "mcpServers": { "soniox-docs": { "serverUrl": "https://docs.soniox.com/api/mcp/mcp" } } } ``` Open [Claude.ai settings](https://claude.ai/settings). Navigate to **Integrations** and click **Add Integration**. Paste the server URL below and click **Connect**: ```text title="Server URL" https://docs.soniox.com/api/mcp/mcp ```
*** ## AI assistant The **Soniox AI assistant** is available directly from the docs. It can: * Answer questions about Soniox APIs * Explain example code or suggest modifications * Provide guidance in context, so you don't need to guess Even if you're new to programming, the AI assistant can help you understand code and API workflows quickly. *** ## LLM context files Soniox provides two files that give AI models context about our APIs and examples: * [llms.txt](/llms.txt) – core context for general tasks * [llms-full.txt](/llms-full.txt) – extended context for advanced workflows Adding these files to your AI tool ensures the model can provide accurate, context-aware help. *** ## Copy and open buttons Copy button At the top of each documentation page, the **Copy page** button makes it easy to bring content into your workflow: * **Copy Markdown** – copy the full page content instantly * **Open in ChatGPT or Claude** – send the page context for live AI interaction These features help you experiment and learn by bringing examples and documentation directly into your coding environment. *** For more information about Soniox products, pricing, or general resources, visit our [website](https://soniox.com/). # Create temporary API key URL: /api-reference/auth/create_temporary_api_key Creates a short-lived API key for specific temporary use cases. The key will automatically expire after the specified duration. Use `single_use` and `max_session_duration_seconds` to limit how the key can be used by a client. See the [Temporary API keys guide](https://docs.soniox.com/guides/temporary-api-keys) for details. ## Create temporary API key **Endpoint:** `POST /v1/auth/temporary-api-key` Creates a short-lived API key for specific temporary use cases. The key will automatically expire after the specified duration. Use `single_use` and `max_session_duration_seconds` to limit how the key can be used by a client. See the [Temporary API keys guide](https://docs.soniox.com/guides/temporary-api-keys) for details. ### Request Body Content-Type: `application/json` (Required) Example (JSON): ```json { "client_reference_id": "reference_id", "expires_in_seconds": 1800, "max_session_duration_seconds": 120, "single_use": true, "usage_type": "transcribe_websocket" } ``` Schema (YAML Structural Definition): ```yaml properties: usage_type: description: Intended usage of the temporary API key. enum: - transcribe_websocket - tts_rt type: string expires_in_seconds: description: Duration in seconds until the temporary API key expires. maximum: 3600 minimum: 1 type: integer client_reference_id: anyOf: - maxLength: 256 type: string - type: 'null' description: Optional tracking identifier string. Does not need to be unique. single_use: anyOf: - type: boolean - type: 'null' description: If true, the temporary API key can be used only once. max_session_duration_seconds: anyOf: - maximum: 18000 minimum: 1 type: integer - type: 'null' description: >- Maximum connection duration in seconds for WebSocket and TTS HTTP streaming endpoints. If exceeded, the connection will be dropped. If not set, no limit is applied. required: - usage_type - expires_in_seconds type: object ``` ### Responses * **201**: Created temporary API key. Example (JSON): ```json { "api_key": "snx_temp_AcsDGHvigal7tHRzzzqJI7EdJ5CFwk9C0PtXN_s_cUKJ.Oo1TyosFa7b3rgAcXA2bayqBFO7667gXROEu0mH0U4vgvlNzCqVGgTzitabbXlK7FKH-sSy0F1NKI1OOJzQaAw.YPj4oA", "expires_at": "2025-02-22T22:47:37.150Z" } ``` Schema (YAML Structural Definition): ```yaml properties: api_key: description: Created temporary API key. type: string expires_at: description: UTC timestamp indicating when generated temporary API key will expire. format: date-time type: string required: - api_key - expires_at type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: One or more body fields are missing or invalid (`usage_type`, `expires_in_seconds` out of range, `client_reference_id` too long, `max_session_duration_seconds` out of range, etc.). Inspect `validation_errors`. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Errors URL: /api-reference/errors Reference for every error type returned by Soniox APIs (REST, async, STT WebSocket, TTS WebSocket, TTS REST), with the cause and how to resolve each one. import { Callout } from "@/components/callout"; import { Badge } from "@openapi/ui/components/method-label"; ## Overview This page documents errors from every Soniox API surface: * **REST API** at `api.soniox.com`: synchronous endpoints for files, transcriptions, speakers, usage logs, temporary API keys, and async transcription submission. * **Async transcription failure**: a job created via `POST /v1/transcriptions` returned `200`, but the transcription itself ends in `status: "failed"` after the audio is downloaded or transcribed. * **STT WebSocket** at `stt-rt.soniox.com`: real-time speech-to-text. * **TTS WebSocket** at `tts-rt.soniox.com/tts-websocket`: real-time text-to-speech. * **TTS REST** at `tts-rt.soniox.com/tts`: single-request text-to-speech. All surfaces share one `error_type` taxonomy. Branch your client code on `error_type`, not on the human-readable message; the wording may change, the slug will not. Every error response carries: * `error_type`: stable, machine-readable identifier. See [API error types](#api-error-types) for the full list. * `request_id`: unique per request. Include it when contacting [support@soniox.com](mailto:support@soniox.com); server logs are keyed on it. * `more_info`: a URL pointing at the section on this page describing the `error_type`. The pattern is `https://soniox.com/docs/api-reference/errors#` with underscores replaced by hyphens. The HTTP status code mapped to each `error_type` is the same on every surface. *** ## Response structure ### REST API response REST API errors return a JSON body with the HTTP status code: ```json { "status_code": 401, "error_type": "unauthenticated", "message": "Incorrect API key provided. You can get an API key at https://console.soniox.com", "validation_errors": [], "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda", "more_info": "https://soniox.com/docs/api-reference/errors#unauthenticated" } ``` HTTP status code, mirrored in the response body for convenience. Stable, machine-readable identifier of the error. Branch on this, not on `message`. See the [error reference](#api-error-types) below for the full list. Human-readable description of the error. Safe to show to operators or log; do not parse or pattern-match against it. Populated when `error_type` is `invalid_request` and the cause is a per-field validation failure. Each entry has `error_type`, `location` (dotted path of the offending field), and `message`. Unique identifier of this request. Server logs are keyed on it, so include it when contacting [support@soniox.com](mailto:support@soniox.com). Link to the section on this page describing the `error_type`. The URL pattern is `https://soniox.com/docs/api-reference/errors#` with underscores replaced by hyphens. ### Async transcription failure When you create a transcription with `POST /v1/transcriptions`, the call returns `200` and a transcription object as soon as the job is accepted. The work itself happens asynchronously: the audio is downloaded (if a URL was supplied), then transcribed. If the **job** fails, the HTTP layer doesn't see the failure. Instead, `GET /v1/transcriptions/{id}` returns `status: "failed"` with `error_type` and `error_message` fields populated. Always check `status` and read these fields when polling a transcription. ```json { "id": "84c32fc6-4fb5-4e7a-b656-b5ec70493753", "status": "failed", "error_type": "file_download_failed", "error_message": "Failed to download audio from the provided URL.", "...": "..." } ``` Failed async jobs are **not auto-retried**. Fix the cause and submit a new transcription. The `error_type` values that can appear on a failed job are flagged below with **Async** on their **Surfaces** line. ### Voice processing failure When you create a voice with `POST /v1/voices`, the call returns `201` as soon as the reference clip is accepted. The voice is then processed for each Text-to-Speech model asynchronously, so a per-model failure is not visible to the HTTP layer. Instead, `GET /v1/voices/{id}` reports a per-model status in the `models` array. A model the voice failed to process for has `status: "failed"` with `error_type` and `error_message` populated: ```json { "id": "21b9c8e2-1c3a-4d5e-9f8a-123456789abc", "name": "narrator", "models": [ { "model": "tts-rt-v2", "status": "failed", "error_type": "voice_audio_too_long", "error_message": "The reference audio clip is too long for this model. Upload a shorter clip." } ] } ``` A failure is **terminal and not auto-retried**. Fix the reference clip and create a new voice. The `error_type` values that can appear here are flagged below with **Voice** on their **Surfaces** line. Using a voice for a model whose status is not `ready` returns an HTTP error at stream start (see [`voice_not_ready`](#voice-not-ready), [`voice_not_prepared`](#voice-not-prepared), and [`voice_failed`](#voice-failed)). ### STT WebSocket error frame On error, the STT WebSocket sends a single JSON text frame and then closes the connection with WebSocket close code `1000` (Normal Closure). Branch on `error_type` inside the frame, not on the close code. ```json { "tokens": [], "error_code": 401, "error_type": "unauthenticated", "error_message": "Incorrect API key provided. You can get an API key at https://console.soniox.com", "more_info": "https://soniox.com/docs/api-reference/errors#unauthenticated", "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda" } ``` The error frame reuses the shape of a normal response frame (hence the empty `tokens` array), with the error fields populated. `error_code` is the HTTP status as an integer, and the human-readable text lives in `error_message` rather than `message`. The frame does not carry a `validation_errors` array; a single failure is described in `error_message`. ### TTS WebSocket error frame The TTS WebSocket multiplexes multiple streams over a single connection. Every error frame carries a `stream_id`: ```json { "stream_id": "stream-1", "error_code": 400, "error_type": "invalid_stream_state", "error_message": "Stream stream-1 is already active on this connection. Choose a different stream_id, or cancel the existing stream first.", "more_info": "https://soniox.com/docs/api-reference/errors#invalid-stream-state", "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda" } ``` **Per-stream errors do not close the connection.** Other streams on the same connection continue running and the client may keep using the WebSocket. A `{"terminated": true, "stream_id": "..."}` frame typically follows for the affected stream. Connection-level errors (malformed top-level message, server shutting down) carry `stream_id: ""` and close the connection. ### TTS REST response TTS REST has two error paths depending on whether response headers have been sent. **Headers not yet sent.** Validation and authentication errors, as well as errors raised before audio streaming starts, return a JSON body with the HTTP status code: ```http HTTP/1.1 401 Unauthorized Content-Type: application/json { "error_code": 401, "error_type": "unauthenticated", "error_message": "Missing API key. Provide it as an Authorization header (e.g. 'Authorization: Bearer '). You can get an API key at https://console.soniox.com.", "more_info": "https://soniox.com/docs/api-reference/errors#unauthenticated", "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda" } ``` **Headers already sent (mid-stream failure).** The initial response was `200 OK` and audio bytes have already been flushed to the client. The connection closes abruptly with no in-band error payload. Clients should treat a truncated audio stream as a server-side failure. The exception is [`max_audio_duration_reached`](#max-audio-duration-reached), where the response ends cleanly with truncated audio. *** ## API error types Each section below documents one `error_type`. The badge shows the HTTP status code (the same on every surface), and the **Surfaces** line lists every API where this `error_type` can appear. ### `invalid_request` HTTP 400 Organization endpoints also return `invalid_request` with HTTP 404 when the project or project API key does not exist in the organization. **Surfaces:** [REST](#rest-api-response) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The request body or query parameters failed validation. Common triggers: * **REST:** a required field is missing, a value is out of range, an enum value is unknown, a multipart upload is malformed or has unknown size, an uploaded file exceeds the per-file byte limit, or a request-level invariant is violated (for example, `end_time` not strictly after `start_time` on `GET /v1/usage-logs`). * **WebSocket / TTS REST:** a required start-request or per-stream field is missing or too long, a JSON message is malformed, an audio frame is not valid base64, a translation parameter combination is invalid, `speed` is outside the supported range (between `0.7` and `1.3`), or `reduce_silence` is enabled on a model that does not support it. * **STT WebSocket:** the `context` object exceeds the [context size limit](/stt/concepts/context#context-size-limit) of 8,000 tokens. When the cause on REST is a per-field validation failure, the response includes `validation_errors` with the exact `location` and reason for each field: ```json { "status_code": 400, "error_type": "invalid_request", "message": "Invalid request.", "validation_errors": [ { "error_type": "missing", "location": "file.file", "message": "Field required" } ], "request_id": "..." } ``` WebSocket and TTS REST responses do not carry `validation_errors`; the single failure is described in `error_message`. **Solution.** Read `validation_errors` (REST) or `error_message` (streaming) and resend the request with corrected values. ### `invalid_cursor` HTTP 400 **Surfaces:** [REST](#rest-api-response) **Cause.** The `cursor` query parameter on a paginated endpoint (`/v1/files`, `/v1/transcriptions`, `/v1/usage-logs`) could not be decoded. The cursor is opaque and only valid when copied verbatim from the previous page's `next_page_cursor`; any modification, truncation, or stale cursor triggers this error. **Solution.** Omit `cursor` to start from the first page, or pass the exact `next_page_cursor` from the previous response without modification. Keep all other query parameters constant across pages of the same listing. ### `model_not_available` HTTP 400 **Surfaces:** [REST](#rest-api-response) · [Async](#async-transcription-failure) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The requested `model` is unknown, has been retired, or is not enabled for the calling project or region. **Solution.** Use a model from the [STT models catalog](/stt/models) or [TTS models catalog](/tts/models). If you've been pinning a specific model, switch to a current one before its retirement date. ### `max_concurrent_streams_reached` HTTP 400 **Surfaces:** [TTS WebSocket](#tts-websocket-error-frame) **Cause.** The TTS WebSocket connection has reached its server-imposed cap on the number of simultaneous streams it can run. This is a per-connection limit and is **not** the per-organization or per-project concurrency cap (which surfaces as [`limit_exceeded`](#limit-exceeded)). **Solution.** Send a `cancel` message for one of the active streams on this connection to free a slot, or open a new WebSocket connection. ### `max_concurrent_connections_reached` HTTP 429 **Surfaces:** [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) **Cause.** The organization or project already holds as many open WebSocket connections as its connection limit allows. The connection limit is a multiple of the concurrent streams limit. Idle connections count too: a connection is counted from shortly after it opens when the API key is sent with the connection, or from its start message otherwise, until it closes. See [WebSocket authentication](/guides/websocket-authentication#connection-limit). **Solution.** Close connections you are not using, or start streams on the ones you hold, then retry with backoff. Raising the concurrent streams limit in the [Soniox Console](https://console.soniox.com/org/limits/) raises the connection limit with it. ### `invalid_stream_state` HTTP 400 **Surfaces:** [TTS WebSocket](#tts-websocket-error-frame) **Cause.** A request was issued against a stream that is in the wrong state for that operation. Concrete cases: * `start` with a `stream_id` that is already active on the connection. * `text` or `cancel` for a `stream_id` that does not exist. * `text` or `text_end` after the stream already received `text_end`. * `cancel` after the stream was already cancelled. **Solution.** Read `error_message` for the specific state issue. Most cases indicate a client-side bug; verify the stream lifecycle follows `start` → `text…` → `text_end` (or `cancel` from any state). ### `invalid_audio_file` HTTP 400 **Surfaces:** [REST](#rest-api-response) (`POST /v1/files` upload) · [Async](#async-transcription-failure) **Cause.** The audio could not be decoded, contains no audio stream, or exceeds the model's maximum audio duration. For async jobs this is set during the download / convert step or during the transcribe step's duration recheck. **Solution.** Try transcribing the file directly in the [Soniox Console](https://console.soniox.com) to confirm whether the file itself is the problem. If it is, re-encode to a supported container/codec or split long audio into shorter segments. See the [supported audio formats](/stt/async/async-transcription#audio-formats). ### `unauthenticated` HTTP 401 **Surfaces:** [REST](#rest-api-response) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The request did not authenticate. The `Authorization` header was missing (or, on the WebSocket APIs, no key was sent with the connection), or the API key was malformed, revoked, expired, scoped to a different environment, or longer than 256 characters. Temporary API keys can also fail here when they are expired, single-use and already consumed, or used for an action they were not issued for. **Solution.** Pass a valid key as `Authorization: Bearer `. On the WebSocket APIs send it with the connection, in the Authorization header or the protocols list; see [WebSocket authentication](/guides/websocket-authentication). If you still send `api_key` in the start message, see [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). Get or rotate API keys in the [Soniox Console](https://console.soniox.com). For client apps, use a [temporary API key](/guides/temporary-api-keys). ### `permission_denied` HTTP 403 **Surfaces:** [REST](#rest-api-response) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The API key is valid, but it does not have the permission this call needs. Each key has a list of permissions, and some have a Read and a Write level: a Read key is refused on calls that create, change or delete. Creating a temporary API key needs both the **Temporary API keys** permission and the permission for the service in `usage_type`. The two kinds of key are not interchangeable: organization endpoints accept only an [organization API key](/guides/organization-api#organization-api-keys), and project endpoints refuse one. **Solution.** Edit the key's permissions in the [Soniox Console](https://console.soniox.com), or use a key that has the permission. A change can take a few minutes to apply. See [API key permissions](/guides/api-key-permissions) for what each permission allows. For `/v1/organization` endpoints, use an organization API key. ### `organization_balance_exhausted` HTTP 402 **Surfaces:** [REST](#rest-api-response) · [Async](#async-transcription-failure) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The available balance has dropped to zero. Raised before the request runs, and also evaluated when an async job is about to start downloading or transcribing. In the async case the job moves to `failed` with this `error_type`. **Solution.** Top up at [Billing overview](https://console.soniox.com/org/billing/overview/) or enable autopay. Failed async jobs are not auto-retried; resubmit after funding. ### `organization_monthly_budget_exhausted` HTTP 402 **Surfaces:** [REST](#rest-api-response) · [Async](#async-transcription-failure) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The organization has hit its configured monthly budget cap (`monthly_budget_usd`). Resets at the start of the next calendar month. **Solution.** Raise the cap on the [organization limits](https://console.soniox.com/org/limits/) page, or wait for the month to roll over. ### `project_monthly_budget_exhausted` HTTP 402 **Surfaces:** [REST](#rest-api-response) · [Async](#async-transcription-failure) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The project has hit its configured monthly budget cap. **Solution.** Raise the cap on the [project limits](https://console.soniox.com/org/projects/limits/) page, or wait for the month to roll over. ### `file_download_blocked` **Surfaces:** [Async](#async-transcription-failure) (failed transcription, no HTTP error) **Cause.** The supplied `audio_url` could not be fetched for safety reasons: the URL resolved to a private or otherwise blocked IP (SSRF guard). **Solution.** Use a publicly reachable URL whose host resolves to a routable IP. If the project or organization was deleted, recreate it (or use a different one) and resubmit. ### `file_download_failed` **Surfaces:** [Async](#async-transcription-failure) (failed transcription, no HTTP error) **Cause.** Fetching `audio_url` failed: HTTP error (4xx / 5xx), DNS failure, TLS failure, connection timeout, or the server closed the connection mid-stream. 4xx responses are not retried; other transient failures are retried internally up to a bound before the job is marked as failed. **Solution.** Make the URL reachable and stable. For files you control, prefer uploading via `POST /v1/files` rather than relying on a remote URL. ### `transcription_output_too_long` **Surfaces:** [Async](#async-transcription-failure) (failed transcription, no HTTP error) **Cause.** The transcription completed but produced more output than the model is allowed to return in a single job. Not expected to occur in normal use. If you see this `error_type`, please contact [support@soniox.com](mailto:support@soniox.com) with the transcription ID. ### `file_not_found` HTTP 404 **Surfaces:** [REST](#rest-api-response) · [Async](#async-transcription-failure) **Cause.** No file with the given ID exists in the project the API key belongs to. Returned for IDs that never existed, IDs that were deleted, and IDs that exist but belong to a different project. Soniox does not leak cross-project existence. On async jobs it means the file referenced by `file_id` was deleted after the transcription was created but before it started processing. **Solution.** Confirm the ID by listing files via `GET /v1/files`, and make sure the API key is scoped to the project that owns the file. Keep an uploaded file until the transcription that uses it reaches a terminal state (`completed` or `error`), then delete it. ### `transcription_not_found` HTTP 404 **Surfaces:** [REST](#rest-api-response) **Cause.** No transcription with the given ID exists in the caller's project. Same semantics as [`file_not_found`](#file-not-found): deleted, never existed, or belongs to a different project. **Solution.** Confirm the ID with `GET /v1/transcriptions`, and check that the API key is scoped to the project that owns the transcription. ### `voice_not_found` HTTP 404 **Surfaces:** [REST](#rest-api-response) (`GET`/`DELETE /v1/voices/{id}`, `POST /v1/voices/{id}/recompute`) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** No voice with the given ID exists in the calling project. Returned for IDs that never existed, were deleted, or belong to a different project; Soniox does not leak cross-project existence. On the TTS APIs this is raised at stream start when the `voice` field is a UUID that does not resolve to a voice in the project. **Solution.** Confirm the ID with `GET /v1/voices`, and make sure the API key is scoped to the project that owns the voice. To use a built-in voice instead, pass its name (for example `Adrian`); see [voices](/tts/concepts/voices). ### `voice_name_conflict` HTTP 409 **Surfaces:** [REST](#rest-api-response) (`POST /v1/voices`) **Cause.** A voice with the same `name` already exists in the project. Voice names are unique per project. **Solution.** Choose a different name, or delete the existing voice with `DELETE /v1/voices/{id}` first. ### `voice_not_prepared` HTTP 409 **Surfaces:** [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The voice exists but has not been prepared for the requested `model`, so it cannot be used with it yet. This typically happens when a model is released after the voice was created: the voice reports `status: "not_computed"` for that model. **Solution.** Call `POST /v1/voices/{id}/recompute` (optionally with a `model`) to prepare the voice for the model, poll `GET /v1/voices/{id}` until that model's status is `ready`, then retry the request. ### `voice_not_ready` HTTP 503 **Surfaces:** [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The voice is still being processed for the requested model (per-model status `processing`). This is transient: processing starts right after the voice is created or recomputed and usually finishes within seconds. **Solution.** Retry after a short delay, or poll `GET /v1/voices/{id}` until the model's status is `ready` before starting the stream. ### `voice_failed` HTTP 503 **Surfaces:** [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** Processing the voice failed permanently for the requested model, so the voice cannot be used with it. Despite the 503 status this is **terminal, not retryable**. Inspect the voice's `models[].error_type` and `error_message` via `GET /v1/voices/{id}` for the underlying reason (for example [`voice_audio_too_long`](#voice-audio-too-long) or [`voice_invalid_audio`](#voice-invalid-audio)). **Solution.** Create a new voice from a valid reference clip. Recompute does not recover a voice that has terminally failed. ### `voice_audio_too_long` **Surfaces:** [Voice](#voice-processing-failure) (failed voice processing, no HTTP error) **Cause.** The reference audio clip is longer than the model allows (currently a maximum of 2 minutes). Clip duration is not checked at upload time, so this surfaces as a per-model processing failure rather than an upload error. **Solution.** Create a new voice from a shorter clip (at most 2 minutes). ### `voice_invalid_audio` **Surfaces:** [Voice](#voice-processing-failure) (failed voice processing, no HTTP error) **Cause.** The reference audio clip could not be processed. It may be in an unsupported format, corrupted, or contain no audio. **Solution.** Re-encode the clip to a supported audio format and create a new voice. ### `temp_api_key_session_expired` HTTP 403 **Surfaces:** [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The temporary API key in use was created with a `max_session_duration_seconds` cap, and that duration has elapsed for the current session. The temporary key itself may still be valid for new sessions (subject to its other limits); only the current session has been cut off. **Solution.** Create a new temporary API key (or use the same one if it has remaining uses) and start a new session. Long-running clients should refresh before the per-session cap rather than after. ### `request_timeout` HTTP 408 **Surfaces:** [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** A deadline was exceeded before the request could complete. Most common triggers: * **STT WebSocket: client too slow on audio.** The client failed to send audio chunks fast enough. For example, the initial chunk never arrived, or the decoder starved mid-stream. * **TTS WebSocket: client too slow on text.** After the config message, the client did not send any text within a few seconds, or paused more than a few seconds between text chunks without sending `text_end` to close the stream. Keepalive messages keep the connection open but do not extend this window. See [Connection keepalive](/tts/rt/connection-keepalive). **Solution.** Retry the request. For STT, ensure audio is streamed in real time or faster and that the first chunk is sent promptly after opening the connection. For TTS, send text chunks as soon as you have them and send `text_end` when the input is complete; if you do not know when the next text will arrive, end the stream and start a new one when it is ready. If the timeout persists across retries, contact [support@soniox.com](mailto:support@soniox.com) with the `request_id`. ### `transcription_invalid_state` HTTP 409 **Surfaces:** [REST](#rest-api-response) The transcription exists but is in a state that doesn't allow the requested operation. Read `message` for the specific reason. #### Not completed yet `GET /v1/transcriptions/{id}/transcript` while `status` is `queued`, `downloading`, or `transcribing`. **Solution.** Poll `GET /v1/transcriptions/{id}` until `status` is `completed`, or configure a webhook on the transcription to be notified. #### Failed The transcript was requested for a transcription that ended in `status: "failed"`. **Solution.** Read `error_type` and `error_message` from `GET /v1/transcriptions/{id}` to see why, and submit a new transcription after fixing the cause. #### No longer available Transcript data was retained for a limited window after completion and has since been purged. **Solution.** Re-submit the original audio as a new transcription. #### Cannot delete while processing `DELETE /v1/transcriptions/{id}` while `status` is `transcribing`. **Solution.** Wait for `status` to reach `completed` or `failed`, then retry the delete. ### `max_duration_reached` HTTP 413 **Surfaces:** [STT WebSocket](#stt-websocket-error-frame) **Cause.** The real-time connection reached the maximum allowed session duration (a fixed server-side cap) and was closed. This is a hard ceiling on how long a single WebSocket session may run, independent of any per-temporary-API-key cap (which surfaces as [`temp_api_key_session_expired`](#temp-api-key-session-expired)). Reconnecting on the same connection cannot extend it. **Solution.** Open a new WebSocket connection and resume streaming. For long-running capture, roll over to a fresh connection before the cap is reached rather than waiting for the server to close the session. ### `max_audio_duration_reached` HTTP 413 **Surfaces:** [TTS WebSocket](#tts-websocket-error-frame) **Cause.** Generated audio is capped at 2 minutes per request. When the cap is reached, generation stops and the audio output is truncated. This limit is fixed and cannot be increased. It is distinct from [`max_duration_reached`](#max-duration-reached), which caps the session duration of an STT WebSocket connection. On the **TTS WebSocket**, the final audio chunk is delivered without `audio_end`, followed by an error response and a `terminated` message for the stream: ```json { "error_code": 413, "error_type": "max_audio_duration_reached", "error_message": "The generated audio reached the maximum audio duration per request and the output was truncated. Synthesize the remaining text with a new request." } ``` The WebSocket connection stays open; other streams continue, and you can generate the remaining text on a new stream. On **TTS REST**, audio is streamed, so by the time the cap is reached the `200 OK` response is already committed and no error can be reported. The response simply ends with the truncated audio. **Solution.** Split long text into multiple requests, each below the [audio duration cap](/tts/rest-api/limits-and-quotas). On the WebSocket, start a new stream for the remaining text. ### `limit_exceeded` HTTP 429 **Surfaces:** [REST](#rest-api-response) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) A single `error_type` covers many distinct limits. Read `message` (REST) or `error_message` (streaming) to find out which one was hit. The sub-causes below are grouped by what kind of limit triggered the response. All current limits and your usage are visible in the [Soniox Console](https://console.soniox.com). Per-product reference: [Async STT](/stt/async/limits-and-quotas), [Real-time STT](/stt/rt/limits-and-quotas), [REST TTS](/tts/rest-api/limits-and-quotas), [Real-time TTS](/tts/rt/limits-and-quotas). #### Requests per minute (RPM) Too many calls of the same kind in a 60-second window, evaluated per organization or per project. RPM limits exist for: * WebSocket transcription * Async transcription * File management * Text-to-Speech * Temporary API key creation * Usage logs **Solution.** Slow down, batch where possible, or raise the limit in the console: [organization limits](https://console.soniox.com/org/limits/) or [project limits](https://console.soniox.com/org/projects/limits/). #### Concurrent requests Too many simultaneous in-flight requests on the organization or project. Applies to streaming workloads such as STT WebSocket, TTS WebSocket, and TTS REST. **Solution.** Reduce parallelism in the client, or request a higher concurrent-requests cap in the console. The TTS WebSocket also enforces a per-connection cap on simultaneous streams, which surfaces as the separate [`max_concurrent_streams_reached`](#max-concurrent-streams-reached) `error_type`. Open WebSocket connections, including idle ones, have their own limit, which surfaces as [`max_concurrent_connections_reached`](#max-concurrent-connections-reached). #### Total file count / total file size (GB) Adding this file would put the organization or project over its retained-storage cap (`files_total_count` or `files_total_size_gb`). **Solution.** Delete unused files via `DELETE /v1/files/{id}`, or raise the cap in the console. #### Pending file count Too many uploaded files are awaiting transcription (`transcribe_async_pending_num_files`). **Solution.** Wait for in-flight transcriptions to complete, then retry. #### Total transcription count / pending transcription count Analogous caps on the number of stored transcriptions (`transcribe_async_total_num_files`, `transcribe_async_pending_num_files`). **Solution.** Delete completed transcriptions with `DELETE /v1/transcriptions/{id}`, or raise the cap. ### `internal_error` HTTP 500 **Surfaces:** [REST](#rest-api-response) · [Async](#async-transcription-failure) · [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** Unhandled server-side exception, or an unrecoverable internal inconsistency. **Solution.** Retry once. If the error persists, contact [support@soniox.com](mailto:support@soniox.com) and include the `request_id` from the response. ### `service_unavailable` HTTP 503 **Surfaces:** [STT WebSocket](#stt-websocket-error-frame) · [TTS WebSocket](#tts-websocket-error-frame) · [TTS REST](#tts-rest-response) **Cause.** The service cannot accept the request right now. Concrete sub-causes include a backend model service being overloaded, encoder or decoder cache exhausted, the server gracefully shutting down, or no eligible model backend being available. The numeric `(code N)` in the message identifies the specific sub-cause for support triage. **Solution.** Retry with exponential backoff. The condition is transient; the retry will typically be routed to a healthy backend. If retries consistently fail, contact [support@soniox.com](mailto:support@soniox.com) with the `request_id` and the `(code N)` from the error message. *** ## Getting help If you can't determine the cause from `error_type` and `message`, or if an `internal_error` keeps recurring, contact [support@soniox.com](mailto:support@soniox.com) and include: * The `request_id` from the error response. * The `error_type` and `message` (or `error_message`). * The endpoint and HTTP method, or for async failures the transcription ID. * A short description of what you were trying to do. # Soniox API reference URL: /api-reference Soniox API reference for Speech-to-Text and Text-to-Speech. ## Base URLs API base URLs depend on two factors: the specific service you are calling (Speech-to-Text, Text-to-Speech, Authentication) and your project's region. For a complete list of regional domains (e.g., US, EU, Japan, India) and their corresponding REST and WebSocket endpoints, please refer to our [Data residency](/data-residency) guide. *** ## REST API **OpenAPI schema**: [https://docs.soniox.com/openapi.yaml](https://docs.soniox.com/openapi.yaml) ### Authentication Create and manage API keys for authentication. * **[Create temporary API key](/api-reference/auth/create_temporary_api_key)**: Create short-lived API keys. ### Speech-to-Text REST API for Speech-to-Text is available at `https://api.soniox.com/v1` and includes: * **[Files](/api-reference/stt/files/get_files)**: Manage audio files by uploading, listing, retrieving, and deleting them. * **[Transcriptions](/api-reference/stt/transcriptions/get_transcriptions)**: Create and manage transcriptions for audio files. * **[STT models](/api-reference/stt/get_models)**: List available STT models. See [Get started](/stt/get-started) for an introduction. ### Text-to-Speech REST API for Text-to-Speech is available at `https://tts-rt.soniox.com/tts`. * **[Generate TTS](/api-reference/tts/generate_tts)**: Generate speech from text. * **[TTS models](/api-reference/tts/get_tts_models)**: List available TTS models. Voice management is available at `https://api.soniox.com/v1`. * **[Voices](/api-reference/tts/voices/create_voice)**: Create custom voices from a reference clip and list, retrieve, recompute, and delete them. See [Get started](/tts/get-started) for an introduction and [Voice cloning](/tts/concepts/voice-cloning) for a guide. ### Other Additional REST endpoints are available at `https://api.soniox.com/v1`. * **[Concurrency limits](/api-reference/other/get_concurrency_limits)**: Retrieve current concurrent counts and configured limits for the project and organization. * **[Concurrent streams history](/api-reference/other/get_concurrent_streams_history)**: Retrieve historical concurrent stream counts for the project, aggregated per minute, hour, or day. * **[Usage logs](/api-reference/other/get_usage_logs)**: Retrieve per-request usage log entries for the project. * **[Usage summary](/api-reference/other/get_usage_summary)**: Retrieve daily cost and activity for the project, broken down per model. ### Organization The [Organization API](/guides/organization-api) is available at `https://api.soniox.com/v1/organization` and needs an [organization API key](/guides/organization-api#organization-api-keys). * **[Organization](/api-reference/organization/get_organization)**: Retrieve the organization. * **[Projects](/api-reference/organization/get_organization_projects)**: List the organization's projects. * **[Balance](/api-reference/organization/get_organization_balance)**: Retrieve the prepaid balance and billing setup. * **[Monthly usage](/api-reference/organization/get_organization_monthly_usage)**: Retrieve the cost of a month for the organization and each project. * **[Usage summary](/api-reference/organization/get_organization_usage_summary)**: Retrieve daily cost and activity for each project and model. * **[Limits](/api-reference/organization/get_organization_limits)**: Retrieve the monthly budget and the rate and quota limits per region. * **[Project API keys](/api-reference/organization/get_organization_project_api_keys)**: List, create, and delete the API keys of a project. *** ## Errors Every Soniox API surface (REST, async transcription, STT WebSocket, TTS WebSocket, TTS REST) returns a stable `error_type` you can branch on in code, alongside a human-readable message and a `request_id` for support. See the [Errors reference](/api-reference/errors) for the full list of error types, their causes, and how to resolve them. *** ## WebSocket API ### Realtime Speech-to-Text Use WebSocket API to transcribe and translate live audio streams in real-time. * **Endpoint**: `wss://stt-rt.soniox.com` * **Reference**: [WebSocket API](/api-reference/stt/websocket-api) ### Realtime Text-to-Speech Use WebSocket API for low-latency, streaming speech generation. * **Endpoint**: `wss://tts-rt.soniox.com/tts-websocket` * **Reference**: [WebSocket API](/api-reference/tts/websocket-api) # Create a project API key URL: /api-reference/organization/create_organization_project_api_key Creates an API key for the project. The key is returned once, in this response, and cannot be retrieved again. ## Create a project API key **Endpoint:** `POST /v1/organization/projects/{project_id}/api-keys` Creates an API key for the project. The key is returned once, in this response, and cannot be retrieved again. ### Request Body Content-Type: `application/json` (Required) Schema (YAML Structural Definition): ```yaml properties: name: description: Label of the API key. type: string permissions: description: >- What the key may call, as `resource:level`. At least one; one level per resource. items: description: '`resource:level`; write includes read.' enum: - stt_rt:write - stt_async:read - stt_async:write - files:read - files:write - tts_rt:write - voices:read - voices:write - voice_agent:read - voice_agent:write - usage:read - models:read - temporary_keys:write - legacy:write type: string type: array required: - name - permissions type: object ``` ### Parameters * `project_id` (path) (Required): ### Responses * **201**: Created Schema (YAML Structural Definition): ```yaml properties: id: description: Unique identifier of the API key. format: uuid type: string key: description: The API key. Returned only here; it cannot be retrieved again. type: string key_prefix: description: Leading characters of the key, so keys can be told apart. type: string name: anyOf: - type: string - type: 'null' description: Label of the API key. permissions: description: What the key may call, as `resource:level`; write includes read. items: description: '`resource:level`; write includes read.' enum: - stt_rt:write - stt_async:read - stt_async:write - files:read - files:write - tts_rt:write - voices:read - voices:write - voice_agent:read - voice_agent:write - usage:read - models:read - temporary_keys:write - legacy:write type: string type: array created_at: description: When the key was created. format: date-time type: string created_by: description: The organization API key that created it. type: string created_by_key_id: description: Id of the organization API key that created this key. format: uuid type: string required: - id - key - key_prefix - name - permissions - created_at - created_by - created_by_key_id type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **503**: Service Unavailable Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Delete a project API key URL: /api-reference/organization/delete_organization_project_api_key Deletes one API key of the project. Requests made with it are refused from then on. ## Delete a project API key **Endpoint:** `DELETE /v1/organization/projects/{project_id}/api-keys/{key_id}` Deletes one API key of the project. Requests made with it are refused from then on. ### Parameters * `project_id` (path) (Required): * `key_id` (path) (Required): ### Responses * **204**: No Content * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get the organization URL: /api-reference/organization/get_organization The organization the API key belongs to. ## Get the organization **Endpoint:** `GET /v1/organization` The organization the API key belongs to. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: id: description: Unique identifier of the organization. format: uuid type: string name: description: Name of the organization. type: string created_at: description: When the organization was created. format: date-time type: string required: - id - name - created_at type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get the organization balance URL: /api-reference/organization/get_organization_balance Prepaid balance and billing setup of the organization. Poll it to alert on a balance below a threshold of your own. ## Get the organization balance **Endpoint:** `GET /v1/organization/balance` Prepaid balance and billing setup of the organization. Poll it to alert on a balance below a threshold of your own. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: available_balance_usd: description: Prepaid balance left to spend. type: string free_balance_usd: description: Part of the available balance that was granted, not paid for. type: string used_balance_usd: description: Prepaid balance spent so far. type: string invoice_billing_enabled: description: Usage is invoiced instead of drawn from the prepaid balance. type: boolean balance_exhausted: description: >- The prepaid balance is spent and requests are refused. Always false with invoice billing. type: boolean autopay_enabled: description: The balance is topped up automatically below the threshold. type: boolean autopay_threshold_usd: anyOf: - type: string - type: 'null' description: Balance below which a top-up is charged. Null without a billing setup. autopay_amount_usd: anyOf: - type: string - type: 'null' description: Amount of one top-up. Null without a billing setup. has_payment_method: description: A payment method is on file. type: boolean has_payment_error: description: The last payment attempt failed. type: boolean required: - available_balance_usd - free_balance_usd - used_balance_usd - invoice_billing_enabled - balance_exhausted - autopay_enabled - autopay_threshold_usd - autopay_amount_usd - has_payment_method - has_payment_error type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get the organization limits URL: /api-reference/organization/get_organization_limits Monthly budget and, per region the organization can use, the rate and quota limits in effect. Concurrency limits are per session type. ## Get the organization limits **Endpoint:** `GET /v1/organization/limits` Monthly budget and, per region the organization can use, the rate and quota limits in effect. Concurrency limits are per session type. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: monthly_budget_usd: description: Organization budget in effect. type: string monthly_budget_max_usd: description: Highest budget the organization may set for itself. type: string monthly_budget_notification_usd: anyOf: - type: string - type: 'null' description: Usage at which the organization is emailed. Null when unset. regions: description: Limits per region the organization has access to, defaults filled in. items: properties: region: description: Region the limits apply to. type: string transcribe_rpm: description: Real-time STT sessions per minute. type: string transcribe_concurrent: description: Concurrent real-time STT sessions. type: integer tts_rpm: description: TTS requests per minute. type: string tts_concurrent: description: Concurrent TTS sessions. type: integer transcribe_async_rpm: description: Async transcription requests per minute. type: string transcribe_async_concurrent: description: Async transcriptions processed at once. type: integer transcribe_async_total_num_files: description: Async transcriptions kept in total. type: integer transcribe_async_pending_num_files: description: Async transcriptions waiting or in progress. type: integer files_rpm: description: File requests per minute. type: string files_total_size_gb: description: Total size of stored files, in GB. type: string files_total_count: description: Stored files in total. type: integer voices_rpm: description: Voice requests per minute. type: string voices_total_count: description: Cloned voices in total. type: integer webhooks_concurrent: description: Webhook deliveries in flight at once. type: integer required: - region - transcribe_rpm - transcribe_concurrent - tts_rpm - tts_concurrent - transcribe_async_rpm - transcribe_async_concurrent - transcribe_async_total_num_files - transcribe_async_pending_num_files - files_rpm - files_total_size_gb - files_total_count - voices_rpm - voices_total_count - webhooks_concurrent type: object type: array required: - monthly_budget_usd - monthly_budget_max_usd - monthly_budget_notification_usd - regions type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get the organization's usage for a month URL: /api-reference/organization/get_organization_monthly_usage Cost of one calendar month for the organization and each of its projects, with the budget it is measured against. ## Get the organization's usage for a month **Endpoint:** `GET /v1/organization/usage/monthly` Cost of one calendar month for the organization and each of its projects, with the budget it is measured against. ### Parameters * `month` (query): Calendar month as YYYY-MM, UTC. Defaults to the current month. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: month: description: The month, as YYYY-MM. type: string usage_usd: description: Cost of the month across every project. type: string free_usage_usd: description: Part of the usage covered by granted balance. type: string invoiced_usage_usd: description: Part of the usage that is invoiced. type: string api_usage_usd: description: Part of the usage made through the API. type: string playground_usage_usd: description: Part of the usage made in the Soniox Console playground. type: string monthly_budget_usd: anyOf: - type: string - type: 'null' description: >- Organization budget in effect. Null for a month other than the current one: only today's budget is stored, so it says nothing about a month that has closed. monthly_budget_notification_usd: anyOf: - type: string - type: 'null' description: >- Usage at which the organization is emailed. Null when unset, and for a month other than the current one. remaining_budget_usd: anyOf: - type: string - type: 'null' description: >- Budget minus usage, never below zero. Null for a month other than the current one. budget_exhausted: anyOf: - type: boolean - type: 'null' description: >- Usage reached the budget and requests are refused. Null for a month other than the current one. projects: description: >- Projects with usage this month, highest cost first. Projects deleted since are included, so the per-project costs add up to `usage_usd`. items: properties: id: description: Unique identifier of the project. format: uuid type: string name: description: Name of the project. type: string usage_usd: description: Cost of the month for this project. type: string free_usage_usd: description: Part of the usage covered by granted balance. type: string invoiced_usage_usd: description: Part of the usage that is invoiced. type: string api_usage_usd: description: Part of the usage made through the API. type: string playground_usage_usd: description: Part of the usage made in the Soniox Console playground. type: string monthly_budget_usd: anyOf: - type: string - type: 'null' description: Project budget. Null means only the organization budget applies. required: - id - name - usage_usd - free_usage_usd - invoiced_usage_usd - api_usage_usd - playground_usage_usd - monthly_budget_usd type: object type: array required: - month - usage_usd - free_usage_usd - invoiced_usage_usd - api_usage_usd - playground_usage_usd - monthly_budget_usd - monthly_budget_notification_usd - remaining_budget_usd - budget_exhausted - projects type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # List a project's API keys URL: /api-reference/organization/get_organization_project_api_keys Every API key of the project, newest first. The keys themselves are not returned. ## List a project's API keys **Endpoint:** `GET /v1/organization/projects/{project_id}/api-keys` Every API key of the project, newest first. The keys themselves are not returned. ### Parameters * `project_id` (path) (Required): ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: api_keys: description: API keys of the project, newest first. Never the key itself. items: properties: id: description: Unique identifier of the API key. format: uuid type: string key_prefix: description: Leading characters of the key, so keys can be told apart. type: string name: anyOf: - type: string - type: 'null' description: Label of the API key. `null` for keys created without one. permissions: description: What the key may call, as `resource:level`; write includes read. items: description: '`resource:level`; write includes read.' enum: - stt_rt:write - stt_async:read - stt_async:write - files:read - files:write - tts_rt:write - voices:read - voices:write - voice_agent:read - voice_agent:write - usage:read - models:read - temporary_keys:write - legacy:write type: string type: array created_at: description: When the key was created. format: date-time type: string created_by: description: >- Who created the key: the email address of a console user, or the organization API key that created it. type: string created_by_key_id: anyOf: - format: uuid type: string - type: 'null' description: >- The organization API key that created it. Null for a console-made key. required: - id - key_prefix - name - permissions - created_at - created_by - created_by_key_id type: object type: array required: - api_keys type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # List the organization's projects URL: /api-reference/organization/get_organization_projects Every project of the organization, oldest first. ## List the organization's projects **Endpoint:** `GET /v1/organization/projects` Every project of the organization, oldest first. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: projects: description: >- Projects of the organization, oldest first. Deleted projects are not included. items: properties: id: description: Unique identifier of the project. format: uuid type: string name: description: Name of the project. type: string description: description: Description of the project. Empty when none was set. type: string region: description: Region the project's data is stored and processed in. type: string created_at: description: When the project was created. format: date-time type: string required: - id - name - description - region - created_at type: object type: array required: - projects type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get the organization's usage summary URL: /api-reference/organization/get_organization_usage_summary Cost and activity per day, for each project of the organization and each model it used. Projects since deleted are included, so the per-project costs add up to the total. The window is half-open, [start_time, end_time), aggregated by whole UTC day, and must not cover more than 366 days. ## Get the organization's usage summary **Endpoint:** `GET /v1/organization/usage/summary` Cost and activity per day, for each project of the organization and each model it used. Projects since deleted are included, so the per-project costs add up to the total. The window is half-open, \[start\_time, end\_time), aggregated by whole UTC day, and must not cover more than 366 days. ### Parameters * `start_time` (query) (Required): Start of the window (inclusive). Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-01T00:00:00Z`). Its UTC day is included. * `end_time` (query) (Required): End of the window (exclusive). Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-03T00:00:00Z`) and strictly after `start_time`. Its UTC day is included unless it falls exactly on midnight. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: total: description: >- Cost and activity across every project of the organization. Equals the sum of the `projects` entries. properties: model: anyOf: - type: string - type: 'null' description: Model identifier. `null` on the `total` entry. days: description: >- One UTC day (`YYYY-MM-DD`) per element, in ascending order. Every day in the requested window is present, including days with no usage. All the per-day arrays below align to this axis. items: format: date type: string type: array total_cost_usd: description: >- Total cost over the window, in USD. Equals `total_input_cost_usd` + `total_output_cost_usd` + `total_duration_cost_usd`. type: string total_input_cost_usd: description: Total cost of input tokens over the window, in USD. type: string total_output_cost_usd: description: Total cost of output tokens over the window, in USD. type: string total_duration_cost_usd: description: >- Total cost over the window for models billed by session duration rather than by tokens, in USD. `0` for Speech-to-Text and Text-to-Speech models. type: string total_api_cost_usd: description: Part of `total_cost_usd` from requests made with an API key, in USD. type: string total_playground_cost_usd: description: >- Part of `total_cost_usd` from requests made in the Soniox Console playground, in USD. type: string cost_usd: description: Cost per day, in USD, aligned to `days`. items: type: string type: array input_cost_usd: description: Cost of input tokens per day, in USD, aligned to `days`. items: type: string type: array output_cost_usd: description: Cost of output tokens per day, in USD, aligned to `days`. items: type: string type: array duration_cost_usd: description: Duration-billed cost per day, in USD, aligned to `days`. items: type: string type: array api_cost_usd: description: >- Cost of requests made with an API key per day, in USD, aligned to `days`. items: type: string type: array playground_cost_usd: description: >- Cost of requests made in the Soniox Console playground per day, in USD, aligned to `days`. items: type: string type: array total_num_requests: description: Number of requests over the window. type: integer total_input_text_tokens: description: Input text tokens over the window. type: integer total_input_audio_tokens: description: Input audio tokens over the window. type: integer total_input_audio_duration_ms: description: Input audio over the window, in milliseconds. type: integer total_output_text_tokens: description: Output text tokens over the window. type: integer total_output_audio_tokens: description: Output audio tokens over the window. type: integer total_output_audio_duration_ms: description: Output audio over the window, in milliseconds. type: integer total_duration_ms: description: >- Billed session duration over the window, in milliseconds, for models billed by duration. `0` for Speech-to-Text and Text-to-Speech models. type: integer num_requests: description: Number of requests per day, aligned to `days`. items: type: integer type: array input_text_tokens: description: Input text tokens per day, aligned to `days`. items: type: integer type: array input_audio_tokens: description: Input audio tokens per day, aligned to `days`. items: type: integer type: array input_audio_duration_ms: description: Input audio per day, in milliseconds, aligned to `days`. items: type: integer type: array output_text_tokens: description: Output text tokens per day, aligned to `days`. items: type: integer type: array output_audio_tokens: description: Output audio tokens per day, aligned to `days`. items: type: integer type: array output_audio_duration_ms: description: Output audio per day, in milliseconds, aligned to `days`. items: type: integer type: array duration_ms: description: Billed session duration per day, in milliseconds, aligned to `days`. items: type: integer type: array required: - days - total_cost_usd - total_input_cost_usd - total_output_cost_usd - total_duration_cost_usd - total_api_cost_usd - total_playground_cost_usd - cost_usd - input_cost_usd - output_cost_usd - duration_cost_usd - api_cost_usd - playground_cost_usd - total_num_requests - total_input_text_tokens - total_input_audio_tokens - total_input_audio_duration_ms - total_output_text_tokens - total_output_audio_tokens - total_output_audio_duration_ms - total_duration_ms - num_requests - input_text_tokens - input_audio_tokens - input_audio_duration_ms - output_text_tokens - output_audio_tokens - output_audio_duration_ms - duration_ms type: object projects: description: >- Projects with usage in the window, highest cost first. Projects deleted since are included, so the per-project costs add up to `total`. items: properties: id: description: Unique identifier of the project. format: uuid type: string name: description: Name of the project. type: string total: description: Cost and activity across all models of the project. properties: model: anyOf: - type: string - type: 'null' description: Model identifier. `null` on the `total` entry. days: description: >- One UTC day (`YYYY-MM-DD`) per element, in ascending order. Every day in the requested window is present, including days with no usage. All the per-day arrays below align to this axis. items: format: date type: string type: array total_cost_usd: description: >- Total cost over the window, in USD. Equals `total_input_cost_usd` + `total_output_cost_usd` + `total_duration_cost_usd`. type: string total_input_cost_usd: description: Total cost of input tokens over the window, in USD. type: string total_output_cost_usd: description: Total cost of output tokens over the window, in USD. type: string total_duration_cost_usd: description: >- Total cost over the window for models billed by session duration rather than by tokens, in USD. `0` for Speech-to-Text and Text-to-Speech models. type: string total_api_cost_usd: description: >- Part of `total_cost_usd` from requests made with an API key, in USD. type: string total_playground_cost_usd: description: >- Part of `total_cost_usd` from requests made in the Soniox Console playground, in USD. type: string cost_usd: description: Cost per day, in USD, aligned to `days`. items: type: string type: array input_cost_usd: description: Cost of input tokens per day, in USD, aligned to `days`. items: type: string type: array output_cost_usd: description: Cost of output tokens per day, in USD, aligned to `days`. items: type: string type: array duration_cost_usd: description: Duration-billed cost per day, in USD, aligned to `days`. items: type: string type: array api_cost_usd: description: >- Cost of requests made with an API key per day, in USD, aligned to `days`. items: type: string type: array playground_cost_usd: description: >- Cost of requests made in the Soniox Console playground per day, in USD, aligned to `days`. items: type: string type: array total_num_requests: description: Number of requests over the window. type: integer total_input_text_tokens: description: Input text tokens over the window. type: integer total_input_audio_tokens: description: Input audio tokens over the window. type: integer total_input_audio_duration_ms: description: Input audio over the window, in milliseconds. type: integer total_output_text_tokens: description: Output text tokens over the window. type: integer total_output_audio_tokens: description: Output audio tokens over the window. type: integer total_output_audio_duration_ms: description: Output audio over the window, in milliseconds. type: integer total_duration_ms: description: >- Billed session duration over the window, in milliseconds, for models billed by duration. `0` for Speech-to-Text and Text-to-Speech models. type: integer num_requests: description: Number of requests per day, aligned to `days`. items: type: integer type: array input_text_tokens: description: Input text tokens per day, aligned to `days`. items: type: integer type: array input_audio_tokens: description: Input audio tokens per day, aligned to `days`. items: type: integer type: array input_audio_duration_ms: description: Input audio per day, in milliseconds, aligned to `days`. items: type: integer type: array output_text_tokens: description: Output text tokens per day, aligned to `days`. items: type: integer type: array output_audio_tokens: description: Output audio tokens per day, aligned to `days`. items: type: integer type: array output_audio_duration_ms: description: Output audio per day, in milliseconds, aligned to `days`. items: type: integer type: array duration_ms: description: >- Billed session duration per day, in milliseconds, aligned to `days`. items: type: integer type: array required: - days - total_cost_usd - total_input_cost_usd - total_output_cost_usd - total_duration_cost_usd - total_api_cost_usd - total_playground_cost_usd - cost_usd - input_cost_usd - output_cost_usd - duration_cost_usd - api_cost_usd - playground_cost_usd - total_num_requests - total_input_text_tokens - total_input_audio_tokens - total_input_audio_duration_ms - total_output_text_tokens - total_output_audio_tokens - total_output_audio_duration_ms - total_duration_ms - num_requests - input_text_tokens - input_audio_tokens - input_audio_duration_ms - output_text_tokens - output_audio_tokens - output_audio_duration_ms - duration_ms type: object models: description: Per-model cost and activity, highest cost first. items: properties: model: anyOf: - type: string - type: 'null' description: Model identifier. `null` on the `total` entry. days: description: >- One UTC day (`YYYY-MM-DD`) per element, in ascending order. Every day in the requested window is present, including days with no usage. All the per-day arrays below align to this axis. items: format: date type: string type: array total_cost_usd: description: >- Total cost over the window, in USD. Equals `total_input_cost_usd` + `total_output_cost_usd` + `total_duration_cost_usd`. type: string total_input_cost_usd: description: Total cost of input tokens over the window, in USD. type: string total_output_cost_usd: description: Total cost of output tokens over the window, in USD. type: string total_duration_cost_usd: description: >- Total cost over the window for models billed by session duration rather than by tokens, in USD. `0` for Speech-to-Text and Text-to-Speech models. type: string total_api_cost_usd: description: >- Part of `total_cost_usd` from requests made with an API key, in USD. type: string total_playground_cost_usd: description: >- Part of `total_cost_usd` from requests made in the Soniox Console playground, in USD. type: string cost_usd: description: Cost per day, in USD, aligned to `days`. items: type: string type: array input_cost_usd: description: Cost of input tokens per day, in USD, aligned to `days`. items: type: string type: array output_cost_usd: description: Cost of output tokens per day, in USD, aligned to `days`. items: type: string type: array duration_cost_usd: description: Duration-billed cost per day, in USD, aligned to `days`. items: type: string type: array api_cost_usd: description: >- Cost of requests made with an API key per day, in USD, aligned to `days`. items: type: string type: array playground_cost_usd: description: >- Cost of requests made in the Soniox Console playground per day, in USD, aligned to `days`. items: type: string type: array total_num_requests: description: Number of requests over the window. type: integer total_input_text_tokens: description: Input text tokens over the window. type: integer total_input_audio_tokens: description: Input audio tokens over the window. type: integer total_input_audio_duration_ms: description: Input audio over the window, in milliseconds. type: integer total_output_text_tokens: description: Output text tokens over the window. type: integer total_output_audio_tokens: description: Output audio tokens over the window. type: integer total_output_audio_duration_ms: description: Output audio over the window, in milliseconds. type: integer total_duration_ms: description: >- Billed session duration over the window, in milliseconds, for models billed by duration. `0` for Speech-to-Text and Text-to-Speech models. type: integer num_requests: description: Number of requests per day, aligned to `days`. items: type: integer type: array input_text_tokens: description: Input text tokens per day, aligned to `days`. items: type: integer type: array input_audio_tokens: description: Input audio tokens per day, aligned to `days`. items: type: integer type: array input_audio_duration_ms: description: Input audio per day, in milliseconds, aligned to `days`. items: type: integer type: array output_text_tokens: description: Output text tokens per day, aligned to `days`. items: type: integer type: array output_audio_tokens: description: Output audio tokens per day, aligned to `days`. items: type: integer type: array output_audio_duration_ms: description: Output audio per day, in milliseconds, aligned to `days`. items: type: integer type: array duration_ms: description: >- Billed session duration per day, in milliseconds, aligned to `days`. items: type: integer type: array required: - days - total_cost_usd - total_input_cost_usd - total_output_cost_usd - total_duration_cost_usd - total_api_cost_usd - total_playground_cost_usd - cost_usd - input_cost_usd - output_cost_usd - duration_cost_usd - api_cost_usd - playground_cost_usd - total_num_requests - total_input_text_tokens - total_input_audio_tokens - total_input_audio_duration_ms - total_output_text_tokens - total_output_audio_tokens - total_output_audio_duration_ms - total_duration_ms - num_requests - input_text_tokens - input_audio_tokens - input_audio_duration_ms - output_text_tokens - output_audio_tokens - output_audio_duration_ms - duration_ms type: object type: array required: - id - name - total - models type: object type: array required: - total - projects type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **403**: Forbidden Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get concurrency limits URL: /api-reference/other/get_concurrency_limits Current concurrent counts plus configured concurrency limits for the project and its organization. Region-scoped. ## Get concurrency limits **Endpoint:** `GET /v1/concurrency-limits` Current concurrent counts plus configured concurrency limits for the project and its organization. Region-scoped. ### Responses * **200**: Current counts and configured limits. Schema (YAML Structural Definition): ```yaml properties: project: properties: current: description: Live counts. properties: transcribe_concurrent: type: integer tts_concurrent: type: integer required: - transcribe_concurrent - tts_concurrent type: object limits: description: Configured limits properties: transcribe_concurrent: anyOf: - type: integer - type: 'null' tts_concurrent: anyOf: - type: integer - type: 'null' required: - transcribe_concurrent - tts_concurrent type: object required: - current - limits type: object organization: properties: current: description: Live counts. properties: transcribe_concurrent: type: integer tts_concurrent: type: integer required: - transcribe_concurrent - tts_concurrent type: object limits: description: Configured limits properties: transcribe_concurrent: anyOf: - type: integer - type: 'null' tts_concurrent: anyOf: - type: integer - type: 'null' required: - transcribe_concurrent - tts_concurrent type: object required: - current - limits type: object required: - project - organization type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate or usage limit exceeded. Error types: * `limit_exceeded`: * `Requests per minute limit has been exceeded for your organization.` * `Requests per minute limit has been exceeded for your project.` Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get concurrent streams history URL: /api-reference/other/get_concurrent_streams_history Returns historical concurrent stream counts for the project, aggregated per period. The project is implied by the API key used for authentication. Region-scoped. Every aggregation period in the requested window is returned, with no gaps. Periods with no recorded activity have every field set to `0`. ## Get concurrent streams history **Endpoint:** `GET /v1/concurrent-streams-history` Returns historical concurrent stream counts for the project, aggregated per period. The project is implied by the API key used for authentication. Region-scoped. Every aggregation period in the requested window is returned, with no gaps. Periods with no recorded activity have every field set to `0`. ### Parameters * `start_time` (query) (Required): Start of the time window (inclusive). Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-28T09:00:00Z`). Filters by `period_start`. * `end_time` (query) (Required): End of the time window (exclusive). Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-28T09:00:00Z`) and strictly after `start_time`. Filters by `period_start`. * `period_sec` (query) (Required): Aggregation period in seconds. One of `60` (per-minute), `3600` (hourly), `86400` (daily). The period also caps how long the requested window may be. * `kind` (query) (Required): Stream kind to return. `stt` covers Speech-to-Text WebSocket sessions, `tts` covers Text-to-Speech WebSocket streams and REST requests. ### Responses * **200**: Per-period concurrent stream aggregates. Schema (YAML Structural Definition): ```yaml properties: kind: allOf: - enum: - stt - tts type: string description: Stream kind these entries describe (`stt` or `tts`). entries: description: >- Per-period concurrent stream aggregates for the authenticated project, ordered by `period_start` ascending. Every aggregation period in the requested window is returned, with no gaps. Periods with no recorded activity have every field set to `0`. items: properties: period_start: description: >- Start of the aggregation period, UTC. Aligned to a multiple of `period_sec`. format: date-time type: string period_sec: description: Aggregation period in seconds. type: integer sample_min: description: >- Lowest recorded concurrent stream count in the period. Always `0`, because that is what the per-minute tier records. Use `sample_max` for the peak. type: integer sample_max: description: >- Peak concurrent stream count in the period. Stays exact when periods are rolled up into hours and days. `0` when the period had no activity. type: integer sample_sum: description: >- Sum of the recorded concurrency values in the period. Divide by `sample_count` for the average concurrency while streams were active, or by `total_count` for the average across the whole period with idle slots counted as zero. type: integer sample_count: description: >- Number of values actually recorded in the period. For `period_sec=60` this is how many samples were taken during that minute, so it is usually larger than `total_count`. For hourly and daily periods it is the number of source periods that had data, at most `total_count`. `0` when the period had no activity. type: integer total_count: description: >- Number of slots the period covers. `1` for `period_sec=60`, `60` for `3600` (minutes per hour), `24` for `86400` (hours per day). `0` when the period had no activity. type: integer required: - period_start - period_sec - sample_min - sample_max - sample_sum - sample_count - total_count type: object type: array required: - kind - entries type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: A query parameter is missing or invalid. Common causes: `period_sec` is not one of `60`, `3600`, `86400`, `start_time` / `end_time` not parseable as ISO 8601, `end_time` not strictly after `start_time`, the window between them exceeds the maximum for the requested `period_sec`, or the window would return more than 20000 entries. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get usage logs URL: /api-reference/other/get_usage_logs Returns per-request usage log entries for the project. The project is implied by the API key used for authentication. Filters by request end time. The window between start_time and end_time must not exceed 31 days. start_time must not be earlier than 91 days ago. ## Get usage logs **Endpoint:** `GET /v1/usage-logs` Returns per-request usage log entries for the project. The project is implied by the API key used for authentication. Filters by request end time. The window between start\_time and end\_time must not exceed 31 days. start\_time must not be earlier than 91 days ago. ### Parameters * `start_time` (query) (Required): Start of the time window (inclusive). Filters by request end time. Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-28T09:00:00Z`). * `end_time` (query) (Required): End of the time window (exclusive). Filters by request end time. Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-28T09:00:00Z`). * `limit` (query): Maximum number of usage log entries to return. * `sort` (query): Sort order by end\_time.Use `end_time_desc` to get the most recent entries first. When paginating, pass the same `sort` value alongside the cursor. * `cursor` (query): Pagination cursor for the next page of results. ### Responses * **200**: Per-request usage log entries. Schema (YAML Structural Definition): ```yaml properties: usage_logs: description: Per-request usage log entries ordered by end_time, uuid (per `sort`). items: properties: uuid: description: Unique identifier of the request. format: uuid type: string request_scope: description: Scope of the request (api / playground). type: string client_reference_id: description: >- Client reference ID supplied on the original request. Empty string if none. type: string model: description: Model identifier. type: string start_time: description: When the request started. format: date-time type: string end_time: description: When the request ended. format: date-time type: string input_text_tokens: type: integer input_audio_tokens: type: integer input_audio_duration_ms: type: integer output_text_tokens: type: integer output_audio_tokens: type: integer output_audio_duration_ms: type: integer cost_usd: type: string input_cost_usd: type: string input_text_cost_usd: type: string input_audio_cost_usd: type: string output_cost_usd: type: string output_text_cost_usd: type: string output_audio_cost_usd: type: string required: - uuid - request_scope - client_reference_id - model - start_time - end_time - input_text_tokens - input_audio_tokens - input_audio_duration_ms - output_text_tokens - output_audio_tokens - output_audio_duration_ms - cost_usd - input_cost_usd - input_text_cost_usd - input_audio_cost_usd - output_cost_usd - output_text_cost_usd - output_audio_cost_usd type: object type: array next_page_cursor: anyOf: - type: string - type: 'null' description: >- A pagination token that references the next page of results. When more data is available, this field contains a value to pass in the cursor parameter of a subsequent request. When null, no additional results are available. required: - usage_logs type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: A query parameter is missing or invalid. Common causes: `start_time` / `end_time` not parseable as ISO 8601, `end_time` not strictly after `start_time`, the window between them exceeds 31 days, or `cursor` does not match the supplied `start_time` / `end_time` / `sort`. * `invalid_cursor`: The `cursor` parameter is invalid. Omit `cursor` to start pagination from the beginning. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get usage summary URL: /api-reference/other/get_usage_summary Returns daily cost and activity for the project, broken down per model and summed across all models. The project is implied by the API key used for authentication. Usage is aggregated by whole UTC day. The window is half-open, `[start_time, end_time)`, and a day is included when the window covers any part of it, so an `end_time` exactly at midnight excludes that day. The window must not cover more than 366 UTC days. ## Get usage summary **Endpoint:** `GET /v1/usage/summary` Returns daily cost and activity for the project, broken down per model and summed across all models. The project is implied by the API key used for authentication. Usage is aggregated by whole UTC day. The window is half-open, `[start_time, end_time)`, and a day is included when the window covers any part of it, so an `end_time` exactly at midnight excludes that day. The window must not cover more than 366 UTC days. ### Parameters * `start_time` (query) (Required): Start of the window (inclusive). Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-01T00:00:00Z`). Its UTC day is included. * `end_time` (query) (Required): End of the window (exclusive). Must be an ISO 8601 timestamp in UTC (e.g. `2026-04-03T00:00:00Z`) and strictly after `start_time`. Its UTC day is included unless it falls exactly on midnight. ### Responses * **200**: Daily cost and activity aggregates. Schema (YAML Structural Definition): ```yaml properties: total: allOf: - properties: model: anyOf: - type: string - type: 'null' description: Model identifier. `null` on the `total` entry. days: description: >- One UTC day (`YYYY-MM-DD`) per element, in ascending order. Every day in the requested window is present, including days with no usage. All the per-day arrays below align to this axis. items: format: date type: string type: array total_cost_usd: description: >- Total cost over the window, in USD. Equals `total_input_cost_usd` + `total_output_cost_usd` + `total_duration_cost_usd`. type: string total_input_cost_usd: description: Total cost of input tokens over the window, in USD. type: string total_output_cost_usd: description: Total cost of output tokens over the window, in USD. type: string total_duration_cost_usd: description: >- Total cost over the window for models billed by session duration rather than by tokens, in USD. `0` for Speech-to-Text and Text-to-Speech models. type: string total_api_cost_usd: description: >- Part of `total_cost_usd` from requests made with an API key, in USD. type: string total_playground_cost_usd: description: >- Part of `total_cost_usd` from requests made in the Soniox Console playground, in USD. type: string cost_usd: description: Cost per day, in USD, aligned to `days`. items: type: string type: array input_cost_usd: description: Cost of input tokens per day, in USD, aligned to `days`. items: type: string type: array output_cost_usd: description: Cost of output tokens per day, in USD, aligned to `days`. items: type: string type: array duration_cost_usd: description: Duration-billed cost per day, in USD, aligned to `days`. items: type: string type: array api_cost_usd: description: >- Cost of requests made with an API key per day, in USD, aligned to `days`. items: type: string type: array playground_cost_usd: description: >- Cost of requests made in the Soniox Console playground per day, in USD, aligned to `days`. items: type: string type: array total_num_requests: description: Number of requests over the window. type: integer total_input_text_tokens: description: Input text tokens over the window. type: integer total_input_audio_tokens: description: Input audio tokens over the window. type: integer total_input_audio_duration_ms: description: Input audio over the window, in milliseconds. type: integer total_output_text_tokens: description: Output text tokens over the window. type: integer total_output_audio_tokens: description: Output audio tokens over the window. type: integer total_output_audio_duration_ms: description: Output audio over the window, in milliseconds. type: integer total_duration_ms: description: >- Billed session duration over the window, in milliseconds, for models billed by duration. `0` for Speech-to-Text and Text-to-Speech models. type: integer num_requests: description: Number of requests per day, aligned to `days`. items: type: integer type: array input_text_tokens: description: Input text tokens per day, aligned to `days`. items: type: integer type: array input_audio_tokens: description: Input audio tokens per day, aligned to `days`. items: type: integer type: array input_audio_duration_ms: description: Input audio per day, in milliseconds, aligned to `days`. items: type: integer type: array output_text_tokens: description: Output text tokens per day, aligned to `days`. items: type: integer type: array output_audio_tokens: description: Output audio tokens per day, aligned to `days`. items: type: integer type: array output_audio_duration_ms: description: Output audio per day, in milliseconds, aligned to `days`. items: type: integer type: array duration_ms: description: >- Billed session duration per day, in milliseconds, aligned to `days`. items: type: integer type: array required: - days - total_cost_usd - total_input_cost_usd - total_output_cost_usd - total_duration_cost_usd - total_api_cost_usd - total_playground_cost_usd - cost_usd - input_cost_usd - output_cost_usd - duration_cost_usd - api_cost_usd - playground_cost_usd - total_num_requests - total_input_text_tokens - total_input_audio_tokens - total_input_audio_duration_ms - total_output_text_tokens - total_output_audio_tokens - total_output_audio_duration_ms - total_duration_ms - num_requests - input_text_tokens - input_audio_tokens - input_audio_duration_ms - output_text_tokens - output_audio_tokens - output_audio_duration_ms - duration_ms type: object description: Cost and activity across all models. Its `model` is `null`. models: description: >- One entry per model that recorded usage in the window. Empty when the project had no usage. items: properties: model: anyOf: - type: string - type: 'null' description: Model identifier. `null` on the `total` entry. days: description: >- One UTC day (`YYYY-MM-DD`) per element, in ascending order. Every day in the requested window is present, including days with no usage. All the per-day arrays below align to this axis. items: format: date type: string type: array total_cost_usd: description: >- Total cost over the window, in USD. Equals `total_input_cost_usd` + `total_output_cost_usd` + `total_duration_cost_usd`. type: string total_input_cost_usd: description: Total cost of input tokens over the window, in USD. type: string total_output_cost_usd: description: Total cost of output tokens over the window, in USD. type: string total_duration_cost_usd: description: >- Total cost over the window for models billed by session duration rather than by tokens, in USD. `0` for Speech-to-Text and Text-to-Speech models. type: string total_api_cost_usd: description: Part of `total_cost_usd` from requests made with an API key, in USD. type: string total_playground_cost_usd: description: >- Part of `total_cost_usd` from requests made in the Soniox Console playground, in USD. type: string cost_usd: description: Cost per day, in USD, aligned to `days`. items: type: string type: array input_cost_usd: description: Cost of input tokens per day, in USD, aligned to `days`. items: type: string type: array output_cost_usd: description: Cost of output tokens per day, in USD, aligned to `days`. items: type: string type: array duration_cost_usd: description: Duration-billed cost per day, in USD, aligned to `days`. items: type: string type: array api_cost_usd: description: >- Cost of requests made with an API key per day, in USD, aligned to `days`. items: type: string type: array playground_cost_usd: description: >- Cost of requests made in the Soniox Console playground per day, in USD, aligned to `days`. items: type: string type: array total_num_requests: description: Number of requests over the window. type: integer total_input_text_tokens: description: Input text tokens over the window. type: integer total_input_audio_tokens: description: Input audio tokens over the window. type: integer total_input_audio_duration_ms: description: Input audio over the window, in milliseconds. type: integer total_output_text_tokens: description: Output text tokens over the window. type: integer total_output_audio_tokens: description: Output audio tokens over the window. type: integer total_output_audio_duration_ms: description: Output audio over the window, in milliseconds. type: integer total_duration_ms: description: >- Billed session duration over the window, in milliseconds, for models billed by duration. `0` for Speech-to-Text and Text-to-Speech models. type: integer num_requests: description: Number of requests per day, aligned to `days`. items: type: integer type: array input_text_tokens: description: Input text tokens per day, aligned to `days`. items: type: integer type: array input_audio_tokens: description: Input audio tokens per day, aligned to `days`. items: type: integer type: array input_audio_duration_ms: description: Input audio per day, in milliseconds, aligned to `days`. items: type: integer type: array output_text_tokens: description: Output text tokens per day, aligned to `days`. items: type: integer type: array output_audio_tokens: description: Output audio tokens per day, aligned to `days`. items: type: integer type: array output_audio_duration_ms: description: Output audio per day, in milliseconds, aligned to `days`. items: type: integer type: array duration_ms: description: Billed session duration per day, in milliseconds, aligned to `days`. items: type: integer type: array required: - days - total_cost_usd - total_input_cost_usd - total_output_cost_usd - total_duration_cost_usd - total_api_cost_usd - total_playground_cost_usd - cost_usd - input_cost_usd - output_cost_usd - duration_cost_usd - api_cost_usd - playground_cost_usd - total_num_requests - total_input_text_tokens - total_input_audio_tokens - total_input_audio_duration_ms - total_output_text_tokens - total_output_audio_tokens - total_output_audio_duration_ms - total_duration_ms - num_requests - input_text_tokens - input_audio_tokens - input_audio_duration_ms - output_text_tokens - output_audio_tokens - output_audio_duration_ms - duration_ms type: object type: array required: - total - models type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: A query parameter is missing or invalid. Common causes: `start_time` / `end_time` not parseable as ISO 8601, `end_time` not strictly after `start_time`, or the window covers more than 366 UTC days. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not found. Error types: * `not_found`: The project could not be resolved while collecting its usage. Retry, and contact support if it persists. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Delete file URL: /api-reference/stt/files/delete_file Permanently deletes specified file. If a transcription that has not started processing yet still references the file, that transcription fails with `file_not_found`, so delete the file only after the transcription reaches `completed` or `error`. ## Delete file **Endpoint:** `DELETE /v1/files/{file_id}` Permanently deletes specified file. If a transcription that has not started processing yet still references the file, that transcription fails with `file_not_found`, so delete the file only after the transcription reaches `completed` or `error`. ### Parameters * `file_id` (path) (Required): ### Responses * **204**: File deleted. * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: File not found. Error types: * `file_not_found`: No file with this ID exists in the project the API key is scoped to (it may have been deleted, the ID may be wrong, or it may belong to a different project). Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get file URL: /api-reference/stt/files/get_file Retrieve metadata for an uploaded file. ## Get file **Endpoint:** `GET /v1/files/{file_id}` Retrieve metadata for an uploaded file. ### Parameters * `file_id` (path) (Required): ### Responses * **200**: File metadata. Example (JSON): ```json { "client_reference_id": "some_internal_id", "created_at": "2024-11-26T00:00:00Z", "filename": "example.mp3", "id": "84c32fc6-4fb5-4e7a-b656-b5ec70493753", "size": 123456 } ``` Schema (YAML Structural Definition): ```yaml description: File metadata. properties: id: description: Unique identifier of the file. format: uuid type: string filename: description: Name of the file. type: string size: description: Size of the file in bytes. type: integer created_at: description: UTC timestamp indicating when the file was uploaded. format: date-time type: string client_reference_id: anyOf: - type: string - type: 'null' description: Tracking identifier string. required: - id - filename - size - created_at type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: File not found. Error types: * `file_not_found`: No file with this ID exists in the project the API key is scoped to (it may have been deleted, the ID may be wrong, or it may belong to a different project). Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get files URL: /api-reference/stt/files/get_files Retrieves list of uploaded files. ## Get files **Endpoint:** `GET /v1/files` Retrieves list of uploaded files. ### Parameters * `limit` (query): Maximum number of files to return. * `cursor` (query): Pagination cursor for the next page of results. ### Responses * **200**: List of files. Example (JSON): ```json { "files": [ { "created_at": "2024-11-26T00:00:00Z", "filename": "example.mp3", "id": "84c32fc6-4fb5-4e7a-b656-b5ec70493753", "size": 123456 } ], "next_page_cursor": "cursor_or_null" } ``` Schema (YAML Structural Definition): ```yaml description: A list of files. properties: files: description: List of uploaded files. items: description: File metadata. example: client_reference_id: some_internal_id created_at: '2024-11-26T00:00:00Z' filename: example.mp3 id: 84c32fc6-4fb5-4e7a-b656-b5ec70493753 size: 123456 properties: id: description: Unique identifier of the file. format: uuid type: string filename: description: Name of the file. type: string size: description: Size of the file in bytes. type: integer created_at: description: UTC timestamp indicating when the file was uploaded. format: date-time type: string client_reference_id: anyOf: - type: string - type: 'null' description: Tracking identifier string. required: - id - filename - size - created_at type: object type: array next_page_cursor: anyOf: - type: string - type: 'null' description: >- A pagination token that references the next page of results. When more data is available, this field contains a value to pass in the cursor parameter of a subsequent request. When null, no additional results are available. required: - files type: object ``` * **400**: Invalid request. Error types: * `invalid_cursor`: The `cursor` parameter is invalid. Omit `cursor` to start pagination from the beginning. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate, total file count, or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get files count URL: /api-reference/stt/files/get_files_count Returns the total number of files, split by source. ## Get files count **Endpoint:** `GET /v1/files/count` Returns the total number of files, split by source. ### Responses * **200**: Total number of files, split by source. Schema (YAML Structural Definition): ```yaml properties: playground: description: Number of files uploaded via the Playground. type: integer public_api: description: Number of files uploaded via Public API. type: integer total: description: Total number of files across all sources. type: integer required: - total - public_api - playground type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Upload file URL: /api-reference/stt/files/upload_file Uploads a new file. ## Upload file **Endpoint:** `POST /v1/files` Uploads a new file. ### Request Body Content-Type: `multipart/form-data` (Required) Schema (YAML Structural Definition): ```yaml type: object properties: client_reference_id: anyOf: - maxLength: 256 type: string - type: 'null' description: Optional tracking identifier string. Does not need to be unique. file: description: >- The file to upload. Original file name will be used unless a custom filename is provided. format: binary type: string required: - file ``` ### Responses * **201**: Uploaded file. Example (JSON): ```json { "client_reference_id": "some_internal_id", "created_at": "2024-11-26T00:00:00Z", "filename": "example.mp3", "id": "84c32fc6-4fb5-4e7a-b656-b5ec70493753", "size": 123456 } ``` Schema (YAML Structural Definition): ```yaml description: File metadata. properties: id: description: Unique identifier of the file. format: uuid type: string filename: description: Name of the file. type: string size: description: Size of the file in bytes. type: integer created_at: description: UTC timestamp indicating when the file was uploaded. format: date-time type: string client_reference_id: anyOf: - type: string - type: 'null' description: Tracking identifier string. required: - id - filename - size - created_at type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: One or more parts of the multipart body are missing or invalid (missing `file`, filename or `client_reference_id` too long, malformed multipart body), or the uploaded file exceeds the per-file upload limit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate, the total file count or total file size cap (organization or project), or this upload would exceed those caps. The `message` describes which limit was hit. Delete unused files via `DELETE /v1/files/{id}` or request a higher limit in the Soniox Console. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get models URL: /api-reference/stt/get_models Retrieves list of available models and their attributes. ## Get models **Endpoint:** `GET /v1/models` Retrieves list of available models and their attributes. ### Responses * **200**: List of available models and their attributes. Example (JSON): ```json { "models": [ { "aliased_model_id": null, "context_version": 2, "id": "stt-rt-v4", "languages": [ { "code": "af", "name": "Afrikaans" }, { "code": "sq", "name": "Albanian" }, { "code": "ar", "name": "Arabic" }, { "code": "az", "name": "Azerbaijani" }, { "code": "eu", "name": "Basque" }, { "code": "be", "name": "Belarusian" }, { "code": "bn", "name": "Bengali" }, { "code": "bs", "name": "Bosnian" }, { "code": "bg", "name": "Bulgarian" }, { "code": "ca", "name": "Catalan" }, { "code": "zh", "name": "Chinese" }, { "code": "hr", "name": "Croatian" }, { "code": "cs", "name": "Czech" }, { "code": "da", "name": "Danish" }, { "code": "nl", "name": "Dutch" }, { "code": "en", "name": "English" }, { "code": "et", "name": "Estonian" }, { "code": "fi", "name": "Finnish" }, { "code": "fr", "name": "French" }, { "code": "gl", "name": "Galician" }, { "code": "de", "name": "German" }, { "code": "el", "name": "Greek" }, { "code": "gu", "name": "Gujarati" }, { "code": "he", "name": "Hebrew" }, { "code": "hi", "name": "Hindi" }, { "code": "hu", "name": "Hungarian" }, { "code": "id", "name": "Indonesian" }, { "code": "it", "name": "Italian" }, { "code": "ja", "name": "Japanese" }, { "code": "kn", "name": "Kannada" }, { "code": "kk", "name": "Kazakh" }, { "code": "ko", "name": "Korean" }, { "code": "lv", "name": "Latvian" }, { "code": "lt", "name": "Lithuanian" }, { "code": "mk", "name": "Macedonian" }, { "code": "ms", "name": "Malay" }, { "code": "ml", "name": "Malayalam" }, { "code": "mr", "name": "Marathi" }, { "code": "no", "name": "Norwegian" }, { "code": "fa", "name": "Persian" }, { "code": "pl", "name": "Polish" }, { "code": "pt", "name": "Portuguese" }, { "code": "pa", "name": "Punjabi" }, { "code": "ro", "name": "Romanian" }, { "code": "ru", "name": "Russian" }, { "code": "sr", "name": "Serbian" }, { "code": "sk", "name": "Slovak" }, { "code": "sl", "name": "Slovenian" }, { "code": "es", "name": "Spanish" }, { "code": "sw", "name": "Swahili" }, { "code": "sv", "name": "Swedish" }, { "code": "tl", "name": "Tagalog" }, { "code": "ta", "name": "Tamil" }, { "code": "te", "name": "Telugu" }, { "code": "th", "name": "Thai" }, { "code": "tr", "name": "Turkish" }, { "code": "uk", "name": "Ukrainian" }, { "code": "ur", "name": "Urdu" }, { "code": "vi", "name": "Vietnamese" }, { "code": "cy", "name": "Welsh" } ], "name": "Speech-to-Text Real-time v4", "one_way_translation": "all_languages", "endpoint_latency_adjustment_max_level": 0, "supports_endpoint_latency_adjustment": false, "supports_endpoint_sensitivity": false, "supports_language_hints_strict": true, "supports_max_endpoint_delay": true, "transcription_mode": "real_time", "translation_targets": [], "two_way_translation": "all_languages", "two_way_translation_pairs": [] }, { "aliased_model_id": null, "context_version": 2, "id": "stt-rt-v3", "languages": [ { "code": "af", "name": "Afrikaans" }, { "code": "sq", "name": "Albanian" }, { "code": "ar", "name": "Arabic" }, { "code": "az", "name": "Azerbaijani" }, { "code": "eu", "name": "Basque" }, { "code": "be", "name": "Belarusian" }, { "code": "bn", "name": "Bengali" }, { "code": "bs", "name": "Bosnian" }, { "code": "bg", "name": "Bulgarian" }, { "code": "ca", "name": "Catalan" }, { "code": "zh", "name": "Chinese" }, { "code": "hr", "name": "Croatian" }, { "code": "cs", "name": "Czech" }, { "code": "da", "name": "Danish" }, { "code": "nl", "name": "Dutch" }, { "code": "en", "name": "English" }, { "code": "et", "name": "Estonian" }, { "code": "fi", "name": "Finnish" }, { "code": "fr", "name": "French" }, { "code": "gl", "name": "Galician" }, { "code": "de", "name": "German" }, { "code": "el", "name": "Greek" }, { "code": "gu", "name": "Gujarati" }, { "code": "he", "name": "Hebrew" }, { "code": "hi", "name": "Hindi" }, { "code": "hu", "name": "Hungarian" }, { "code": "id", "name": "Indonesian" }, { "code": "it", "name": "Italian" }, { "code": "ja", "name": "Japanese" }, { "code": "kn", "name": "Kannada" }, { "code": "kk", "name": "Kazakh" }, { "code": "ko", "name": "Korean" }, { "code": "lv", "name": "Latvian" }, { "code": "lt", "name": "Lithuanian" }, { "code": "mk", "name": "Macedonian" }, { "code": "ms", "name": "Malay" }, { "code": "ml", "name": "Malayalam" }, { "code": "mr", "name": "Marathi" }, { "code": "no", "name": "Norwegian" }, { "code": "fa", "name": "Persian" }, { "code": "pl", "name": "Polish" }, { "code": "pt", "name": "Portuguese" }, { "code": "pa", "name": "Punjabi" }, { "code": "ro", "name": "Romanian" }, { "code": "ru", "name": "Russian" }, { "code": "sr", "name": "Serbian" }, { "code": "sk", "name": "Slovak" }, { "code": "sl", "name": "Slovenian" }, { "code": "es", "name": "Spanish" }, { "code": "sw", "name": "Swahili" }, { "code": "sv", "name": "Swedish" }, { "code": "tl", "name": "Tagalog" }, { "code": "ta", "name": "Tamil" }, { "code": "te", "name": "Telugu" }, { "code": "th", "name": "Thai" }, { "code": "tr", "name": "Turkish" }, { "code": "uk", "name": "Ukrainian" }, { "code": "ur", "name": "Urdu" }, { "code": "vi", "name": "Vietnamese" }, { "code": "cy", "name": "Welsh" } ], "name": "Speech-to-Text Real-time v3", "one_way_translation": "all_languages", "endpoint_latency_adjustment_max_level": 0, "supports_endpoint_latency_adjustment": false, "supports_endpoint_sensitivity": false, "supports_language_hints_strict": true, "supports_max_endpoint_delay": false, "transcription_mode": "real_time", "translation_targets": [], "two_way_translation": "all_languages", "two_way_translation_pairs": [] }, { "aliased_model_id": null, "context_version": 2, "id": "stt-async-v4", "languages": [ { "code": "af", "name": "Afrikaans" }, { "code": "sq", "name": "Albanian" }, { "code": "ar", "name": "Arabic" }, { "code": "az", "name": "Azerbaijani" }, { "code": "eu", "name": "Basque" }, { "code": "be", "name": "Belarusian" }, { "code": "bn", "name": "Bengali" }, { "code": "bs", "name": "Bosnian" }, { "code": "bg", "name": "Bulgarian" }, { "code": "ca", "name": "Catalan" }, { "code": "zh", "name": "Chinese" }, { "code": "hr", "name": "Croatian" }, { "code": "cs", "name": "Czech" }, { "code": "da", "name": "Danish" }, { "code": "nl", "name": "Dutch" }, { "code": "en", "name": "English" }, { "code": "et", "name": "Estonian" }, { "code": "fi", "name": "Finnish" }, { "code": "fr", "name": "French" }, { "code": "gl", "name": "Galician" }, { "code": "de", "name": "German" }, { "code": "el", "name": "Greek" }, { "code": "gu", "name": "Gujarati" }, { "code": "he", "name": "Hebrew" }, { "code": "hi", "name": "Hindi" }, { "code": "hu", "name": "Hungarian" }, { "code": "id", "name": "Indonesian" }, { "code": "it", "name": "Italian" }, { "code": "ja", "name": "Japanese" }, { "code": "kn", "name": "Kannada" }, { "code": "kk", "name": "Kazakh" }, { "code": "ko", "name": "Korean" }, { "code": "lv", "name": "Latvian" }, { "code": "lt", "name": "Lithuanian" }, { "code": "mk", "name": "Macedonian" }, { "code": "ms", "name": "Malay" }, { "code": "ml", "name": "Malayalam" }, { "code": "mr", "name": "Marathi" }, { "code": "no", "name": "Norwegian" }, { "code": "fa", "name": "Persian" }, { "code": "pl", "name": "Polish" }, { "code": "pt", "name": "Portuguese" }, { "code": "pa", "name": "Punjabi" }, { "code": "ro", "name": "Romanian" }, { "code": "ru", "name": "Russian" }, { "code": "sr", "name": "Serbian" }, { "code": "sk", "name": "Slovak" }, { "code": "sl", "name": "Slovenian" }, { "code": "es", "name": "Spanish" }, { "code": "sw", "name": "Swahili" }, { "code": "sv", "name": "Swedish" }, { "code": "tl", "name": "Tagalog" }, { "code": "ta", "name": "Tamil" }, { "code": "te", "name": "Telugu" }, { "code": "th", "name": "Thai" }, { "code": "tr", "name": "Turkish" }, { "code": "uk", "name": "Ukrainian" }, { "code": "ur", "name": "Urdu" }, { "code": "vi", "name": "Vietnamese" }, { "code": "cy", "name": "Welsh" } ], "name": "Speech-to-Text Async v4", "one_way_translation": "all_languages", "endpoint_latency_adjustment_max_level": 0, "supports_endpoint_latency_adjustment": false, "supports_endpoint_sensitivity": false, "supports_language_hints_strict": true, "supports_max_endpoint_delay": false, "transcription_mode": "async", "translation_targets": [], "two_way_translation": "all_languages", "two_way_translation_pairs": [] }, { "aliased_model_id": null, "context_version": 2, "id": "stt-async-v3", "languages": [ { "code": "af", "name": "Afrikaans" }, { "code": "sq", "name": "Albanian" }, { "code": "ar", "name": "Arabic" }, { "code": "az", "name": "Azerbaijani" }, { "code": "eu", "name": "Basque" }, { "code": "be", "name": "Belarusian" }, { "code": "bn", "name": "Bengali" }, { "code": "bs", "name": "Bosnian" }, { "code": "bg", "name": "Bulgarian" }, { "code": "ca", "name": "Catalan" }, { "code": "zh", "name": "Chinese" }, { "code": "hr", "name": "Croatian" }, { "code": "cs", "name": "Czech" }, { "code": "da", "name": "Danish" }, { "code": "nl", "name": "Dutch" }, { "code": "en", "name": "English" }, { "code": "et", "name": "Estonian" }, { "code": "fi", "name": "Finnish" }, { "code": "fr", "name": "French" }, { "code": "gl", "name": "Galician" }, { "code": "de", "name": "German" }, { "code": "el", "name": "Greek" }, { "code": "gu", "name": "Gujarati" }, { "code": "he", "name": "Hebrew" }, { "code": "hi", "name": "Hindi" }, { "code": "hu", "name": "Hungarian" }, { "code": "id", "name": "Indonesian" }, { "code": "it", "name": "Italian" }, { "code": "ja", "name": "Japanese" }, { "code": "kn", "name": "Kannada" }, { "code": "kk", "name": "Kazakh" }, { "code": "ko", "name": "Korean" }, { "code": "lv", "name": "Latvian" }, { "code": "lt", "name": "Lithuanian" }, { "code": "mk", "name": "Macedonian" }, { "code": "ms", "name": "Malay" }, { "code": "ml", "name": "Malayalam" }, { "code": "mr", "name": "Marathi" }, { "code": "no", "name": "Norwegian" }, { "code": "fa", "name": "Persian" }, { "code": "pl", "name": "Polish" }, { "code": "pt", "name": "Portuguese" }, { "code": "pa", "name": "Punjabi" }, { "code": "ro", "name": "Romanian" }, { "code": "ru", "name": "Russian" }, { "code": "sr", "name": "Serbian" }, { "code": "sk", "name": "Slovak" }, { "code": "sl", "name": "Slovenian" }, { "code": "es", "name": "Spanish" }, { "code": "sw", "name": "Swahili" }, { "code": "sv", "name": "Swedish" }, { "code": "tl", "name": "Tagalog" }, { "code": "ta", "name": "Tamil" }, { "code": "te", "name": "Telugu" }, { "code": "th", "name": "Thai" }, { "code": "tr", "name": "Turkish" }, { "code": "uk", "name": "Ukrainian" }, { "code": "ur", "name": "Urdu" }, { "code": "vi", "name": "Vietnamese" }, { "code": "cy", "name": "Welsh" } ], "name": "Speech-to-Text Async v3", "one_way_translation": "all_languages", "endpoint_latency_adjustment_max_level": 0, "supports_endpoint_latency_adjustment": false, "supports_endpoint_sensitivity": false, "supports_language_hints_strict": false, "supports_max_endpoint_delay": false, "transcription_mode": "async", "translation_targets": [], "two_way_translation": "all_languages", "two_way_translation_pairs": [] } ] } ``` Schema (YAML Structural Definition): ```yaml properties: models: description: List of available models and their attributes. items: properties: id: description: Unique identifier of the model. type: string aliased_model_id: anyOf: - type: string - type: 'null' description: If this is an alias, the id of the aliased model. name: description: Name of the model. type: string context_version: anyOf: - type: integer - type: 'null' description: Version of context supported. transcription_mode: description: Transcription mode of the model. enum: - real_time - async type: string languages: description: List of languages supported by the model. items: properties: code: description: 2-letter language code. type: string name: description: Language name. type: string required: - code - name type: object type: array supports_language_hints_strict: type: boolean supports_max_endpoint_delay: type: boolean supports_endpoint_sensitivity: type: boolean supports_endpoint_latency_adjustment: type: boolean endpoint_latency_adjustment_max_level: description: >- Maximum endpoint_latency_adjustment_level the model accepts. Valid levels are 0 (no adjustment) through this value; 0 means the feature is unsupported. type: integer translation_targets: description: >- List of supported one-way translation targets. If list is empty, check for one_way_translation field items: properties: target_language: type: string source_languages: items: type: string type: array exclude_source_languages: items: type: string type: array required: - target_language - source_languages - exclude_source_languages type: object type: array two_way_translation_pairs: description: >- List of supported two-way translation pairs. If list is empty, check for two_way_translation field items: type: string type: array one_way_translation: anyOf: - type: string - type: 'null' description: >- When contains string 'all_languages', any laguage from languages can be used two_way_translation: anyOf: - type: string - type: 'null' description: >- When contains string 'all_languages',' any laguage pair from languages can be used required: - id - aliased_model_id - name - context_version - transcription_mode - languages - supports_language_hints_strict - supports_max_endpoint_delay - supports_endpoint_sensitivity - supports_endpoint_latency_adjustment - endpoint_latency_adjustment_max_level - translation_targets - two_way_translation_pairs - one_way_translation - two_way_translation type: object type: array required: - models type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Create transcription URL: /api-reference/stt/transcriptions/create_transcription Creates a new transcription. ## Create transcription **Endpoint:** `POST /v1/transcriptions` Creates a new transcription. ### Request Body Content-Type: `application/json` (Required) Schema (YAML Structural Definition): ```yaml properties: model: description: Speech-to-text model to use for the transcription. maxLength: 32 type: string audio_url: anyOf: - maxLength: 4096 pattern: ^https?://[^\s]+$ type: string - type: 'null' description: >- URL of the audio file to transcribe. Cannot be specified if `file_id` is specified. file_id: anyOf: - format: uuid type: string - type: 'null' description: >- ID of the uploaded file to transcribe. Cannot be specified if `audio_url` is specified. Keep the file until the transcription reaches `completed` or `error`; deleting it earlier fails the transcription with `file_not_found`. language_hints: anyOf: - items: maxLength: 10 type: string maxItems: 100 type: array - type: 'null' description: >- Expected languages in the audio. If not specified, languages are automatically detected. language_hints_strict: anyOf: - type: boolean - type: 'null' description: When `true`, the model will rely more on language hints. enable_speaker_diarization: anyOf: - type: boolean - type: 'null' description: >- When `true`, speakers are identified and separated in the transcription output. enable_language_identification: anyOf: - type: boolean - type: 'null' description: When `true`, language is detected for each part of the transcription. translation: anyOf: - properties: type: enum: - one_way - two_way type: string target_language: anyOf: - type: string - type: 'null' language_a: anyOf: - type: string - type: 'null' language_b: anyOf: - type: string - type: 'null' required: - type type: object - type: 'null' description: Translation configuration. context: anyOf: - properties: general: anyOf: - items: properties: key: description: Item key (e.g. "Domain"). type: string value: description: Item value (e.g. "medicine"). type: string required: - key - value type: object type: array - type: 'null' description: General context items. text: anyOf: - type: string - type: 'null' description: Text context. terms: anyOf: - items: type: string type: array - type: 'null' description: Terms that might occur in speech. translation_terms: anyOf: - items: properties: source: description: Source term. type: string target: description: Target term to translate to. type: string required: - source - target type: object type: array - type: 'null' description: >- Hints how to translate specific terms. Ignored if translation is not enabled. type: object - type: string - type: 'null' description: >- Additional context to improve transcription accuracy and formatting of specialized terms. webhook_url: anyOf: - maxLength: 256 pattern: ^https?://[^\s]+$ type: string - type: 'null' description: >- URL to receive webhook notifications when transcription is completed or fails. webhook_auth_header_name: anyOf: - maxLength: 256 type: string - type: 'null' description: Name of the authentication header sent with webhook notifications. webhook_auth_header_value: anyOf: - maxLength: 256 type: string - type: 'null' description: Authentication header value sent with webhook notifications. client_reference_id: anyOf: - maxLength: 256 type: string - type: 'null' description: Optional tracking identifier string. Does not need to be unique. required: - model type: object ``` ### Responses * **201**: Created transcription. Example (JSON): ```json { "audio_duration_ms": 0, "audio_url": "https://soniox.com/media/examples/coffee_shop.mp3", "client_reference_id": "some_internal_id", "created_at": "2024-11-26T00:00:00Z", "error_message": null, "error_type": null, "file_id": null, "filename": "coffee_shop.mp3", "id": "73d4357d-cad2-4338-a60d-ec6f2044f721", "language_hints": [ "en", "fr" ], "model": "stt-async-preview", "status": "queued", "webhook_auth_header_name": "Authorization", "webhook_auth_header_value": "******************", "webhook_status_code": null, "webhook_url": "https://example.com/webhook" } ``` Schema (YAML Structural Definition): ```yaml description: A transcription. properties: id: description: Unique identifier for the transcription request. format: uuid type: string status: description: Transcription status. enum: - queued - processing - completed - error type: string created_at: description: UTC timestamp indicating when the transcription was created. format: date-time type: string model: description: Speech-to-text model used for the transcription. type: string audio_url: anyOf: - type: string - type: 'null' description: URL of the file being transcribed. file_id: anyOf: - format: uuid type: string - type: 'null' description: ID of the file being transcribed. filename: description: Name of the file being transcribed. type: string language_hints: anyOf: - items: type: string type: array - type: 'null' description: >- Expected languages in the audio. If not specified, languages are automatically detected. enable_speaker_diarization: description: >- When `true`, speakers are identified and separated in the transcription output. type: boolean enable_language_identification: description: When `true`, language is detected for each part of the transcription. type: boolean audio_duration_ms: anyOf: - type: integer - type: 'null' description: >- Duration of the audio in milliseconds. Only available after processing begins. error_type: anyOf: - type: string - type: 'null' description: >- Error type if transcription failed. `null` for successful or in-progress transcriptions. error_message: anyOf: - type: string - type: 'null' description: >- Error message if transcription failed. `null` for successful or in-progress transcriptions. webhook_url: anyOf: - type: string - type: 'null' description: >- URL to receive webhook notifications when transcription is completed or fails. webhook_auth_header_name: anyOf: - type: string - type: 'null' description: Name of the authentication header sent with webhook notifications. webhook_auth_header_value: anyOf: - type: string - type: 'null' description: >- Authentication header value. Always returned masked as `******************`. webhook_status_code: anyOf: - type: integer - type: 'null' description: >- HTTP status code received from your server when webhook was delivered. `null` if not yet sent. client_reference_id: anyOf: - type: string - type: 'null' description: Tracking identifier string. required: - id - status - created_at - model - filename - enable_speaker_diarization - enable_language_identification type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: One or more request body fields are missing or invalid (model, audio source, language hints, translation config, webhook config, etc.). Inspect `validation_errors`. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **402**: Balance or budget exhausted. Error types: * `organization_balance_exhausted`: The organization's prepaid balance has dropped to zero. Top up at [https://console.soniox.com/org/billing/overview](https://console.soniox.com/org/billing/overview) or enable autopay. * `organization_monthly_budget_exhausted`: The organization has hit its configured monthly budget cap. Raise the cap at [https://console.soniox.com/org/limits](https://console.soniox.com/org/limits), or wait for the month to roll over. * `project_monthly_budget_exhausted`: The project has hit its configured monthly budget cap. Raise the cap at [https://console.soniox.com/org/projects/limits](https://console.soniox.com/org/projects/limits), or wait for the month to roll over. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate, total transcription count, or pending transcription count limit (organization or project). The `message` describes which limit was hit. Delete completed transcriptions via `DELETE /v1/transcriptions/{id}` or request a higher limit in the Soniox Console. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Delete transcription URL: /api-reference/stt/transcriptions/delete_transcription Permanently deletes a transcription. Files uploaded through the Files API are not deleted; use the delete file endpoint to remove them. Cannot delete transcriptions that are currently processing. ## Delete transcription **Endpoint:** `DELETE /v1/transcriptions/{transcription_id}` Permanently deletes a transcription. Files uploaded through the Files API are not deleted; use the delete file endpoint to remove them. Cannot delete transcriptions that are currently processing. ### Parameters * `transcription_id` (path) (Required): ### Responses * **204**: Transcription deleted. * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Transcription not found. Error types: * `transcription_not_found`: No transcription with this ID exists in the project the API key is scoped to (it may have been deleted, the ID may be wrong, or it may belong to a different project). Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **409**: Invalid transcription state. Error types: * `transcription_invalid_state`: The transcription cannot be deleted in its current state — it is still processing. Wait until `status` reaches `completed` or `error` and retry. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get transcription URL: /api-reference/stt/transcriptions/get_transcription Retrieves detailed information about a specific transcription. ## Get transcription **Endpoint:** `GET /v1/transcriptions/{transcription_id}` Retrieves detailed information about a specific transcription. ### Parameters * `transcription_id` (path) (Required): ### Responses * **200**: Transcription details. Example (JSON): ```json { "audio_duration_ms": 0, "audio_url": "https://soniox.com/media/examples/coffee_shop.mp3", "client_reference_id": "some_internal_id", "created_at": "2024-11-26T00:00:00Z", "error_message": null, "error_type": null, "file_id": null, "filename": "coffee_shop.mp3", "id": "73d4357d-cad2-4338-a60d-ec6f2044f721", "language_hints": [ "en", "fr" ], "model": "stt-async-preview", "status": "queued", "webhook_auth_header_name": "Authorization", "webhook_auth_header_value": "******************", "webhook_status_code": null, "webhook_url": "https://example.com/webhook" } ``` Schema (YAML Structural Definition): ```yaml description: A transcription. properties: id: description: Unique identifier for the transcription request. format: uuid type: string status: description: Transcription status. enum: - queued - processing - completed - error type: string created_at: description: UTC timestamp indicating when the transcription was created. format: date-time type: string model: description: Speech-to-text model used for the transcription. type: string audio_url: anyOf: - type: string - type: 'null' description: URL of the file being transcribed. file_id: anyOf: - format: uuid type: string - type: 'null' description: ID of the file being transcribed. filename: description: Name of the file being transcribed. type: string language_hints: anyOf: - items: type: string type: array - type: 'null' description: >- Expected languages in the audio. If not specified, languages are automatically detected. enable_speaker_diarization: description: >- When `true`, speakers are identified and separated in the transcription output. type: boolean enable_language_identification: description: When `true`, language is detected for each part of the transcription. type: boolean audio_duration_ms: anyOf: - type: integer - type: 'null' description: >- Duration of the audio in milliseconds. Only available after processing begins. error_type: anyOf: - type: string - type: 'null' description: >- Error type if transcription failed. `null` for successful or in-progress transcriptions. error_message: anyOf: - type: string - type: 'null' description: >- Error message if transcription failed. `null` for successful or in-progress transcriptions. webhook_url: anyOf: - type: string - type: 'null' description: >- URL to receive webhook notifications when transcription is completed or fails. webhook_auth_header_name: anyOf: - type: string - type: 'null' description: Name of the authentication header sent with webhook notifications. webhook_auth_header_value: anyOf: - type: string - type: 'null' description: >- Authentication header value. Always returned masked as `******************`. webhook_status_code: anyOf: - type: integer - type: 'null' description: >- HTTP status code received from your server when webhook was delivered. `null` if not yet sent. client_reference_id: anyOf: - type: string - type: 'null' description: Tracking identifier string. required: - id - status - created_at - model - filename - enable_speaker_diarization - enable_language_identification type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Transcription not found. Error types: * `transcription_not_found`: No transcription with this ID exists in the project the API key is scoped to (it may have been deleted, the ID may be wrong, or it may belong to a different project). Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get transcription transcript URL: /api-reference/stt/transcriptions/get_transcription_transcript Retrieves the full transcript text and detailed tokens for a completed transcription. Only available for successfully completed transcriptions. ## Get transcription transcript **Endpoint:** `GET /v1/transcriptions/{transcription_id}/transcript` Retrieves the full transcript text and detailed tokens for a completed transcription. Only available for successfully completed transcriptions. ### Parameters * `transcription_id` (path) (Required): ### Responses * **200**: Transcription transcript. Example (JSON): ```json { "id": "19b6d61d-02db-4c25-bc71-b4094dc310c8", "text": "Hello", "tokens": [ { "confidence": 0.95, "end_ms": 90, "start_ms": 10, "text": "Hel" }, { "confidence": 0.98, "end_ms": 160, "start_ms": 110, "text": "lo" } ] } ``` Schema (YAML Structural Definition): ```yaml description: The transcription text. properties: id: description: Unique identifier of the transcription this transcript belongs to. format: uuid type: string text: description: Complete transcribed text content. type: string tokens: description: List of detailed token information with timestamps and metadata. items: description: The transcript token. example: confidence: 0.95 end_ms: 90 start_ms: 10 text: Hel properties: text: description: Token text content. type: string start_ms: description: Start time of the token in milliseconds. type: integer end_ms: description: End time of the token in milliseconds. type: integer confidence: description: Confidence score of the token, between 0.0 and 1.0. type: number speaker: anyOf: - type: string - type: 'null' description: >- Speaker identifier. Only present when speaker diarization is enabled. language: anyOf: - type: string - type: 'null' description: >- Detected language code for this token. Only present when language identification is enabled. is_audio_event: anyOf: - type: boolean - type: 'null' description: >- Boolean indicating if this token represents an audio event. Only present when audio event detection is enabled. translation_status: anyOf: - type: string - type: 'null' description: >- Translation status ("none", "original" or "translation"). Only when if translation is enabled. required: - text - start_ms - end_ms - confidence type: object type: array required: - id - text - tokens type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Transcription not found. Error types: * `transcription_not_found`: No transcription with this ID exists in the project the API key is scoped to (it may have been deleted, the ID may be wrong, or it may belong to a different project). Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **409**: Invalid transcription state. The transcription exists but the transcript cannot be returned in its current state. Error types: * `transcription_invalid_state`. The `message` indicates which sub-case applies: * **Not completed yet** — transcription is still queued, downloading, or transcribing. Poll `GET /transcriptions/{id}` until `status` is `completed`, or configure a webhook on the transcription. * **Failed** — transcription ended in `failed` state. Inspect `error_type` / `error_message` on `GET /transcriptions/{id}` for the failure reason. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get transcriptions URL: /api-reference/stt/transcriptions/get_transcriptions Retrieves list of transcriptions. ## Get transcriptions **Endpoint:** `GET /v1/transcriptions` Retrieves list of transcriptions. ### Parameters * `limit` (query): Maximum number of transcriptions to return. * `cursor` (query): Pagination cursor for the next page of results. ### Responses * **200**: A list of transcriptions. Schema (YAML Structural Definition): ```yaml properties: transcriptions: description: List of transcriptions. items: description: A transcription. example: audio_duration_ms: 0 audio_url: https://soniox.com/media/examples/coffee_shop.mp3 client_reference_id: some_internal_id created_at: '2024-11-26T00:00:00Z' error_message: null error_type: null file_id: null filename: coffee_shop.mp3 id: 73d4357d-cad2-4338-a60d-ec6f2044f721 language_hints: - en - fr model: stt-async-preview status: queued webhook_auth_header_name: Authorization webhook_auth_header_value: '******************' webhook_status_code: null webhook_url: https://example.com/webhook properties: id: description: Unique identifier for the transcription request. format: uuid type: string status: description: Transcription status. enum: - queued - processing - completed - error type: string created_at: description: UTC timestamp indicating when the transcription was created. format: date-time type: string model: description: Speech-to-text model used for the transcription. type: string audio_url: anyOf: - type: string - type: 'null' description: URL of the file being transcribed. file_id: anyOf: - format: uuid type: string - type: 'null' description: ID of the file being transcribed. filename: description: Name of the file being transcribed. type: string language_hints: anyOf: - items: type: string type: array - type: 'null' description: >- Expected languages in the audio. If not specified, languages are automatically detected. enable_speaker_diarization: description: >- When `true`, speakers are identified and separated in the transcription output. type: boolean enable_language_identification: description: >- When `true`, language is detected for each part of the transcription. type: boolean audio_duration_ms: anyOf: - type: integer - type: 'null' description: >- Duration of the audio in milliseconds. Only available after processing begins. error_type: anyOf: - type: string - type: 'null' description: >- Error type if transcription failed. `null` for successful or in-progress transcriptions. error_message: anyOf: - type: string - type: 'null' description: >- Error message if transcription failed. `null` for successful or in-progress transcriptions. webhook_url: anyOf: - type: string - type: 'null' description: >- URL to receive webhook notifications when transcription is completed or fails. webhook_auth_header_name: anyOf: - type: string - type: 'null' description: Name of the authentication header sent with webhook notifications. webhook_auth_header_value: anyOf: - type: string - type: 'null' description: >- Authentication header value. Always returned masked as `******************`. webhook_status_code: anyOf: - type: integer - type: 'null' description: >- HTTP status code received from your server when webhook was delivered. `null` if not yet sent. client_reference_id: anyOf: - type: string - type: 'null' description: Tracking identifier string. required: - id - status - created_at - model - filename - enable_speaker_diarization - enable_language_identification type: object type: array next_page_cursor: anyOf: - type: string - type: 'null' description: >- A pagination token that references the next page of results. When more data is available, this field contains a value to pass in the cursor parameter of a subsequent request. When null, no additional results are available. required: - transcriptions type: object ``` * **400**: Invalid request. Error types: * `invalid_cursor`: The `cursor` parameter is invalid. Omit `cursor` to start pagination from the beginning. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get transcriptions count URL: /api-reference/stt/transcriptions/get_transcriptions_count Returns the total number of transcriptions, split by request scope. ## Get transcriptions count **Endpoint:** `GET /v1/transcriptions/count` Returns the total number of transcriptions, split by request scope. ### Responses * **200**: Total number of transcriptions, split by request scope. Schema (YAML Structural Definition): ```yaml properties: playground: description: Number of transcriptions created via the Playground. type: integer public_api: description: Number of transcriptions created via Public API. type: integer total: description: Total number of transcriptions across all scopes. type: integer required: - total - public_api - playground type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate or other capacity limit. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # WebSocket API URL: /api-reference/stt/websocket-api Learn how to use and integrate Soniox Speech-to-Text WebSocket API. import { Badge } from "@openapi/ui/components/method-label"; ## Overview The **Soniox WebSocket API** provides real-time **transcription and translation** of live audio with ultra-low latency. It supports advanced features like **speaker diarization, context customization,** and **manual finalization** — all over a persistent WebSocket connection. Ideal for live scenarios such as meetings, broadcasts, multilingual communication, and voice interfaces. *** ## WebSocket endpoint Connect to the API using: ```text wss://stt-rt.soniox.com/transcribe-websocket ``` *** ## Authentication Send your API key with the connection, in the Authorization header or the protocols list. See [WebSocket authentication](/guides/websocket-authentication). The key sent with the connection is the connection's key for its whole life. The `api_key` field of the start request is **deprecated**. From **15 January 2027** a connection that sends its key only there is refused. See [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). *** ## Configuration Before streaming audio, configure the transcription session by sending a JSON message such as: ```json { "model": "stt-rt-v5", "audio_format": "auto", "language_hints": ["en", "es"], "context": { "general": [ { "key": "domain", "value": "Healthcare" }, { "key": "topic", "value": "Diabetes management consultation" }, { "key": "doctor", "value": "Dr. Martha Smith" }, { "key": "patient", "value": "Mr. David Miller" }, { "key": "organization", "value": "St John's Hospital" } ], "text": "Mr. David Miller visited his healthcare provider last month for a routine follow-up related to diabetes care. The clinician reviewed his recent test results, noted improved glucose levels, and adjusted his medication schedule accordingly. They also discussed meal planning strategies and scheduled the next check-up for early spring.", "terms": [ "Celebrex", "Zyrtec", "Xanax", "Prilosec", "Amoxicillin Clavulanate Potassium" ], "translation_terms": [ { "source": "Mr. Smith", "target": "Sr. Smith" }, { "source": "St John's", "target": "St John's" }, { "source": "stroke", "target": "ictus" } ] }, "enable_speaker_diarization": true, "enable_language_identification": true, "translation": { "type": "two_way", "language_a": "en", "language_b": "es" } } ``` *** ### Parameters **Deprecated.** Send the API key with the connection instead; see [Authentication](#authentication) and [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). Real-time model to use. See [models](/stt/models).
Example: `"stt-rt-v5"`
Audio format of the stream. See [audio formats](/stt/rt/real-time-transcription#audio-formats). Required for raw audio formats. See [audio formats](/stt/rt/real-time-transcription#audio-formats). Required for raw audio formats. See [audio formats](/stt/rt/real-time-transcription#audio-formats). See [language hints](/stt/concepts/language-hints). See [language restrictions](/stt/concepts/language-restrictions). See [context](/stt/concepts/context). See [speaker diarization](/stt/concepts/speaker-diarization). See [language identification](/stt/concepts/language-identification). See [endpoint detection](/stt/rt/endpoint-detection). Must be between 500 and 3000. Default value is 2000. See [endpoint detection](/stt/rt/endpoint-detection). Must be between -1.0 and 1.0. Default value is 0.0. Supported only by the Soniox v5 model. See [endpoint detection](/stt/rt/endpoint-detection). Must be between 0 and 3. Default value is 0. Supported only by the Soniox v5 model. See [endpoint detection](/stt/rt/endpoint-detection). Optional client-defined identifier recorded with this request in [usage logs](/guides/usage-logs). Does not need to be unique. Ignored if the request authenticates with a [temporary API key](/guides/temporary-api-keys). See [real-time translation](/translation/stt-translation/rt-translation).

**One-way translation**

Must be set to `one_way`. Language to translate the transcript into.

**Two-way translation**

Must be set to `two_way`. First language for two-way translation. Second language for two-way translation.
*** ## Connection timeouts There is no deadline for the start request, but send a [keepalive](/stt/rt/connection-keepalive) control message at least every **40 seconds** until it, or the connection is closed as idle with WebSocket status `1001`. The connection counts against your connection limit the whole time. After the start request, the keepalive rules apply as usual. Open connections, including idle ones, count against a connection limit, a multiple of your concurrent requests limit; see [Limits & quotas](/stt/rt/limits-and-quotas). Full details in [WebSocket authentication](/guides/websocket-authentication). Still sending `api_key` in the start request? Different timeouts apply; see [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). *** ## Audio streaming After configuration, start streaming audio: * Send audio as binary WebSocket frames. * Each stream supports up to 300 minutes of audio. *** ## Ending the stream To gracefully close a streaming session: * Send an **empty text frame**, an empty string. An empty binary frame is an empty audio chunk and does not end the stream. * The server will return one or more responses, including [finished response](#finished-response), and then close the connection. *** ## Response Soniox returns **responses** in JSON format. A typical successful response looks like: ```json { "tokens": [ { "text": "Hello", "start_ms": 600, "end_ms": 760, "confidence": 0.97, "is_final": true, "speaker": "1" } ], "final_audio_proc_ms": 760, "total_audio_proc_ms": 880 } ``` ### Field descriptions List of processed tokens (words or subwords). Each token may include: Token text. Start timestamp of the token (in milliseconds). Not included if `translation_status` is `translation`. End timestamp of the token (in milliseconds). Not included if `translation_status` is `translation`. Confidence score (`0.0`–`1.0`). Whether the token is finalized. Speaker label (if diarization enabled). See [real-time translation](/translation/stt-translation/rt-translation). Language of the `token.text`. See [real-time translation](/translation/stt-translation/rt-translation). Audio processed into final tokens. Audio processed into final + non-final tokens. *** ## Finished response At the end of a stream, Soniox sends a **final message** to indicate the session is complete: ```json { "tokens": [], "final_audio_proc_ms": 1560, "total_audio_proc_ms": 1680, "finished": true } ``` After this, the server closes the WebSocket connection. *** ## Error response If an error occurs, the server returns an **error message** and immediately closes the connection: ```json { "tokens": [], "error_code": 503, "error_type": "service_unavailable", "error_message": "Cannot continue request (code 11). Please restart the request. Refer to: https://soniox.com/url/cannot-continue-request (request ID 3d37a3bd-5078-47ee-a369-b204e3bbedda)", "more_info": "https://soniox.com/docs/api-reference/errors#service-unavailable", "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda" } ``` Standard HTTP status code of the error. Stable, machine-readable identifier of the error. Branch on this, not on `error_message`. See the [Errors reference](/api-reference/errors) for the full catalog and recovery steps. Human-readable description of the error. Link to the section on the [Errors](/api-reference/errors) page describing this `error_type`. Unique identifier of this request. Include it when contacting [support@soniox.com](mailto:support@soniox.com); server logs are keyed on it. For the full catalog of `error_type` values across all Soniox APIs, see the [Errors reference](/api-reference/errors). Full list of possible error codes and messages: 400 Bad request } > The request is malformed or contains invalid parameters. `error_type` is one of [`invalid_request`](/api-reference/errors#invalid-request) or [`model_not_available`](/api-reference/errors#model-not-available). * `Audio data channels must be specified for PCM formats` * `Audio data sample rate must be specified for PCM formats` * `Audio decode error` * `Audio is too long.` * `Audio frame is not valid base64. Send audio as either a binary WebSocket frame, or a text frame containing standard base64-encoded bytes.` * `` `client_reference_id` is N characters, which exceeds the maximum allowed length of 256. `` * `Context is too long.` * `Context is too long: N tokens, the maximum is 8000 tokens.` * `Control request body is not valid JSON.` * `Control request type is invalid. Valid values: "finalize", "keepalive".` * `Field endpoint_latency_adjustment_level must be between 0 and N.` * `Field endpoint_sensitivity cannot be less than -1.` * `Field endpoint_sensitivity cannot be more than 1.` * `Field max_non_final_tokens_duration_ms cannot be less than N.` * `Field max_non_final_tokens_duration_ms cannot be more than N.` * `Field translation.exclude_source_languages is not supported by model X.` * `Field translation.source_languages cannot be empty.` * `Field translation.source_languages for model X should be empty or it can be one element list having string '*'.` * `Invalid audio data format: avi` * `Invalid language hint.` * `Invalid language in translation.exclude_source_languages: X.` * `Invalid language in translation.language_a.` * `Invalid language in translation.language_b.` * `Invalid language in translation.source_languages: X.` * `Invalid language in translation.target_language.` * `Language hints must be unique.` * `Languages in translation.exclude_source_languages must be unique.` * `Languages in translation.source_languages must be unique.` * `Missing audio format. Specify a valid audio format (e.g. s16le, f32le, wav, ogg, flac...) or "auto" for auto format detection.` * `Model does not support endpoint_latency_adjustment_level.` * `Model does not support endpoint_sensitivity.` * `Model does not support language_hints_strict.` * `Model does not support max_endpoint_delay_ms.` * `Model does not support one way translation.` * `Model does not support two way translation.` * `No audio received.` * `Prompt too long for model` * `Received too much audio data in total.` * `Specified model X does not support real-time transcription. If you wish to use real-time transcription, specify model Y.` * `Send the API key either in the Authorization header or in the WebSocket protocols list, not both.` * `Authorization header must be "Bearer ".` * `soniox-api-key must be sent in the WebSocket protocols list together with exactly one other entry, the API key.` * `The api_key in the start request does not match the API key sent with the connection. Send the same key or omit it.` * `Start request is malformed.` * `Start request must be a text message.` * `The requested model is not available. See https://soniox.com/docs/stt/models for the list of supported models.` * `translation.language_a and translation.language_b must be different (both are X).` * `translation.language_a must be present if translation.language_b is present.` * `translation.language_b must be present if translation.language_a is present.` * `Two way translation between translation.language_a=X and translation.language_b=Y is not supported.` 401 Unauthorized } > Authentication is missing or incorrect. Ensure a valid API key is provided before retrying. `error_type`: [`unauthenticated`](/api-reference/errors#unauthenticated). * `Incorrect API key provided. You can get an API key at https://console.soniox.com` * `Invalid or expired temporary API key. Create a new temporary API key and retry. See https://soniox.com/docs/guides/temporary-api-keys for details.` * `Missing API key. Provide API key as a header (i.e. Authorization: Bearer ). You can get an API key at https://console.soniox.com` * `Missing API key. Send it with the connection: the Authorization header "Bearer ", or soniox-api-key and the key in the WebSocket protocols list.` (from 15 January 2027, for a connection that sends no key with the connection; see [Migrate WebSocket authentication](/guides/migrate-websocket-authentication)) * ``The temporary API key cannot be used for this action. Each temporary API key is scoped to a specific `usage_type`; create a new key with the correct usage type.`` 402 Payment required } > The organization's balance or monthly usage limit has been reached. Additional credits are required before making further requests. `error_type` is one of [`organization_balance_exhausted`](/api-reference/errors#organization-balance-exhausted), [`organization_monthly_budget_exhausted`](/api-reference/errors#organization-monthly-budget-exhausted), or [`project_monthly_budget_exhausted`](/api-reference/errors#project-monthly-budget-exhausted). * `Organization balance exhausted. Please either add funds manually or enable autopay.` * `Organization monthly budget exhausted. Please increase it.` * `Project monthly budget exhausted. Please increase it.` 403 Forbidden } > The API key does not have the permission for real-time speech-to-text, or the temporary API key in use was created with a `max_session_duration_seconds` cap and that duration has elapsed for the current session. `error_type` is one of [`permission_denied`](/api-reference/errors#permission-denied) or [`temp_api_key_session_expired`](/api-reference/errors#temp-api-key-session-expired). * `The API key does not have permission for this product. Edit the key's permissions at https://console.soniox.com` * `Temporary API key session duration limit exceeded. Create a new temporary API key to start a new session.` 408 Request timeout } > A backend call exceeded its deadline before completing. Retry the request. `error_type`: [`request_timeout`](/api-reference/errors#request-timeout). * `Audio data decode timeout` * `Input too slow` * `Request timeout.` * `Timed out while waiting for the first audio chunk` 413 Content too large } > The connection reached the maximum allowed session duration and was closed. Open a new WebSocket connection to continue streaming. `error_type`: [`max_duration_reached`](/api-reference/errors#max-duration-reached). * `This WebSocket connection has reached the maximum allowed duration and was closed. Please open a new WebSocket connection to continue transcribing.` 429 Too many requests } > A usage or rate limit has been exceeded. You may retry after a delay or request an increase in limits via the Soniox Console. `error_type` is one of [`limit_exceeded`](/api-reference/errors#limit-exceeded) or [`max_concurrent_connections_reached`](/api-reference/errors#max-concurrent-connections-reached). * `Concurrent requests limit for real-time transcription has been exceeded for your organization.` * `Concurrent requests limit for real-time transcription has been exceeded for your project.` * `Requests per minute limit for real-time transcription has been exceeded for your organization.` * `Requests per minute limit for real-time transcription has been exceeded for your project.` * `Concurrent WebSocket connections limit for real-time transcription has been exceeded for your organization. Close connections you are not using, or start streams on the ones you hold: the limit is a multiple of your concurrent streams limit.` * `Concurrent WebSocket connections limit for real-time transcription has been exceeded for your project. Close connections you are not using, or start streams on the ones you hold: the limit is a multiple of your concurrent streams limit.` 500 Internal server error } > An unexpected server-side error occurred. The request may be retried. `error_type`: [`internal_error`](/api-reference/errors#internal-error). * `The server had an error processing your request. Sorry about that! You can retry your request, or contact us through our support email support@soniox.com if you keep seeing this error.` 503 Service unavailable } > The service cannot accept the request right now (upstream overload, cache exhausted, shutdown). Retry with backoff. The numeric `(code N)` in the message identifies the sub-cause for support triage. `error_type`: [`service_unavailable`](/api-reference/errors#service-unavailable). * `Cannot continue request (code N). Please restart the request. Refer to: https://soniox.com/url/cannot-continue-request` # Generate speech URL: /api-reference/tts/generate_tts Generates audio from text using the TTS REST endpoint. ## Generate speech **Endpoint:** `POST /tts` Generates audio from text using the TTS REST endpoint. ### Request Body Content-Type: `application/json` (Required) Example (JSON): ```json { "model": "tts-rt-v1", "language": "en", "voice": "Adrian", "audio_format": "wav", "text": "Hello from Soniox Text-to-Speech.", "sample_rate": 24000, "bitrate": 128000, "client_reference_id": "some_internal_id", "speed": 1.2, "reduce_silence": true } ``` Schema (YAML Structural Definition): ```yaml properties: model: default: tts-rt-v1 description: TTS model to use. type: string language: description: Language code of the input text. type: string voice: description: >- Voice to use: a built-in voice name (for example `Adrian`) or the ID of a [cloned voice](https://docs.soniox.com/tts/concepts/voice-cloning). type: string audio_format: description: Output audio format (for example `mp3`, `wav`, `pcm_s16le`, `pcm_s16be`). type: string text: description: Input text to generate audio from. type: string sample_rate: anyOf: - type: integer - type: 'null' description: Optional output sample rate in Hz. bitrate: anyOf: - type: integer - type: 'null' description: Optional output bitrate in bits per second. client_reference_id: anyOf: - maxLength: 256 type: string - type: 'null' description: >- Optional tracking identifier string. Does not need to be unique. Ignored if the request authenticates with a temporary API key. speed: anyOf: - type: number - type: 'null' description: >- Optional speaking rate of the generated speech, from `0.7` to `1.3`. `1.0` is the normal speed; lower values slow speech down and higher values speed it up. Defaults to `1.0`. reduce_silence: anyOf: - type: boolean - type: 'null' description: >- Optional. When `true`, shortens the pauses between words so the generated speech flows more naturally. Defaults to `false`. Only supported on models with `supports_silence_reduction` set to `true`; enabling it on any other model returns an `invalid_request` error. required: - model - language - voice - audio_format - text type: object ``` ### Parameters * `X-Request-Id` (header): Optional request ID for tracing. ### Responses * **200**: Generated audio stream. Response body contains raw audio bytes. Schema (YAML Structural Definition): ```yaml format: binary type: string ``` * **400**: Bad request. The request is malformed or contains invalid parameters. `error_type` is one of [`invalid_request`](https://docs.soniox.com/api-reference/errors#invalid-request) or [`model_not_available`](https://docs.soniox.com/api-reference/errors#model-not-available). Possible messages: * `Invalid JSON body` * `Missing required field: model` * `Model name is too long (max length 50).` * `Missing required field: language` * `Language is too long (max length 50).` * `Missing required field: voice` * `Voice is too long (max length 50).` * `Missing required field: audio_format` * `Audio format is too long (max length 50).` * `Missing required field: text` * `Text is too long (max length 5000).` * `API key is too long (max length 250).` * `Client reference ID is too long (max length 256).` * `Invalid voice '' for model ''.` * `Invalid language '' for model ''.` * `The requested model is not available. See https://soniox.com/docs/tts/models for the list of supported TTS models.` (`error_type: model_not_available`) Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **401**: Authentication is missing or incorrect. Ensure a valid API key is provided before retrying. `error_type`: [`unauthenticated`](https://docs.soniox.com/api-reference/errors#unauthenticated). Possible messages: * `Missing API key. Provide it as an Authorization header (e.g. 'Authorization: Bearer '). You can get an API key at https://console.soniox.com.` * `Authorization header must use the Bearer scheme (e.g. 'Authorization: Bearer '). You can get an API key at https://console.soniox.com.` * `Incorrect API key provided. You can get an API key at https://console.soniox.com` * `Invalid or expired temporary API key. Create a new temporary API key and retry. See https://soniox.com/docs/guides/temporary-api-keys for details.` * The temporary API key cannot be used for this action. Each temporary API key is scoped to a specific `usage_type`; create a new key with the correct usage type. Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **402**: The organization's balance or monthly budget has been reached. Additional credits or a higher cap are required before making further requests. `error_type` is one of [`organization_balance_exhausted`](https://docs.soniox.com/api-reference/errors#organization-balance-exhausted), [`organization_monthly_budget_exhausted`](https://docs.soniox.com/api-reference/errors#organization-monthly-budget-exhausted), or [`project_monthly_budget_exhausted`](https://docs.soniox.com/api-reference/errors#project-monthly-budget-exhausted). Possible messages: * `Organization balance exhausted. Please either add funds manually or enable autopay.` * `Organization monthly budget exhausted. Please increase it.` * `Project monthly budget exhausted. Please increase it.` Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **403**: The temporary API key in use was created with a `max_session_duration_seconds` cap, and that duration has elapsed for the current session. Create a new temporary API key to start a new session. `error_type`: [`temp_api_key_session_expired`](https://docs.soniox.com/api-reference/errors#temp-api-key-session-expired). Possible messages: * `Temporary API key session duration limit exceeded. Create a new temporary API key to start a new session.` Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **408**: A backend call exceeded its deadline before completing. Retry the request. `error_type`: [`request_timeout`](https://docs.soniox.com/api-reference/errors#request-timeout). Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **429**: A usage or rate limit has been exceeded. You may retry after a delay or request an increase in limits via the Soniox Console. `error_type`: [`limit_exceeded`](https://docs.soniox.com/api-reference/errors#limit-exceeded). Possible messages: * `Requests per minute limit for text-to-speech has been exceeded for your organization.` * `Requests per minute limit for text-to-speech has been exceeded for your project.` * `Concurrent requests limit for text-to-speech has been exceeded for your organization.` * `Concurrent requests limit for text-to-speech has been exceeded for your project.` Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **500**: An unexpected server-side error occurred. The request may be retried. `error_type`: [`internal_error`](https://docs.soniox.com/api-reference/errors#internal-error). Possible messages: * `The server had an error processing your request. Sorry about that! You can retry your request, or contact us through our support email support@soniox.com if you keep seeing this error.` Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` * **503**: The service cannot accept the request right now (upstream overload, cache exhausted, shutdown). Retry with backoff. The numeric `(code N)` in the message identifies the sub-cause for support triage. `error_type`: [`service_unavailable`](https://docs.soniox.com/api-reference/errors#service-unavailable). Possible messages: * `Cannot continue request (code N). Please restart the request. Refer to: https://soniox.com/url/cannot-continue-request` Schema (YAML Structural Definition): ```yaml properties: error_code: description: HTTP status code for the error. type: integer error_type: description: > Machine-readable error category. Branch your client on this value, not on `error_message`. See the [Errors reference](https://docs.soniox.com/api-reference/errors) for the full catalog. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `service_unavailable`, `internal_error`. type: string error_message: description: Human-readable error message. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL pointing to the section on the Soniox docs error reference page that describes this `error_type`. request_id: description: | Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string required: - error_code - error_type - error_message - request_id type: object ``` # Get shared voices URL: /api-reference/tts/get_shared_voices Retrieves the shared voices built into a TTS model, optionally filtered by gender, age, accent, use case and style. All given filters must match. For the voices you have cloned yourself, see `GET /v1/voices` instead. ## Get shared voices **Endpoint:** `GET /v1/shared-voices` Retrieves the shared voices built into a TTS model, optionally filtered by gender, age, accent, use case and style. All given filters must match. For the voices you have cloned yourself, see `GET /v1/voices` instead. ### Parameters * `model` (query) (Required): Id of the TTS model whose voices to return. * `gender` (query): Only return voices of this gender. * `age` (query): Only return voices of this age. * `accent` (query): Only return voices with this accent. * `use_case` (query): Only return voices tagged with every listed use case. Repeat the parameter to pass several values, or separate them with commas. * `style` (query): Only return voices tagged with every listed style. Repeat the parameter to pass several values, or separate them with commas. * `limit` (query): Maximum number of voices to return. * `cursor` (query): Pagination cursor for the next page of results. Pass the same filters alongside it; the cursor points into the filtered list, not the whole catalogue. ### Responses * **200**: List of shared voices matching the filters. Schema (YAML Structural Definition): ```yaml properties: voices: description: List of voices matching the filters. items: properties: id: description: Unique identifier of the voice. type: string description: description: Description of the TTS voice. type: string gender: description: Gender of the TTS voice. enum: - male - female - neutral type: string age: description: Perceived age of the speaker. enum: - young - middle_aged - old type: string accent: description: Accent of the voice, e.g. `american`, `british`. type: string use_case: description: >- Tags describing what the voice is suited for, e.g. `narration`, `conversational`. items: type: string type: array style: description: Tags describing how the voice sounds, e.g. `warm`, `energetic`. items: type: string type: array required: - id - description - gender - age - accent - use_case - style type: object type: array next_page_cursor: anyOf: - type: string - type: 'null' description: >- A pagination token that references the next page of results. When more data is available, this field contains a value to pass in the cursor parameter of a subsequent request. When null, no additional results are available. required: - voices type: object ``` * **400**: Invalid request. Error types: * `invalid_request`: The `model` parameter is missing, or a filter or pagination value is invalid (unknown `gender` or `age`, a value longer than 40 characters, more than 10 `use_case` / `style` values, or `limit` outside 1-200). Inspect `validation_errors`. * `invalid_cursor`: The `cursor` parameter is invalid. Omit `cursor` to start pagination from the beginning. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: TTS model not found. Error types: * `invalid_request`: No TTS model with this id exists. List the available models with `GET /v1/tts-models` and retry with one of their ids. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate limit for model listing. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get TTS models URL: /api-reference/tts/get_tts_models Retrieves list of available TTS models and their attributes. ## Get TTS models **Endpoint:** `GET /v1/tts-models` Retrieves list of available TTS models and their attributes. ### Responses * **200**: List of available TTS models and their attributes. Example (JSON): ```json { "models": [ { "aliased_model_id": null, "id": "tts-rt-v1", "name": "TTS v1", "languages": [ { "code": "af", "name": "Afrikaans" }, { "code": "ar", "name": "Arabic" }, { "code": "az", "name": "Azerbaijani" }, { "code": "be", "name": "Belarusian" }, { "code": "bg", "name": "Bulgarian" }, { "code": "bn", "name": "Bengali" }, { "code": "bs", "name": "Bosnian" }, { "code": "ca", "name": "Catalan" }, { "code": "cs", "name": "Czech" }, { "code": "cy", "name": "Welsh" }, { "code": "da", "name": "Danish" }, { "code": "de", "name": "German" }, { "code": "el", "name": "Greek" }, { "code": "en", "name": "English" }, { "code": "es", "name": "Spanish" }, { "code": "et", "name": "Estonian" }, { "code": "eu", "name": "Basque" }, { "code": "fa", "name": "Persian" }, { "code": "fi", "name": "Finnish" }, { "code": "fr", "name": "French" }, { "code": "gl", "name": "Galician" }, { "code": "gu", "name": "Gujarati" }, { "code": "he", "name": "Hebrew" }, { "code": "hi", "name": "Hindi" }, { "code": "hr", "name": "Croatian" }, { "code": "hu", "name": "Hungarian" }, { "code": "id", "name": "Indonesian" }, { "code": "is", "name": "Icelandic" }, { "code": "it", "name": "Italian" }, { "code": "ja", "name": "Japanese" }, { "code": "kk", "name": "Kazakh" }, { "code": "kn", "name": "Kannada" }, { "code": "ko", "name": "Korean" }, { "code": "lt", "name": "Lithuanian" }, { "code": "lv", "name": "Latvian" }, { "code": "mk", "name": "Macedonian" }, { "code": "ml", "name": "Malayalam" }, { "code": "mr", "name": "Marathi" }, { "code": "ms", "name": "Malay" }, { "code": "nl", "name": "Dutch" }, { "code": "no", "name": "Norwegian" }, { "code": "pa", "name": "Punjabi" }, { "code": "pl", "name": "Polish" }, { "code": "pt", "name": "Portuguese" }, { "code": "ro", "name": "Romanian" }, { "code": "ru", "name": "Russian" }, { "code": "sk", "name": "Slovak" }, { "code": "sl", "name": "Slovenian" }, { "code": "sq", "name": "Albanian" }, { "code": "sr", "name": "Serbian" }, { "code": "su", "name": "Sundanese" }, { "code": "sv", "name": "Swedish" }, { "code": "sw", "name": "Swahili" }, { "code": "ta", "name": "Tamil" }, { "code": "te", "name": "Telugu" }, { "code": "th", "name": "Thai" }, { "code": "tl", "name": "Tagalog" }, { "code": "tr", "name": "Turkish" }, { "code": "uk", "name": "Ukrainian" }, { "code": "ur", "name": "Urdu" }, { "code": "vi", "name": "Vietnamese" }, { "code": "zh", "name": "Chinese" } ], "voices": [ { "id": "Maya", "description": "A steady, clear voice with a natural presence and measured delivery that feels confident, warm, and easy to listen to.", "gender": "female" }, { "id": "Daniel", "description": "A rich, steady male voice with a polished tone, controlled pacing, and a reassuring presence that feels confident and mature.", "gender": "male" }, { "id": "Noah", "description": "A lively, youthful male voice with crisp clarity, quick natural pacing, and an upbeat tone that feels friendly, expressive, and modern.", "gender": "male" }, { "id": "Nina", "description": "A bright, expressive female voice with youthful energy, natural rhythm, and a friendly tone that feels warm, engaging, and full of personality.", "gender": "female" }, { "id": "Emma", "description": "A smooth, natural female voice with a relaxed pace, subtle warmth, and a contemporary tone that feels confident, personable, and easygoing.", "gender": "female" }, { "id": "Jack", "description": "A friendly, confident male voice with clear articulation, steady energy, and a natural tone that feels approachable, upbeat, and sincere.", "gender": "male" }, { "id": "Adrian", "description": "A deep, focused male voice with crisp articulation, measured pacing, and a composed tone that feels authoritative, clear, and professional.", "gender": "male" }, { "id": "Claire", "description": "A polished, articulate female voice with a bright tone, smooth pacing, and a confident presence that feels refined, clear, and approachable.", "gender": "female" }, { "id": "Grace", "description": "A gentle, soothing female voice with soft clarity, unhurried pacing, and a reassuring tone that feels kind, calm, and comforting.", "gender": "female" }, { "id": "Owen", "description": "A grounded male voice with even pacing and a dry, composed tone that feels steady, natural, and quietly confident.", "gender": "male" }, { "id": "Mina", "description": "A soft, thoughtful female voice with gentle clarity, steady pacing, and a warm tone that feels composed, sincere, and easy to listen to.", "gender": "female" }, { "id": "Kenji", "description": "A calm, precise male voice with smooth clarity, balanced pacing, and a composed tone that feels respectful, modern, and trustworthy.", "gender": "male" }, { "id": "Rafael", "description": "A clear, composed male voice with a warm Spanish accent, balanced pacing, and a confident tone that feels approachable and precise.", "gender": "male" }, { "id": "Mateo", "description": "A warm, youthful male voice with a soft Spanish accent, clear pacing, and an open tone that feels sincere, friendly, and optimistic.", "gender": "male" }, { "id": "Lucia", "description": "A clear, mature female voice with a natural Spanish accent, steady pacing, and a composed tone that feels warm, focused, and approachable.", "gender": "female" }, { "id": "Sofia", "description": "A bright, friendly female voice with a natural Spanish accent, clear articulation, and an inviting tone that feels warm, confident, and easy to follow.", "gender": "female" }, { "id": "Oliver", "description": "A refined male voice with a smooth British accent, gentle pacing, and a calm tone that feels trustworthy, articulate, and reassuring.", "gender": "male" }, { "id": "Arthur", "description": "A deep, mature male voice with a rich British accent, measured pacing, and a textured tone that feels composed, assured, and quietly powerful.", "gender": "male" }, { "id": "Isla", "description": "A lively female voice with a bright British accent, clear delivery, and expressive energy that feels fresh, friendly, and naturally engaging.", "gender": "female" }, { "id": "Victoria", "description": "A poised female voice with a refined British accent, smooth pacing, and a lightly textured tone that feels elegant, confident, and composed.", "gender": "female" }, { "id": "Cooper", "description": "A bold male voice with a strong Australian accent, relaxed pacing, and a casual tone that feels confident, rugged, and easygoing.", "gender": "male" }, { "id": "Mason", "description": "A relaxed male voice with a natural Australian accent, smooth pacing, and a casual tone that feels friendly, grounded, and effortlessly confident.", "gender": "male" }, { "id": "Ruby", "description": "A confident female voice with a natural Australian accent, lively pacing, and a warm tone that feels personable, sharp, and engaging.", "gender": "female" }, { "id": "Elise", "description": "A warm female voice with a natural Australian accent, clear pronunciation, and a confident tone that feels supportive, polished, and easy to follow.", "gender": "female" }, { "id": "Arjun", "description": "A deep male voice with a natural Indian accent, warm resonance, and an easygoing tone that feels friendly, grounded, and confident.", "gender": "male" }, { "id": "Rohan", "description": "A lively male voice with a natural Indian accent, expressive rhythm, and confident energy that feels charismatic, upbeat, and full of personality.", "gender": "male" }, { "id": "Priya", "description": "A clear female voice with a natural Indian accent, warm pacing, and a composed tone that feels helpful, attentive, and easy to trust.", "gender": "female" }, { "id": "Meera", "description": "A polished female voice with a natural Indian accent, crisp articulation, and a steady tone that feels professional, reassuring, and dependable.", "gender": "female" } ] } ] } ``` Schema (YAML Structural Definition): ```yaml properties: models: description: List of available TTS models and their attributes. items: properties: id: description: Unique identifier of the model. type: string aliased_model_id: anyOf: - type: string - type: 'null' description: If this is an alias, the id of the aliased model. name: description: Name of the model. type: string languages: description: List of languages supported by the model. items: properties: code: description: 2-letter language code. type: string name: description: Language name. type: string required: - code - name type: object type: array voices: description: List of available voices for this model. items: properties: id: description: Unique identifier of the voice. type: string description: description: Description of the TTS voice. type: string gender: description: Gender of the TTS voice. enum: - male - female - neutral type: string required: - id - description - gender type: object type: array supports_timestamps: type: boolean supports_voice_cloning: description: >- Whether the model supports voice cloning, that is voices created with `POST /v1/voices`. type: boolean voice_cloning_max_audio_duration_ms: anyOf: - type: integer - type: 'null' description: >- Maximum duration (in milliseconds) of the reference audio accepted for voice cloning. Null when the model does not support voice cloning. supports_speed_adjustment: description: >- Whether the model supports adjusting the speaking rate via the `speed` parameter. type: boolean speed_min: anyOf: - type: number - type: 'null' description: >- Minimum supported speaking rate. Null when the model does not support speed adjustment. speed_max: anyOf: - type: number - type: 'null' description: >- Maximum supported speaking rate. Null when the model does not support speed adjustment. supports_silence_reduction: description: >- Whether the model supports shortening the pauses between words via the `reduce_silence` parameter. type: boolean required: - id - aliased_model_id - name - languages - voices - supports_timestamps - supports_voice_cloning - voice_cloning_max_audio_duration_ms - supports_speed_adjustment - speed_min - speed_max - supports_silence_reduction type: object type: array required: - models type: object ``` * **401**: Authentication error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Rate / capacity limit exceeded. Error types: * `limit_exceeded`: The caller hit a per-minute request rate limit for model listing. The `message` describes which limit was hit. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal server error. Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Create voice URL: /api-reference/tts/voices/create_voice Uploads a reference audio clip and creates a new voice. ## Create voice **Endpoint:** `POST /v1/voices` Uploads a reference audio clip and creates a new voice. ### Request Body Content-Type: `multipart/form-data` (Required) Schema (YAML Structural Definition): ```yaml type: object properties: name: description: A name for the voice, unique within your project. maxLength: 128 minLength: 1 type: string file: description: The reference audio clip for the voice. format: binary type: string required: - name - file ``` ### Responses * **201**: Created Schema (YAML Structural Definition): ```yaml properties: id: description: Unique identifier of the voice. format: uuid type: string name: description: Name of the voice. type: string filename: description: Original file name of the uploaded audio clip. type: string created_at: description: UTC timestamp indicating when the voice was created. format: date-time type: string models: description: >- Voice status for each available model. A model with status 'not_computed' is not prepared yet (e.g. it was released after the voice was created); call recompute to prepare the voice for it. items: properties: model: description: Name of the model. type: string status: description: Has to be 'ready' for the voice to be usable with this model. enum: - not_computed - processing - ready - failed type: string error_type: anyOf: - type: string - type: 'null' description: >- Machine-readable error category when status is 'failed'. Stable across releases — safe to use in control flow. `null` otherwise. error_message: anyOf: - type: string - type: 'null' description: >- Human-readable error message when status is 'failed' (e.g. the reference audio is too long). `null` otherwise. required: - model - status type: object type: array required: - id - name - filename - created_at - models type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **409**: Conflict Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Delete voice URL: /api-reference/tts/voices/delete_voice Permanently deletes the specified voice and its embeddings. ## Delete voice **Endpoint:** `DELETE /v1/voices/{voice_id}` Permanently deletes the specified voice and its embeddings. ### Parameters * `voice_id` (path) (Required): ### Responses * **204**: No Content * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get voice URL: /api-reference/tts/voices/get_voice Retrieve metadata for a voice. ## Get voice **Endpoint:** `GET /v1/voices/{voice_id}` Retrieve metadata for a voice. ### Parameters * `voice_id` (path) (Required): ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: id: description: Unique identifier of the voice. format: uuid type: string name: description: Name of the voice. type: string filename: description: Original file name of the uploaded audio clip. type: string created_at: description: UTC timestamp indicating when the voice was created. format: date-time type: string models: description: >- Voice status for each available model. A model with status 'not_computed' is not prepared yet (e.g. it was released after the voice was created); call recompute to prepare the voice for it. items: properties: model: description: Name of the model. type: string status: description: Has to be 'ready' for the voice to be usable with this model. enum: - not_computed - processing - ready - failed type: string error_type: anyOf: - type: string - type: 'null' description: >- Machine-readable error category when status is 'failed'. Stable across releases — safe to use in control flow. `null` otherwise. error_message: anyOf: - type: string - type: 'null' description: >- Human-readable error message when status is 'failed' (e.g. the reference audio is too long). `null` otherwise. required: - model - status type: object type: array required: - id - name - filename - created_at - models type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get voices URL: /api-reference/tts/voices/get_voices Retrieves the list of voices in your project. ## Get voices **Endpoint:** `GET /v1/voices` Retrieves the list of voices in your project. ### Parameters * `limit` (query): Maximum number of voices to return. * `cursor` (query): Pagination cursor for the next page of results. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: voices: description: List of voices. items: properties: id: description: Unique identifier of the voice. format: uuid type: string name: description: Name of the voice. type: string filename: description: Original file name of the uploaded audio clip. type: string created_at: description: UTC timestamp indicating when the voice was created. format: date-time type: string models: description: >- Voice status for each available model. A model with status 'not_computed' is not prepared yet (e.g. it was released after the voice was created); call recompute to prepare the voice for it. items: properties: model: description: Name of the model. type: string status: description: Has to be 'ready' for the voice to be usable with this model. enum: - not_computed - processing - ready - failed type: string error_type: anyOf: - type: string - type: 'null' description: >- Machine-readable error category when status is 'failed'. Stable across releases — safe to use in control flow. `null` otherwise. error_message: anyOf: - type: string - type: 'null' description: >- Human-readable error message when status is 'failed' (e.g. the reference audio is too long). `null` otherwise. required: - model - status type: object type: array required: - id - name - filename - created_at - models type: object type: array next_page_cursor: anyOf: - type: string - type: 'null' description: >- A pagination token that references the next page of results. When more data is available, this field contains a value to pass in the cursor parameter of a subsequent request. When null, no additional results are available. required: - voices type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Get voices count URL: /api-reference/tts/voices/get_voices_count Returns the total number of voices in your project. ## Get voices count **Endpoint:** `GET /v1/voices/count` Returns the total number of voices in your project. ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: total: description: Total number of voices in your project. type: integer required: - total type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # Recompute voice URL: /api-reference/tts/voices/recompute_voice Prepares the voice for use with available models it is not ready for yet. Use this after a new model is released to make an existing voice usable with it. Models the voice is already prepared for are left unchanged. ## Recompute voice **Endpoint:** `POST /v1/voices/{voice_id}/recompute` Prepares the voice for use with available models it is not ready for yet. Use this after a new model is released to make an existing voice usable with it. Models the voice is already prepared for are left unchanged. ### Request Body Content-Type: `application/json` (Required) Schema (YAML Structural Definition): ```yaml properties: model: anyOf: - type: string - type: 'null' description: >- The model to prepare this voice for. If omitted, the voice is prepared for every available model it is not ready for yet. type: object ``` ### Parameters * `voice_id` (path) (Required): ### Responses * **200**: OK Schema (YAML Structural Definition): ```yaml properties: id: description: Unique identifier of the voice. format: uuid type: string name: description: Name of the voice. type: string filename: description: Original file name of the uploaded audio clip. type: string created_at: description: UTC timestamp indicating when the voice was created. format: date-time type: string models: description: >- Voice status for each available model. A model with status 'not_computed' is not prepared yet (e.g. it was released after the voice was created); call recompute to prepare the voice for it. items: properties: model: description: Name of the model. type: string status: description: Has to be 'ready' for the voice to be usable with this model. enum: - not_computed - processing - ready - failed type: string error_type: anyOf: - type: string - type: 'null' description: >- Machine-readable error category when status is 'failed'. Stable across releases — safe to use in control flow. `null` otherwise. error_message: anyOf: - type: string - type: 'null' description: >- Human-readable error message when status is 'failed' (e.g. the reference audio is too long). `null` otherwise. required: - model - status type: object type: array required: - id - name - filename - created_at - models type: object ``` * **400**: Bad Request Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **401**: Unauthorized Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **404**: Not Found Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **429**: Too Many Requests Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` * **500**: Internal Server Error Schema (YAML Structural Definition): ```yaml properties: status_code: description: HTTP status code of the response. type: integer error_type: description: > Machine-readable error category. Examples: `invalid_request`, `unauthenticated`, `limit_exceeded`, `model_not_available`, `internal_error`. type: string message: description: Human-readable error message. type: string validation_errors: description: >- List of per-field validation errors. Populated only when `error_type` is `invalid_request` and the failure came from request-body validation. items: properties: error_type: type: string location: type: string message: type: string required: - error_type - location - message type: object type: array request_id: description: >- Unique identifier for this request. Include it when contacting support at support@soniox.com so we can look up server-side logs. type: string more_info: anyOf: - type: string - type: 'null' description: > Optional URL with additional information about this error. Points to the Soniox documentation for errors a developer can resolve via code or configuration. required: - status_code - error_type - message - validation_errors - request_id type: object ``` # WebSocket API URL: /api-reference/tts/websocket-api Learn how to use and integrate Soniox Text-to-Speech WebSocket API. import {Badge} from "@openapi/ui/components/method-label"; ## Overview The **Soniox WebSocket API** provides real-time Text-to-Speech with low latency over a persistent WebSocket connection. A single connection can host up to 5 **[concurrent streams](/tts/rt/streams)** multiplexed by `stream_id`. Ideal for voice agents, interactive assistants, and LLM-driven applications where audio must start playing before the full text is generated. *** ## WebSocket endpoint Connect to the API using: ```text wss://tts-rt.soniox.com/tts-websocket ``` *** ## Authentication Send your API key with the connection, in the Authorization header or the protocols list. See [WebSocket authentication](/guides/websocket-authentication). The key sent with the connection is the connection's key for its whole life: every stream on the connection runs on it. A single-use temporary key sent with the connection allows one stream on that connection. The `api_key` field of the config message is **deprecated**. From **15 January 2027** a connection that sends its key only there is refused. See [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). *** ## Configuration Before streaming text for a stream, send a configuration message on the WebSocket connection. Send one config message per `stream_id` you want to start. ```json { "model": "tts-rt-v2", "language": "en", "voice": "Adrian", "audio_format": "wav", "sample_rate": 24000, "stream_id": "stream-001" } ``` *** ### Parameters **Deprecated.** Send the API key with the connection instead; see [Authentication](#authentication) and [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). Client-generated stream identifier. Must be unique among active streams on the same WebSocket connection. You may reuse a `stream_id` only after its previous stream is terminated. Text-to-Speech model to use. See [models](/tts/models).
Example: `"tts-rt-v2"`
Language code. See the list of [supported languages](/tts/concepts/supported-languages) and their ISO codes.
Example: `"en"`
Voice to use: a built-in voice name (see [voices](/tts/concepts/voices)) or the ID of a [cloned voice](/tts/concepts/voice-cloning).
Example: `"Adrian"`
Audio format of the stream. See [audio formats](/tts/concepts/audio-formats).
Example: `"wav"`
Optional output sample rate in Hz. See [audio formats](/tts/concepts/audio-formats).
Example: `24000`
Codec bitrate in bps (for lossy compressed formats). See [audio formats](/tts/concepts/audio-formats).
Example: `128000`
Optional client-defined identifier recorded with this request in [usage logs](/guides/usage-logs). Does not need to be unique. Ignored if the request authenticates with a [temporary API key](/guides/temporary-api-keys). Request character-level timestamps in the responses. Defaults to `false`. See [Timestamps](/tts/rt/timestamps). Speaking rate of the generated speech, from `0.7` to `1.3`. `1.0` is the normal speed; lower values slow speech down and higher values speed it up. Defaults to `1.0`. See [Speech speed](/tts/concepts/speech-speed).
Example: `1.2`
Shorten the pauses between words so the generated speech flows more naturally. Defaults to `false`. Only supported on models with `supports_silence_reduction: true` - see [List models](/api-reference/tts/get_tts_models). Setting it to `true` on any other model returns an [`invalid_request`](/api-reference/errors#invalid-request) error. See [Reduce silence](/tts/concepts/reduce-silence).
*** ## Connection timeouts The server closes connections and streams that are not doing real work: * **After connecting**, the connection is authenticated at once. Send a [keepalive](/tts/rt/connection-keepalive) or any other message at least every **40 seconds**, or the connection is closed as idle. There is no deadline for the first stream. * **Within a stream**, keep sending text. A stream that receives no `text` message for more than a few seconds without `text_end: true` is terminated with a [`request_timeout`](/api-reference/errors#request-timeout) error. Keepalive messages do not reset this timer. * **Between streams**, the same **40-second** idle limit applies. Send a [keepalive](/tts/rt/connection-keepalive) every 20–30 seconds to stay under it. See [Connection keepalive](/tts/rt/connection-keepalive) for details. Open connections, including idle ones, also count against a connection limit, a multiple of your concurrent streams limit; see [Limits & quotas](/tts/rt/limits-and-quotas) and [WebSocket authentication](/guides/websocket-authentication). Still sending `api_key` in the config message? Different timeouts apply; see [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). *** ## Text streaming After sending the configuration message for a stream, send text messages for that same `stream_id`: ```json { "text": "Hello there, this is chunk one.", "text_end": false, "stream_id": "stream-001" } ``` Final text chunk: ```json { "text": "And this is the end.", "text_end": true, "stream_id": "stream-001" } ``` *** ## Ending the stream A stream ends with a three-step handshake: the client sends a text message with `text_end: true`, the server sends the last audio payload with `audio_end: true`, then `{"terminated": true}`. For the full lifecycle, including error completion and client-initiated cancellation see [Stream termination](/tts/rt/termination). ### Normal completion A stream completes in this order: 1. The client sends a text message with `text_end: true` for the target `stream_id`. ```json { "text": "And this is the end.", "text_end": true, "stream_id": "stream-001" } ``` 2. The server sends the last audio payload with `audio_end: true`. ```json { "audio": "", "audio_end": true, "stream_id": "stream-001" } ``` 3. The server sends a final stream event with `terminated: true`. ```json { "terminated": true, "stream_id": "stream-001" } ``` #### What `audio_end` means `audio_end: true` marks the **last audio chunk** for that stream. No more `audio` payloads will follow. You should still keep the stream open and wait for the terminal `terminated: true` event. #### What `terminated` means `terminated: true` indicates the server has fully closed the stream and released all stream resources. Only after `terminated: true` it is safe to: * reuse the same `stream_id` * stop tracking stream state * consider the stream lifecycle complete Treat the stream as complete only after you receive `terminated: true`. ### Error completion If an error occurs for a stream: 1. The server sends an error response for that `stream_id`. ```json { "stream_id": "stream-001", "error_code": 400, "error_type": "invalid_request", "error_message": "Missing model", "more_info": "https://soniox.com/docs/api-reference/errors#invalid-request", "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda" } ``` 2. The server sends `{"terminated": true}` for that same `stream_id`. ```json { "terminated": true, "stream_id": "stream-001" } ``` 3. The failed stream is removed, but the WebSocket connection stays open and other streams can continue. *** ### Client-initiated cancellation To cancel a stream, send a cancel message. The server finalizes the stream and does not send audio chunks. Cancel request: ```json { "stream_id": "stream-001", "cancel": true } ``` Finalization response: ```json { "terminated": true, "stream_id": "stream-001" } ``` *** ## Error handling One failed stream does not close the whole WebSocket connection. 1. **Stream-level runtime errors** (inside a running stream): * The server sends an error response for that `stream_id`. * The server then sends `{"terminated": true}` for that same `stream_id`. * Only that stream ends; other active streams continue. 2. **Validation/input errors** (invalid start/text message, unknown stream, malformed stream message): * The server sends an error response. * The WebSocket message loop stays alive, so valid streams can continue. 3. **Connection-level failures** (WebSocket disconnect/read/write failure, forced shutdown): * The WebSocket connection closes. * All streams on that connection end. *** ## Response Server messages are JSON and include `stream_id` for stream-specific events. Successful audio messages include `audio` (base64 chunk), and terminal messages include `terminated`. ```json { "audio": "", "audio_end": false, "stream_id": "stream-001" } ``` ### Timestamps When a stream is started with [`return_timestamps: true`](#parameters), audio responses include a `timestamps` object with character-to-audio alignment. Each object covers only the characters in that frame; concatenate the `characters` arrays across frames to reconstruct the full spoken text. ```json { "stream_id": "stream-001", "audio": "", "timestamps": { "characters": ["H", "e", "l", "l", "o"], "character_start_times_seconds": [0.0, 0.1, 0.2, 0.3, 0.4], "character_end_times_seconds": [0.1, 0.2, 0.3, 0.4, 0.5] } } ``` One entry per character of the spoken text. Start time of each character, in seconds. End time of each character, in seconds. For delivery semantics and the preprocessed-text mapping, see [Timestamps](/tts/rt/timestamps). ### Terminal stream message ```json { "terminated": true, "stream_id": "stream-001" } ``` *** ## Error response If an error occurs, the server returns an **error message**: ```json { "stream_id": "stream-001", "error_code": 400, "error_type": "invalid_request", "error_message": "Missing model", "more_info": "https://soniox.com/docs/api-reference/errors#invalid-request", "request_id": "3d37a3bd-5078-47ee-a369-b204e3bbedda" } ``` HTTP status code of the error. Stable, machine-readable identifier of the error. Branch on this, not on `error_message`. See the [Errors reference](/api-reference/errors) for the full catalog and recovery steps. Human-readable description of the error. Link to the section on the [Errors](/api-reference/errors) page describing this `error_type`. Unique identifier of this request. Include it when contacting [support@soniox.com](mailto:support@soniox.com); server logs are keyed on it. For error scoping and isolation behavior when one WebSocket hosts multiple streams, see [Streams](/tts/rt/streams#error-isolation). For the full catalog of `error_type` values across all Soniox APIs, see the [Errors reference](/api-reference/errors). ### Full list of possible error codes and messages 400 Bad Request } > The request is malformed or contains invalid parameters. `error_type` is one of [`invalid_request`](/api-reference/errors#invalid-request), [`invalid_stream_state`](/api-reference/errors#invalid-stream-state), [`max_concurrent_streams_reached`](/api-reference/errors#max-concurrent-streams-reached), or [`model_not_available`](/api-reference/errors#model-not-available). * `API key is too long (max length 250).` * `Audio format is too long (max length 50).` * `Expected a text message. Binary frames are not accepted on this endpoint.` * `Invalid language '' for model ''.` * `Invalid message format. Expected JSON matching a start, text, or keep-alive request.` * `Send the API key either in the Authorization header or in the WebSocket protocols list, not both.` * `Authorization header must be "Bearer ".` * `soniox-api-key must be sent in the WebSocket protocols list together with exactly one other entry, the API key.` * `The api_key in the start message does not match the API key sent with the connection. Send the same key or omit it.` * `Invalid voice '' for model ''.` * `Language is required.` * `Language is too long (max length 50).` * `Maximum concurrent streams per connection (N) reached. Send a cancel message for one of your active streams to free a slot, or open a new WebSocket connection.` * `Missing audio_format` * `Missing language` * `Missing model` * `Missing stream_id` * `Missing voice` * `Model does not support silence reduction.` * `Model name is too long (max length 50).` * `Stream has already been cancelled. Start a new stream to send more text.` * `Stream has already received text_end and is closed for input. Start a new stream to send more text.` * `Stream is already active on this connection. Choose a different stream_id, or cancel the existing stream first.` * `Stream not found. Send a start message first.` * `Stream ID is too long (max length 256).` * `Text is too long (max length 5000).` * `The 'cancel' field cannot be combined with 'text' or 'text_end'. Send 'cancel' on its own to stop a stream.` * `The requested model does not support timestamps. Set return_timestamps to false or use a model that supports timestamps.` * `The requested model is not available. See https://soniox.com/docs/tts/models for the list of supported TTS models.` * `Voice is too long (max length 50).` 401 Unauthorized } > Authentication is missing or incorrect. Ensure a valid API key is provided before retrying. `error_type`: [`unauthenticated`](/api-reference/errors#unauthenticated). * `Incorrect API key provided. You can get an API key at https://console.soniox.com` * `Invalid or expired temporary API key. Create a new temporary API key and retry. See https://soniox.com/docs/guides/temporary-api-keys for details.` * `Missing API key. Provide API key as a header (i.e. Authorization: Bearer ). You can get an API key at https://console.soniox.com` * `Missing API key. Send it with the connection: the Authorization header "Bearer ", or soniox-api-key and the key in the WebSocket protocols list.` (from 15 January 2027, for a connection that sends no key with the connection; see [Migrate WebSocket authentication](/guides/migrate-websocket-authentication)) * ``The temporary API key cannot be used for this action. Each temporary API key is scoped to a specific `usage_type`; create a new key with the correct usage type.`` 402 Payment Required } > The organization's balance or monthly usage limit has been reached. `error_type` is one of [`organization_balance_exhausted`](/api-reference/errors#organization-balance-exhausted), [`organization_monthly_budget_exhausted`](/api-reference/errors#organization-monthly-budget-exhausted), or [`project_monthly_budget_exhausted`](/api-reference/errors#project-monthly-budget-exhausted). * `Organization balance exhausted. Please either add funds manually or enable autopay.` * `Organization monthly budget exhausted. Please increase it.` * `Project monthly budget exhausted. Please increase it.` 403 Forbidden } > The API key does not have the permission for text-to-speech, or the temporary API key in use was created with a `max_session_duration_seconds` cap and that duration has elapsed for the current session. `error_type` is one of [`permission_denied`](/api-reference/errors#permission-denied) or [`temp_api_key_session_expired`](/api-reference/errors#temp-api-key-session-expired). * `The API key does not have permission for this product. Edit the key's permissions at https://console.soniox.com` * `Temporary API key session duration limit exceeded. Create a new temporary API key to start a new session.` 408 Request Timeout } > A backend call exceeded its deadline before completing. Retry the request. `error_type`: [`request_timeout`](/api-reference/errors#request-timeout). 413 Payload Too Large } > The generated audio reached the maximum audio duration per request (2 minutes) and the output was truncated. The final audio chunk is delivered without `audio_end`, followed by this error and a `terminated` message. The connection stays open; generate the remaining text on a new stream. `error_type`: [`max_audio_duration_reached`](/api-reference/errors#max-audio-duration-reached). * `The generated audio reached the maximum audio duration per request and the output was truncated. Synthesize the remaining text with a new request.` 429 Too Many Requests } > A usage or rate limit has been exceeded. You may retry after a delay or request an increase in limits via the Soniox Console. `error_type` is one of [`limit_exceeded`](/api-reference/errors#limit-exceeded) or [`max_concurrent_connections_reached`](/api-reference/errors#max-concurrent-connections-reached). * `Concurrent requests limit for text-to-speech has been exceeded for your organization.` * `Concurrent requests limit for text-to-speech has been exceeded for your project.` * `Requests per minute limit for text-to-speech has been exceeded for your organization.` * `Requests per minute limit for text-to-speech has been exceeded for your project.` * `Concurrent WebSocket connections limit for text-to-speech has been exceeded for your organization. Close connections you are not using, or start streams on the ones you hold: the limit is a multiple of your concurrent streams limit.` * `Concurrent WebSocket connections limit for text-to-speech has been exceeded for your project. Close connections you are not using, or start streams on the ones you hold: the limit is a multiple of your concurrent streams limit.` 500 Internal Server Error } > An unexpected server-side error occurred. The request may be retried. `error_type`: [`internal_error`](/api-reference/errors#internal-error). * `The server had an error processing your request. Sorry about that! You can retry your request, or contact us through our support email support@soniox.com if you keep seeing this error.` 503 Service Unavailable } > The service cannot accept the request right now (upstream overload, cache exhausted, shutdown). Retry with backoff. The numeric `(code N)` in the message identifies the sub-cause for support triage. `error_type`: [`service_unavailable`](/api-reference/errors#service-unavailable). * `Cannot continue request (code N). Please restart the request. Refer to: https://soniox.com/url/cannot-continue-request` ## Code example **Prerequisite:** Complete the steps in [Get started](/tts/get-started). See on GitHub: [soniox\_sdk\_realtime.py](https://github.com/soniox/soniox_examples/blob/master/text_to_speech/python_sdk/soniox_sdk_realtime.py). ``` import argparse import os import threading import time from pathlib import Path from uuid import uuid4 from soniox import SonioxClient from soniox.errors import SonioxRealtimeError from soniox.types import RealtimeTTSConfig from soniox.utils import output_file_for_audio_format VALID_SAMPLE_RATES = [8000, 16000, 24000, 44100, 48000] VALID_BITRATES = [32000, 64000, 96000, 128000, 192000, 256000, 320000] VALID_AUDIO_FORMATS = [ "pcm_f32le", "pcm_s16le", "pcm_mulaw", "pcm_alaw", "wav", "aac", "mp3", "opus", "flac", ] DEFAULT_LINES = [ "Welcome to Soniox real-time Text-to-Speech. ", "As text is streamed in, audio streams back in parallel with high accuracy, ", "so your application can start playing speech ", "within milliseconds of the first word.", ] def get_config( model: str, language: str, voice: str, audio_format: str, sample_rate: int | None, bitrate: int | None, stream_id: str | None, ) -> RealtimeTTSConfig: config = RealtimeTTSConfig( # Stream id for this realtime TTS session. # If omitted, a random id is generated. stream_id=stream_id or f"tts-{uuid4()}", # # Select the model to use. # See: docs.soniox.com/tts/models model=model, # # Set the language of the input text. # See: docs.soniox.com/tts/concepts/supported-languages language=language, # # Select the voice to use. # See: docs.soniox.com/tts/concepts/voices voice=voice, # # Set output audio format and optional encoding parameters. # See: docs.soniox.com/api-reference/tts/websocket-api audio_format=audio_format, sample_rate=sample_rate, bitrate=bitrate, ) return config def run_session( client: SonioxClient, lines: list[str], model: str, language: str, voice: str, audio_format: str, sample_rate: int | None, bitrate: int | None, stream_id: str | None, output_path: str | None, ) -> None: # Build a realtime Text-to-Speech session configuration. config = get_config( model=model, language=language, voice=voice, audio_format=audio_format, sample_rate=sample_rate, bitrate=bitrate, stream_id=stream_id, ) sanitized_lines = [line.strip() for line in lines if line.strip()] if not sanitized_lines: raise ValueError("Text is empty after parsing.") destination = ( Path(output_path) if output_path else output_file_for_audio_format(audio_format, "tts_realtime") ) print("Connecting to Soniox...") audio_chunks: list[bytes] = [] try: with client.realtime.tts.connect(config=config) as session: print("Session started.") send_errors: list[Exception] = [] def send_worker() -> None: try: for line in sanitized_lines: session.send_text_chunk(line, text_end=False) time.sleep(0.1) session.finish() except Exception as exc: send_errors.append(exc) threading.Thread(target=send_worker, daemon=True).start() # Receive streamed audio chunks from the websocket. for audio_chunk in session.receive_audio_chunks(): audio_chunks.append(audio_chunk) if send_errors: raise RuntimeError(f"Failed to send realtime text: {send_errors[0]}") print("Session finished.") finally: audio = b"".join(audio_chunks) if audio: destination.write_bytes(audio) print(f"Wrote {len(audio)} bytes to {destination.resolve()}") else: print("No audio file was written.") def main() -> None: parser = argparse.ArgumentParser() parser.add_argument( "--line", action="append", default=None, help="Line to send to realtime TTS (repeat --line for multiple lines).", ) parser.add_argument("--model", default="tts-rt-v2") parser.add_argument("--language", default="en") parser.add_argument("--voice", default="Adrian") parser.add_argument("--audio_format", default="wav") parser.add_argument("--sample_rate", type=int) parser.add_argument("--bitrate", type=int) parser.add_argument("--stream_id", help="Optional stream id.") parser.add_argument( "--output_path", help="Optional output file path. If omitted, a timestamped path is generated.", ) args = parser.parse_args() if args.audio_format not in VALID_AUDIO_FORMATS: raise ValueError(f"audio_format must be one of {VALID_AUDIO_FORMATS}") if args.sample_rate is not None and args.sample_rate not in VALID_SAMPLE_RATES: raise ValueError(f"sample_rate must be None or one of {VALID_SAMPLE_RATES}") if args.bitrate is not None and args.bitrate not in VALID_BITRATES: raise ValueError(f"bitrate must be None or one of {VALID_BITRATES}") api_key = os.environ.get("SONIOX_API_KEY") if not api_key: raise RuntimeError( "Missing SONIOX_API_KEY.\n" "1. Get your API key at https://console.soniox.com\n" "2. Run: export SONIOX_API_KEY=" ) client = SonioxClient(api_key=api_key) try: run_session( client=client, lines=args.line or DEFAULT_LINES, model=args.model, language=args.language, voice=args.voice, audio_format=args.audio_format, sample_rate=args.sample_rate, bitrate=args.bitrate, stream_id=args.stream_id, output_path=args.output_path, ) except SonioxRealtimeError as exc: print("Soniox realtime error:", exc) finally: client.close() if __name__ == "__main__": main() ``` ```sh title="Terminal" # Generate speech with default settings (wav output) python soniox_sdk_realtime.py --line "Hello from Soniox realtime Text-to-Speech." # Generate raw PCM output python soniox_sdk_realtime.py --audio_format pcm_s16le --sample_rate 24000 --output_path tts-output.pcm ``` See on GitHub: [soniox\_sdk\_realtime.js](https://github.com/soniox/soniox_examples/blob/master/text_to_speech/nodejs_sdk/soniox_sdk_realtime.js). ``` import { RealtimeError, SonioxNodeClient } from "@soniox/node"; import fs from "fs"; import path from "path"; import { parseArgs } from "node:util"; import process from "process"; const VALID_SAMPLE_RATES = [8000, 16000, 24000, 44100, 48000]; const VALID_BITRATES = [32000, 64000, 96000, 128000, 192000, 256000, 320000]; const VALID_AUDIO_FORMATS = [ "pcm_f32le", "pcm_s16le", "pcm_mulaw", "pcm_alaw", "wav", "aac", "mp3", "opus", "flac", ]; const RAW_PCM_FORMATS = ["pcm_s16le", "pcm_f32le", "pcm_mulaw", "pcm_alaw"]; const DEFAULT_LINES = [ "Welcome to Soniox real-time Text-to-Speech. ", "As text is streamed in, audio streams back in parallel with high accuracy, ", "so your application can start playing speech ", "within milliseconds of the first word.", ]; // Initialize the client. // The API key is read from the SONIOX_API_KEY environment variable. const client = new SonioxNodeClient(); // Resolve a concrete output file path. // If the provided path has no extension, derive one from audio_format: // * pcm_s16le -> .wav (we wrap the bytes in a WAV container below) // * other pcm_* -> .pcm (raw, no container) // * anything else -> the format name (e.g. .flac, .mp3, .opus) function resolveOutputPath(outputPath, audioFormat) { if (outputPath && path.extname(outputPath)) { return outputPath; } const ext = audioFormat === "pcm_s16le" ? "wav" : RAW_PCM_FORMATS.includes(audioFormat) ? "pcm" : audioFormat; const base = outputPath || "tts_realtime"; return `${base}.${ext}`; } function pcmS16leToWav(pcm, { sampleRate, numChannels = 1 }) { const bitsPerSample = 16; const byteRate = sampleRate * numChannels * (bitsPerSample / 8); const blockAlign = numChannels * (bitsPerSample / 8); const dataSize = pcm.byteLength; const header = Buffer.alloc(44); header.write("RIFF", 0, "ascii"); header.writeUInt32LE(36 + dataSize, 4); header.write("WAVE", 8, "ascii"); header.write("fmt ", 12, "ascii"); header.writeUInt32LE(16, 16); header.writeUInt16LE(1, 20); header.writeUInt16LE(numChannels, 22); header.writeUInt32LE(sampleRate, 24); header.writeUInt32LE(byteRate, 28); header.writeUInt16LE(blockAlign, 32); header.writeUInt16LE(bitsPerSample, 34); header.write("data", 36, "ascii"); header.writeUInt32LE(dataSize, 40); return Buffer.concat([header, Buffer.from(pcm)]); } // Build a realtime TTS stream config. function getStreamConfig({ model, language, voice, audioFormat, sampleRate, bitrate, streamId, }) { const config = { // Client-defined stream id (auto-generated if omitted). ...(streamId && { stream_id: streamId }), // Select the model to use. // See: docs.soniox.com/tts/models model, // Set the language of the input text. // See: docs.soniox.com/tts/concepts/supported-languages language, // Select the voice to use. // See: docs.soniox.com/tts/concepts/voices voice, // Set output audio format and optional encoding parameters. // See: docs.soniox.com/api-reference/tts/websocket-api audio_format: audioFormat, }; if (sampleRate !== undefined) config.sample_rate = sampleRate; if (bitrate !== undefined) config.bitrate = bitrate; return config; } async function runSession({ lines, model, language, voice, audioFormat, sampleRate, bitrate, streamId, outputPath, }) { const sanitizedLines = lines .map((line) => line.trim()) .filter((line) => line.length > 0); if (sanitizedLines.length === 0) { throw new Error("Text is empty after parsing."); } const destination = resolveOutputPath(outputPath, audioFormat); const config = getStreamConfig({ model, language, voice, audioFormat, sampleRate, bitrate, streamId, }); console.log("Connecting to Soniox..."); const stream = await client.realtime.tts(config); console.log("Session started."); // Send text chunks in the background while receiving audio. let sendError = null; const sendPromise = (async () => { try { for (const line of sanitizedLines) { stream.sendText(line); // Sleep for 100 ms to simulate real-time streaming. await new Promise((res) => setTimeout(res, 100)); } stream.finish(); } catch (err) { sendError = err; } })(); // Collect streamed audio chunks. const audioChunks = []; try { for await (const chunk of stream) { audioChunks.push(chunk); } } finally { await sendPromise; stream.close(); } if (sendError) { throw new Error(`Failed to send realtime text: ${sendError.message}`); } console.log("Session finished."); const audio = Buffer.concat(audioChunks.map((c) => Buffer.from(c))); if (audio.length > 0) { // Wrap raw pcm_s16le in a WAV container so the .wav file plays everywhere. const bytes = audioFormat === "pcm_s16le" && path.extname(destination).toLowerCase() === ".wav" ? pcmS16leToWav(audio, { sampleRate }) : audio; fs.writeFileSync(destination, bytes); console.log(`Wrote ${bytes.length} bytes to ${path.resolve(destination)}`); } else { console.log("No audio file was written."); } } async function main() { const { values: argv } = parseArgs({ options: { line: { type: "string", multiple: true }, model: { type: "string", default: "tts-rt-v2" }, language: { type: "string", default: "en" }, voice: { type: "string", default: "Adrian" }, audio_format: { type: "string", default: "pcm_s16le" }, sample_rate: { type: "string" }, bitrate: { type: "string" }, stream_id: { type: "string" }, output_path: { type: "string" }, }, }); if (!VALID_AUDIO_FORMATS.includes(argv.audio_format)) { throw new Error( `audio_format must be one of ${VALID_AUDIO_FORMATS.join(", ")}`, ); } let sampleRate = argv.sample_rate !== undefined ? Number(argv.sample_rate) : undefined; if (sampleRate === undefined && RAW_PCM_FORMATS.includes(argv.audio_format)) { sampleRate = 24000; } if (sampleRate !== undefined && !VALID_SAMPLE_RATES.includes(sampleRate)) { throw new Error( `sample_rate must be one of ${VALID_SAMPLE_RATES.join(", ")}`, ); } const bitrate = argv.bitrate !== undefined ? Number(argv.bitrate) : undefined; if (bitrate !== undefined && !VALID_BITRATES.includes(bitrate)) { throw new Error(`bitrate must be one of ${VALID_BITRATES.join(", ")}`); } try { await runSession({ lines: argv.line && argv.line.length > 0 ? argv.line : DEFAULT_LINES, model: argv.model, language: argv.language, voice: argv.voice, audioFormat: argv.audio_format, sampleRate, bitrate, streamId: argv.stream_id, outputPath: argv.output_path, }); } catch (err) { if (err instanceof RealtimeError) { console.error("Soniox realtime error:", err.message); } else { throw err; } } } main().catch((err) => { console.error("Error:", err.message); process.exit(1); }); ``` ```sh title="Terminal" # Generate speech with default settings (wav output) node soniox_sdk_realtime.js --line "Hello from Soniox realtime Text-to-Speech." # Generate raw PCM output node soniox_sdk_realtime.js --audio_format pcm_s16le --sample_rate 24000 --output_path tts-output.pcm ``` {/* NOTE: Empty tag is needed so code block renders correctly */}
See on GitHub: [soniox\_realtime.py](https://github.com/soniox/soniox_examples/blob/master/text_to_speech/python/soniox_realtime.py). ``` import argparse import base64 import json import os import threading import time from typing import Any from websockets import ConnectionClosedOK from websockets.sync.client import connect SONIOX_TTS_WEBSOCKET_URL = "wss://tts-rt.soniox.com/tts-websocket" MODEL = "tts-rt-v2" VALID_SAMPLE_RATES = [8000, 16000, 24000, 44100, 48000] VALID_BITRATES = [32000, 64000, 96000, 128000, 192000, 256000, 320000] VALID_AUDIO_FORMATS = [ "pcm_f32le", "pcm_s16le", "pcm_mulaw", "pcm_alaw", "wav", "aac", "mp3", "opus", "flac", ] DEFAULT_LINES = [ "Welcome to Soniox real-time Text-to-Speech. ", "As text is streamed in, audio streams back in parallel with high accuracy, ", "so your application can start playing speech ", "within milliseconds of the first word.", ] def get_output_path(*, output_path: str, audio_format: str) -> str: """ Generates the resulting output path for the given audio format. """ if "." in os.path.basename(output_path): return output_path ext = "pcm" if audio_format in ("pcm_s16le", "pcm_s16be") else audio_format return f"{output_path}.{ext}" # Get Soniox TTS config. def get_config( stream_id: str, language: str, voice: str, audio_format: str, sample_rate: int | None, bitrate: int | None, ) -> dict: config: dict[str, Any] = { # Client-defined stream id to identify this realtime request. "stream_id": stream_id, # # Select the model to use. # See: docs.soniox.com/tts/models "model": MODEL, # # Set the language of the input text. # See: docs.soniox.com/tts/concepts/supported-languages "language": language, # # Select the voice to use. # See: docs.soniox.com/tts/concepts/voices "voice": voice, # # Audio format. # See: docs.soniox.com/tts/concepts/audio-formats "audio_format": audio_format, } if sample_rate is not None: config["sample_rate"] = sample_rate if bitrate is not None: config["bitrate"] = bitrate return config def get_text_request(text: str, stream_id: str, text_end: bool) -> dict: return { "text": text, "text_end": text_end, "stream_id": stream_id, } # Stream text lines to the websocket. def stream_text(lines: list[str], stream_id: str, ws) -> None: for line in lines: clean_line = line.strip() if not clean_line: continue ws.send(json.dumps(get_text_request(clean_line, stream_id, text_end=False))) # Sleep for 100 ms to simulate real-time streaming. time.sleep(0.1) # Send text_end=true after the last chunk. ws.send(json.dumps(get_text_request("", stream_id, text_end=True))) def send_requests( ws, lines: list[str], language: str, voice: str, audio_format: str, sample_rate: int | None, bitrate: int | None, stream_id: str, ) -> None: config = get_config( stream_id=stream_id, language=language, voice=voice, audio_format=audio_format, sample_rate=sample_rate, bitrate=bitrate, ) ws.send(json.dumps(config)) stream_text(lines, stream_id, ws) def run_session( api_key: str, lines: list[str], language: str, voice: str, audio_format: str, sample_rate: int | None, bitrate: int | None, stream_id: str, output_path: str, ) -> None: print("Connecting to Soniox...") # Get your API key at console.soniox.com, then run: export SONIOX_API_KEY= with connect( SONIOX_TTS_WEBSOCKET_URL, additional_headers={"Authorization": f"Bearer {api_key}"}, ) as ws: send_errors: list[Exception] = [] def send_worker() -> None: try: send_requests( ws, lines, language, voice, audio_format, sample_rate, bitrate, stream_id, ) except Exception as exc: send_errors.append(exc) # Send config and text in the background while receiving responses. threading.Thread( target=send_worker, daemon=True, ).start() print("Session started.") audio_chunks: list[bytes] = [] try: while True: if send_errors: raise RuntimeError(f"Failed to send realtime requests: {send_errors[0]}") message = ws.recv() res = json.loads(message) # Error from server. if res.get("error_code") is not None: print(f"Error: {res['error_code']} - {res['error_message']}") break # Collect audio bytes from base64-encoded chunks. audio_b64 = res.get("audio") if audio_b64: audio_chunks.append(base64.b64decode(audio_b64)) # Session finished. if res.get("terminated"): break except ConnectionClosedOK: # Normal, server closed after finished. pass except KeyboardInterrupt: print("\nInterrupted by user.") except Exception as e: print(f"Error: {e}") finally: audio_data = b"".join(audio_chunks) if audio_data: destination = get_output_path(output_path=output_path, audio_format=audio_format) with open(destination, "wb") as fh: fh.write(audio_data) print(f"Wrote {len(audio_data)} bytes to {destination}") else: print("No audio file was written.") def main(): parser = argparse.ArgumentParser() parser.add_argument( "--line", action="append", default=None, help="Line to send to realtime TTS (repeat --line for multiple lines).", ) parser.add_argument("--language", default="en") parser.add_argument("--voice", default="Adrian") parser.add_argument("--audio_format", default="wav") parser.add_argument("--stream_id", default="stream-1") parser.add_argument("--output_path", default="tts-ws") parser.add_argument("--sample_rate", type=int) parser.add_argument("--bitrate", type=int) args = parser.parse_args() if args.audio_format not in VALID_AUDIO_FORMATS: raise ValueError(f"audio_format must be one of {VALID_AUDIO_FORMATS}") if args.sample_rate is not None and args.sample_rate not in VALID_SAMPLE_RATES: raise ValueError(f"sample_rate must be None or one of {VALID_SAMPLE_RATES}") if args.bitrate is not None and args.bitrate not in VALID_BITRATES: raise ValueError(f"bitrate must be None or one of {VALID_BITRATES}") api_key = os.environ.get("SONIOX_API_KEY") if not api_key: raise RuntimeError( "Missing SONIOX_API_KEY.\n" "1. Get your API key at https://console.soniox.com\n" "2. Run: export SONIOX_API_KEY=" ) run_session( api_key=api_key, lines=args.line or DEFAULT_LINES, language=args.language, voice=args.voice, audio_format=args.audio_format, sample_rate=args.sample_rate, bitrate=args.bitrate, stream_id=args.stream_id, output_path=args.output_path, ) if __name__ == "__main__": main() ``` ```sh title="Terminal" # Generate speech with default settings (wav output) python soniox_realtime.py --line "Hello from Soniox websocket Text-to-Speech." # Generate raw PCM output python soniox_realtime.py --audio_format pcm_s16le --sample_rate 24000 --output_path tts-output ``` See on GitHub: [soniox\_realtime.js](https://github.com/soniox/soniox_examples/blob/master/text_to_speech/nodejs/soniox_realtime.js). ``` import fs from "fs"; import path from "path"; import WebSocket from "ws"; import { parseArgs } from "node:util"; import process from "process"; const SONIOX_TTS_WEBSOCKET_URL = "wss://tts-rt.soniox.com/tts-websocket"; const MODEL = "tts-rt-v2"; const VALID_SAMPLE_RATES = [8000, 16000, 24000, 44100, 48000]; const VALID_BITRATES = [32000, 64000, 96000, 128000, 192000, 256000, 320000]; const VALID_AUDIO_FORMATS = [ "pcm_f32le", "pcm_s16le", "pcm_mulaw", "pcm_alaw", "wav", "aac", "mp3", "opus", "flac", ]; const RAW_PCM_FORMATS = ["pcm_s16le", "pcm_f32le", "pcm_mulaw", "pcm_alaw"]; const DEFAULT_LINES = [ "Welcome to Soniox real-time Text-to-Speech. ", "As text is streamed in, audio streams back in parallel with high accuracy, ", "so your application can start playing speech ", "within milliseconds of the first word.", ]; // Resolve a concrete output file path. // If the provided path has no extension, derive one from audio_format: // * pcm_s16le -> .wav (we wrap the bytes in a WAV container below) // * other pcm_* -> .pcm (raw, no container) // * anything else -> the format name (e.g. .flac, .mp3, .opus) function resolveOutputPath(outputPath, audioFormat) { if (outputPath && path.extname(outputPath)) { return outputPath; } const ext = audioFormat === "pcm_s16le" ? "wav" : RAW_PCM_FORMATS.includes(audioFormat) ? "pcm" : audioFormat; const base = outputPath || "tts-ws"; return `${base}.${ext}`; } function pcmS16leToWav(pcm, { sampleRate, numChannels = 1 }) { const bitsPerSample = 16; const byteRate = sampleRate * numChannels * (bitsPerSample / 8); const blockAlign = numChannels * (bitsPerSample / 8); const dataSize = pcm.byteLength; const header = Buffer.alloc(44); header.write("RIFF", 0, "ascii"); header.writeUInt32LE(36 + dataSize, 4); header.write("WAVE", 8, "ascii"); header.write("fmt ", 12, "ascii"); header.writeUInt32LE(16, 16); header.writeUInt16LE(1, 20); header.writeUInt16LE(numChannels, 22); header.writeUInt32LE(sampleRate, 24); header.writeUInt32LE(byteRate, 28); header.writeUInt16LE(blockAlign, 32); header.writeUInt16LE(bitsPerSample, 34); header.write("data", 36, "ascii"); header.writeUInt32LE(dataSize, 40); return Buffer.concat([header, Buffer.from(pcm)]); } // Get Soniox TTS config. function getConfig({ streamId, language, voice, audioFormat, sampleRate, bitrate, }) { const config = { // Client-defined stream id to identify this realtime request. stream_id: streamId, // Select the model to use. // See: docs.soniox.com/tts/models model: MODEL, // Set the language of the input text. // See: docs.soniox.com/tts/concepts/supported-languages language, // Select the voice to use. // See: docs.soniox.com/tts/concepts/voices voice, // Audio format. // See: docs.soniox.com/tts/concepts/audio-formats audio_format: audioFormat, }; if (sampleRate !== undefined) config.sample_rate = sampleRate; if (bitrate !== undefined) config.bitrate = bitrate; return config; } function getTextRequest(text, streamId, textEnd) { return { text, text_end: textEnd, stream_id: streamId, }; } // Stream text lines to the websocket. async function streamText(lines, streamId, ws) { for (const line of lines) { const cleanLine = line.trim(); if (!cleanLine) continue; ws.send(JSON.stringify(getTextRequest(cleanLine, streamId, false))); // Sleep for 100 ms to simulate real-time streaming. await new Promise((res) => setTimeout(res, 100)); } // Send text_end=true after the last chunk. ws.send(JSON.stringify(getTextRequest("", streamId, true))); } function runSession({ apiKey, lines, language, voice, audioFormat, sampleRate, bitrate, streamId, outputPath, }) { return new Promise((resolve, reject) => { console.log("Connecting to Soniox..."); // Get your API key at console.soniox.com, then run: export SONIOX_API_KEY= const ws = new WebSocket(SONIOX_TTS_WEBSOCKET_URL, { headers: { Authorization: `Bearer ${apiKey}` }, }); const audioChunks = []; const finalize = (err) => { const destination = resolveOutputPath(outputPath, audioFormat); if (audioChunks.length > 0) { const audio = Buffer.concat(audioChunks); // Wrap raw pcm_s16le in a WAV container so the .wav file plays everywhere. const bytes = audioFormat === "pcm_s16le" && path.extname(destination).toLowerCase() === ".wav" ? pcmS16leToWav(audio, { sampleRate }) : audio; fs.writeFileSync(destination, bytes); console.log(`Wrote ${bytes.length} bytes to ${path.resolve(destination)}`); } else { console.log("No audio file was written."); } if (err) reject(err); else resolve(); }; ws.on("open", () => { const config = getConfig({ streamId, language, voice, audioFormat, sampleRate, bitrate, }); // Send first request with config. ws.send(JSON.stringify(config)); // Start streaming text in the background. streamText(lines, streamId, ws).catch((err) => { console.error("Text stream error:", err); }); console.log("Session started."); }); ws.on("message", (msg) => { let res; try { res = JSON.parse(msg.toString()); } catch { return; } // Error from server. // See: https://docs.soniox.com/api-reference/tts/websocket-api#error-response if (res.error_code) { console.error(`Error: ${res.error_code} - ${res.error_message}`); ws.close(); return; } // Collect audio bytes from base64-encoded chunks. if (res.audio) { audioChunks.push(Buffer.from(res.audio, "base64")); } // Session finished. if (res.terminated) { console.log("Session finished."); ws.close(); } }); ws.on("close", () => { finalize(null); }); ws.on("error", (err) => { console.error("WebSocket error:", err.message); finalize(err); }); }); } async function main() { const { values: argv } = parseArgs({ options: { line: { type: "string", multiple: true }, language: { type: "string", default: "en" }, voice: { type: "string", default: "Adrian" }, audio_format: { type: "string", default: "pcm_s16le" }, stream_id: { type: "string", default: "stream-1" }, output_path: { type: "string", default: "tts-ws" }, sample_rate: { type: "string" }, bitrate: { type: "string" }, }, }); if (!VALID_AUDIO_FORMATS.includes(argv.audio_format)) { throw new Error( `audio_format must be one of ${VALID_AUDIO_FORMATS.join(", ")}`, ); } let sampleRate = argv.sample_rate !== undefined ? Number(argv.sample_rate) : undefined; if (sampleRate === undefined && RAW_PCM_FORMATS.includes(argv.audio_format)) { sampleRate = 24000; } if (sampleRate !== undefined && !VALID_SAMPLE_RATES.includes(sampleRate)) { throw new Error( `sample_rate must be one of ${VALID_SAMPLE_RATES.join(", ")}`, ); } const bitrate = argv.bitrate !== undefined ? Number(argv.bitrate) : undefined; if (bitrate !== undefined && !VALID_BITRATES.includes(bitrate)) { throw new Error(`bitrate must be one of ${VALID_BITRATES.join(", ")}`); } const apiKey = process.env.SONIOX_API_KEY; if (!apiKey) { throw new Error( "Missing SONIOX_API_KEY.\n" + "1. Get your API key at https://console.soniox.com\n" + "2. Run: export SONIOX_API_KEY=", ); } await runSession({ apiKey, lines: argv.line && argv.line.length > 0 ? argv.line : DEFAULT_LINES, language: argv.language, voice: argv.voice, audioFormat: argv.audio_format, sampleRate, bitrate, streamId: argv.stream_id, outputPath: argv.output_path, }); } main().catch((err) => { console.error("Error:", err.message); process.exit(1); }); ``` ```sh title="Terminal" # Generate speech with default settings (wav output) node soniox_realtime.js --line "Hello from Soniox websocket Text-to-Speech." # Generate raw PCM output node soniox_realtime.js --audio_format pcm_s16le --sample_rate 24000 --output_path tts-output ``` # Community and support URL: /community-and-support Engage with our community to explore new updates, participate in discussions, contribute to our projects, and report any issues you encounter. import { LinkCard } from "@/components/link-card"; import { GitHubIcon } from "@/components/github-icon"; ## Support We offer three levels of support depending on your plan: **Free**
Get help from the developer community through our [Discord server](https://discord.gg/rWfnk9uM5j). **Business and Enterprise support**
For production deployments, Soniox offers dedicated support channels, response-time SLAs, and escalation paths based on your support plan. Contact [sales@soniox.com](mailto:sales@soniox.com) to discuss the right support option for your team. *** ## Github We use GitHub to track issues related to official Soniox SDKs and integrations. Check our [Soniox GitHub](https://github.com/soniox) profile for all available code. *** ## Website For more information about our products, pricing or Soniox in general, visit out [website](https://soniox.com/). # Account and organization deletion URL: /console/account-deletion Delete your Soniox account or an organization, learn what is deleted with it, and fix the issues that can block deletion. You can delete your Soniox account from the Console and, if your role allows it, an organization. Neither can be undone. ## What gets deleted What happens to each of your organizations depends on whether anyone else is in it: * **Organizations where you are the only member** are deleted with your account, along with all of their projects, API keys, files, and transcripts. * **Organizations with other members** stay as they are. Soniox only removes you from them. If you want to keep your team's work, make sure someone else is an Admin of the organization before you delete your account. ## Delete your account Select your email, then [**Manage your Soniox account**](https://console.soniox.com/user/settings/), and scroll to **Delete account**. Read the list of what will be deleted. If something blocks deletion, see [Fix what blocks deletion](#fix-what-blocks-deletion). Select **Delete my account**. Confirm that it's you. If you sign in with a password, enter it. Then type your email address and select **Delete account**. Soniox signs you out once the account is deleted. ## Delete an organization You can delete an organization without deleting your account, if your role allows it. See [Members and roles](/console/members-and-roles). Soniox deletes all of the organization's data, and its members lose access. Before you can delete an organization: * **Delete all projects first.** See [Delete a project](/console/projects#delete-a-project). * **You can't delete your default organization**, the one Soniox created when you signed up. Soniox deletes it only with your account. * **Fix any billing issues.** See the rows marked **Both** in [Fix what blocks deletion](#fix-what-blocks-deletion). To delete an organization: Go to Organization > **Settings** and find **Delete organization**. Select **Delete this organization**, type the organization's name to confirm, and select **Delete organization**. ## Fix what blocks deletion Soniox won't delete an account or organization while doing so would leave a team without an Admin or leave money behind. The page lists each issue with a button that takes you to the fix. Fix them all, then try again. | The page says | Applies to | What to do | | ------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | You are the only admin of this organization | Account | In Organization > **Members**, make another member an Admin. | | Your email is this organization's contact email | Account | In Organization > **Settings**, change the contact email to someone else's. | | You are the only member of this organization | Account | [Delete that organization](#delete-an-organization) first, or invite another member. This applies to every organization except your default one. | | The organization has a negative balance | Both | In Organization > **Billing**, add funds to bring the balance above zero. | | The organization has a paid balance | Both | Select **Contact support** to email Soniox about the money left in the organization. If only a small amount is left, the page doesn't block deletion but warns you that you'll lose the money. | | Open invoice, invoice billing, active contract, or support package | Both | Select **Contact support** to email Soniox. Soniox needs to close these first. | # Console URL: /console What the Soniox Console is, how organizations and projects fit together, and where to find each setting. import { LinkCards } from "@/components/link-card"; The [Soniox Console](https://console.soniox.com/) is where you manage your Soniox account. Use it to create API keys, invite your team, try models in the playground, watch usage, set spending limits, and pay your bills. ## How the Console is organized Everything in the Console belongs to one of three levels: * **Account**: you, the person who signs in. Your account holds your name, email, password, and two-factor settings. * **Organization**: your company or team. It holds members, billing, limits, and security settings. One account can belong to several organizations. * **Project**: a workspace inside an organization. It holds API keys, usage, and the files and transcripts your requests create. Each project runs in one region. When you sign up, Soniox creates an organization for you. You are its first Admin. ## Where to find things The sidebar has an **Organization** section and a **Project** section. Switch between organizations and projects at the top of the page. | You want to | Go to | | ---------------------------------- | --------------------------------------------------------------------------------------------------- | | Invite people or change their role | [Organization > **Members**](https://console.soniox.com/org/members/) | | Set a monthly spending limit | [Organization > **Limits**](https://console.soniox.com/org/limits/) | | Add funds or download invoices | [Organization > **Billing**](https://console.soniox.com/org/billing/overview/) | | Request access to a region | [Organization > **Security & compliance**](https://console.soniox.com/org/security-and-compliance/) | | Require two-factor authentication | [Organization > **Settings**](https://console.soniox.com/org/settings/) | | Create or delete API keys | [Project > **API keys**](https://console.soniox.com/org/projects/api/keys/) | | See usage, costs, and request logs | [Project > **Usage**](https://console.soniox.com/org/projects/usage/cost/) | | Rename or delete a project | [Project > **Settings**](https://console.soniox.com/org/projects/settings/) | | Delete an organization | [Organization > **Settings**](https://console.soniox.com/org/settings/) | | Delete your account | [Your email > **Manage your Soniox account**](https://console.soniox.com/user/settings/) | ## Contact email Each organization has a **contact email**. Soniox sends important messages about the organization there, such as when you reach a [monthly usage limit](/console/limits#cost-limits) or get an answer to a limit increase request. You can change it, and the organization's name, under Organization > **Settings**, if your role allows it. Use an address your team reads, such as a shared inbox, so the messages don't get lost when someone leaves. ## Learn more # Limits URL: /console/limits Set a monthly spending limit for your organization or a project, and see or raise your API quotas in the Soniox Console. Limits protect you from surprise bills and keep the service stable for everyone. The Console has two kinds: * **Cost limits** cap how much you spend in a month, in US dollars. * **API quotas** cap how much you use the API at once, such as how many real-time streams can be open at the same time. You can set both for the whole organization and for each project. Who can see and change limits depends on your role. See [Members and roles](/console/members-and-roles). ## Cost limits ### Organization Go to Organization > **Limits**. At the top you see the **Soniox maximum**, the most your organization can spend in a month. Below it, you can set two values of your own: * **Organization monthly usage limit**: when your organization spends more than this in a calendar month (UTC), Soniox rejects further API requests and sends an email to your organization's contact email. * **Email notification trigger**: when your organization spends more than this in a calendar month, Soniox only sends the email. Requests keep working. Leave a field empty if you don't want that limit. Spending starts again from zero at the start of each month. Limits may take a short while to take effect, and you still pay for any usage above the limit in that time. Set the limit a little below the amount you can't go over. ### Project Go to Project > **Limits** to set the same two values for one project. A project limit can't be higher than the organization limit. ### Raise the maximum If the Soniox maximum is too low, select **Request usage limit increase** on Organization > **Limits**. Enter the new limit you want and a short reason. Soniox sends the answer to your organization's contact email. ## API quotas Find API quotas for each product under Organization > **Limits**. Each product has **one main limit**, such as the number of Speech-to-Text streams that can run at once. When you raise the main limit, Soniox raises the related limits with it. ### Raise a quota Select **Request increase** next to a product, enter the value you want, and explain why you need it. You need funds in your organization before you can request a higher quota. **Limit increase history** lists past requests and their answers. ### Project quotas By default, a project uses the organization's quotas. To keep one project from using up your whole quota, go to Project > **Limits** and set a lower value for that project. To undo it, select **Inherit from organization**. Select **Show advanced limits** to set the related limits one by one. ## Learn more * [Concurrency limits](/guides/concurrency-limits): watch live and past concurrent streams. * Product limits: [real-time Speech-to-Text](/stt/rt/limits-and-quotas), [async Speech-to-Text](/stt/async/limits-and-quotas), [real-time Text-to-Speech](/tts/rt/limits-and-quotas), and [Text-to-Speech REST API](/tts/rest-api/limits-and-quotas). # Members and roles URL: /console/members-and-roles Invite people to your Soniox organization and give each of them the Admin, Member, or Billing Viewer role. See exactly what each role can see and change. Members are the people who can sign in to your organization in the Console. Each member has one **role**, and the role decides what they can see and change. ## Roles Soniox has three roles: * **Admin** can do everything in the organization, including billing, members, and settings. Give it to owners and team leads. * **Member** works with projects: API keys, the playground, and usage. Give it to developers. * **Billing Viewer** sees costs and invoices for the whole organization, and nothing inside projects. Give it to finance and accounting. Give each person only the access they need. You can't create your own roles or change what a role allows. ## What each role can do ### Projects | Task | Admin | Member | Billing Viewer | | ---------------------------------------------------- | ----- | ------ | -------------- | | Open every project in the organization | Yes | Yes | No | | Create a project | Yes | Yes | No | | Rename or delete a project | Yes | Yes | No | | Create, edit, and delete a project's API keys | Yes | Yes | No | | Use the Speech-to-Text and Text-to-Speech playground | Yes | Yes | No | | See a project's usage, costs, and request logs | Yes | Yes | No | A Member can open every project, not only the ones they created, and can delete any project and its API keys. Give the Member role only to people you trust with your production keys. ### Billing | Task | Admin | Member | Billing Viewer | | ------------------------------------------------------ | ----- | ------ | -------------- | | See the balance, costs, transactions, and reports | Yes | No | Yes | | Download receipts and invoices | Yes | No | Yes | | Add funds, turn on autopay, and manage payment methods | Yes | No | No | ### Limits | Task | Admin | Member | Billing Viewer | | -------------------------------------- | ----- | ------ | -------------- | | See organization limits | Yes | Yes | Yes | | See project limits | Yes | Yes | No | | Change organization and project limits | Yes | No | No | | Request a limit increase | Yes | No | No | See [Limits](/console/limits) for what each limit does. ### Organization | Task | Admin | Member | Billing Viewer | | -------------------------------------------------------- | ----- | ------ | -------------- | | Invite members, change their roles, and remove them | Yes | No | No | | Rename the organization and change its contact email | Yes | No | No | | Require two-factor authentication for all members | Yes | No | No | | Request access to a region | Yes | No | No | | Get compliance documents (SOC 2, DPA, BAA) | Yes | No | No | | Create [organization API keys](/guides/organization-api) | Yes | No | No | | Delete the organization | Yes | No | No | If you open a page your role doesn't cover, the Console tells you your role. Ask an Admin to change it if you need access. ## Invite a member Only Admins can invite people. Each person needs a Soniox account first. If they don't have one, ask them to [sign up](https://console.soniox.com/). Go to Organization > **Members** and select **Invite new members**. Enter the email address of each person you want to invite, and choose a role for each one. Select **Roles** in the form for a short reminder of what each role allows. Send the invite. The person gets an email and joins your organization once they accept it. The invite expires after 7 days. To send a new one, invite them again. ## Change a role or remove a member On Organization > **Members**, an Admin can change a member's role or remove them from the organization with the actions next to their name. Removing a member doesn't delete their Soniox account. It only takes away their access to your organization. Only another Admin can change your role or remove you. # Projects and regions URL: /console/projects Use projects to separate API keys, usage, and data, and choose the region where each project processes and stores data. A **project** is a workspace inside your organization. Each project has its own API keys, usage reports, limits, and stored files and transcripts. Use projects to keep things apart. Common setups: * One project for **development** and one for **production**, so test traffic never touches production keys or limits. * One project per **product** or **customer**, so you can see the cost of each one. * A project in another **region**, to keep data in a certain part of the world or to lower latency for users near it. ## Create a project Open the project switcher at the top of the page and select **Create project**. Enter a **name** and, if you like, a **description**. Choose a **region**. Regions your organization can't use yet are grayed out. To use one, select **Request access** next to it. See [Request a region](#request-a-region). Select **Create project**, then create an API key for it under Project > **API keys**. ## Regions The region decides where Soniox processes and stores the project's audio and transcripts. For example, a project in the European Union region keeps that data in the EU. * **You can't change a project's region later.** To use another region, create a new project in that region. * **Use the region's API domain.** An API key from an EU project must call `api.eu.soniox.com`, not `api.soniox.com`. [Data residency](/data-residency#regional-endpoints) lists the domains for each region. * **Some regions need approval.** See [Request a region](#request-a-region). For what stays in the region and what doesn't, see [Data residency](/data-residency). ### Request a region To use a region your organization doesn't have yet, ask Soniox for access. You need funds in your organization and a role that allows it. See [Members and roles](/console/members-and-roles). Go to Organization > **Security & compliance** and select **Request access**. You can also start a request from the region list when you create a project. Explain why you need the region, and send the request. The region shows as **Pending** until Soniox approves it. ## Delete a project Go to Project > **Settings** and select **Delete this project**. To confirm, type the project's name. All API keys in the project stop working at once, and all of its files and transcripts are deleted. # Data residency URL: /data-residency Learn about data residency. Soniox keeps your data yours. Any content you send to the Soniox API (audio, transcripts, or metadata) is **never used to train or improve our models.** For more information, see our [Security and privacy](/security-and-privacy). *** ## What is data residency Data residency lets you choose **where** Soniox processes and stores your content. When you select a region for a project, **all audio and transcript data for that project stays in that region**, for both processing and storage. *** ## How data residency works When data residency is enabled for your account: * You choose a **region** when creating a new project. * Any API requests made using that project's API key are handled **fully within the selected region.** * All **content data** (audio + transcripts) remains within that region for processing and storage. ### System data Data residency **does not apply to system data** such as account and project metadata, usage statistics, and billing data. This system data may be processed outside the selected region. **Your content (audio + transcripts) never leaves the region you choose.** *** ## Using data residency Data residency is set **per project** within your Soniox organization. To get access to a region, select **Request access** under **Region access** in the Console [Security & compliance](https://console.soniox.com/org/security-and-compliance/) section. The region stays pending until it is approved. See [Projects and regions](/console/projects#regions). ### 1. Create a project with a region When creating a new project: * Select the region from the **region** dropdown. * Each project receives region-specific API keys. ### 2. Use the region-specific API domain To ensure processing stays in the region, use: * The **API key** from the regional project. * The **correct API domain** for that region (see below). *** ## Regional endpoints | Region | Regional storage | Regional processing | Capabilities | API domain | | ------------------ | ---------------- | ------------------- | ------------------ | ------------------------------------------------------------------------------- | | **United States** | ✅ Yes | ✅ Yes | Full API supported | `api.soniox.com`
`stt-rt.soniox.com`
`tts-rt.soniox.com` | | **European Union** | ✅ Yes | ✅ Yes | Full API supported | `api.eu.soniox.com`
`stt-rt.eu.soniox.com`
`tts-rt.eu.soniox.com` | | **Japan** | ✅ Yes | ✅ Yes | Full API supported | `api.jp.soniox.com`
`stt-rt.jp.soniox.com`
`tts-rt.jp.soniox.com` | | **India** | ✅ Yes | ✅ Yes | Full API supported | `api.in.soniox.com`
`stt-rt.in.soniox.com`
`tts-rt.in.soniox.com` | # Soniox Live URL: /demo-apps/soniox-live Demo apps showing how to add Soniox Speech-to-Text to your product import Image from "next/image"; ## Overview Soniox Live is a **demo app** that shows how to stream audio from your microphone directly to the Soniox [Real-time API](/api-reference/stt/websocket-api) for instant transcription and translation. This is not the [Soniox App](https://soniox.com/soniox-app) (our end-user product). Instead, it is a **reference implementation** for developers who want to learn how to embed Soniox into their own web or mobile applications. Web and mobile demo apps screenshot ## Features * Stream audio from your mic to Soniox in real time * Low-latency, high-accuracy transcription in 60+ languages * Low-latency speech translation to 60+ languages * Runs in the browser (React) and mobile (React Native) * Lightweight server issues temporary client keys for secure access ## Usage flow 1. Tap **Start** to begin streaming from your mic 2. **Live captions** appear word by word, then finalize 3. Toggle **Translation** and choose a target language for live translated captions 4. Tap **Stop** to end the session ## Architecture * **Server (Python):** Stores your secret Soniox API key and issues **temporary API keys** to clients * **Frontend (React & React Native):** Requests a temporary API key from your server, then streams microphone audio directly to Soniox servers for real-time transcription and translation We provide all the implementations with links to GitHub: * [Python server](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-live-demo/server) * [React frontend](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-live-demo/react) (web) * [React Native frontend](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-live-demo/react-native) (mobile) # Speech-to-speech translation URL: /demo-apps/soniox-speech-to-speech-translation Demo app showing how to add real-time speech-to-speech translation with Soniox. ## Overview [Soniox Speech-to-speech Translation](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-speech-to-speech-translation-demo) demo app shows how to combine the Soniox real-time speech-to-text with translation and real-time text-to-speech WebSocket APIs into a complete speech-to-speech translation pipeline - voice input in one language, hear the translation in another, in real time. This is a **reference implementation** for developers who want to learn how to wire the two real-time APIs together at the protocol level, without an SDK. The backend is a small FastAPI service; the frontend is a vanilla HTML/JS page. ## Features * Stream audio from an audio file or your mic to Soniox in real time * Live transcription in 60+ languages, with automatic source-language detection * Mid-sentence speech translation to 60+ languages - translation tokens stream as you talk * Live spoken translation through one of the [Soniox voices](/tts/concepts/voices), played back to you * Optional speaker diarization and language identification * Toggle for text-only translation mode that skips TTS entirely ## Usage flow 1. Pick a **target language** and a **voice** in the sidebar 2. Tap **Start talking** to begin streaming from your mic 3. The **original transcript** appears on the left; the **translation** appears on the right, word by word 4. The translated speech plays through your speakers in the chosen voice 5. Tap **Stop** to end the session ## Architecture * **Server (Python / FastAPI):** Holds your Soniox API key, accepts a WebSocket from the browser, and proxies audio and tokens between the browser and Soniox. Manages the per-utterance TTS stream lifecycle, pre-warming, and connection keepalive. * **Frontend (vanilla HTML / JS):** Captures audio file or microphone audio with `MediaRecorder`, streams the bytes to the backend over WebSocket, renders incoming token JSON into the transcript columns, and plays incoming PCM audio through the Web Audio API. Source code available in our [GitHub examples repo](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-speech-to-speech-translation-demo). # Soniox Voice Agent URL: /demo-apps/soniox-voice-agent Demo app showing how to implement a voice-to-voice AI agent with Soniox voice solutions import Image from "next/image"; ## Overview Soniox Voice Agent is a **demo app** that shows how to build a complete voice-to-voice conversational AI assistant. It demonstrates how to integrate streaming speech-to-text, a large language model (LLM), and streaming text-to-speech (TTS) into a seamless, low-latency application. The demo bot is pre-configured as an appointment booking assistant for a fictional car repair shop, "Soniox AutoWorks." It can book appointments for services such as oil changes and car repairs, collect customer names and vehicle information, provide available appointment slots, and interactively guide users through the booking process. The entire voice bot codebase is designed for easy customization and extension to other domains. You can quickly adapt the bot to different business needs, integrate new tools, or change its persona, making it a flexible starting point for any conversational AI application. {/* Voice bot web interface screenshot */} ## Features * **End-to-end real-time**: Fully streaming architecture (voice-in, voice-out) for natural, low-latency conversations * **Multilingual**: Understands and responds to users in multiple languages * **Customizable AI**: The bot's persona and business logic are defined in a single, easy-to-edit file * **Extensible tools**: Connect the LLM to your own APIs and databases to perform real-world actions * **Multiple ways to interact**: Web frontend, Twilio phone call, or any other WebSocket-based connection ## Usage flow 1. Connect via **web browser** or **phone call** 2. Speak naturally in any language to the AI agent 3. The bot transcribes your speech, understands intent, and generates a response 4. Listen to the AI's spoken response in real-time 5. The conversation continues with full context awareness ## Architecture * **Server (Python):** Orchestrates the conversation with modular processors (VAD, STT, LLM, TTS) * **Frontend (React):** Captures microphone audio, streams it to the backend, and plays back responses * **Twilio proxy (Python):** Optional bridge to connect phone calls to the voice bot backend We provide all the implementations with links to GitHub: * [Python server](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-voice-bot-demo/server) * [React frontend](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-voice-bot-demo/frontend) (web) * [Twilio proxy](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-voice-bot-demo/twilio) (phone integration) ## How it works The system is built on a modular, asynchronous architecture. When a user connects, a session is created to orchestrate the entire conversation, managing the flow of data between four core processors: #### Voice Activity Detection (VAD) Processor Uses Silero VAD to detect speech boundaries in incoming audio. Emits events to interrupt TTS when the user starts speaking. #### Speech-to-Text (STT) Processor The user's voice is captured by a client (web app or phone call) and streamed to the backend. The STT Processor uses the Soniox API to transcribe the audio into text in real-time. #### Language Model (LLM) Processor The transcribed text is sent to the LLM Processor. It maintains the conversation history, determines the user's intent, and decides whether to generate a direct response or use a predefined tool (like checking available slots). #### Text-to-Speech (TTS) Processor The LLM's final text response is sent to the TTS Processor, which uses the Soniox API to convert it back into audio and streams it to the user, completing the conversational turn. ## Next steps Use this [project](https://github.com/soniox/soniox_examples/tree/master/apps/soniox-voice-bot-demo) as a starting point to build your own voice assistant: * Customize the bot's persona and instructions in `server/tools.py` * Implement your own tools to connect to external APIs and databases * Adapt the frontend or Twilio integration to your needs # FAQ URL: /faq Common troubleshooting guidance and answers for integrating with the Soniox API. This page answers common questions related to integrating with the Soniox API. High WebSocket connection startup time is usually caused by one or more of the following: * **Network latency:** High round-trip time between your client and Soniox increases the duration of the TLS handshake and WebSocket upgrade. * **Region selection:** Using an endpoint located far from your compute environment adds unnecessary cross-region latency during connection establishment. See [Data residency](/data-residency) for more info. * **Large initial context payload:** Sending a large [context](/stt/concepts/context) during initialization delays readiness because the server must fully receive and process the payload before the session becomes active. To minimize perceived startup delay, you should always **buffer audio locally before the WebSocket connection is established** and immediately stream all buffered audio chunks after sending the initial configuration message. You can request a limit increase from the [Soniox Console organization limits](https://console.soniox.com/org/limits) page. Requests are reviewed within 1-3 business days. See [Limits](/console/limits) for how. Yes. Soniox provides standard legal and compliance documentation for companies integrating the Soniox API into their products or services. This may include an MSA, DPA, and security or compliance documentation required for procurement or security review processes. Documentation is available for Business and Enterprise customers. Please contact [support@soniox.com](mailto:support@soniox.com) to request access or begin the review process. # API key permissions URL: /guides/api-key-permissions Limit what each Soniox API key can do, so each key has only the access it needs. ## Overview Every API key in a project has a list of permissions. Each permission lets the key use one part of the Soniox API, such as real-time transcription or file management. A call to anything else is refused with [`permission_denied`](/api-reference/errors#permission-denied). Give each key only the access it needs. For example, if your server uses a key only to create temporary API keys for a browser, that key does not need access to your files or your usage data. If it leaks, the damage is limited. Keys created before permissions were introduced have full access and keep working as before. *** ## Setting permissions 1. In the [Soniox Console](https://console.soniox.com), open your project and go to **API keys**. 2. Select **Create API key** and give the key a name. 3. Turn on **Full access**, or choose a level for each permission the key needs. 4. Create the key and copy it. The full key is shown only once. Only organization admins can create and edit keys. *** ## Permissions * **Speech-to-text, real-time**: the [Speech-to-Text WebSocket API](/api-reference/stt/websocket-api). * **Speech-to-text, async**: [transcriptions](/api-reference/stt/transcriptions/get_transcriptions). This permission is enough to transcribe a file that is already uploaded. Uploading the file needs **Files**. * **Files**: uploading and managing [files](/api-reference/stt/files/get_files). * **Text-to-speech, real-time**: the [Text-to-Speech WebSocket API](/api-reference/tts/websocket-api) and the [REST endpoint](/api-reference/tts/generate_tts), including speech generated with a cloned voice. * **Cloned voices**: managing [cloned voices](/api-reference/tts/voices/get_voices). * **Usage and limits**: [usage logs](/api-reference/other/get_usage_logs), [usage summary](/api-reference/other/get_usage_summary), [concurrency limits](/api-reference/other/get_concurrency_limits) and [concurrent streams history](/api-reference/other/get_concurrent_streams_history). * **Model listing**: [STT models](/api-reference/stt/get_models), [TTS models](/api-reference/tts/get_tts_models) and [shared voices](/api-reference/tts/get_shared_voices). * **Temporary API keys**: [creating temporary API keys](/api-reference/auth/create_temporary_api_key). This needs a second permission, see [below](#temporary-api-keys). Async transcription, files and cloned voices have two levels. **Read** allows listing and fetching. **Write** allows everything Read does, plus creating and deleting. The other permissions are either on or off. *** ## Temporary API keys Creating a [temporary API key](/guides/temporary-api-keys) needs two permissions: **Temporary API keys**, and the permission for the service in `usage_type`. | `usage_type` | The API key also needs | | ---------------------- | ------------------------- | | `transcribe_websocket` | Speech-to-text, real-time | | `tts_rt` | Text-to-speech, real-time | Temporary API keys have no permissions of their own. A temporary key can do what its `usage_type` allows. *** ## Editing a key You can change the name and permissions of a key at any time. The key itself stays the same. A change can take a few minutes to apply. Streams that are already running and temporary API keys that were already created are not affected. *** ## Errors A call that the key has no permission for is refused with HTTP status `403`. This means the key is valid but does not have the permission. An invalid or deleted key gets `401` [`unauthenticated`](/api-reference/errors#unauthenticated) instead. ```json { "status_code": 403, "error_type": "permission_denied", "message": "The API key does not have permission for this product. Edit the key's permissions at https://console.soniox.com", "validation_errors": [], "request_id": "b4c1f4d5-8d8e-4a1c-9a8c-2a0e6f7c1d3e", "more_info": "https://soniox.com/docs/api-reference/errors#permission-denied" } ``` # Concurrency limits URL: /guides/concurrency-limits Live counts of active real-time requests alongside the configured concurrency limits for the project and the organization that owns it, plus historical per-period concurrency. ## Overview Soniox applies concurrency limits to real-time APIs to ensure stability and fair use. Each project and organization has a limit on the number of [Speech-to-Text WebSocket](/api-reference/stt/websocket-api) sessions and [Text-to-Speech WebSocket](/api-reference/tts/websocket-api) streams it can have open at the same time. Active [`POST /tts`](/api-reference/tts/generate_tts) REST requests count toward the same `tts_concurrent` limit. To monitor live concurrency, open the project's **Usage > Activity** page in the [Soniox Console](https://console.soniox.com/) - the dashboard shows real-time charts of concurrent requests against the configured limit for both the project and the organization. The organization limit is checked first, then the project limit. A request is rejected as soon as one is at its cap, and the `429` response identifies which tier rejected it. See [rate and usage limits](/api-reference/errors#limit_exceeded) for the response shape. *** ## What gets returned The response has two top-level scopes, `project` and `organization`. Each scope contains: * `current` - live counts of active requests right now. * `limits` - the configured cap for that scope, or `null` when no cap is configured. When a value under `project.limits` is `null`, the project has no cap of its own and only the organization limit applies. Two services are tracked under each scope: * `transcribe_concurrent` - open Speech-to-Text WebSocket sessions. * `tts_concurrent` - open Text-to-Speech WebSocket streams and active Text-to-Speech REST requests. ```json { "project": { "current": { "transcribe_concurrent": 2, "tts_concurrent": 0 }, "limits": { "transcribe_concurrent": 4, "tts_concurrent": 1 } }, "organization": { "current": { "transcribe_concurrent": 5, "tts_concurrent": 1 }, "limits": { "transcribe_concurrent": 10, "tts_concurrent": 2 } } } ``` See [`GET /v1/concurrency-limits`](/api-reference/other/get_concurrency_limits) for the full schema and field types. *** ## Historical concurrency `GET /v1/concurrency-limits` reports only the counts right now. To see how concurrency moved over time - for example to size a limit increase against actual peaks - use [`GET /v1/concurrent-streams-history`](/api-reference/other/get_concurrent_streams_history). It returns per-period aggregates for the authenticated project, which is the same data behind the **Usage > Activity** charts in the Console. Pick one `kind` per request: * `stt` - Speech-to-Text WebSocket sessions. * `tts` - Text-to-Speech WebSocket streams and REST requests. Choose the granularity with `period_sec`. The longer the period, the longer the window allowed, and the longer the data is kept: | `period_sec` | Granularity | Maximum window | Retained for | | ------------ | ----------- | -------------- | ------------ | | `60` | Per minute | 7 days | 7 days | | `3600` | Hourly | 90 days | 90 days | | `86400` | Daily | 366 days | 2 years | `start_time` is inclusive and `end_time` is exclusive, both ISO 8601 UTC. ```http GET /v1/concurrent-streams-history?start_time=2026-04-28T09:00:00Z&end_time=2026-04-28T10:00:00Z&period_sec=60&kind=tts Authorization: Bearer ``` ```json { "kind": "tts", "entries": [ { "period_start": "2026-04-28T09:00:00Z", "period_sec": 60, "sample_min": 0, "sample_max": 4, "sample_sum": 21, "sample_count": 9, "total_count": 1 }, { "period_start": "2026-04-28T09:01:00Z", "period_sec": 60, "sample_min": 0, "sample_max": 0, "sample_sum": 0, "sample_count": 0, "total_count": 0 } ] } ``` Periods with no activity are still returned, with every field set to `0`. Use `sample_max` for the peak concurrency in a period and `sample_sum / sample_count` for the average. See [`GET /v1/concurrent-streams-history`](/api-reference/other/get_concurrent_streams_history) for the full schema and field types. *** You can request higher limits in the [Soniox Console](https://console.soniox.com/org/limits). See [Limits](/console/limits) for how. # Direct stream URL: /guides/direct-stream Stream directly from microphone to Soniox Speech-to-Text WebSocket API to minimize latency. import Image from "next/image"; ## Overview Applies to [Text-to-Speech](/tts/get-started) and [Speech-to-Text](/stt/get-started). Examples use Speech-to-Text. This guide walks you through capturing and transcribing microphone audio in real time using the Soniox [WebSocket API](/api-reference/stt/websocket-api) — optimized for the lowest possible latency. The direct stream approach enables the browser to send audio directly to the Soniox WebSocket API over a WebSocket connection, eliminating the need for any intermediary server. This results in faster transcription and a simpler architecture. Soniox's [Web SDK](/sdk/web-SDK) (`@soniox/client`) handles everything client-side — capturing microphone input, managing the WebSocket connection, and authenticating using temporary API keys. Use this setup when you want real-time speech-to-text performance directly in the browser **with minimal delay**. Soniox Speech-to-Text direct stream flowchart *** ## Temporary API keys [Temporary API keys](/guides/temporary-api-keys) (obtained from the [REST API](/api-reference/auth/create_temporary_api_key)) are required solely to establish the WebSocket connection. Once the connection is established, it will be kept alive as long it remains active. The `expires_in_seconds` configuration parameter should be set to a short duration. Following parameters are required to create a temporary API key: ```json { "usage_type": "transcribe_websocket", "expires_in_seconds": 60 } ``` To attribute browser-side traffic to an end user or session, bind a `client_reference_id` to the temporary API key — it is recorded in [usage logs](/guides/usage-logs) for every request authenticated with the key. Clients cannot override it. API request limits apply when creating temporary API keys. See **Limits** section in the [Soniox Console](https://console.soniox.com). *** ## Example This is an example of a browser-based transcription, but same principle applies to any other type of client - you minimize latency by connecting the client directly to the WebSocket API using a temporary API key. First we create a simple HTTP server that on request: 1. Renders the `index.html` template. 2. Exposes an endpoint to serve the temporary API key (`/temporary-api-key`). Python server using [FastAPI](https://fastapi.tiangolo.com/): ``` import os from pathlib import Path import requests import uvicorn from dotenv import load_dotenv from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse, JSONResponse from fastapi.templating import Jinja2Templates load_dotenv() templates = Jinja2Templates(directory=Path(__file__).parent / "templates") app = FastAPI() @app.get("/", response_class=HTMLResponse) async def get_index(request: Request): return templates.TemplateResponse( request=request, name="index.html", ) @app.get("/temporary-api-key", response_class=JSONResponse) async def get_temporary_api_key(): try: response = requests.post( "https://api.soniox.com/v1/auth/temporary-api-key", headers={ "Authorization": f"Bearer {os.getenv('SONIOX_API_KEY')}", "Content-Type": "application/json", }, json={ "usage_type": "transcribe_websocket", "expires_in_seconds": 60, }, ) if not response.ok: raise Exception(f"Error: {response.json()}") temporaryApiKeyData = response.json() return temporaryApiKeyData except Exception as error: print(error) return JSONResponse( status_code=500, content={"error": f"Server failed to obtain temporary api key: {error}"}, ) if __name__ == "__main__": port = int(os.getenv("PORT", 8000)) uvicorn.run(app, host="0.0.0.0", port=port) ``` Node.js server using [Express](https://expressjs.com/): ``` import "dotenv/config"; import express from "express"; import path from "path"; import { fileURLToPath } from "url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const app = express(); app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "templates/index.html")); }); app.get("/temporary-api-key", async (req, res) => { try { const response = await fetch( "https://api.soniox.com/v1/auth/temporary-api-key", { method: "POST", headers: { Authorization: `Bearer ${process.env.SONIOX_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ usage_type: "transcribe_websocket", expires_in_seconds: 60, }), }, ); if (!response.ok) { throw await response.json(); } res.json(await response.json()); } catch (error) { console.error(error); res.status(500).json({ error: `Server failed to obtain temporary api key: ${JSON.stringify(error)}`, }); } }); app.listen(process.env.PORT, () => { console.log(`HTTP server listening on http://0.0.0.0:${process.env.PORT}`); }); ``` Our HTML client template contains a single "Start" button, that when clicked: 1. Requests microphone permissions. 2. Calls the `/temporary-api-key` endpoint to obtain a temporary API key. 3. Creates a [`SonioxClient`](/sdk/web-SDK) whose `config` function returns the temporary API key. 4. Connects to the [WebSocket API](/api-reference/stt/websocket-api). 5. Starts transcribing from microphone input and renders transcribed text into a `div` in real-time. ```

Browser direct stream example


```
### Run it Put `index.html` in a `templates/` folder next to the server, and create a `.env` file: ```text SONIOX_API_KEY= PORT=8000 ``` ```bash pip install fastapi uvicorn requests python-dotenv jinja2 python server.py ``` ```bash npm init -y npm pkg set type=module npm install express dotenv node server.js ``` Open [http://localhost:8000](http://localhost:8000) and click **Start**. # Guides URL: /guides Practical Soniox guides for streaming architectures, temporary API keys, usage logs, and concurrency limits. import { LinkCards } from "@/components/link-card"; Soniox guides help you design production-ready Speech-to-Text and Text-to-Speech integrations around real-time streaming, secure client access, usage attribution, and operational limits. Use these guides when you need architectural guidance beyond the API reference: how to connect browsers to Soniox, when to introduce a proxy, how to issue short-lived credentials, and how to monitor usage and capacity. # Migrate WebSocket authentication URL: /guides/migrate-websocket-authentication How to move from api_key in the start message to sending the key with the connection, with before-and-after code. ## What's changing `api_key` in the first message (the Speech-to-Text start request or the Text-to-Speech config message) is **deprecated**. Send the key with the connection instead, in the Authorization header or the protocols list. The old way works until **15 January 2027**. From that date a connection that does not send its key with the connection is refused. See [WebSocket authentication](/guides/websocket-authentication) for the full description of the new way. *** ## Update your code Remove `api_key` from the start message and send the key when you connect. Add the Authorization header with `websockets`. ```python from websockets.sync.client import connect config = { "api_key": api_key, # [!code --] "model": "stt-rt-v5", "audio_format": "auto", } with connect(SONIOX_WEBSOCKET_URL) as ws: # [!code --] with connect( # [!code ++] SONIOX_WEBSOCKET_URL, # [!code ++] additional_headers={"Authorization": f"Bearer {api_key}"}, # [!code ++] ) as ws: # [!code ++] ws.send(json.dumps(config)) ``` Add the Authorization header with `ws`. ```javascript import WebSocket from "ws"; const config = { api_key: apiKey, // [!code --] model: "stt-rt-v5", audio_format: "auto", }; const ws = new WebSocket(SONIOX_WEBSOCKET_URL); // [!code --] const ws = new WebSocket(SONIOX_WEBSOCKET_URL, { // [!code ++] headers: { Authorization: `Bearer ${apiKey}` }, // [!code ++] }); // [!code ++] ws.on("open", () => { ws.send(JSON.stringify(config)); }); ``` Pass `soniox-api-key` and a [temporary API key](/guides/temporary-api-keys) in the protocols list. ```javascript const ws = new WebSocket(url); // [!code --] const ws = new WebSocket(url, ["soniox-api-key", temporaryApiKey]); // [!code ++] ws.onopen = () => { ws.send( JSON.stringify({ api_key: temporaryApiKey, // [!code --] model: "stt-rt-v5", audio_format: "auto", }), ); }; ``` On Text-to-Speech the change is the same, only the URL differs: send the key when you connect to `wss://tts-rt.soniox.com/tts-websocket` and leave `api_key` out of every config message. See the [Text-to-Speech example](/guides/websocket-authentication#text-to-speech). {/* TODO: SDKs. Uncomment after the SDK releases with connection auth are out and fill in the minimum versions. */} {/* ## SDKs */} {/* The official SDKs send the key with the connection from these versions. Update and you are done. */} {/* | Package | Minimum version | */} {/* | --- | --- | */} {/* | `@soniox/node` | X.Y.Z | */} {/* | `@soniox/client` | X.Y.Z | */} {/* | `soniox` (Python) | X.Y.Z | */} *** ## What else changes The connection is authenticated the moment it opens, which changes these rules: | | `api_key` in the start message (deprecated) | Key sent with the connection | | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Deadline to start | Speech-to-Text: the start request must arrive within **20 seconds** of connecting. Text-to-Speech: the first config message must arrive within about **10 seconds**. Otherwise the connection is closed with WebSocket status `1001`. | None. Open the connection early and start when you are ready. | | Keepalive before the start message | Speech-to-Text: not accepted. The first message is read as the start request and rejected with a `400` error frame. Text-to-Speech: does not authenticate the connection. | Works. Send one at least every **40 seconds**, or the connection is closed as idle with WebSocket status `1001`. See [connection timeouts](/guides/websocket-authentication#connection-timeouts). | | [Connection limit](/guides/websocket-authentication#connection-limit) | The connection is counted from its start message. Over the limit, it gets the `429` [`max_concurrent_connections_reached`](/api-reference/errors#max-concurrent-connections-reached) error frame in response to that message: on Speech-to-Text it is then closed, on Text-to-Speech only that stream is refused. | The connection is counted about one second after it opens. Over the limit, it gets the `429` error frame and is closed. | | `api_key` in the start message | Required. | Omit it, or repeat the same key. A different key is refused with a `400` [`invalid_request`](/api-reference/errors#invalid-request) error frame: on Speech-to-Text the connection is then closed, on Text-to-Speech only that stream is refused and the connection stays open. | | Temporary keys | A key in the older `temp:` format works. On Text-to-Speech, a fresh single-use key in each config message works. | Keys that start with `snx_temp_` work in the Authorization header and in the protocols list. A `temp:` key works only in the Authorization header. A single-use key allows one stream on the connection. | *** ## After 15 January 2027 A connection that does not send its key with the connection is refused with a `401` [`unauthenticated`](/api-reference/errors#unauthenticated) error frame and closed: ```json { "error_code": 401, "error_type": "unauthenticated", "error_message": "Missing API key. Send it with the connection: the Authorization header \"Bearer \", or soniox-api-key and the key in the WebSocket protocols list." } ``` If you see this error, go to [Update your code](#update-your-code). # Organization API URL: /guides/organization-api Read your organization's profile, projects, balance, usage and limits, and manage project API keys from your own tooling. ## Overview The Organization API gives access to your organization as a whole, instead of to one project. Use it to monitor spend and limits across all projects, or to create and delete project API keys from your own tooling. With the Organization API you can read and manage: * **Organization profile and projects**: [the organization](/api-reference/organization/get_organization) and [its projects](/api-reference/organization/get_organization_projects). * **Balance and spend**: [the prepaid balance](/api-reference/organization/get_organization_balance) and billing setup. * **Usage and limits across projects**: [monthly usage](/api-reference/organization/get_organization_monthly_usage), the daily [usage summary](/api-reference/organization/get_organization_usage_summary) per project and model, and [limits](/api-reference/organization/get_organization_limits). * **Project API keys**: [listing](/api-reference/organization/get_organization_project_api_keys), [creating](/api-reference/organization/create_organization_project_api_key) and [deleting](/api-reference/organization/delete_organization_project_api_key) the API keys of any project. The endpoints are under `https://api.soniox.com/v1/organization` and need an [organization API key](#organization-api-keys). *** ## Organization API keys An organization API key is a dedicated key for the Organization API. Organization API keys start with `snx_org_`, so you can tell them apart from project API keys. The two kinds are not interchangeable. An organization API key cannot call Speech-to-Text, Text-to-Speech or other project endpoints, and a project API key cannot call organization endpoints. Either call is refused with [`permission_denied`](/api-reference/errors#permission-denied). ### Creating and editing a key Only organization admins can create, edit and delete organization API keys. An organization can have up to 10. 1. In the [Soniox Console](https://console.soniox.com), open your organization and go to **Settings** > **Organization API keys**. 2. Select **Create API key** and give the key a name. 3. Turn on **Full access**, or choose a level for each permission the key needs. 4. Create the key and copy it. The full key is shown only once. You can change the name and permissions of a key at any time. The key itself stays the same. Changes and deletions can take a few minutes to apply. Until then, a deleted key may still work. ### Permissions Each organization API key has its own list of permissions, one for each area of the Organization API listed in the [overview](#overview). They are separate from [project API key permissions](/guides/api-key-permissions). The **Project API keys** permission has two levels. **Read** allows listing. **Write** also allows creating and deleting. The other permissions are either on or off. *** ## Making requests Send the key as a bearer token, the same way as a project API key: ```sh curl https://api.soniox.com/v1/organization/balance \ -H "Authorization: Bearer $SONIOX_ORG_API_KEY" ``` Organization endpoints are served only at `https://api.soniox.com`. The [regional domains](/data-residency) refuse them with `400` [`invalid_request`](/api-reference/errors#invalid-request), even when the project is in that domain's region. All organization endpoints share one rate limit per organization, 50 requests per minute by default. Calls over the limit are refused with `429` [`limit_exceeded`](/api-reference/errors#limit-exceeded). Project API keys have their own limits, so organization calls do not count against them. *** ## Reading usage [Monthly usage](/api-reference/organization/get_organization_monthly_usage) is the cost of one calendar month, for the organization and each project, next to the budget it is measured against. It includes requests made in the Soniox Console playground as well as API requests, because it is the number the budget check uses. `api_usage_usd` and `playground_usage_usd` split it by where the requests came from. The [usage summary](/api-reference/organization/get_organization_usage_summary) is totaled per UTC day, per project and per model. It has the same shape, window rules and `api_cost_usd` / `playground_cost_usd` split as the project [usage summary](/guides/usage-summary). Projects that have since been deleted are included in both reports, so the per-project costs always add up to the total. *** ## Managing project API keys With **Project API keys** set to **Write**, an organization API key can create and delete keys for any project of the organization. List the projects first to get their IDs: ```sh curl https://api.soniox.com/v1/organization/projects \ -H "Authorization: Bearer $SONIOX_ORG_API_KEY" ``` Then create a key with the permissions it needs. A project can have up to 10 API keys. Permissions use the `resource:level` form, with at most one level per resource. See [API key permissions](/guides/api-key-permissions) for what each one allows. ```sh curl https://api.soniox.com/v1/organization/projects/$PROJECT_ID/api-keys \ -H "Authorization: Bearer $SONIOX_ORG_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "transcription-worker", "permissions": ["stt_async:write", "files:write"]}' ``` The new key is in the `key` field of the response. It is returned only once, so store it right away. The `created_by` field names the organization API key that created it. To remove a key, call [Delete a project API key](/api-reference/organization/delete_organization_project_api_key) with its `id`. Like a deleted organization API key, it may keep working for a few minutes. *** ## Errors | Status | `error_type` | Cause | | ------ | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `400` | [`invalid_request`](/api-reference/errors#invalid-request) | The call went to a regional domain, the request body is invalid, or the project already has 10 API keys. | | `401` | [`unauthenticated`](/api-reference/errors#unauthenticated) | The key is invalid or deleted. | | `403` | [`permission_denied`](/api-reference/errors#permission-denied) | The key lacks the permission, or it is a project API key. | | `404` | [`invalid_request`](/api-reference/errors#invalid-request) | The project or project API key does not exist in this organization. | | `429` | [`limit_exceeded`](/api-reference/errors#limit-exceeded) | The organization exceeded its rate limit. | # Proxy stream URL: /guides/proxy-stream How to stream audio from a client app to Soniox Speech-to-Text WebSocket API through a proxy server. import Image from "next/image"; ## Overview Applies to [Text-to-Speech](/tts/get-started) and [Speech-to-Text](/stt/get-started). Examples use Speech-to-Text. This guide explains how to stream microphone audio from a client to the Soniox [WebSocket API](/api-reference/stt/websocket-api) through a proxy server. The client captures audio and sends it over a WebSocket to your proxy server. The proxy opens the Soniox WebSocket with your API key, forwards the audio, and sends the results back to the client. Use a proxy when you want to **inspect, transform, or store audio and transcription data on the server** before it reaches the client. The browser never sees a Soniox key, so you need no temporary keys, but every user holds one connection on your server and one from your server to Soniox, and the second counts against your [connection limit](/guides/websocket-authentication#connection-limit). If you only want results with the lowest latency, use [direct stream](/guides/direct-stream) instead. Soniox STT stream with proxy flowchart ## Example In the following example, we create a proxy HTTP server that: 1. Listens for incoming WebSocket connections from the client. 2. Forwards audio data from the client to the [WebSocket API](/api-reference/stt/websocket-api). 3. Relays transcription results back to the client. The proxy authenticates with your `SONIOX_API_KEY`, sent in the Authorization header as described in [WebSocket authentication](/guides/websocket-authentication). The browser never sees it. The example accepts any client; in production, authenticate your own users before you open a Soniox connection for them. Python server that will act as a proxy between our client and [WebSocket API](/api-reference/stt/websocket-api). ``` import os import json import asyncio from pathlib import Path from dotenv import load_dotenv import websockets from websockets.datastructures import Headers from websockets.http11 import Response load_dotenv() INDEX_HTML = Path(__file__).parent / "templates" / "index.html" async def handle_client(websocket): print("Browser client connected") # create a message queue to store client messages received before # Soniox WebSocket API connection is ready, so we don't loose any message_queue = [] soniox_ws = None soniox_ws_ready = False async def init_soniox_connection(): nonlocal soniox_ws, soniox_ws_ready try: soniox_ws = await websockets.connect( "wss://stt-rt.soniox.com/transcribe-websocket", additional_headers={ "Authorization": f"Bearer {os.getenv('SONIOX_API_KEY')}" }, ) print("Connected to Soniox STT WebSocket API") # Send initial configuration message start_message = json.dumps( { "audio_format": "auto", "model": "stt-rt-v5", "language_hints": ["en"], } ) await soniox_ws.send(start_message) print("Sent start message to Soniox") # mark connection as ready soniox_ws_ready = True # process any queued messages while len(message_queue) > 0 and soniox_ws_ready: data = message_queue.pop(0) await forward_data(data) # receive messages from Soniox STT WebSocket API async for message in soniox_ws: try: await websocket.send(message) except Exception as e: print(f"Error forwarding Soniox response: {e}") break except Exception as e: print(f"Soniox WebSocket error: {e}") soniox_ws_ready = False finally: if soniox_ws: await soniox_ws.close() soniox_ws_ready = False print("Soniox WebSocket closed") await websocket.close() async def forward_data(data): try: if soniox_ws: await soniox_ws.send(data) except Exception as e: print(f"Error forwarding data to Soniox: {e}") # initialize Soniox connection soniox_task = asyncio.create_task(init_soniox_connection()) try: # receive messages from browser client async for data in websocket: if soniox_ws_ready: # forward messages instantly await forward_data(data) else: # queue the message to be processed # as soon as connection to Soniox STT WebSocket API is ready message_queue.append(data) except Exception as e: print(f"Error with browser client: {e}") finally: print("Browser client disconnected") soniox_task.cancel() try: await soniox_task except asyncio.CancelledError: pass def serve_index(connection, request): # WebSocket upgrade: return None so websockets hands it to handle_client if request.headers.get("Upgrade", "").lower() == "websocket": return None # any other request: serve the browser client body = INDEX_HTML.read_bytes() return Response(200, "OK", Headers({"Content-Type": "text/html"}), body) async def main(): port = int(os.getenv("PORT", 8000)) server = await websockets.serve( handle_client, "0.0.0.0", port, process_request=serve_index ) print(f"WebSocket proxy server listening on http://0.0.0.0:{port}") await server.wait_closed() if __name__ == "__main__": asyncio.run(main()) ``` Node.js server that will act as a proxy between our client and [WebSocket API](/api-reference/stt/websocket-api). ``` require("dotenv").config(); const WebSocket = require("ws"); const http = require("http"); const fs = require("fs"); const path = require("path"); // serve the browser client; WebSocket upgrades on the same port go to wss below const server = http.createServer((req, res) => { res.writeHead(200, { "Content-Type": "text/html" }); fs.createReadStream(path.join(__dirname, "templates/index.html")).pipe(res); }); const wss = new WebSocket.Server({ server }); wss.on("connection", (ws) => { console.log("Browser client connected"); // create a message queue to store client messages received before // Soniox WebSocket API connection is ready, so we don't loose any const messageQueue = []; let sonioxWs = null; let sonioxWsReady = false; function initSonioxConnection() { sonioxWs = new WebSocket("wss://stt-rt.soniox.com/transcribe-websocket", { headers: { Authorization: `Bearer ${process.env.SONIOX_API_KEY}` }, }); sonioxWs.on("open", () => { console.log("Connected to Soniox STT WebSocket API"); // send initial configuration message const startMessage = JSON.stringify({ audio_format: "auto", model: "stt-rt-v5", language_hints: ["en"], }); sonioxWs.send(startMessage); console.log("Sent start message to Soniox"); // mark connection as ready sonioxWsReady = true; // process any queued messages while (messageQueue.length > 0 && sonioxWsReady) { const { data, isBinary } = messageQueue.shift(); forwardData(data, isBinary); } }); // receive messages from Soniox STT WebSocket API sonioxWs.on("message", (data) => { // note: // at this point we could manipulate and enhance the transcribed data try { ws.send(data.toString()); } catch (err) { console.error("Error forwarding Soniox response:", err); } }); sonioxWs.on("error", (error) => { console.log("Soniox WebSocket error:", error); sonioxWsReady = false; }); sonioxWs.on("close", (code, reason) => { console.log("Soniox WebSocket closed:", code, reason); sonioxWsReady = false; ws.close(); }); } // forward message data to Soniox STT WebSocket API function forwardData(data, isBinary) { try { // keep the frame type, so the empty text frame still ends the stream sonioxWs.send(data, { binary: isBinary }); } catch (err) { console.error("Error forwarding data to Soniox:", err); } } // initialize Soniox connection initSonioxConnection(); // receive messages from browser client ws.on("message", (data, isBinary) => { if (sonioxWsReady) { // forward messages instantly forwardData(data, isBinary); } else { // queue the message to be processed // as soon as connection to Soniox STT WebSocket API is ready messageQueue.push({ data, isBinary }); } }); ws.on("close", () => { console.log("Browser client disconnected"); if (sonioxWs) { try { sonioxWs.close(); } catch (err) { console.error("Error closing Soniox connection:", err); } } }); }); server.listen(process.env.PORT, () => { console.log( `WebSocket proxy server listening on http://0.0.0.0:${process.env.PORT}`, ); }); ``` Next, we create a basic HTML page as the client (same concept works for any other app framework). The HTML client: 1. Connects to the proxy server via WebSocket. 2. Captures audio stream from the microphone through the [`MediaRecorder`](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder). 3. Streams audio data to the proxy server. 4. Receives messages from the proxy server and renders transcribed text into a `div`. ```

Browser proxy stream example


```
### Run it Put `index.html` in a `templates/` folder next to the server, and create a `.env` file: ```text SONIOX_API_KEY= PORT=8000 ``` ```bash pip install websockets python-dotenv python server.py ``` ```bash npm init -y npm install ws dotenv node server.js ``` Open [http://localhost:8000](http://localhost:8000) and click **Start**. # Temporary API keys URL: /guides/temporary-api-keys Short-lived credentials that let untrusted clients connect directly to Soniox without exposing your long-lived API key. ## Overview A long-lived Soniox API key authenticates against your account and bills usage to it. If it leaks (embedded in a client app, captured in transit, or shared by mistake), anyone can spend your credits until you rotate the key. Temporary API keys are short-lived credentials your backend mints from a long-lived key and hands to a client. They are the only safe way for an untrusted client to connect directly to Soniox. Usage is still billed to the issuing account, so each key carries restrictions that limit what a leaked or replayed key can do: * `usage_type`: which Soniox service the key is valid for (always required). * `expires_in_seconds`: how long the key can be used to open new streams (always required). * `single_use`: the key may open at most one stream. * `max_session_duration_seconds`: the maximum duration of any one stream opened with the key. * `client_reference_id`: tracking identifier bound to the key; appears in [usage logs](/guides/usage-logs) for every request authenticated with it. The flow is always the same: 1. Client requests a temporary key from an endpoint on your backend. 2. Backend uses its long-lived API key to call Soniox and returns the temporary key to the client. 3. Client opens a stream directly to Soniox using the temporary key. See the [direct stream guide](/guides/direct-stream) for a complete client/server example. *** ## Creating a temporary API key Run this code on a **backend server you control**, never in the client. The long-lived API key must never leave your server. The minimal request needs only `usage_type` and `expires_in_seconds`. See the [API reference](/api-reference/auth/create_temporary_api_key) for the full request shape. ```python # Server-side endpoint your client calls @app.post("/temporary-api-key") def create_temporary_api_key(): response = requests.post( "https://api.soniox.com/v1/auth/temporary-api-key", headers={ "Authorization": f"Bearer {SONIOX_API_KEY}", "Content-Type": "application/json", }, json={ "usage_type": "transcribe_websocket", "expires_in_seconds": 60, }, ) response.raise_for_status() return response.json() ``` The API key that creates a temporary key needs the **Temporary API keys** permission and the permission for the service in `usage_type`. See [API key permissions](/guides/api-key-permissions#temporary-api-keys). Our SDKs provide helpers for the same call: * [Node SDK](/sdk/node-SDK/reference/classes#sonioxauthapi-createtemporarykey): `client.auth.createTemporaryKey(...)` * [Python SDK](/sdk/python-SDK/stt/realtime-transcription): `client.auth.create_temporary_api_key(...)` *** ## Usage type `usage_type` is required and locks the key to exactly one Soniox service: * `transcribe_websocket`: for the [Speech-to-Text WebSocket API](/api-reference/stt/websocket-api). * `tts_rt`: for [Text-to-Speech](/api-reference/tts/websocket-api), both the WebSocket API and the [REST endpoint](/api-reference/tts/generate_tts). A key issued for one service cannot be used against the other. Issue a separate key for each service the client needs. *** ## Expiration `expires_in_seconds` controls **how long the key can be used to open new streams**. It does not terminate streams that are already open. Use `max_session_duration_seconds` (below) to bound an individual session. *** ## Single use When `single_use` is `true`, the temporary API key may be used to open a stream exactly once. Any later attempt to open a stream with the same key is rejected, even if the key has not yet expired. Use this whenever the client is expected to perform a single transcription or speech generation session. It ensures that a key intercepted in transit cannot be reused to start additional billable sessions. ```json { "usage_type": "transcribe_websocket", "expires_in_seconds": 60, "single_use": true } ``` *** ## Max session duration `max_session_duration_seconds` sets the maximum duration of a single stream opened with the temporary API key. The timer starts when the stream is opened (not when the underlying connection is established). Omitting the field disables the limit. The limit applies **per stream**. On a [multi-stream connection](/tts/rt/streams), each stream is timed independently using the value carried by the temporary API key. ```json { "usage_type": "tts_rt", "expires_in_seconds": 300, "max_session_duration_seconds": 60 } ``` Set `max_session_duration_seconds` based on the longest legitimate session you expect. A value that is too low will cut off real users; a value that is too high reduces protection if the key is leaked. For text-to-speech, the limit caps how long the stream stays open, not the duration of generated audio. In practice, TTS streams audio at roughly real-time pace, so a stream-duration cap also bounds how much audio a single session can produce. When the limit is reached, the stream is terminated with HTTP status `403` and the message `Temporary API key session duration limit exceeded.` How that error is delivered depends on the endpoint. ### Speech-to-Text WebSocket [`/transcribe-websocket`](/api-reference/stt/websocket-api) carries one stream per connection. When the session duration limit is reached, the server sends a final JSON response and closes the WebSocket with `StatusNormalClosure`: ```json { "error_code": 403, "error_type": "temp_api_key_session_expired", "error_message": "Temporary API key session duration limit exceeded." } ``` ### Text-to-Speech WebSocket [`/tts-websocket`](/api-reference/tts/websocket-api) supports multiple streams over a single connection. The limit is enforced per stream. Each `start_stream` starts its own timer using the value from the temporary API key. When a stream's limit is reached, the server returns a stream-scoped error response followed by a `terminated` message for that `stream_id`. Other streams on the same connection are unaffected and the connection stays open: ```json { "stream_id": "...", "error_code": 403, "error_type": "temp_api_key_session_expired", "error_message": "Temporary API key session duration limit exceeded." } ``` ### Text-to-Speech REST [`/tts`](/api-reference/tts/generate_tts) serves a single stream per request. How the error is reported depends on whether audio bytes have already been sent: * **Before any audio has been sent**, a standard HTTP error response: ```json { "error_code": 403, "error_type": "temp_api_key_session_expired", "error_message": "Temporary API key session duration limit exceeded. Create a new temporary API key to start a new session." } ``` Once audio streaming has started, errors cannot be delivered to the client. *** ## Tracking Bind a `client_reference_id` to the temporary API key at creation time. Every request authenticated with the key is recorded in [usage logs](/guides/usage-logs) with that identifier — clients cannot override it. ```json { "usage_type": "transcribe_websocket", "expires_in_seconds": 60, "client_reference_id": "user_8f2c4b1a" } ``` # Usage logs URL: /guides/usage-logs Per-request record of every transcription or speech generation processed by Soniox - model, audio duration, tokens, cost, and an optional client_reference_id. ## Overview Usage logs are the per-request record of all Speech-to-Text and Text-to-Speech traffic in your Soniox project. Each entry captures the model, audio duration, tokens, cost, timing, and an optional [`client_reference_id`](#tracking-with-client_reference_id). Use them to: * **Monitor cost** - track total Soniox spend, or split it per end user, tenant, or product feature using `client_reference_id`. * **Debug a session** - trace a specific request (model, duration, `uuid`) when a user reports an issue. * **Catch anomalies** - spot leaked API keys, runaway loops, or unusual user behavior through sudden usage spikes. When a client can't be trusted to set `client_reference_id` (browser, mobile, third-party integrations), bind it to a [temporary API key](/guides/temporary-api-keys) at creation - the identifier is then set server-side and cannot be overridden. Logs are available via the [`GET /v1/usage-logs`](/api-reference/other/get_usage_logs) API. For daily cost totals per model rather than individual requests, see [usage summary](/guides/usage-summary). *** ## What gets logged Each entry captures the request's identity (`uuid`, `model`, `request_scope`, `client_reference_id`), its timing (`start_time`, `end_time` in UTC), token and audio-duration counts for input and output, and the resulting cost broken down by input/output and text/audio. See [`GET /v1/usage-logs`](/api-reference/other/get_usage_logs) for the full schema and field types. Only successfully completed requests are logged. Requests that fail before completion - for example, due to an invalid API key, insufficient funds, or a validation error - do not appear in usage logs. *** ## Tracking with `client_reference_id` `client_reference_id` is an optional string you attach to a request to tag its log entry. Use it when you need to know exact Soniox API usage per end-user - for billing, monitoring, or debugging. * **Type:** string * **Max length:** 256 characters Supported on all four APIs: ### Speech-to-Text WebSocket Set in the [configuration message](/api-reference/stt/websocket-api): ```json { "model": "stt-rt-v5", "audio_format": "auto", "client_reference_id": "user_8f2c4b1a" } ``` ### Speech-to-Text Async Set in the body of [`POST /v1/transcriptions`](/api-reference/stt/transcriptions/create_transcription): ```json { "model": "stt-async-v5", "audio_url": "https://example.com/audio.mp3", "client_reference_id": "user_8f2c4b1a" } ``` ### Text-to-Speech WebSocket Set in the [stream configuration message](/api-reference/tts/websocket-api): ```json { "model": "tts-rt-v2", "language": "en", "voice": "Adrian", "audio_format": "wav", "stream_id": "stream-001", "client_reference_id": "user_8f2c4b1a" } ``` ### Text-to-Speech REST Set in the body of [`POST /tts`](/api-reference/tts/generate_tts): ```json { "model": "tts-rt-v2", "language": "en", "voice": "Adrian", "audio_format": "wav", "text": "Hello from Soniox.", "client_reference_id": "user_8f2c4b1a" } ``` *** ## Binding `client_reference_id` to a temporary API key A `client_reference_id` can also be bound to a [temporary API key](/api-reference/auth/create_temporary_api_key) at creation time. Every request authenticated with that key is logged with that identifier - no per-request field required from the client. ```json { "usage_type": "transcribe_websocket", "expires_in_seconds": 60, "client_reference_id": "user_8f2c4b1a" } ``` For temporary API keys, `client_reference_id` must be set at creation time - it cannot be set or overridden later via the request. If no `client_reference_id` was bound when the key was created, log entries for requests using that key will have no `client_reference_id`, even if one is passed in the request. *** ## Accessing logs Fetch entries with [`GET /v1/usage-logs`](/api-reference/other/get_usage_logs). # Usage summary URL: /guides/usage-summary Daily cost and activity for a project, broken down per model and summed across all models. ## Overview The usage summary is a project's cost and activity rolled up by UTC day, per model and across all models. It is the same data behind the project's **Usage** page in the [Soniox Console](https://console.soniox.com/). Use it to: * **Report spend** - total cost for a billing period, or per model. * **Chart trends** - plot daily cost or request volume over weeks and months. * **Attribute cost** - see which models account for most of the spend. For a per-request record instead, see [usage logs](/guides/usage-logs). Summaries are available via the [`GET /v1/usage/summary`](/api-reference/other/get_usage_summary) API. *** ## Choosing a window `start_time` is inclusive and `end_time` is exclusive, both ISO 8601 UTC. A UTC day is included when the window covers any part of it, so an `end_time` at exactly midnight leaves out its own day: `2026-04-01T00:00:00Z` to `2026-04-03T00:00:00Z` returns April 1 and April 2. A window may cover at most 366 UTC days. *** ## What gets returned The response has a `total` entry covering all models, and a `models` array with one entry per model that recorded usage. The `total` entry is the one with a `model` of `null`, and a project with no usage gets an empty `models` array. Every entry carries a `days` array of UTC dates, and the per-day arrays align to it by index. Every day in the window appears, so days with no usage are zeros. Cost is split by where the requests came from: `api_cost_usd` for requests made with an API key and `playground_cost_usd` for requests made in the Soniox Console playground. Like the other cost fields, each has a per-day array and a `total_` field for the window. ```http GET /v1/usage/summary?start_time=2026-04-01T00:00:00Z&end_time=2026-04-03T00:00:00Z Authorization: Bearer ``` ```json { "total": { "model": null, "days": ["2026-04-01", "2026-04-02"], "total_cost_usd": "0.2567250000", "total_input_cost_usd": "0.0415500000", "total_output_cost_usd": "0.2151750000", "total_duration_cost_usd": "0.0000000000", "total_api_cost_usd": "0.2567250000", "total_playground_cost_usd": "0.0000000000", "cost_usd": ["0.1711500000", "0.0855750000"], "input_cost_usd": ["0.0277000000", "0.0138500000"], "output_cost_usd": ["0.1434500000", "0.0717250000"], "duration_cost_usd": ["0.0000000000", "0.0000000000"], "api_cost_usd": ["0.1711500000", "0.0855750000"], "playground_cost_usd": ["0.0000000000", "0.0000000000"], "total_num_requests": 285, "total_input_text_tokens": 4800, "total_input_audio_tokens": 15000, "total_input_audio_duration_ms": 1800000, "total_output_text_tokens": 10800, "total_output_audio_tokens": 8250, "total_output_audio_duration_ms": 990000, "total_duration_ms": 0, "num_requests": [190, 95], "input_text_tokens": [3200, 1600], "input_audio_tokens": [10000, 5000], "input_audio_duration_ms": [1200000, 600000], "output_text_tokens": [7200, 3600], "output_audio_tokens": [5500, 2750], "output_audio_duration_ms": [660000, 330000], "duration_ms": [0, 0] }, "models": [ { "model": "stt-async-v5", "days": ["2026-04-01", "2026-04-02"], "total_cost_usd": "0.0613500000", "total_input_cost_usd": "0.0235500000", "total_output_cost_usd": "0.0378000000", "total_duration_cost_usd": "0.0000000000", "total_api_cost_usd": "0.0613500000", "total_playground_cost_usd": "0.0000000000", "cost_usd": ["0.0409000000", "0.0204500000"], "input_cost_usd": ["0.0157000000", "0.0078500000"], "output_cost_usd": ["0.0252000000", "0.0126000000"], "duration_cost_usd": ["0.0000000000", "0.0000000000"], "api_cost_usd": ["0.0409000000", "0.0204500000"], "playground_cost_usd": ["0.0000000000", "0.0000000000"], "total_num_requests": 60, "total_input_text_tokens": 300, "total_input_audio_tokens": 15000, "total_input_audio_duration_ms": 1800000, "total_output_text_tokens": 10800, "total_output_audio_tokens": 0, "total_output_audio_duration_ms": 0, "total_duration_ms": 0, "num_requests": [40, 20], "input_text_tokens": [200, 100], "input_audio_tokens": [10000, 5000], "input_audio_duration_ms": [1200000, 600000], "output_text_tokens": [7200, 3600], "output_audio_tokens": [0, 0], "output_audio_duration_ms": [0, 0], "duration_ms": [0, 0] }, { "model": "tts-rt-v2", "days": ["2026-04-01", "2026-04-02"], "total_cost_usd": "0.1953750000", "total_input_cost_usd": "0.0180000000", "total_output_cost_usd": "0.1773750000", "total_duration_cost_usd": "0.0000000000", "total_api_cost_usd": "0.1953750000", "total_playground_cost_usd": "0.0000000000", "cost_usd": ["0.1302500000", "0.0651250000"], "input_cost_usd": ["0.0120000000", "0.0060000000"], "output_cost_usd": ["0.1182500000", "0.0591250000"], "duration_cost_usd": ["0.0000000000", "0.0000000000"], "api_cost_usd": ["0.1302500000", "0.0651250000"], "playground_cost_usd": ["0.0000000000", "0.0000000000"], "total_num_requests": 225, "total_input_text_tokens": 4500, "total_input_audio_tokens": 0, "total_input_audio_duration_ms": 0, "total_output_text_tokens": 0, "total_output_audio_tokens": 8250, "total_output_audio_duration_ms": 990000, "total_duration_ms": 0, "num_requests": [150, 75], "input_text_tokens": [3000, 1500], "input_audio_tokens": [0, 0], "input_audio_duration_ms": [0, 0], "output_text_tokens": [0, 0], "output_audio_tokens": [5500, 2750], "output_audio_duration_ms": [660000, 330000], "duration_ms": [0, 0] } ] } ``` See [`GET /v1/usage/summary`](/api-reference/other/get_usage_summary) for the full schema and field types. Only successfully started requests are counted. Requests rejected before they start - for example, due to an invalid API key, insufficient funds, or a validation error - are not included. # WebSocket authentication URL: /guides/websocket-authentication How to send your API key with a WebSocket connection, and the timeouts and connection limit that apply. ## Overview Send your API key when you open the connection, in the Authorization header or in the protocols list. The connection is yours from the moment it opens, so you can open it early and start streaming the instant you have audio or text. This works on the [Speech-to-Text](/api-reference/stt/websocket-api) and [Text-to-Speech](/api-reference/tts/websocket-api) WebSocket APIs. Use a regular key from the [Soniox Console](https://console.soniox.com/) on your servers and a [temporary API key](/guides/temporary-api-keys) in client apps. Still sending `api_key` in the start message? That works until **15 January 2027**; see [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). *** ## Send the API key with the connection ### Authorization header The standard HTTP header, sent on the WebSocket upgrade request. Most server-side WebSocket libraries can set it, for example `websockets` in Python and `ws` in Node.js. ```text Authorization: Bearer ``` ```python import asyncio, json, os import websockets async def main(): async with websockets.connect( "wss://stt-rt.soniox.com/transcribe-websocket", additional_headers={"Authorization": f"Bearer {os.environ['SONIOX_API_KEY']}"}, ) as ws: # No api_key in the start message. await ws.send(json.dumps({"model": "stt-rt-v5", "audio_format": "auto"})) # ... send audio, read responses ... asyncio.run(main()) ``` ```javascript import WebSocket from "ws"; const ws = new WebSocket("wss://stt-rt.soniox.com/transcribe-websocket", { headers: { Authorization: `Bearer ${process.env.SONIOX_API_KEY}` }, }); ws.on("open", () => { // No api_key in the start message. ws.send(JSON.stringify({ model: "stt-rt-v5", audio_format: "auto" })); }); ``` ### Protocols list Browsers cannot set headers on a WebSocket. Instead, pass the key as the second argument of `new WebSocket(url, protocols)`: the entry `soniox-api-key` followed by the key. The browser sends this list in the `Sec-WebSocket-Protocol` header. ```javascript const ws = new WebSocket("wss://stt-rt.soniox.com/transcribe-websocket", [ "soniox-api-key", temporaryApiKey, // from your backend, see the temporary API keys guide ]); ws.onopen = () => { // No api_key in the start message. ws.send(JSON.stringify({ model: "stt-rt-v5", audio_format: "auto" })); }; ``` A bad key does not fail the handshake: `onopen` fires, then an error frame with `error_code` and `error_type` arrives in `onmessage`, and the server closes the connection. ### Text-to-Speech The Authorization header and the protocols list work the same way on Text-to-Speech. Leave `api_key` out of the config message. ```javascript const ws = new WebSocket("wss://tts-rt.soniox.com/tts-websocket", [ "soniox-api-key", temporaryApiKey, ]); ws.onopen = () => { // No api_key in the config message. ws.send(JSON.stringify({ stream_id: "stream-1", model: "tts-rt-v2", language: "en", voice: "Adrian", audio_format: "pcm_s16le", sample_rate: 24000, })); ws.send(JSON.stringify({ stream_id: "stream-1", text: "Hello!", text_end: true })); }; ``` Never embed a long-lived API key in a browser or mobile app. Have your backend mint a [temporary API key](/guides/temporary-api-keys) and pass that to the client. The [direct stream guide](/guides/direct-stream) shows the full flow. ### Rules * **One key per connection.** The key sent with the connection is the connection's key for its whole life. Every stream on that connection runs on it. * **Leave `api_key` out of the start message.** The same key is accepted, a different one is refused. See [Migrate WebSocket authentication](/guides/migrate-websocket-authentication). * **Use the Authorization header or the protocols list, not both.** Sending both, `soniox-api-key` without a key, or a malformed `Authorization` value gets a `400` error frame and the connection closes. * **Authentication errors arrive as an error frame after the connection opens,** not as a failed handshake, so browsers can read them. * **Temporary keys.** Temporary keys start with `snx_temp_` and work in the Authorization header and in the protocols list. A key in the older `temp:` format is not a valid protocols list entry; send it in the Authorization header. * **[Single-use temporary keys](/guides/temporary-api-keys#single-use).** A single-use key sent with the connection allows exactly one stream on that connection. On Text-to-Speech, where one connection can carry several streams, use a regular temporary key at connect if you need more than one stream. *** ## Connection timeouts Sending the key with the connection lets you open the connection before you have anything to send, and start the instant you do. The connection has no deadline for its first stream: it stays open as long as you keep it alive, and it counts against your [connection limit](#connection-limit) the whole time. ### Speech-to-Text Send a keepalive, `{"type": "keepalive"}`, at least every **40 seconds** until the start request, or the connection is closed as idle with WebSocket status `1001`. Once the stream has started, the [keepalive](/stt/rt/connection-keepalive) rules apply as before. ### Text-to-Speech Send any message, for example `{"keep_alive": true}`, at least every **40 seconds**, or the connection is closed as idle with WebSocket status `1001`. After the first stream the same rule applies between streams: a message at least every 40 seconds, see [keepalive](/tts/rt/connection-keepalive). A connection you hold open costs you a connection slot, so open only what you will use. The limit is 40 seconds without a message; send a keepalive every 20 to 30 seconds to stay clear of it. The same rule applies on both products and works from any client, browsers included. *** ## Connection limit Every open WebSocket connection counts against a connection limit, separate from your concurrency limit. It stops idle connections piling up. * **The limit is a multiple of your concurrent requests limit** (Speech-to-Text) **or concurrent streams limit** (Text-to-Speech). It applies per organization, and per project where a project limit is set. Raising your concurrency limit in the [Soniox Console](https://console.soniox.com/org/limits) raises the connection limit with it. * **A connection is counted** about one second after it opens, or from its start message if that comes first. It is released when it closes. * **A connection slot is not a stream slot.** You can hold more connections than streams, but starting a stream still needs a free stream slot. * **Over the limit**, the next connection gets a `429` [`max_concurrent_connections_reached`](/api-reference/errors#max-concurrent-connections-reached) error frame and is closed. Close connections you are not using, or start streams on the ones you hold. Speech-to-Text connections carry one stream and close with it, so the connection limit only matters there for connections opened ahead of time. Text-to-Speech connections stay open between streams, so count the connections you keep, not the streams you run. *** ## Errors | Error | `error_type` | When | | ----- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `400` | [`invalid_request`](/api-reference/errors#invalid-request) | Both the Authorization header and the protocols list sent, `soniox-api-key` in the protocols list without the key, a malformed `Authorization` value, or a key over the length limit. | | `401` | [`unauthenticated`](/api-reference/errors#unauthenticated) | No key was sent, or the key is invalid or expired. It is checked about one second after connecting, or at the start message if that comes first, and the connection is closed. | | `429` | [`max_concurrent_connections_reached`](/api-reference/errors#max-concurrent-connections-reached) | The organization or project is at its connection limit. | All other errors, for example a missing permission or an exhausted balance, arrive as an error frame in response to the start message. # Overview URL: / Soniox provides powerful, production-ready APIs for transcribing, translating, generating, and understanding audio content. import { LinkCards, SpeechToTextIcon, TextToSpeechIcon, TranslationIcon, } from "@/components/link-card"; import { Step, Steps } from "fumadocs-ui/components/steps"; ## Get started with Soniox APIs Welcome to Soniox, the voice AI platform for speech-to-text, text-to-speech, and translation, with unmatched accuracy in 60+ languages. Build production-ready voice products with fast, accurate APIs for transcribing audio, generating natural speech, translating across languages, and extracting structure and meaning from conversations. Whether you are creating real-time voice interfaces, processing large audio volumes, or powering multilingual experiences, Soniox is designed to help you move quickly and scale with confidence. Integrate Soniox through simple REST and WebSocket APIs, with SDKs and real-time streaming support for modern applications. ## Products , description: "Transcribe speech in real time across 60+ languages, with native-speaker accuracy for multilingual, language-switching, and multi-speaker conversations.", arrowInSeparateLine: true, titleSize: "text-xl", cta: "Get started", }, { title: "Text-to-Speech", href: "/tts/get-started", headIcon: , description: "Generate natural, high-fidelity speech in 60+ languages, with precise handling of alphanumerics, names, borrowed words, and language switching.", arrowInSeparateLine: true, titleSize: "text-xl", cta: "Get started", }, { title: "Speech Translation", href: "/translation/get-started", headIcon: , description: "Translate speech in real time across 3,600 language pairs, with low-latency output before sentences finish and high-quality multilingual results.", arrowInSeparateLine: true, titleSize: "text-xl", cta: "Get started", }, ]} /> ## Before you begin To start using Soniox, create a [Soniox account](https://console.soniox.com/signup/). Visit the [Soniox Console](https://console.soniox.com/) to generate and manage API keys, view usage, logs, and billing. Soniox Console is your self-service control center for everything Soniox. # Community integrations URL: /integrations/community-integrations Discover useful Soniox integrations built by the community import Image from "next/image"; Web and mobile demo apps screenshot ## Overview This page lists code repositories, SDKs and other useful tools built by our user community. We appreciate the investment in time and willingness to give back to the community from these developers. Note that the projects linked here are community-built integrations and are not officially supported by Soniox. For any questions or support requests, please contact the respective developers or project maintainers. *** ## Agent Voice Response (AVR) [Agent Voice Response](https://github.com/agentvoiceresponse) is the ultimate conversational AI platform for Asterisk PBX systems. Experience ultra-low latency speech-to-speech, advanced Voice Activity Detection, and intelligent noise suppression. Choose between cloud and local AI providers based on your needs. Perfect for FreePBX, Asterisk-based contact centers, and enterprise telephony solutions. Integration wiki: [https://wiki.agentvoiceresponse.com/en/avr-soniox-speech-to-text](https://wiki.agentvoiceresponse.com/en/avr-soniox-speech-to-text). *** ## Go SDK (unofficial) Unofficial Go SDK for the Soniox Speech-to-Text real-time WebSocket API. Enable Soniox real-time speech-to-text transcription and translation in your Go applications. GitHub repository: [https://github.com/moxierobots/soniox-stt-go](https://github.com/moxierobots/soniox-stt-go). *** ## C++ library (unofficial) SonioxPP is an unofficial C++17 library for the Soniox API. It covers real-time WebSocket and async REST speech-to-text, plus REST and real-time WebSocket text-to-speech, with support for speaker diarization, language identification, translation, custom vocabulary, and temporary API keys. GitHub repository: [https://github.com/fatehmtd/SonioxPP](https://github.com/fatehmtd/SonioxPP). *** # Integrations URL: /integrations Explore Soniox Speech-to-Text and Text-to-Speech integrations for real-time, multilingual voice applications. Connect Soniox with LiveKit, Pipecat, LangChain, Twilio, Vercel AI SDK, and more. import { LinkCards } from "@/components/link-card"; Soniox Speech-to-Text integrates seamlessly with leading real-time communication platforms, AI frameworks, automation tools, and developer SDKs. These integrations make it easy to add high-accuracy, low-latency, multilingual speech recognition to live audio, voice agents, call centers, and AI-powered applications, without building everything from scratch. Whether you’re streaming audio in real time, orchestrating AI workflows, or deploying speech recognition at scale, Soniox integrations let you move faster while maintaining enterprise-grade accuracy and performance. Explore the available integrations to quickly connect Soniox Speech-to-Text to your existing stack and start transcribing speech in real time. See also [community integrations](/integrations/community-integrations). # LangChain.js (JavaScript) URL: /integrations/langchain/langchain-js Soniox document loader for LangChain.js import Image from "next/image"; ## Overview [LangChain](https://www.langchain.com/) is a popular framework for building applications powered by large language models (LLMs). The `@soniox/langchain` package provides a document loader that transcribes audio files using Soniox's speech-to-text API, making it easy to incorporate audio transcription into your LangChain pipelines. ## Setup Install the package: ```bash npm2yarn npm install @soniox/langchain ``` ### Credentials Get your Soniox API key from the [Soniox Console](https://console.soniox.com) and set it as an environment variable: ```bash export SONIOX_API_KEY=your_api_key ``` ## Usage ### Basic transcription Transcribe audio files using the `SonioxAudioTranscriptLoader`: ```typescript import { SonioxAudioTranscriptLoader } from "@soniox/langchain"; // Fetch the file const response = await fetch( "https://github.com/soniox/soniox_examples/raw/refs/heads/master/speech_to_text/assets/coffee_shop.mp3", ); const audioBuffer = await response.bytes(); // Uint8Array const loader = new SonioxAudioTranscriptLoader({ audio: audioBuffer, // Or you can pass in a URL string }); const docs = await loader.load(); console.log(docs[0].pageContent); // Transcribed text ``` ### Two-way translation Transcribe and translate between two languages simultaneously: ```typescript const loader = new SonioxAudioTranscriptLoader( { audio: audioBuffer, }, { translation: { type: "two_way", language_a: "en", language_b: "es", }, language_hints: ["en", "es"], }, ); const docs = await loader.load(); ``` ### One-way translation Translate from any detected language to a target language: ```typescript const loader = new SonioxAudioTranscriptLoader( { audio: audioBuffer, }, { translation: { type: "one_way", target_language: "fr", }, language_hints: ["en", "es"], }, ); const docs = await loader.load(); ``` ## Advanced usage ### Language hints Provide [language hints](/stt/concepts/language-hints) to improve transcription accuracy: ```typescript const loader = new SonioxAudioTranscriptLoader( { audio: audioBuffer, }, { language_hints: ["en", "es"], }, ); ``` ### Context for improved accuracy Provide domain-specific [context](/stt/concepts/context) to improve transcription accuracy: ```typescript const loader = new SonioxAudioTranscriptLoader( { audio: audioBuffer, }, { context: { general: [ { key: "industry", value: "healthcare" }, { key: "meeting_type", value: "consultation" }, ], terms: ["hypertension", "cardiology", "metformin"], translation_terms: [ { source: "blood pressure", target: "presión arterial" }, { source: "medication", target: "medicamento" }, ], }, }, ); ``` ## API reference ### Constructor parameters #### SonioxLoaderParams (required) | Parameter | Type | Required | Description | | ------------------- | ---------------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | | `audio` | `Uint8Array \| string` | Yes | Audio file as buffer or URL | | `audioFormat` | `SonioxAudioFormat` | No | Audio file format | | `apiKey` | `string` | No | Soniox API key (defaults to `SONIOX_API_KEY` env var) | | `apiBaseUrl` | `string` | No | API base URL (defaults to `https://api.soniox.com/v1`). See [regional endpoints](/data-residency#regional-endpoints). | | `pollingIntervalMs` | `number` | No | Polling interval in ms (min: 1000, default: 1000) | | `pollingTimeoutMs` | `number` | No | Polling timeout in ms (default: 180000) | #### SonioxLoaderOptions (optional) | Parameter | Type | Description | | -------------------------------- | ---------------------------- | ---------------------------------------- | | `model` | `SonioxTranscriptionModelId` | Model to use (default: `"stt-async-v4"`) | | `translation` | `object` | Translation configuration | | `language_hints` | `string[]` | Language hints for transcription | | `language_hints_strict` | `boolean` | Enforce strict language hints | | `enable_speaker_diarization` | `boolean` | Enable speaker identification | | `enable_language_identification` | `boolean` | Enable language detection | | `context` | `object` | Context for improved accuracy | Browse the [API reference](/api-reference/stt/transcriptions/create_transcription) for a full list of supported options. ### Supported audio formats * `aac` - Advanced Audio Coding * `aiff` - Audio Interchange File Format * `amr` - Adaptive Multi-Rate * `asf` - Advanced Systems Format * `flac` - Free Lossless Audio Codec * `mp3` - MPEG Audio Layer III * `ogg` - Ogg Vorbis * `wav` - Waveform Audio File Format * `webm` - WebM Audio ### Return value The `load()` method returns an array containing a single `Document` object: ```typescript Document { pageContent: string, // The transcribed text metadata: SonioxTranscriptResponse // Full transcript with metadata } ``` The metadata includes transcribed text, speaker information (if diarization enabled), language information (if identification enabled), translation data (if translation enabled), and timing information. ## Related * [LangChain documentation](https://docs.langchain.com/oss/javascript/integrations/document_loaders/web_loaders/soniox) * [Package on NPM](https://www.npmjs.com/package/@soniox/langchain) # LangChain (Python) URL: /integrations/langchain/langchain Soniox document loader for LangChain import Image from "next/image"; ## Overview [LangChain](https://www.langchain.com/) is a popular framework for building applications powered by large language models (LLMs). The `langchain-soniox` package provides a document loader that transcribes audio files using Soniox's speech-to-text API, making it easy to incorporate audio transcription into your LangChain pipelines. ## Setup Install the package: ```bash pip install langchain-soniox ``` ### Credentials Get your Soniox API key from the [Soniox Console](https://console.soniox.com) and set it as an environment variable: ```bash export SONIOX_API_KEY=your_api_key ``` ## Usage ### Basic transcription Transcribe audio files using the `SonioxDocumentLoader`: ```python from langchain_soniox import SonioxDocumentLoader # Using a URL loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3" ) docs = list(loader.lazy_load()) print(docs[0].page_content) # Transcribed text ``` You can also load audio from a local file or from bytes: ```python # Using a local file path loader = SonioxDocumentLoader(file_path="/path/to/audio.mp3") # Using binary data with open("/path/to/audio.mp3", "rb") as f: audio_bytes = f.read() loader = SonioxDocumentLoader(file_data=audio_bytes) ``` ### Async loading For async operations, use `alazy_load()`: ```python import asyncio from langchain_soniox import SonioxDocumentLoader async def transcribe_async(): loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3" ) docs = [doc async for doc in loader.alazy_load()] print(docs[0].page_content) asyncio.run(transcribe_async()) ``` ## Advanced usage ### Language hints Soniox automatically detects and transcribes speech in [**60+ languages**](/stt/concepts/supported-languages). When you know which languages are likely to appear in your audio, provide `language_hints` to improve accuracy by biasing recognition toward those languages. Language hints **do not restrict** recognition — they only **bias** the model toward the specified languages, while still allowing other languages to be detected if present. ```python from langchain_soniox import ( SonioxDocumentLoader, SonioxTranscriptionOptions, ) loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3", options=SonioxTranscriptionOptions( language_hints=["en", "es"], ), ) docs = list(loader.lazy_load()) ``` For more details, see the [Soniox language hints documentation](/stt/concepts/language-hints). ### Speaker diarization Enable speaker identification to distinguish between different speakers: ```python from langchain_soniox import ( SonioxDocumentLoader, SonioxTranscriptionOptions, ) loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3", options=SonioxTranscriptionOptions( enable_speaker_diarization=True, ), ) docs = list(loader.lazy_load()) # Access speaker information in the metadata current_speaker = None output = "" for token in docs[0].metadata["tokens"]: if current_speaker != token["speaker"]: current_speaker = token["speaker"] output += f"\nSpeaker {current_speaker}: {token['text'].lstrip()}" else: output += token["text"] print(output) ``` ### Language identification Enable automatic language detection and identification: ```python from langchain_soniox import ( SonioxDocumentLoader, SonioxTranscriptionOptions, ) loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3", options=SonioxTranscriptionOptions( enable_language_identification=True, ), ) docs = list(loader.lazy_load()) # Access language information in the metadata current_language = None output = "" for token in docs[0].metadata["tokens"]: if current_language != token["language"]: current_language = token["language"] output += f"\n[{current_language}] {token['text'].lstrip()}" else: output += token["text"] print(output) ``` ### Context for improved accuracy Provide domain-specific [context](/stt/concepts/context) to improve transcription accuracy. Context helps the model understand your domain, recognize important terms, and apply custom vocabulary. The `context` object supports four optional sections: ```python from langchain_soniox import ( SonioxDocumentLoader, SonioxTranscriptionOptions, StructuredContext, StructuredContextGeneralItem, StructuredContextTranslationTerm, ) loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3", options=SonioxTranscriptionOptions( context=StructuredContext( # Structured key-value information (domain, topic, intent, etc.) general=[ StructuredContextGeneralItem(key="domain", value="Healthcare"), StructuredContextGeneralItem( key="topic", value="Diabetes management consultation" ), StructuredContextGeneralItem(key="doctor", value="Dr. Martha Smith"), ], # Longer free-form background text or related documents text="The patient has a history of...", # Domain-specific or uncommon words terms=["Celebrex", "Zyrtec", "Xanax"], # Custom translations for ambiguous terms translation_terms=[ StructuredContextTranslationTerm( source="Mr. Smith", target="Sr. Smith" ), StructuredContextTranslationTerm(source="MRI", target="RM"), ], ), ), ) docs = list(loader.lazy_load()) ``` For more details, see the [Soniox context documentation](/stt/concepts/context). ### Translation Translate from any detected language to a target language: ```python from langchain_soniox import ( SonioxDocumentLoader, SonioxTranscriptionOptions, TranslationConfig, ) loader = SonioxDocumentLoader( file_url="https://soniox.com/media/examples/coffee_shop.mp3", options=SonioxTranscriptionOptions( translation=TranslationConfig( type="one_way", target_language="fr", ), language_hints=["en"], ), ) docs = list(loader.lazy_load()) for token in docs[0].metadata["tokens"]: if token["translation_status"] == "translation": translated_text += token["text"] else: original_text += token["text"] print(original_text) print(translated_text) ``` You can also transcribe and translate between two languages simultaneously using `two_way` translation type. Learn more about translation [here](/translation/stt-translation/async-translation). ## API reference ### Constructor parameters | Parameter | Type | Required | Default | Description | | ------------------------------ | ---------------------------- | -------- | ------------------------------ | -------------------------------------------------- | | `file_path` | `str` | No\* | `None` | Path to local audio file to transcribe | | `file_data` | `bytes` | No\* | `None` | Binary data of audio file to transcribe | | `file_url` | `str` | No\* | `None` | URL of audio file to transcribe | | `api_key` | `str` | No | `SONIOX_API_KEY` env var | Soniox API key | | `base_url` | `str` | No | `https://api.soniox.com/v1` | API base URL (see [regional endpoints][endpoints]) | | `options` | `SonioxTranscriptionOptions` | No | `SonioxTranscriptionOptions()` | Transcription options | | `polling_interval_seconds` | `float` | No | `1.0` | Time between status polls (seconds) | | `timeout_seconds` | `float` | No | `300.0` (5 minutes) | Maximum time to wait for transcription | | `http_request_timeout_seconds` | `float` | No | `60.0` | Timeout for individual HTTP requests | \* You must specify **exactly one** of: `file_path`, `file_data`, or `file_url`. [endpoints]: /data-residency#regional-endpoints ### Transcription options The `SonioxTranscriptionOptions` class supports these parameters: | Parameter | Type | Description | | -------------------------------- | ------------------- | ----------------------------------------------------- | | `model` | `str` | Async model to use (see [available models][models]) | | `language_hints` | `list[str]` | Language hints for transcription (ISO language codes) | | `language_hints_strict` | `bool` | Enforce strict language hints | | `enable_speaker_diarization` | `bool` | Enable speaker identification | | `enable_language_identification` | `bool` | Enable language detection | | `translation` | `TranslationConfig` | Translation configuration | | `context` | `StructuredContext` | Context for improved accuracy | | `client_reference_id` | `str` | Custom reference ID for your records | | `webhook_url` | `str` | Webhook URL for completion notifications | | `webhook_auth_header_name` | `str` | Custom auth header name for webhook | | `webhook_auth_header_value` | `str` | Custom auth header value for webhook | Browse the [API documentation](/api-reference/stt/transcriptions/create_transcription) for a full list of supported options. [models]: /stt/models ### Return value The `lazy_load()` and `alazy_load()` methods yield a single `Document` object: ```python Document( page_content=str, # The transcribed text metadata={ "source": str, # File URL, path, or "file_upload" "transcription_id": str, # Unique transcription ID "audio_duration_ms": int, # Audio duration in milliseconds "model": str, # Model used for transcription "created_at": str, # ISO 8601 timestamp "tokens": list[dict], # Detailed token-level information } ) ``` The `tokens` array in metadata includes detailed information for each transcribed word: * `text`: The transcribed text * `start_ms`: Start time in milliseconds * `end_ms`: End time in milliseconds * `speaker`: Speaker ID (if diarization enabled), for example `"1"`, `"2"`, etc. * `language`: Detected language (if identification enabled), for example `"en"`, `"fr"`, etc. * `translation_status`: Translation status (`"original"`, `"translated"` or `"none"`) Learn more about the [Soniox API reference](/api-reference/stt/transcriptions/get_transcription_transcript). ## Related * [LangChain documentation](https://docs.langchain.com/oss/python/integrations/document_loaders/soniox) * [Package on PyPI](https://pypi.org/project/langchain-soniox/) # LiveKit URL: /integrations/livekit Integrate Soniox Speech-to-Text and Text-to-Speech into LiveKit Agents. import Image from "next/image"; import { LinkCards } from "@/components/link-card"; ## Overview LiveKit Agents is a real-time framework for building voice, video, and multimodal AI agents. It runs on top of LiveKit's WebRTC media transport, giving agents low-latency, reliable connections to users even on unstable networks, and ships with built-in turn detection, interruption handling, and telephony support. An `AgentSession` orchestrates the speech-to-text, LLM, and text-to-speech components for each conversation. Soniox plugs in as two of these components: * **`soniox.STT`** transcribes incoming user audio in real time using the [Soniox real-time STT API](/stt/rt/real-time-transcription). * **`soniox.TTS`** synthesizes the LLM's responses into speech using the [Soniox real-time TTS API](/tts/rt/real-time-generation). For more details on how LiveKit Agents work, check the [LiveKit Agents documentation](https://docs.livekit.io/agents/). ## Installation Install the Soniox plugin for LiveKit Agents: ```bash pip install livekit-plugins-soniox ``` You will also need to set up your Soniox API key as an environment variable: ```bash export SONIOX_API_KEY= ``` You can obtain a Soniox API key by signing up at the [Soniox Console](https://console.soniox.com/). ## Services ## Guides # Switch your LiveKit STT or TTS provider to Soniox URL: /integrations/livekit/migrate Step-by-step guide to to replace Deepgram, ElevenLabs, AssemblyAI, Cartesia, or OpenAI STT/TTS with Soniox in your LiveKit bot — config mapping and code diffs. import { LinkCards } from "@/components/link-card"; import { Callout } from "@/components/callout"; ## Overview Each provider section below shows how to swap an STT or TTS service for Soniox in an `AgentSession`, plus how the source settings map across. The rest of your LiveKit setup (Agent, room, VAD, LLM, tools) stays the same. For configuration depth, see the [STT](/integrations/livekit/stt) and [TTS](/integrations/livekit/tts) reference pages. For an end-to-end walkthrough, see [Build a voice agent](/integrations/livekit/voice-agent). ## Test Soniox before you migrate The fastest way to evaluate is on our live comparison pages: record a sample on the [STT comparison](https://soniox.com/compare) page or enter text on the [TTS comparison](https://soniox.com/compare-tts) page, and see the result side-by-side with your current provider. Cases to evaluate when building a reliable voice agent across multiple languages: * **Mid-utterance language switching.** Start a sentence in English and finish in Spanish, or drop a French name into an English question. Soniox detects and transcribes both. * **Non-English, end-to-end.** Run a full conversation in your target language. Both STT and TTS cover [60+ languages](/stt/concepts/supported-languages). * **Tricky inputs.** Order numbers, postal codes, emails, phone numbers, brand names, and product codes with non-English spellings. Soniox preserves them on the STT side and pronounces them correctly on the TTS side. * **Low latency.** Soniox leads on time-to-final-transcript so the LLM picks up the moment the user stops talking. ## Before you migrate Install the Soniox extra for LiveKit Agents: ```bash pip install "livekit-agents[soniox]~=1.5" ``` Create an API key in the [Soniox Console](https://console.soniox.com/). The same key works for STT and TTS. ```bash export SONIOX_API_KEY=... ``` LiveKit configures turn-taking on `AgentSession` rather than on the STT service. To use Soniox's built-in endpoint detection, pass `turn_handling=TurnHandlingOptions(turn_detection="stt")` to `AgentSession`. Keep a local VAD (e.g. Silero) in the session — `AgentSession` also uses it for interruption detection (catching when the caller starts speaking while the agent is talking), and `interruption.mode` accepts `"adaptive"` or `"vad"`, not `"stt"`. See [endpoint detection](https://docs.livekit.io/agents/logic/turns/#stt-endpointing). ## From Deepgram ### STT Before: ```python from livekit.plugins import deepgram stt = deepgram.STT( model="nova-3", language="en", keyterm=["Bright Smile Dental", "checkup", "cavity"], punctuate=True, interim_results=True, endpointing_ms=25, enable_diarization=True, ) ``` After: ```python from livekit.plugins import soniox from livekit.plugins.soniox import ContextObject, STTOptions stt = soniox.STT( params=STTOptions( language_hints=["en"], context=ContextObject(terms=["Bright Smile Dental", "checkup", "cavity"]), ), ) ``` | Deepgram setting | Soniox equivalent | Notes | | -------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | `language` | [`language_hints`](/stt/concepts/language-hints) (list) | A hint, not a filter. Soniox still transcribes other languages | | `interim_results` | Always on | Soniox streams [non-final and final tokens](/stt/rt/real-time-transcription) by default | | `punctuate` | Automatic in Soniox | | | `smart_format`, `numerals` | Automatic in Soniox | | | `keyterm` / `keywords` | [`context.terms`](/stt/concepts/context) | Wrap with `ContextObject(terms=[...])` | | `enable_diarization` | [`enable_speaker_diarization`](/stt/concepts/speaker-diarization) | | | `endpointing_ms` | Session-level `turn_handling` | Set `turn_detection="stt"` on `AgentSession`; tune via `max_endpoint_delay_ms` | ## From ElevenLabs ### TTS Before: ```python from livekit.plugins import elevenlabs tts = elevenlabs.TTS( voice_id="", model="eleven_multilingual_v2", language="en", ) ``` After: ```python from livekit.plugins import soniox tts = soniox.TTS(voice="Adrian", language="en") ``` | ElevenLabs TTS setting | Soniox equivalent | Notes | | ---------------------- | ----------------- | ----------------------------------------- | | `voice_id` | `voice` | See [Soniox voices](/tts/concepts/voices) | | `language` | `language` | | | `model` | `model` | Soniox default | ### STT Before: ```python from livekit.plugins import elevenlabs stt = elevenlabs.STT(model_id="scribe_v2_realtime") ``` After: ```python from livekit.plugins import soniox from livekit.plugins.soniox import STTOptions stt = soniox.STT( params=STTOptions( language_hints=["en"], enable_language_identification=True, ), ) ``` | ElevenLabs Realtime STT setting | Soniox equivalent | Notes | | ------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------ | | `model_id` | `model` (default `stt-rt-v5`) | | | VAD / endpointing extra kwargs | Session-level `turn_handling` | Set `turn_detection="stt"` on `AgentSession`; tune via `max_endpoint_delay_ms` | | `language_code` | [`language_hints`](/stt/concepts/language-hints) (list) | | ## From AssemblyAI ### STT Before: ```python from livekit.plugins import assemblyai stt = assemblyai.STT( model="u3-rt-pro", language_detection=True, speaker_labels=True, keyterms_prompt=["Bright Smile Dental", "checkup", "cavity"], format_turns=False, end_of_turn_confidence_threshold=0.4, min_turn_silence=400, max_turn_silence=1280, ) ``` After: ```python from livekit.plugins import soniox from livekit.plugins.soniox import ContextObject, STTOptions stt = soniox.STT( params=STTOptions( enable_language_identification=True, enable_speaker_diarization=True, context=ContextObject(terms=["Bright Smile Dental", "checkup", "cavity"]), ), ) ``` | AssemblyAI setting | Soniox equivalent | Notes | | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | `language_detection` | [`enable_language_identification`](/stt/concepts/language-identification) | On by default in Soniox | | `keyterms_prompt` | [`context.terms`](/stt/concepts/context) | Wrap with `ContextObject(terms=[...])` | | `speaker_labels` | [`enable_speaker_diarization`](/stt/concepts/speaker-diarization) | | | `format_turns` | Automatic in Soniox | | | `end_of_turn_confidence_threshold`,
`min_turn_silence`,
`max_turn_silence` | Session-level `turn_handling` | Set `turn_detection="stt"` on `AgentSession`; tune via `max_endpoint_delay_ms` | ## From Cartesia ### TTS Before: ```python from livekit.plugins import cartesia tts = cartesia.TTS( model="sonic-3", voice="f786b574-daa5-4673-aa0c-cbe3e8534c02", language="en", ) ``` After: ```python from livekit.plugins import soniox tts = soniox.TTS(voice="Adrian", language="en") ``` | Cartesia TTS setting | Soniox equivalent | Notes | | -------------------- | ----------------- | ----------------------------------------- | | `model` | `model` | Soniox default `tts-rt-v2` | | `voice` | `voice` | See [Soniox voices](/tts/concepts/voices) | | `language` | `language` | | Cartesia supports inline SSML-like tags (e.g. ``) in input text. Strip them before passing text to Soniox, otherwise the bot will read the tags aloud literally. ### STT Before: ```python from livekit.plugins import cartesia stt = cartesia.STT(model="ink-whisper", language="en") ``` After: ```python from livekit.plugins import soniox from livekit.plugins.soniox import STTOptions stt = soniox.STT(params=STTOptions(language_hints=["en"])) ``` | Cartesia STT setting | Soniox equivalent | Notes | | -------------------- | ------------------------------------------------------- | -------------------------------------------------------------- | | `model` | `model` (default `stt-rt-v5`) | | | `language` | [`language_hints`](/stt/concepts/language-hints) (list) | A hint, not a filter. Soniox still transcribes other languages | ## From OpenAI OpenAI provides both STT and TTS services in LiveKit. ### STT Before: ```python from livekit.plugins import openai stt = openai.STT( model="gpt-4o-transcribe", language="en", prompt="Expect medical terminology and patient names.", detect_language=True, ) ``` After: ```python from livekit.plugins import soniox from livekit.plugins.soniox import ContextObject, STTOptions stt = soniox.STT( params=STTOptions( language_hints=["en"], context=ContextObject(text="Expect medical terminology and patient names."), ), ) ``` | OpenAI STT setting | Soniox equivalent | Notes | | ------------------ | ------------------------------------------------------------------------- | -------------------------------------------------------------- | | `model` | `model` (default `stt-rt-v5`) | | | `language` | [`language_hints`](/stt/concepts/language-hints) (list) | A hint, not a filter. Soniox still transcribes other languages | | `detect_language` | [`enable_language_identification`](/stt/concepts/language-identification) | On by default in Soniox | | `prompt` | [`context.text`](/stt/concepts/context) | Wrap with `ContextObject(text="...")` | \| `use_realtime` | Soniox is always realtime | | ### TTS Before: ```python from livekit.plugins import openai tts = openai.TTS( model="gpt-4o-mini-tts", voice="ash", ) ``` After: ```python from livekit.plugins import soniox tts = soniox.TTS(voice="Adrian") ``` | OpenAI TTS setting | Soniox equivalent | Notes | | ------------------ | ----------------- | ----------------------------------------- | | `voice` | `voice` | see [Soniox voices](/tts/concepts/voices) | | `model` | `model` | Soniox default `tts-rt-v2` | ## What to read next # Speech-to-Text URL: /integrations/livekit/stt Use Soniox Speech-to-Text in LiveKit Agents. ## Overview `soniox.STT` provides real-time speech-to-text transcription using the [Soniox WebSocket STT API](/api-reference/stt/websocket-api), with support for 60+ languages, context customization, multilingual audio, and speaker diarization. ## Basic usage Use Soniox STT in an `AgentSession` or as a standalone transcription service: ```python from livekit.agents import AgentSession from livekit.plugins import soniox session = AgentSession( stt=soniox.STT(), # ... llm, tts, etc. ) ``` ## Configuration `soniox.STT` accepts top-level constructor arguments (for connection) and an `STTOptions` object passed via `params` (for transcription parameters). ### Constructor arguments | Argument | Type | Default | Description | | -------------- | ------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------- | | `api_key` | `str \| None` | `SONIOX_API_KEY` env var | Soniox API key. | | `base_url` | `str` | `wss://stt-rt.soniox.com/transcribe-websocket` | Soniox WebSocket endpoint. See [regional endpoints](#regional-endpoints). | | `params` | `STTOptions \| None` | `STTOptions()` | Transcription parameters (see below). | | `http_session` | `aiohttp.ClientSession \| None` | `None` | Optional aiohttp session to reuse for the WebSocket connection. | ### STTOptions Pass via `params=soniox.STTOptions(...)`. | Setting | Type | Default | Description | | -------------------------------- | ------------------------------ | ----------- | ------------------------------------------------------------------------------------------ | | `model` | `str` | `stt-rt-v5` | Model to use for transcription. | | `language_hints` | `list[str] \| None` | `None` | Language hints to bias recognition toward expected languages. | | `language_hints_strict` | `bool` | `False` | If true, restrict recognition to the provided languages. | | `context` | `ContextObject \| str \| None` | `None` | Context customization to improve transcription accuracy. | | `num_channels` | `int` | `1` | Number of channels (e.g. 1 (mono) or 2 (stereo)). | | `sample_rate` | `int` | `16000` | Audio sample rate in Hz. | | `enable_speaker_diarization` | `bool` | `False` | Annotate tokens with speaker IDs. | | `enable_language_identification` | `bool` | `True` | Annotate tokens with language IDs. | | `max_endpoint_delay_ms` | `int` | `500` | Maximum delay in ms between speech cessation and endpoint detection. Range: 500–3000. | | `endpoint_sensitivity` | `float` | `0.0` | [Endpoint sensitivity](/stt/rt/endpoint-detection#endpoint_sensitivity) (-1.0 to 1.0). | | `client_reference_id` | `str \| None` | `None` | Client reference ID for tracking. | | `translation` | `TranslationConfig \| None` | `None` | Translation configuration. See [translation](/translation/stt-translation/rt-translation). | ## Advanced usage ### Regional endpoints If you want to use a different region than the default (US), pass a regional `base_url` to the `STT` constructor: ```python from livekit.plugins import soniox stt = soniox.STT(base_url="wss://stt-rt.eu.soniox.com/transcribe-websocket") ``` See the [list of regional endpoints](/data-residency#regional-endpoints) for available endpoints. ### Language hints There is no need to pre-select a language. The model automatically detects and transcribes any supported language and handles multilingual audio seamlessly, even when multiple languages are mixed within a single sentence or conversation. When you have prior knowledge of the languages likely to appear in your audio, language hints help the model prioritize them for greater accuracy: ```python from livekit.plugins import soniox stt = soniox.STT( params=soniox.STTOptions( language_hints=["en", "es"], ), ) ``` See the [list of supported languages](/stt/concepts/supported-languages) and learn more about [language hints](/stt/concepts/language-hints). ### Customization with context By providing context, you help the model better understand and anticipate the language in your audio, even when some terms do not appear clearly or completely. ```python from livekit.plugins import soniox from livekit.plugins.soniox import ( ContextObject, ContextGeneralItem, ContextTranslationTerm, ) stt = soniox.STT( params=soniox.STTOptions( context=ContextObject( general=[ContextGeneralItem(key="domain", value="Healthcare")], terms=["Celebrex", "Zyrtec", "Xanax", "Prilosec", "Amoxicillin Clavulanate Potassium"], translation_terms=[ContextTranslationTerm(source="Mr. Smith", target="Sr. Smith")], ), ), ) ``` Learn more about [customizing with context](/stt/concepts/context). ### Speaker diarization Enable speaker diarization to annotate tokens with speaker IDs: ```python from livekit.plugins import soniox stt = soniox.STT( params=soniox.STTOptions( enable_speaker_diarization=True, ), ) ``` Learn more about [speaker diarization](/stt/concepts/speaker-diarization). ### Endpoint detection Soniox detects natural pauses in speech to finalize transcripts. Two knobs tune it: * `max_endpoint_delay_ms` (500–3000) caps how long Soniox waits after speech stops before firing an endpoint. * `endpoint_sensitivity` (-1.0 to 1.0) shifts how eagerly the model declares an endpoint. Increase for snappier turns; decrease if turns end too early. ```python from livekit.plugins import soniox stt = soniox.STT( params=soniox.STTOptions( max_endpoint_delay_ms=1000, endpoint_sensitivity=0.5, ), ) ``` Learn more about [endpoint detection](/stt/rt/endpoint-detection). ## Reference * [LiveKit Soniox plugin docs](https://docs.livekit.io/agents/models/stt/plugins/soniox/) * [LiveKit Soniox API reference](https://docs.livekit.io/reference/python/v1/livekit/plugins/soniox/index.html) * [Soniox STT WebSocket API](/api-reference/stt/websocket-api) * [Supported languages](/stt/concepts/supported-languages) # Text-to-Speech URL: /integrations/livekit/tts Use Soniox Text-to-Speech in LiveKit Agents. ## Overview `soniox.TTS` provides real-time text-to-speech synthesis using the [Soniox WebSocket TTS API](/api-reference/tts/websocket-api). It delivers: * **Ultra-low latency** — synthesis starts from the first few words, before the full sentence is available, keeping voice agents responsive. * **60+ languages** with native-speaker-quality voices. See [supported languages](/tts/concepts/supported-languages) and [voices](/tts/concepts/voices). * **Accurate alphanumerics** — phone numbers, email addresses, IDs, and other mixed letter-and-digit strings are pronounced correctly. * **Hallucination-free output** — the model speaks the text you send, nothing more. ## Basic usage Use Soniox TTS in an `AgentSession`: ```python from livekit.agents import AgentSession from livekit.plugins import soniox session = AgentSession( tts=soniox.TTS(model="tts-rt-v2", voice="Adrian"), # ... stt, llm, etc. ) ``` ## Configuration `soniox.TTS` accepts top-level constructor arguments for the model, voice, language, and audio settings. ### Constructor arguments | Argument | Type | Default | Description | | --------------- | ------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | `api_key` | `str \| None` | `SONIOX_API_KEY` env var | Soniox API key. | | `model` | `str` | `tts-rt-v2` | TTS model identifier. | | `language` | `str` | `en` | Language code (e.g., `"en"`, `"es"`, `"fr"`). See [supported languages](/tts/concepts/supported-languages). | | `voice` | `str` | `Adrian` | Voice identifier. See [voices](/tts/concepts/voices). | | `audio_format` | `str` | `pcm_s16le` | Output audio format. See [audio formats](/tts/concepts/audio-formats). | | `sample_rate` | `int` | `24000` | Output sample rate in Hz. | | `bitrate` | `int \| None` | `None` | Codec bitrate in bps for lossy compressed formats. | | `websocket_url` | `str` | `wss://tts-rt.soniox.com/tts-websocket` | Soniox WebSocket endpoint. See [regional endpoints](#regional-endpoints). | | `http_session` | `aiohttp.ClientSession \| None` | `None` | Optional aiohttp session to reuse for the WebSocket connection. | ## Advanced usage ### Regional endpoints If you want to use a different region than the default (US), pass a regional `websocket_url` to the `TTS` constructor: ```python from livekit.plugins import soniox tts = soniox.TTS(websocket_url="wss://tts-rt.eu.soniox.com/tts-websocket") ``` See the [list of regional endpoints](/data-residency#regional-endpoints) for available endpoints. ### Voice and language Soniox TTS supports 60+ languages and a range of voices. Specify them via the constructor: ```python from livekit.plugins import soniox tts = soniox.TTS( model="tts-rt-v2", voice="Adrian", language="en", ) ``` See the [list of supported languages](/tts/concepts/supported-languages) and [available voices](/tts/concepts/voices). ### Updating options at runtime Use `update_options()` to change the model, language, or voice mid-session without recreating the `TTS` instance: ```python tts.update_options(voice="Adrian", language="es") ``` ## Reference * [LiveKit Soniox API reference](https://docs.livekit.io/reference/python/v1/livekit/plugins/soniox/index.html#livekit.plugins.soniox.TTS) * [Soniox TTS WebSocket API](/api-reference/tts/websocket-api) * [Voices](/tts/concepts/voices) * [Supported languages](/tts/concepts/supported-languages) # Build a voice agent with LiveKit and Soniox URL: /integrations/livekit/voice-agent Compose Soniox STT and TTS into a complete voice agent running with LiveKit Agents, from a minimal chat bot to a structured appointment-booking flow. import { LinkCards } from "@/components/link-card"; ## Overview The [STT](/integrations/livekit/stt) and [TTS](/integrations/livekit/tts) integration pages already cover how Soniox APIs run with LiveKit. This page combines them into a voice agent built around a dentist receptionist scenario. The walkthrough covers: 1. [The agent shape](#the-agent-shape) — a minimal LiveKit `Agent` running Soniox at both ends. 2. [Turn-taking and context](#turn-taking-and-context) — Soniox endpoint detection and domain context. 3. [Adding tools](#adding-tools) the LLM can call to look up and book appointments. 4. [When you need more structure](#when-you-need-more-structure) — a brief on multi-agent workflows for complex flows. LiveKit framework concepts (Agent, AgentSession, lifecycle hooks, multi-agent handoffs) are covered in [LiveKit's docs](https://docs.livekit.io/agents/). This page focuses on the Soniox-specific pieces. ### Why Soniox for voice agents * **One API key for both ends.** Soniox covers STT and TTS through the unified [speech platform](https://soniox.com/platform). No second vendor to integrate, monitor, or scale. * **Real multilingual support.** STT supports [60+ languages](/stt/concepts/supported-languages) with automatic language identification and code-switched speech. TTS speaks [60+ languages](/tts/concepts/supported-languages). * **Names, numbers, and IDs.** STT recognizes names, phone numbers, emails, and alphanumerics accurately, and TTS pronounces them back the same way. * **Low STT latency.** Soniox leads on time-to-final-transcript, so the LLM picks up the moment the user stops talking. * **Production scaling with good [pricing](https://soniox.com/pricing).** High-concurrency real-time workloads and regional endpoints. ## Setup Install LiveKit Agents with the extras for Soniox, OpenAI as the LLM, and Silero for local voice activity detection: ```bash pip install "livekit-agents[soniox,openai,silero]~=1.5" python-dotenv ``` LiveKit's `console` mode also needs the PortAudio runtime to access your microphone. On Linux: ```bash sudo apt install libportaudio2 ``` On macOS: ```bash brew install portaudio ``` Set your API keys. The same Soniox key works for STT and TTS. Create one in the [Soniox Console](https://console.soniox.com/): ```bash SONIOX_API_KEY=... OPENAI_API_KEY=... # Placeholders for console mode. Replace with real LiveKit Cloud # credentials for dev or prod runs. LIVEKIT_URL=ws://localhost:7880 LIVEKIT_API_KEY=devkey LIVEKIT_API_SECRET=devsecret ``` For this example our agent will run in console mode (no LiveKit server required — local mic and speakers): ```bash python agent.py console ``` For `dev` and `start` modes and full deployment options, see [LiveKit's running an agent](https://docs.livekit.io/agents/ops/) docs. ## The agent shape A LiveKit voice agent is an `Agent` subclass running inside an `AgentSession`. The session wires four services: VAD, STT, LLM, and TTS. See the [Voice AI quickstart](https://docs.livekit.io/agents/start/voice-ai/) for the framework basics. ```python import logging from dotenv import load_dotenv from livekit.agents import ( Agent, AgentSession, JobContext, WorkerOptions, cli, ) from livekit.plugins import openai, silero, soniox load_dotenv() logger = logging.getLogger("voice-agent") class Receptionist(Agent): def __init__(self) -> None: super().__init__( instructions=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), ) async def on_enter(self) -> None: self.session.generate_reply( instructions="Greet the caller and ask how you can help." ) async def entrypoint(ctx: JobContext) -> None: await ctx.connect() session = AgentSession( vad=silero.VAD.load(), stt=soniox.STT(), llm=openai.LLM(model="gpt-4o-mini"), tts=soniox.TTS(voice="Adrian"), ) await session.start(agent=Receptionist(), room=ctx.room) if __name__ == "__main__": cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint)) ``` The two Soniox-specific lines: * `stt=soniox.STT()` — uses defaults (model `stt-rt-v5`, 16 kHz, language identification on). * `tts=soniox.TTS(voice="Adrian")` — one of the [Soniox voices](/tts/concepts/voices). Conversation history is managed by `AgentSession` automatically — no manual aggregator wiring needed. ## Turn-taking and context The minimal bot uses Silero VAD for turn detection. Soniox emits its own end-of-speech events from the STT WebSocket, and they arrive earlier than VAD's silence timer. Switching to Soniox endpoint detection makes the conversation feel snappier. Domain context is the second tuning knob: Soniox STT accepts a list of `terms` (proper nouns, jargon, identifiers) and a set of `general` key/value facts about the domain. Both bias transcription accuracy for the session. ```python from livekit.agents import TurnHandlingOptions from livekit.plugins.soniox import ( ContextGeneralItem, ContextObject, STTOptions, ) CLINIC_CONTEXT = ContextObject( terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], general=[ ContextGeneralItem(key="domain", value="Dental practice"), ContextGeneralItem(key="topic", value="Booking an appointment"), ], ) session = AgentSession( vad=silero.VAD.load(), stt=soniox.STT( params=STTOptions( language_hints=["en", "es"], context=CLINIC_CONTEXT, max_endpoint_delay_ms=1000, ), ), llm=openai.LLM(model="gpt-4o-mini"), tts=soniox.TTS(voice="Adrian"), turn_handling=TurnHandlingOptions( turn_detection="stt", interruption={"mode": "vad"}, ), ) ``` Three changes: * `turn_handling={"turn_detection": "stt", ...}` switches turn detection from VAD silence to Soniox's STT end-of-speech events. See [endpoint detection](/integrations/livekit/stt#endpoint-detection). * `interruption={"mode": "vad"}` keeps interruption local. LiveKit's default uses a cloud ML model that requires real LiveKit Cloud credentials — `"vad"` is the right choice for console mode. * `max_endpoint_delay_ms=1000` raises Soniox's silence threshold from 500 ms. Anything shorter logs `stt end of speech received while user is speaking` warnings as Soniox declares endpoint before Silero VAD agrees the speaker stopped. A second of patience eliminates the desync. Silero VAD stays in the pipeline even though Soniox now owns turn detection. `AgentSession` uses VAD for a second job: interruption detection — catching when the caller starts speaking while the agent is still talking. `interruption.mode` accepts `"adaptive"` (a LiveKit Cloud ML model) or `"vad"`, so local Silero stays as the practical choice for that job. The labor split lines up with each tool's strengths: Soniox decides when a turn ends, Silero decides when one starts. To learn more, check out [LiveKit's Turn-Taking Docs](https://docs.livekit.io/agents/logic/turns/#stt-endpointing) The `context` field tunes STT to your domain. List the brand names, jargon, and identifiers your users will say in `terms`. Use `general` for structured facts that bias what the model expects to hear about. See [STT context](/stt/concepts/context) for examples. ```python import logging from dotenv import load_dotenv from livekit.agents import ( Agent, AgentSession, JobContext, TurnHandlingOptions, WorkerOptions, cli, ) from livekit.plugins import openai, silero, soniox from livekit.plugins.soniox import ( ContextGeneralItem, ContextObject, STTOptions, ) load_dotenv() logger = logging.getLogger("voice-agent") CLINIC_CONTEXT = ContextObject( terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], general=[ ContextGeneralItem(key="domain", value="Dental practice"), ContextGeneralItem(key="topic", value="Booking an appointment"), ], ) class Receptionist(Agent): def __init__(self) -> None: super().__init__( instructions=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), ) async def on_enter(self) -> None: self.session.generate_reply( instructions="Greet the caller and ask how you can help." ) async def entrypoint(ctx: JobContext) -> None: await ctx.connect() session = AgentSession( vad=silero.VAD.load(), stt=soniox.STT( params=STTOptions( language_hints=["en"], context=CLINIC_CONTEXT, max_endpoint_delay_ms=1000, ), ), llm=openai.LLM(model="gpt-4o-mini"), tts=soniox.TTS(voice="Adrian"), turn_handling=TurnHandlingOptions( turn_detection="stt", interruption={"mode": "vad"}, ), ) await session.start(agent=Receptionist(), room=ctx.room) if __name__ == "__main__": cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint)) ``` ## Adding tools Function calling in LiveKit is done via [`@function_tool`](https://docs.livekit.io/agents/build/tools/) methods on the `Agent` subclass. The decorator reads the signature and docstring to build the LLM-facing schema — no separate schema object to maintain. The dentist needs two tools: one to look up open slots, one to book. ```python from livekit.agents import Agent, function_tool class DentalCalendar: """Mock calendar. Replace with your real booking system.""" # The same four times are offered every day. DAILY_SCHEDULE = ["09:00", "10:30", "14:00", "15:30"] def __init__(self) -> None: # ISO datetimes that are already booked. self.booked: set[str] = {"2026-05-12T10:30"} self._next_confirmation = 1000 async def find_slots(self, date: str) -> list[str]: # Return open ISO datetimes for the given date. slots_for_day = [f"{date}T{time}" for time in self.DAILY_SCHEDULE] return [slot for slot in slots_for_day if slot not in self.booked] async def book(self, name: str, slot: str, reason: str) -> str: # Mark a slot as booked and return a confirmation ID. self.booked.add(slot) self._next_confirmation += 1 return f"DENT-{self._next_confirmation}" calendar = DentalCalendar() class Receptionist(Agent): def __init__(self) -> None: super().__init__( instructions=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. " "They will be spoken aloud." "When booking, confirm name, date, time, and reason " "before calling the tool." ), ) async def on_enter(self) -> None: self.session.generate_reply( instructions="Greet the caller and ask how you can help." ) @function_tool async def check_availability(self, date: str) -> str: """Look up open appointment slots for a given date. Args: date: ISO date, e.g. "2026-05-12". """ slots = await calendar.find_slots(date) if not slots: return f"No slots available on {date}; fully booked." return f"Open slots on {date}: {', '.join(slots)}." @function_tool async def book_appointment(self, name: str, slot: str, reason: str) -> str: """Book a confirmed appointment. Only call after the patient has confirmed the date, time, and reason. Args: name: Patient's full name. slot: ISO datetime, e.g. "2026-05-12T10:30". reason: Reason for the visit. """ cid = await calendar.book(name=name, slot=slot, reason=reason) return f"Booked. Confirmation: {cid}." ``` The `AgentSession` and entrypoint are unchanged. ### Useful patterns **Audible filler.** Tools that hit the network can stall the conversation. Make the agent speak before the work starts: ```python @function_tool async def check_availability(self, date: str) -> str: """...""" self.session.say("Let me check the schedule.") ... ``` **Date awareness.** GPT models don't reliably know today's date, so relative phrases like *next Tuesday* produce wrong dates. Inject today's date into the system prompt: ```python from datetime import date class Receptionist(Agent): def __init__(self) -> None: super().__init__( instructions=( f"Today's date is {date.today().isoformat()}. " "Resolve relative dates based on today. " "..." ), ) ``` **Ending the call.** Shut the worker down after a successful booking. `get_job_context().shutdown()` is synchronous — schedule it from a delayed task so the final TTS can finish playing: ```python import asyncio from livekit.agents import get_job_context @function_tool async def book_appointment(self, name: str, slot: str, reason: str) -> str: """...""" cid = await calendar.book(name=name, slot=slot, reason=reason) async def _shutdown() -> None: await asyncio.sleep(8.0) get_job_context().shutdown(reason="appointment_booked") asyncio.create_task(_shutdown()) return f"Booked. Confirmation: {cid}." ``` ```python import asyncio import logging from datetime import date from dotenv import load_dotenv from livekit.agents import ( Agent, AgentSession, JobContext, TurnHandlingOptions, WorkerOptions, cli, function_tool, get_job_context, ) from livekit.plugins import openai, silero, soniox from livekit.plugins.soniox import ( ContextGeneralItem, ContextObject, STTOptions, ) load_dotenv() logger = logging.getLogger("voice-agent") TODAY = date.today().isoformat() CLINIC_CONTEXT = ContextObject( terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], general=[ ContextGeneralItem(key="domain", value="Dental practice"), ContextGeneralItem(key="topic", value="Booking an appointment"), ], ) class DentalCalendar: """Mock calendar. Replace with your real booking system.""" # The same four times are offered every day. DAILY_SCHEDULE = ["09:00", "10:30", "14:00", "15:30"] def __init__(self) -> None: # ISO datetimes that are already booked. self.booked: set[str] = {"2026-05-12T10:30"} self._next_confirmation = 1000 async def find_slots(self, date: str) -> list[str]: """Return open ISO datetimes for the given date.""" slots_for_day = [f"{date}T{time}" for time in self.DAILY_SCHEDULE] return [slot for slot in slots_for_day if slot not in self.booked] async def book(self, name: str, slot: str, reason: str) -> str: """Mark a slot as booked and return a confirmation ID.""" self.booked.add(slot) self._next_confirmation += 1 return f"DENT-{self._next_confirmation}" calendar = DentalCalendar() class Receptionist(Agent): def __init__(self) -> None: super().__init__( instructions=( f"Today's date is {TODAY}. " "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud. " "Resolve relative dates based on today. " "When booking, confirm name, date, time, and reason before " "calling the tool." ), ) async def on_enter(self) -> None: self.session.generate_reply( instructions="Greet the caller and ask how you can help." ) @function_tool async def check_availability(self, date: str) -> str: """Look up open appointment slots for a given date. Args: date: ISO date, e.g. "2026-05-12". """ self.session.say("Let me check the schedule.") slots = await calendar.find_slots(date) if not slots: return f"No slots available on {date}; fully booked." return f"Open slots on {date}: {', '.join(slots)}." @function_tool async def book_appointment(self, name: str, slot: str, reason: str) -> str: """Book a confirmed appointment. Only call after the patient has confirmed the date, time, and reason. Args: name: Patient's full name. slot: ISO datetime, e.g. "2026-05-12T10:30". reason: Reason for the visit. """ cid = await calendar.book(name=name, slot=slot, reason=reason) async def _shutdown() -> None: await asyncio.sleep(8.0) get_job_context().shutdown(reason="appointment_booked") asyncio.create_task(_shutdown()) return f"Booked. Confirmation: {cid}." async def entrypoint(ctx: JobContext) -> None: await ctx.connect() session = AgentSession( vad=silero.VAD.load(), stt=soniox.STT( params=STTOptions( language_hints=["en"], context=CLINIC_CONTEXT, max_endpoint_delay_ms=1000, ), ), llm=openai.LLM(model="gpt-4o-mini"), tts=soniox.TTS(voice="Adrian"), turn_handling=TurnHandlingOptions( turn_detection="stt", interruption={"mode": "vad"}, ), ) await session.start(agent=Receptionist(), room=ctx.room) if __name__ == "__main__": cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint)) ``` ## When you need more structure A single `Agent` with all the tools works fine for the dentist demo. It starts to fall apart when: * you have many tools and some shouldn't coexist (e.g. a write-side tool firing during greeting), * the system prompt grows into a wall of *don't do X until Y* rules, * you want distinct personas or phases (triage → specialist, sales → support). LiveKit supports breaking the conversation into multiple `Agent` subclasses, each holding its own subset of tools. A tool returns the next `Agent` instance to hand off control. The shared `chat_ctx` carries forward, so the new agent sees the conversation so far. ```python class GreetAgent(Agent): def __init__(self) -> None: super().__init__( instructions="Greet the caller and ask for their full name.", ) async def on_enter(self) -> None: self.session.generate_reply() @function_tool async def collect_name(self, name: str) -> Agent: """Record the caller's name.""" return BookingAgent(name=name) class BookingAgent(Agent): def __init__(self, name: str) -> None: super().__init__( instructions=( f"You are speaking with {name}. Help them book an appointment. " "Confirm date, time, and reason before calling book_appointment." ), ) self._name = name @function_tool async def book_appointment(self, slot: str, reason: str) -> str: """Book a confirmed appointment. Args: slot: ISO datetime, e.g. "2026-05-12T10:30". reason: Reason for the visit. """ cid = await calendar.book(name=self._name, slot=slot, reason=reason) return f"Booked. Confirmation: {cid}." ``` Pass the initial agent to `session.start(...)`: ```python await session.start(agent=GreetAgent(), room=ctx.room) ``` `book_appointment` cannot be called until the conversation reaches `BookingAgent` — the LLM physically does not see it before then. Branching (urgent vs. non-urgent), cycles (no availability → retry), and multi-step flows extend the same pattern. For the full API, see [LiveKit's workflow docs](https://docs.livekit.io/agents/build/workflows/). ```python import asyncio import logging from datetime import date from dotenv import load_dotenv from livekit.agents import ( Agent, AgentSession, JobContext, TurnHandlingOptions, WorkerOptions, cli, function_tool, get_job_context, ) from livekit.plugins import openai, silero, soniox from livekit.plugins.soniox import ( ContextGeneralItem, ContextObject, STTOptions, ) load_dotenv() logger = logging.getLogger("voice-agent") TODAY = date.today().isoformat() CLINIC_CONTEXT = ContextObject( terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], general=[ ContextGeneralItem(key="domain", value="Dental practice"), ContextGeneralItem(key="topic", value="Booking an appointment"), ], ) class DentalCalendar: """Mock calendar. Replace with your real booking system.""" # The same four times are offered every day. DAILY_SCHEDULE = ["09:00", "10:30", "14:00", "15:30"] def __init__(self) -> None: # ISO datetimes that are already booked. self.booked: set[str] = {"2026-05-12T10:30"} self._next_confirmation = 1000 async def find_slots(self, date: str) -> list[str]: """Return open ISO datetimes for the given date.""" slots_for_day = [f"{date}T{time}" for time in self.DAILY_SCHEDULE] return [slot for slot in slots_for_day if slot not in self.booked] async def book(self, name: str, slot: str, reason: str) -> str: """Mark a slot as booked and return a confirmation ID.""" self.booked.add(slot) self._next_confirmation += 1 return f"DENT-{self._next_confirmation}" calendar = DentalCalendar() class GreetAgent(Agent): def __init__(self) -> None: super().__init__( instructions=( "You are a friendly receptionist at Bright Smile Dental. " "Greet the caller and ask for their full name. " "Once they provide it, call collect_name. " "Keep replies short and natural. They will be spoken aloud." ), ) async def on_enter(self) -> None: self.session.generate_reply( instructions="Greet the caller and ask for their full name." ) @function_tool async def collect_name(self, name: str) -> Agent: """Record the caller's name and hand off to the booking agent. Args: name: The caller's full name. """ return BookingAgent(name=name) class BookingAgent(Agent): def __init__(self, name: str) -> None: super().__init__( instructions=( f"Today's date is {TODAY}. " f"You are speaking with {name}. Help them book an appointment. " "Resolve relative dates based on today. " "Confirm date, time, and reason before calling book_appointment." ), ) self._name = name @function_tool async def check_availability(self, date: str) -> str: """Look up open appointment slots for a given date. Args: date: ISO date, e.g. "2026-05-12". """ self.session.say("Let me check the schedule.") slots = await calendar.find_slots(date) if not slots: return f"No slots available on {date}; fully booked." return f"Open slots on {date}: {', '.join(slots)}." @function_tool async def book_appointment(self, slot: str, reason: str) -> str: """Book a confirmed appointment. Only call after the patient has confirmed the date, time, and reason. Args: slot: ISO datetime, e.g. "2026-05-12T10:30". reason: Reason for the visit. """ cid = await calendar.book(name=self._name, slot=slot, reason=reason) async def _shutdown() -> None: await asyncio.sleep(8.0) get_job_context().shutdown(reason="appointment_booked") asyncio.create_task(_shutdown()) return f"Booked. Confirmation: {cid}." async def entrypoint(ctx: JobContext) -> None: await ctx.connect() session = AgentSession( vad=silero.VAD.load(), stt=soniox.STT( params=STTOptions( language_hints=["en"], context=CLINIC_CONTEXT, max_endpoint_delay_ms=1000, ), ), llm=openai.LLM(model="gpt-4o-mini"), tts=soniox.TTS(voice="Adrian"), turn_handling=TurnHandlingOptions( turn_detection="stt", interruption={"mode": "vad"}, ), ) await session.start(agent=GreetAgent(), room=ctx.room) if __name__ == "__main__": cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint)) ``` ## What to read next # n8n URL: /integrations/n8n How to use Soniox Speech-to-Text AI with n8n import Image from "next/image"; import VideoPlayer from "@/components/video-player"; import { Callout } from "@/components/callout"; ## Overview Soniox Speech-to-Text AI turns audio into highly accurate text. Paired with n8n, you can build powerful automation workflows that transcribe audio from any source. Use the Soniox node in your n8n workflows to: * Transcribe audio files uploaded to cloud storage * Process voice messages from messaging platforms * Build automated transcription pipelines at scale * Combine speech-to-text with other n8n integrations All with enterprise-grade accuracy. *** ## Getting started To use Soniox with n8n, you'll need: * An [n8n](https://n8n.io/) instance (self-hosted or cloud) * A [Soniox account](https://console.soniox.com/) with an API key *** ## Installation Soniox provides a first-party verified node in the n8n marketplace. Search for "Soniox" in the node panel to find it.
Searching for the Soniox verified node in the n8n UI
Alternatively, you can install via npm: ```bash npm install @soniox/n8n-nodes-soniox ``` ## Credentials The Soniox node requires an API key to authenticate. ### Get your API key 1. Sign in to the [Soniox Console](https://console.soniox.com/) 2. Navigate to **API Keys** 3. Create a new key or copy an existing one ### Add credentials in n8n 1. In n8n, go to **Credentials** > **Add Credential** 2. Search for **Soniox API** 3. Enter your API key 4. Click **Save** The credentials will be tested automatically. If successful, you're ready to use the Soniox node. *** ## Operations The Soniox node supports three operations: ### Create transcription Creates a new transcription job from an audio source. You can choose to wait for completion or receive results asynchronously via webhook. **Audio sources:** | Source | Description | | ----------- | ------------------------------------------------------------------------ | | Binary File | Upload audio from a previous node (e.g., HTTP Request, Read Binary File) | | Audio URL | Provide a publicly accessible URL to the audio file | | File ID | Use a file previously uploaded to Soniox | ### Get results Retrieves the status and transcript for an existing transcription job. Use this when processing transcriptions asynchronously. ### Delete Deletes a transcription and its associated file from Soniox. Simply provide the transcription ID — the node automatically fetches the file ID and deletes both resources. Use this to clean up after async workflows. You must ensure the file is deleted after the transcription is completed. Files and transcriptions stored via the Async API are automatically deleted after 30 days. Check [limits and quotas](/stt/async/limits-and-quotas) for more information. *** ## Basic usage ### Transcribe from URL The simplest way to transcribe audio is from a public URL: 1. Add the **Soniox** node to your workflow 2. Select **Create** operation 3. Set **Audio Source** to **Audio URL** 4. Enter the URL to your audio file 5. Execute the workflow The node will wait for the transcription to complete and return the full transcript. ### Transcribe from binary data To transcribe audio from another node (like HTTP Request or Read Binary File): 1. Connect the source node to the Soniox node 2. Select **Create** operation 3. Set **Audio Source** to **Binary File** 4. Set **Binary Property Name** to the property containing your audio (default: `data`) 5. Execute the workflow ### Polling settings When **Wait for Completion** is enabled, you can configure: | Setting | Default | Description | | ------------------- | ------- | -------------------------------------- | | Poll Interval (Sec) | 1 | How often to check for completion | | Max Wait (Sec) | 300 | Maximum time to wait before timing out | If the **Max Wait (Sec)** value is too large, the n8n cloud platform may timeout before the transcription completes. For long audio files, consider using [async processing with webhooks](#async-processing-with-webhooks) instead. *** ## Advanced usage ### Language hints The model automatically detects and transcribes any supported language. It also handles multilingual audio, even when multiple languages appear within the same conversation. If you know which languages are likely to be spoken, you can provide language hints to improve accuracy: 1. In the Soniox node, find **Language Hints** 2. Click **Add Language** 3. Enter the language code (e.g., `en`, `es`, `fr`) 4. Repeat for additional languages See [list of supported languages](/stt/concepts/supported-languages) for all available language codes. Learn more about [language hints](/stt/concepts/language-hints). ### Speaker diarization Enable **Enable Speaker Diarization** to identify and separate different speakers in the audio. The transcript will include speaker labels for each segment. ### Language identification Enable **Enable Language Identification** to include detected language information in the transcript output. ### Customization with context Provide context to help the model better understand domain-specific terminology, names, or phrases. **Simple text context:** 1. Set **Context Mode** to **Text** 2. Enter relevant terms or phrases in the **Context Text** field ``` Celebrex, Zyrtec, Xanax, Prilosec, Amoxicillin ``` **Structured JSON context:** For more control, use structured context: 1. Set **Context Mode** to **Structured JSON** 2. Enter a JSON object in the **Context JSON** field ```json { "general": [ {"key": "domain", "value": "Healthcare"} ], "text": "Medical consultation recording", "terms": ["Celebrex", "Zyrtec", "Xanax"], "translation_terms": [ {"source": "Dr. Smith", "target": "Dr. Smith"} ] } ``` Learn more about [customizing with context](/stt/concepts/context). ### Translation Soniox can translate the transcript to another language during transcription. **One-way translation:** Translate the transcript to a single target language: 1. Set **Translation Type** to **One Way** 2. Enter the **Target Language** code (e.g., `es` for Spanish) **Two-way translation:** For conversations between speakers of two languages, translate each speaker to the other's language: 1. Set **Translation Type** to **Two Way** 2. Enter **Language A** (e.g., `en`) 3. Enter **Language B** (e.g., `es`) *** ## Async processing with webhooks For long audio files or high-volume processing, you can use webhooks instead of waiting for completion: 1. Set **Wait for Completion** to **false** 2. Enter your **Webhook URL** 3. Optionally set **Webhook Auth Header Name** and **Webhook Auth Header Value** for authentication The node will immediately return the transcription ID. Soniox will send the results to your webhook when processing completes.
To fetch results later, use the **Get Results** operation with the transcription ID. *** ## Output options ### Output mode Choose what data to return when the transcription completes: | Mode | Description | | ------------- | -------------------------------------------------------------------------------------- | | Full Response | Returns the complete transcript with all metadata, timestamps, and speaker information | | Text Only | Returns only the transcribed text as a simple string | *** ## Cleanup and resource management When you upload binary files, Soniox stores them temporarily. To avoid accumulating unused files, use the cleanup features: ### Automatic cleanup (recommended) When **Wait for Completion** is enabled, the **Auto Delete** option is available (enabled by default). When enabled, the node automatically deletes: * The **transcription** — always deleted regardless of audio source * The **uploaded file** — only deleted when using Binary File as the audio source (since that's when a file is uploaded) This keeps your Soniox account clean without extra workflow steps. ### Manual cleanup For async workflows (when not waiting for completion), use the **Delete** operation to clean up after processing: 1. Add a new **Soniox** node after receiving the webhook callback 2. Select **Delete** operation 3. Enter the **Transcription ID** 4. Execute The Delete operation automatically fetches the transcription details to find the associated file ID, then deletes both the transcription and its file (if one exists). **Example async cleanup workflow:** 1. **Soniox** (Create) — Upload file, don't wait. 2. **Webhook** trigger — Receives completion callback from Soniox with `id` (transcription ID) 3. Process the transcript as needed 4. **Soniox** (Delete) — Clean up using the transcription ID from step 2 *** ## Resources * [Soniox API Reference](/api-reference) * [Supported Languages](/stt/concepts/supported-languages) * [n8n Documentation](https://docs.n8n.io/) * [GitHub Repository](https://github.com/soniox/n8n-nodes-soniox) # Pipecat URL: /integrations/pipecat Integrate Soniox Speech-to-Text and Text-to-Speech into Pipecat pipelines. import Image from "next/image"; import { LinkCards } from "@/components/link-card"; ## Overview Pipecat is a framework for building voice-enabled, real-time, multimodal AI applications. A typical Pipecat pipeline for voice applications looks like this: 1. **Send Audio** - Transmit and capture streamed audio from the user. 2. **Transcribe Speech** - Convert speech to text as the user is talking. 3. **Process with LLM** - Generate responses using a large language model. 4. **Convert to Speech** - Transform text responses into natural speech. 5. **Play Audio** - Stream the audio response back to the user. Soniox plugs into two stages of this pipeline: * **`SonioxSTTService`** handles the transcribe speech step using the [Soniox real-time STT API](/stt/rt/real-time-transcription). * **`SonioxTTSService`** handles the convert to speech step using the [Soniox real-time TTS API](/tts/rt/real-time-generation). For more details on how Pipecat works, check the [Pipecat documentation](https://docs.pipecat.ai/getting-started/introduction). ## Installation Install the Soniox extras for Pipecat: ```bash pip install "pipecat-ai[soniox]" ``` You will also need to set up your Soniox API key as an environment variable: ```bash export SONIOX_API_KEY= ``` You can obtain a Soniox API key by signing up at the [Soniox Console](https://console.soniox.com/). ## Services ## Guides # Switch your Pipecat STT or TTS provider to Soniox URL: /integrations/pipecat/migrate Step-by-step guide to migrate from Deepgram, ElevenLabs, AssemblyAI, Cartesia, or OpenAI to Soniox STT and TTS in Pipecat, with config mapping and code examples. import { LinkCards } from "@/components/link-card"; import { Callout } from "@/components/callout"; ## Overview Each provider section below shows how to swap an STT or TTS service for Soniox, plus how the source settings map across. The rest of your Pipecat pipeline (transport, LLM, aggregators) stays the same. For configuration depth, see the [STT](/integrations/pipecat/stt) and [TTS](/integrations/pipecat/tts) reference pages. For an end-to-end walkthrough of a Soniox-only voice agent, see [Build a voice agent](/integrations/pipecat/voice-agent). ## Test Soniox before you migrate The fastest way to evaluate is on our live comparison pages: record a sample on the [STT comparison](https://soniox.com/compare) page or enter text on the [TTS comparison](https://soniox.com/compare-tts) page, and see the result side-by-side with your current provider. Cases to evaluate when building a reliable voice agent across multiple languages: * **Mid-utterance language switching.** Start a sentence in English and finish in Spanish, or drop a French name into an English question. Soniox detects and transcribes both. * **Non-English, end-to-end.** Run a full conversation in your target language. Both STT and TTS cover [60+ languages](/stt/concepts/supported-languages). * **Tricky inputs.** Order numbers, postal codes, emails, phone numbers, brand names, and product codes with non-English spellings. Soniox preserves them on the STT side and pronounces them correctly on the TTS side. * **Low latency.** Soniox leads the [Pipecat STT benchmark](https://www.daily.co/blog/benchmarking-stt-for-voice-agents/) on time-to-final-transcript. ## Before you migrate Install the Soniox extras for Pipecat: ```bash pip install "pipecat-ai[soniox]" ``` Create an API key in the [Soniox Console](https://console.soniox.com/). The same key works for STT and TTS. ```bash export SONIOX_API_KEY=... ``` ## From Deepgram ### STT Before: ```python from pipecat.services.deepgram.stt import DeepgramSTTService stt = DeepgramSTTService( api_key=os.environ["DEEPGRAM_API_KEY"], settings=DeepgramSTTService.Settings( model="nova-3-general", language="en-US", smart_format=True, keyterm=["Bright Smile Dental", "checkup", "cavity"], endpointing=300, ), ) ``` After: ```python from pipecat.services.soniox.stt import SonioxSTTService, SonioxContextObject from pipecat.transcriptions.language import Language stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( language_hints=[Language.EN], context=SonioxContextObject(terms=["Bright Smile Dental", "checkup", "cavity"]), ), ) ``` | Deepgram setting | Soniox equivalent | Notes | | ------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | `language` | [`language_hints`](/stt/concepts/language-hints) (list) | a hint, not a filter. Soniox still transcribes other languages | | `interim_results` | always on | Soniox streams [non-final and final tokens](/stt/rt/real-time-transcription) by default | | `punctuate` | automatic in Soniox | | | `smart_format`, `numerals` | automatic in Soniox | | | `keywords` / `keyterm` | [`context.terms`](/stt/concepts/context) | wrap with `SonioxContextObject(terms=[...])` | | `diarize` | [`enable_speaker_diarization`](/stt/concepts/speaker-diarization) | | | `endpointing` (ms),
`utterance_end_ms` | `vad_force_turn_endpoint=False` | uses [Soniox endpointing](/stt/rt/endpoint-detection) | | `redact`, `profanity_filter` | no equivalent | handle in your application if needed | ## From ElevenLabs ### TTS Before: ```python from pipecat.services.elevenlabs.tts import ElevenLabsTTSService tts = ElevenLabsTTSService( api_key=os.environ["ELEVENLABS_API_KEY"], settings=ElevenLabsTTSService.Settings( voice="", model="eleven_turbo_v2_5", stability=0.5, similarity_boost=0.75, ), ) ``` After: ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.environ["SONIOX_API_KEY"], settings=SonioxTTSService.Settings(voice="Adrian"), ) ``` | ElevenLabs TTS setting | Soniox equivalent | Notes | | ------------------------------------------------------------- | ------------------ | ----------------------------------------- | | `voice` | `voice` (Settings) | see [Soniox voices](/tts/concepts/voices) | | `stability`, `similarity_boost`, `style`, `use_speaker_boost` | no equivalent | | | `speed` | no equivalent | | | `apply_text_normalization` | no equivalent | | ### STT Before: ```python from pipecat.services.elevenlabs.stt import ElevenLabsRealtimeSTTService, CommitStrategy stt = ElevenLabsRealtimeSTTService( api_key=os.environ["ELEVENLABS_API_KEY"], commit_strategy=CommitStrategy.VAD, include_language_detection=True, settings=ElevenLabsRealtimeSTTService.Settings( vad_silence_threshold_secs=0.6, vad_threshold=0.5, ), ) ``` After: ```python from pipecat.services.soniox.stt import SonioxSTTService from pipecat.transcriptions.language import Language stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( enable_language_identification=True, language_hints=[Language.EN], ), ) ``` | ElevenLabs Realtime STT setting | Soniox equivalent | Notes | | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------- | | `commit_strategy`,
`vad_silence_threshold_secs`, `vad_threshold`,
`min_speech_duration_ms`, `min_silence_duration_ms` | `vad_force_turn_endpoint=False` | uses [Soniox endpointing](/stt/rt/endpoint-detection) | | `include_language_detection` | [`enable_language_identification`](/stt/concepts/language-identification) | | ## From AssemblyAI ### STT Before: ```python from pipecat.services.assemblyai.stt import AssemblyAISTTService stt = AssemblyAISTTService( api_key=os.environ["ASSEMBLYAI_API_KEY"], settings=AssemblyAISTTService.Settings( language_detection=True, speaker_labels=True, keyterms_prompt=["Bright Smile Dental", "checkup", "cavity"], ), ) ``` After: ```python from pipecat.services.soniox.stt import SonioxSTTService, SonioxContextObject stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( enable_language_identification=True, enable_speaker_diarization=True, context=SonioxContextObject(terms=["Bright Smile Dental", "checkup", "cavity"]), ), ) ``` | AssemblyAI setting | Soniox equivalent | Notes | | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------ | | `language_detection` | [`enable_language_identification`](/stt/concepts/language-identification) | | | `keyterms_prompt` | [`context.terms`](/stt/concepts/context) | wrap with `SonioxContextObject(terms=[...])` | | `prompt` | [`context.text`](/stt/concepts/context) | wrap with `SonioxContextObject(text="...")` | | `speaker_labels` | [`enable_speaker_diarization`](/stt/concepts/speaker-diarization) | | | `format_turns`, `formatted_finals` | automatic in Soniox | | | `min_turn_silence`, `max_turn_silence`,
`end_of_turn_confidence_threshold`,
`vad_threshold` | `vad_force_turn_endpoint=False` | uses [Soniox endpointing](/stt/rt/endpoint-detection) | | `domain` | [`context.general`](/stt/concepts/context) | wrap with `SonioxContextObject(general=[SonioxContextGeneralItem(...)])` | ## From Cartesia ### TTS Before: ```python from pipecat.services.cartesia.tts import CartesiaTTSService tts = CartesiaTTSService( api_key=os.environ["CARTESIA_API_KEY"], settings=CartesiaTTSService.Settings( voice="71a7ad14-091c-4e8e-a314-022ece01c121", model="sonic-2", ), ) ``` After: ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.environ["SONIOX_API_KEY"], settings=SonioxTTSService.Settings(voice="Adrian"), ) ``` | Cartesia TTS setting | Soniox equivalent | Notes | | --------------------------- | ------------------ | ----------------------------------------- | | `voice` | `voice` (Settings) | see [Soniox voices](/tts/concepts/voices) | | `generation_config.speed` | no equivalent | | | `generation_config.volume` | no equivalent | | | `generation_config.emotion` | no equivalent | | | `pronunciation_dict_id` | no equivalent | | Cartesia supports inline `` tags in input text. Strip them before passing text to Soniox, otherwise the bot will read the tags aloud literally. ### STT Before: ```python from pipecat.services.cartesia.stt import CartesiaSTTService stt = CartesiaSTTService( api_key=os.environ["CARTESIA_API_KEY"], settings=CartesiaSTTService.Settings(language="en"), ) ``` After: ```python from pipecat.services.soniox.stt import SonioxSTTService from pipecat.transcriptions.language import Language stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], settings=SonioxSTTService.Settings(language_hints=[Language.EN]), ) ``` | Cartesia STT setting | Soniox equivalent | Notes | | -------------------- | ------------------------------------------------------- | -------------------------------------------------------------- | | `language` | [`language_hints`](/stt/concepts/language-hints) (list) | a hint, not a filter. Soniox still transcribes other languages | ## From OpenAI OpenAI provides both STT and TTS services in Pipecat. ### STT Before: ```python from pipecat.services.openai.stt import OpenAIRealtimeSTTService from pipecat.transcriptions.language import Language stt = OpenAIRealtimeSTTService( api_key=os.environ["OPENAI_API_KEY"], settings=OpenAIRealtimeSTTService.Settings( model="gpt-4o-transcribe", language=Language.EN, prompt="Expect medical terminology and patient names.", noise_reduction="near_field", ), ) ``` After: ```python from pipecat.services.soniox.stt import SonioxSTTService, SonioxContextObject from pipecat.transcriptions.language import Language stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( language_hints=[Language.EN], context=SonioxContextObject(text="Expect medical terminology and patient names."), ), ) ``` | OpenAI Realtime STT setting | Soniox equivalent | Notes | | --------------------------- | ------------------------------------------------------- | -------------------------------------------------------------- | | `language` | [`language_hints`](/stt/concepts/language-hints) (list) | a hint, not a filter. Soniox still transcribes other languages | | `prompt` | [`context.text`](/stt/concepts/context) | wrap with `SonioxContextObject(text="...")` | | `noise_reduction` | no equivalent | | ### TTS Before: ```python from pipecat.services.openai.tts import OpenAITTSService tts = OpenAITTSService( api_key=os.environ["OPENAI_API_KEY"], settings=OpenAITTSService.Settings( voice="alloy", model="gpt-4o-mini-tts", instructions="Speak in a friendly, professional tone.", ), ) ``` After: ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.environ["SONIOX_API_KEY"], settings=SonioxTTSService.Settings(voice="Adrian"), ) ``` | OpenAI TTS setting | Soniox equivalent | Notes | | ------------------ | ------------------ | ----------------------------------------- | | `voice` | `voice` (Settings) | see [Soniox voices](/tts/concepts/voices) | | `instructions` | no equivalent | | | `speed` | no equivalent | | OpenAI TTS is locked to 24 kHz output, so transports or recording stages downstream of it may be configured for that rate. Pass `sample_rate=24000` on `SonioxTTSService` to keep them aligned. See the [TTS reference](/integrations/pipecat/tts) for supported rates. ## What to read next # Speech-to-Text URL: /integrations/pipecat/stt Use Soniox Speech-to-Text in a Pipecat pipeline. import { LinkCards } from "@/components/link-card"; ## Overview `SonioxSTTService` provides real-time speech-to-text transcription using the [Soniox WebSocket API](/api-reference/stt/websocket-api), with support for 60+ languages, context customization, multilingual audio, and speaker diarization. By default, the service uses the `stt-rt-v5` model with `vad_force_turn_endpoint=True`, which disables Soniox's native turn detection and relies on Pipecat's local VAD to finalize transcripts. This significantly reduces the time to final segment. To use Soniox's native endpoint detection instead, set `vad_force_turn_endpoint=False`. ## Basic usage Add `SonioxSTTService` to your Pipecat pipeline: ```python import os from pipecat.pipeline.pipeline import Pipeline from pipecat.services.soniox.stt import SonioxSTTService stt = SonioxSTTService( api_key=os.getenv("SONIOX_API_KEY"), ) pipeline = Pipeline([ transport.input(), stt, llm, # ... ]) ``` ## Configuration `SonioxSTTService` accepts both top-level constructor arguments (for connection and behavior) and a `Settings` object (for runtime-configurable transcription parameters). ### Constructor arguments | Argument | Type | Default | Description | | ------------------------- | --------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------------- | | `api_key` | `str` | required | Soniox API key. | | `url` | `str` | `wss://stt-rt.soniox.com/transcribe-websocket` | Soniox WebSocket endpoint. See [regional endpoints](#regional-endpoints). | | `sample_rate` | `int \| None` | `None` | Audio sample rate in Hz. When `None`, uses the pipeline's configured sample rate. | | `vad_force_turn_endpoint` | `bool` | `True` | When enabled, Pipecat's local VAD triggers transcript finalization. | | `settings` | `SonioxSTTService.Settings` | `None` | Runtime-configurable settings (see below). | ### Settings Pass via `settings=SonioxSTTService.Settings(...)`. These can be updated mid-conversation with `STTUpdateSettingsFrame`. | Setting | Type | Default | Description | | -------------------------------- | --------------------- | ----------- | ----------------------------------------------------------------- | | `model` | `str` | `stt-rt-v5` | Model to use for transcription. | | `language_hints` | `list[Language]` | `None` | Language hints to bias recognition toward expected languages. | | `language_hints_strict` | `bool` | `None` | If true, restrict recognition to the provided languages. | | `context` | `SonioxContextObject` | `None` | Context customization to improve transcription accuracy. | | `enable_speaker_diarization` | `bool` | `False` | Annotate tokens with speaker IDs. | | `enable_language_identification` | `bool` | `False` | Annotate tokens with language IDs. | | `endpoint_sensitivity` | `float` | `0.0` | [Endpoint sensitivity](/stt/rt/endpoint-detection) (-1.0 to 1.0). | | `client_reference_id` | `str` | `None` | Client reference ID for tracking. | ## Advanced usage ### Regional endpoints If you want to use a different region than the default (US), pass a regional `url` to the `SonioxSTTService` constructor: ```python from pipecat.services.soniox.stt import SonioxSTTService stt = SonioxSTTService( api_key=os.getenv("SONIOX_API_KEY"), url="wss://stt-rt.eu.soniox.com/transcribe-websocket", ) ``` See the [list of regional endpoints](/data-residency#regional-endpoints) for available endpoints. ### Language hints There is no need to pre-select a language. The model automatically detects and transcribes any supported language and handles multilingual audio seamlessly, even when multiple languages are mixed within a single sentence or conversation. When you have prior knowledge of the languages likely to appear in your audio, language hints help the model prioritize them for greater accuracy: ```python from pipecat.services.soniox.stt import SonioxSTTService from pipecat.transcriptions.language import Language stt = SonioxSTTService( api_key=os.getenv("SONIOX_API_KEY"), settings=SonioxSTTService.Settings( language_hints=[Language.EN, Language.ES, Language.JA, Language.ZH], ), ) ``` Language variants are ignored, for example `Language.EN_GB` is treated the same as `Language.EN`. See the [list of supported languages](/stt/concepts/supported-languages) and learn more about [language hints](/stt/concepts/language-hints). ### Customization with context By providing context, you help the model better understand and anticipate the language in your audio, even when some terms do not appear clearly or completely. ```python from pipecat.services.soniox.stt import ( SonioxSTTService, SonioxContextObject, SonioxContextGeneralItem, ) stt = SonioxSTTService( api_key=os.getenv("SONIOX_API_KEY"), settings=SonioxSTTService.Settings( context=SonioxContextObject( general=[ SonioxContextGeneralItem(key="domain", value="Healthcare"), ], terms=["Celebrex", "Zyrtec", "Xanax"], ), ), ) ``` Learn more about [customizing with context](/stt/concepts/context). ### Endpoint detection and VAD `SonioxSTTService` has two ways of knowing when to finalize a transcript. #### Pipecat VAD (default) By default, `vad_force_turn_endpoint=True`. Pipecat's local VAD detects when the user has stopped speaking and sends a finalize message to Soniox, returning the final transcript immediately. This is the recommended setup for low-latency voice agents. #### Soniox native endpoint detection To use Soniox's built-in endpoint detection instead, disable the VAD-driven finalize: ```python from pipecat.services.soniox.stt import SonioxSTTService stt = SonioxSTTService( api_key=os.getenv("SONIOX_API_KEY"), vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( endpoint_sensitivity=0.5, ), ) ``` Soniox will then listen for natural pauses in speech and finalize transcripts on its own. Tune `endpoint_sensitivity` (range -1.0 to 1.0) to make endpoints fire sooner (higher) or wait longer (lower). Learn more about [endpoint detection](/stt/rt/endpoint-detection). ## Complete examples The following examples demonstrate how to use `SonioxSTTService` in Pipecat projects: ## Reference * [Pipecat STT API reference](https://reference-server.pipecat.ai/en/latest/api/pipecat.services.soniox.stt.html) * [Soniox STT WebSocket API](/api-reference/stt/websocket-api) * [Supported languages](/stt/concepts/supported-languages) # Text-to-Speech URL: /integrations/pipecat/tts Use Soniox Text-to-Speech in a Pipecat pipeline. import { LinkCards } from "@/components/link-card"; ## Overview `SonioxTTSService` provides real-time text-to-speech synthesis using the [Soniox WebSocket TTS API](/api-reference/tts/websocket-api). Text is streamed incrementally to the Soniox endpoint, and audio is returned as base64-encoded chunks. Up to five concurrent streams are multiplexed over a single WebSocket connection, making the service efficient for interactive voice applications. ## Basic usage Add `SonioxTTSService` to your Pipecat pipeline: ```python import os from pipecat.pipeline.pipeline import Pipeline from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.getenv("SONIOX_API_KEY"), settings=SonioxTTSService.Settings( voice="Adrian", ), ) pipeline = Pipeline([ # ... llm, tts, transport.output(), ]) ``` ## Configuration `SonioxTTSService` accepts both top-level constructor arguments (for connection and audio formatting) and a `Settings` object (for voice, model, and language). ### Constructor arguments | Argument | Type | Default | Description | | ----------------------- | --------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | `api_key` | `str` | required | Soniox API key. | | `url` | `str` | `wss://tts-rt.soniox.com/tts-websocket` | WebSocket endpoint. See [regional endpoints](#regional-endpoints). | | `sample_rate` | `int \| None` | `None` | Output sample rate in Hz. Must be one of `{8000, 16000, 24000, 44100, 48000}` for raw PCM. | | `audio_format` | `str` | `pcm_s16le` | Output audio format. The default matches Pipecat's downstream audio pipeline. | | `text_aggregation_mode` | `TextAggregationMode` | `TextAggregationMode.SENTENCE` | Controls how incoming text is aggregated before synthesis. `SENTENCE` for natural speech, `TOKEN` for lower latency. | | `settings` | `SonioxTTSService.Settings` | `None` | Runtime-configurable settings (see below). | ### Settings Pass via `settings=SonioxTTSService.Settings(...)`. These can be updated mid-conversation with `TTSUpdateSettingsFrame`. | Setting | Type | Default | Description | | ---------- | ----------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `model` | `str` | `tts-rt-v2` | TTS model identifier. | | `voice` | `str` | `Adrian` | Voice name or the ID of a [cloned voice](/tts/concepts/voice-cloning). See [voices](/tts/concepts/voices). | | `language` | `Language \| str` | `Language.EN` | Language for synthesis. | | `speed` | `float \| None` | `None` | Speech rate multiplier from `0.7` to `1.3`; `None` uses the server default (`1.0`). See [speech speed](/tts/concepts/speech-speed). | ## Advanced usage ### Regional endpoints If you want to use a different region than the default (US), pass a regional `url` to the `SonioxTTSService` constructor: ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.getenv("SONIOX_API_KEY"), url="wss://tts-rt.eu.soniox.com/tts-websocket", ) ``` See the [list of regional endpoints](/data-residency#regional-endpoints) for available endpoints. ### Voice and language Soniox TTS supports 60+ languages and a range of voices. Specify them via `Settings`: ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.getenv("SONIOX_API_KEY"), settings=SonioxTTSService.Settings( model="tts-rt-v2", voice="Adrian", language="en", ), ) ``` See the [list of supported languages](/tts/concepts/supported-languages) and [available voices](/tts/concepts/voices). The `voice` setting also accepts the ID of a [cloned voice](/tts/concepts/voice-cloning). ### Speech speed Adjust the speaking rate with the `speed` setting (`0.7` to `1.3`, where `1.0` is normal speed): ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.getenv("SONIOX_API_KEY"), settings=SonioxTTSService.Settings( voice="Adrian", speed=1.15, ), ) ``` See [speech speed](/tts/concepts/speech-speed) for details. ### Sample rate When using a raw PCM audio format, the sample rate must be one of `{8000, 16000, 24000, 44100, 48000}`: ```python from pipecat.services.soniox.tts import SonioxTTSService tts = SonioxTTSService( api_key=os.getenv("SONIOX_API_KEY"), sample_rate=16000, settings=SonioxTTSService.Settings( voice="Adrian", ), ) ``` If `sample_rate` is `None`, the service inherits from the pipeline's configured sample rate. ### Word timestamps The service always requests [word timestamps](/tts/rt/timestamps) from Soniox and emits a `TTSTextFrame` for each word, aligned with the audio as it plays. Downstream processors (captions, context aggregation, interruption handling) receive each word at the moment it is spoken. No configuration is needed. ### Text aggregation By default the service buffers text until sentence boundaries (`TextAggregationMode.SENTENCE`) to produce more natural speech. For lower latency, switch to token-level streaming: ```python from pipecat.services.soniox.tts import SonioxTTSService from pipecat.services.tts_service import TextAggregationMode tts = SonioxTTSService( api_key=os.getenv("SONIOX_API_KEY"), text_aggregation_mode=TextAggregationMode.TOKEN, settings=SonioxTTSService.Settings( voice="Adrian", ), ) ``` ## Complete examples The following example demonstrates how to use `SonioxTTSService` in a Pipecat project: ## Reference * [Pipecat TTS API reference](https://reference-server.pipecat.ai/en/latest/api/pipecat.services.soniox.tts.html) * [Soniox TTS WebSocket API](/api-reference/tts/websocket-api) * [Voices](/tts/concepts/voices) * [Supported languages](/tts/concepts/supported-languages) # Build a voice agent with Pipecat and Soniox URL: /integrations/pipecat/voice-agent Compose Soniox STT and TTS into a complete voice agent running with Pipecat framework, from a minimal chat bot to a structured appointment-booking flow. import { LinkCards } from "@/components/link-card"; ## Overview The [STT](/integrations/pipecat/stt) and [TTS](/integrations/pipecat/tts) integration pages already cover how Soniox APIs run with Pipecat. This page combines them into a voice agent and grows the bot from a chat-only setup to a structured booking assistant. The walkthrough builds a dentist receptionist in three stages: 1. [The pipeline shape](#the-pipeline-shape), then the small additions that make it actually run as a chat bot. 2. [Adding tools](#adding-tools) the LLM can call to look up and book appointments. 3. [Structuring with Pipecat Flows](#structuring-with-pipecat-flows), where the conversation follows a deterministic node graph. ### Why Soniox for voice agents Reasons that matter when shipping a real voice agent: * **One API key for both ends.** Soniox covers STT and TTS through the unified [speech platform](https://soniox.com/platform). No second vendor to integrate, monitor, or scale. * **Real multilingual support.** STT supports [60+ languages](/stt/concepts/supported-languages) with automatic language identification and handles code-switched speech. TTS speaks [60+ languages](/tts/concepts/supported-languages). * **Names, numbers, and IDs.** STT recognizes names, phone numbers, emails, and alphanumerics accurately, and TTS pronounces them back the same way. General-purpose providers usually mangle one or the other. * **Low STT latency.** Soniox leads the [Pipecat STT benchmark](https://www.daily.co/blog/benchmarking-stt-for-voice-agents/) on time-to-final-transcript, so the LLM picks up the moment the user stops talking. * **Production scaling with good [pricing](https://soniox.com/pricing).** Soniox supports high-concurrency real-time workloads and regional endpoints. ## Setup Install Pipecat with the extras for Soniox STT and TTS, OpenAI as the LLM, the development runner, and the transports the examples support (browser WebRTC and Daily): ```bash pip install "pipecat-ai[soniox,openai,runner,webrtc,daily]" ``` For the Pipecat Flows stage at the end, also install: ```bash pip install pipecat-ai-flows ``` Set your API keys. The same Soniox key works for STT and TTS. Create one in the [Soniox Console](https://console.soniox.com/): ```bash export SONIOX_API_KEY=... export OPENAI_API_KEY=... ``` Or put them in a `.env` next to your bot file. The examples below call `load_dotenv()` to pick that up automatically. ### Running the bot Each bot file uses Pipecat's development runner, which picks the transport at startup. The fastest local test is the prebuilt WebRTC UI: ```bash python bot.py -t webrtc ``` Open `http://localhost:7860`, click connect, and start talking. The prebuilt UI hands the bot your microphone and plays its replies through your speakers. Metrics are enabled in every example, so the same page shows per-stage latency, token usage, and function calls live as the conversation runs. The same files also support `-t daily` and `-t twilio` for cloud rooms and telephony. See the [Pipecat development runner guide](https://docs.pipecat.ai/api-reference/server/utilities/runner/guide) for the credentials and tunneling those transports need. ## The pipeline shape A voice agent is a Pipecat pipeline with five stages in order: * A **transport** captures audio from the user. * An **STT service** turns that audio into text. * An **LLM** produces a reply. * A **TTS service** turns the reply back into audio. * The **transport** again plays the audio back to the user. The transport is whatever you use to move audio between the user and the bot. Pipecat ships transports for telephony providers (Twilio, Telnyx, and others), web and WebRTC stacks (Daily, LiveKit, browser WebRTC), and local audio for development. The rest of the pipeline does not change when you swap one for another. ```python import os from pipecat.pipeline.pipeline import Pipeline from pipecat.services.openai.llm import OpenAILLMService from pipecat.services.soniox.stt import ( SonioxContextObject, SonioxContextGeneralItem, SonioxSTTService, ) from pipecat.services.soniox.tts import SonioxTTSService from pipecat.transcriptions.language import Language # ... transport and runner setup omitted, see the full code below ... stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( language_hints=[Language.EN], language_hints_strict=True, context=SonioxContextObject( general=[ SonioxContextGeneralItem(key="domain", value="Dental practice"), SonioxContextGeneralItem(key="topic", value="Booking an appointment"), ], terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], ), ), ) llm = OpenAILLMService( api_key=os.environ["OPENAI_API_KEY"], settings=OpenAILLMService.Settings( system_instruction=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), ), ) tts = SonioxTTSService(api_key=os.environ["SONIOX_API_KEY"]) pipeline = Pipeline([ transport.input(), stt, llm, tts, transport.output(), ]) ``` `vad_force_turn_endpoint=False` tells Pipecat to use Soniox's built-in endpoint detection instead of running a separate local VAD. Tune how eagerly endpoints fire with `endpoint_sensitivity` (range -1.0 to 1.0; higher = sooner). See [endpoint detection](/integrations/pipecat/stt#endpoint-detection-and-vad) for details. The `context` field tunes STT to your domain. List the brand names, jargon, and identifiers your users will say. See [STT context](/stt/concepts/context) for examples and more details. ## Adding turn-taking and history The pipeline above runs, but it has no memory between turns. `LLMContext` solves that: it is the conversation history, and every LLM request includes it. That is how the bot remembers names, resolves pronouns, and answers follow-ups. Two aggregators keep the context current. The user aggregator buffers STT fragments and appends one `{"role": "user", "content": "..."}` message when the user's turn ends. The assistant aggregator buffers the LLM's streaming tokens and appends one `{"role": "assistant", "content": "..."}` message when the response completes. They come as a pair because they share the same context. After a few turns, that context looks like this: ```json [ { "role": "developer", "content": "You are a friendly receptionist..." }, { "role": "user", "content": "Hi, I need to book a cleaning." }, { "role": "assistant", "content": "Of course. May I have your name?" }, { "role": "user", "content": "Jordan Smith." }, { "role": "assistant", "content": "Thanks, Jordan. What day works for you?" } ] ``` Wiring this into the pipeline takes two things: a fresh `LLMContext` and the aggregator pair built from it, slotted in around the LLM. The full bot looks like this: ```python # ... imports from the previous section ... from pipecat.frames.frames import LLMRunFrame from pipecat.pipeline.task import PipelineTask from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair # ... stt, llm, tts from the previous section ... context = LLMContext() user_aggregator, assistant_aggregator = LLMContextAggregatorPair(context) pipeline = Pipeline([ transport.input(), stt, user_aggregator, llm, tts, transport.output(), assistant_aggregator, ]) task = PipelineTask(pipeline) ``` To start the conversation before the user speaks, append a message to the context and queue an `LLMRunFrame`: ```python @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): context.add_message({ "role": "developer", "content": "Greet the caller and ask how you can help.", }) await task.queue_frames([LLMRunFrame()]) ``` That is a complete voice agent, chat-only for now. Tools come next. ```python import os from dotenv import load_dotenv from pipecat.frames.frames import LLMRunFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineParams, PipelineTask from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport from pipecat.services.openai.llm import OpenAILLMService from pipecat.services.soniox.stt import ( SonioxContextObject, SonioxContextGeneralItem, SonioxSTTService, ) from pipecat.services.soniox.tts import SonioxTTSService from pipecat.transcriptions.language import Language from pipecat.transports.base_transport import BaseTransport, TransportParams from pipecat.transports.daily.transport import DailyParams from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams load_dotenv(override=True) transport_params = { "daily": lambda: DailyParams(audio_in_enabled=True, audio_out_enabled=True), "twilio": lambda: FastAPIWebsocketParams(audio_in_enabled=True, audio_out_enabled=True), "webrtc": lambda: TransportParams(audio_in_enabled=True, audio_out_enabled=True), } async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( language_hints=[Language.EN], language_hints_strict=True, context=SonioxContextObject( general=[ SonioxContextGeneralItem(key="domain", value="Dental practice"), SonioxContextGeneralItem(key="topic", value="Booking an appointment"), ], terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], ), ), ) tts = SonioxTTSService(api_key=os.environ["SONIOX_API_KEY"]) llm = OpenAILLMService( api_key=os.environ["OPENAI_API_KEY"], settings=OpenAILLMService.Settings( system_instruction=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), ), ) context = LLMContext() user_aggregator, assistant_aggregator = LLMContextAggregatorPair(context) pipeline = Pipeline( [ transport.input(), stt, user_aggregator, llm, tts, transport.output(), assistant_aggregator, ] ) task = PipelineTask( pipeline, params=PipelineParams(enable_metrics=True, enable_usage_metrics=True) ) @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): context.add_message( { "role": "developer", "content": "Greet the caller and ask how you can help.", } ) await task.queue_frames([LLMRunFrame()]) @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): await task.cancel() runner = PipelineRunner(handle_sigint=runner_args.handle_sigint) await runner.run(task) async def bot(runner_args: RunnerArguments): transport = await create_transport(runner_args, transport_params) await run_bot(transport, runner_args) if __name__ == "__main__": from pipecat.runner.run import main main() ``` ## Adding tools Function calling lets the LLM trigger Python code during a conversation. Each tool has two parts: * A **handler** is the Python function that runs when the tool is called. It receives the LLM's parsed arguments and returns a result. * A **schema** is the declarative description the LLM sees: the tool's name, what it does, and what arguments it expects. The LLM uses the schema to decide when to call a tool and how to fill in its arguments. Pipecat's `FunctionSchema` is what you build for the schema. A single `FunctionSchema` is translated into the right wire format for whichever LLM provider you use, so the same tool definition works across OpenAI, Anthropic, Google, and others. The dentist needs two tools to start: one to look up open slots, one to book an appointment. ```python # ... imports from the previous section ... from pipecat.adapters.schemas.function_schema import FunctionSchema from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.frames.frames import TTSSpeakFrame from pipecat.services.llm_service import FunctionCallParams # ... stt, tts, llm, aggregators, pipeline from the previous section ... # Replace this with your real calendar or booking system. class DentalCalendar: booked: set[str] = {"2026-05-12T10:30"} async def find_slots(self, date: str) -> list[str]: all_slots = [f"{date}T{t}" for t in ("09:00", "10:30", "14:00", "15:30")] return [s for s in all_slots if s not in self.booked] async def book(self, name: str, slot: str, reason: str) -> str: # name and reason unused in mock self.booked.add(slot) return f"DENT-{abs(hash(slot)) % 10000:04d}" calendar = DentalCalendar() # Tool handlers can do anything Python can: API calls, database queries, # RAG lookups, file I/O. Here they hit the mock calendar above. async def check_availability(params: FunctionCallParams): slots = await calendar.find_slots(params.arguments["date"]) await params.result_callback({"slots": slots}) async def book_appointment(params: FunctionCallParams): cid = await calendar.book( name=params.arguments["name"], slot=params.arguments["slot"], reason=params.arguments["reason"], ) await params.result_callback({"confirmation_id": cid, "status": "booked"}) # Register handlers against their tool names. llm.register_function("check_availability", check_availability) llm.register_function("book_appointment", book_appointment) # Describe the tools so the LLM knows when and how to call them. tools = ToolsSchema(standard_tools=[ FunctionSchema( name="check_availability", description=( "Look up open appointment slots. Call this whenever the patient " "asks about availability or mentions a preferred date." ), properties={ "date": {"type": "string", "description": "ISO date, e.g. 2026-05-12"}, }, required=["date"], ), FunctionSchema( name="book_appointment", description=( "Book a confirmed appointment. Only call after the patient has " "explicitly confirmed the date, time, and reason." ), properties={ "name": {"type": "string"}, "slot": {"type": "string", "description": "ISO datetime, e.g. 2026-05-12T10:30"}, "reason": {"type": "string"}, }, required=["name", "slot", "reason"], ), ]) # Construct the LLM context with tools (replaces the bare LLMContext # from the previous section). context = LLMContext(tools=tools) user_aggregator, assistant_aggregator = LLMContextAggregatorPair(context) ``` ### How invocation works The LLM decides when to call a tool, based on the conversation and the tool's `description`. There is no fixed user phrase that maps to a tool. A user asking *is there anything Tuesday?* causes the LLM to call `check_availability` with `date="2026-05-12"`, the same as one asking *what slots are open this week?*. If a required parameter is missing, the LLM should ask the user a clarifying question rather than fill a placeholder, and call the tool once the answer arrives. That is why required arguments are useful: they push the LLM to gather data conversationally before triggering the side effect. ### Useful patterns Audible filler keeps the call from going silent during a tool's network round trip. The `calls` argument is a list of `FunctionCallFromLLM` entries with `function_name`, `tool_call_id`, and `arguments`, so you can pick the filler per tool: ```python @llm.event_handler("on_function_calls_started") async def on_function_calls_started(service, calls): for call in calls: if call.function_name == "check_availability": await tts.queue_frame(TTSSpeakFrame("Let me check the schedule.")) elif call.function_name == "book_appointment": await tts.queue_frame(TTSSpeakFrame("Booking that for you now.")) ``` ### When prompt rules stop being enough This is enough for a small bot, but two real problems show up as the dentist flow grows: * **Accidental writes.** Tools that change real state are easy to fire by accident. A system-prompt rule like *always read back the date and time before calling `book_appointment`* helps, but the LLM follows prompt rules unevenly. One bad turn and the booking goes through unconfirmed. * **More rules to enforce.** Requirements like *collect insurance before booking* or *urgent cases skip slot proposal* pile into the system prompt as natural-language instructions. The longer that prompt, the more often the LLM ignores parts of it. Pipecat Flows fixes both structurally. Each tool is scoped to a specific node, so `book_appointment` cannot be called until the conversation reaches the `confirm` node. Step ordering and branching live in Python instead of the prompt, so the LLM cannot skip them. ```python import os from dotenv import load_dotenv from pipecat.adapters.schemas.function_schema import FunctionSchema from pipecat.adapters.schemas.tools_schema import ToolsSchema from pipecat.frames.frames import LLMRunFrame, TTSSpeakFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineParams, PipelineTask from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport from pipecat.services.llm_service import FunctionCallParams from pipecat.services.openai.llm import OpenAILLMService from pipecat.services.soniox.stt import ( SonioxContextObject, SonioxContextGeneralItem, SonioxSTTService, ) from pipecat.services.soniox.tts import SonioxTTSService from pipecat.transcriptions.language import Language from pipecat.transports.base_transport import BaseTransport, TransportParams from pipecat.transports.daily.transport import DailyParams from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams load_dotenv(override=True) # Replace this with your real calendar or booking system. class DentalCalendar: booked: set[str] = {"2026-05-12T10:30"} async def find_slots(self, date: str) -> list[str]: all_slots = [f"{date}T{t}" for t in ("09:00", "10:30", "14:00", "15:30")] return [s for s in all_slots if s not in self.booked] async def book(self, name: str, slot: str, reason: str) -> str: # name and reason unused in mock self.booked.add(slot) return f"DENT-{abs(hash(slot)) % 10000:04d}" calendar = DentalCalendar() # Tool handlers can do anything Python can: API calls, database queries, # RAG lookups, file I/O. Here they hit the mock calendar above. async def check_availability(params: FunctionCallParams): slots = await calendar.find_slots(params.arguments["date"]) await params.result_callback({"slots": slots}) async def book_appointment(params: FunctionCallParams): cid = await calendar.book( name=params.arguments["name"], slot=params.arguments["slot"], reason=params.arguments["reason"], ) await params.result_callback({"confirmation_id": cid, "status": "booked"}) tools = ToolsSchema( standard_tools=[ FunctionSchema( name="check_availability", description=( "Look up open appointment slots. Call this whenever the patient " "asks about availability or mentions a preferred date." ), properties={ "date": {"type": "string", "description": "ISO date, e.g. 2026-05-12"}, }, required=["date"], ), FunctionSchema( name="book_appointment", description=( "Book a confirmed appointment. Only call after the patient has " "explicitly confirmed the date, time, and reason." ), properties={ "name": {"type": "string"}, "slot": {"type": "string", "description": "ISO datetime, e.g. 2026-05-12T10:30"}, "reason": {"type": "string"}, }, required=["name", "slot", "reason"], ), ] ) transport_params = { "daily": lambda: DailyParams(audio_in_enabled=True, audio_out_enabled=True), "twilio": lambda: FastAPIWebsocketParams(audio_in_enabled=True, audio_out_enabled=True), "webrtc": lambda: TransportParams(audio_in_enabled=True, audio_out_enabled=True), } async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( language_hints=[Language.EN], language_hints_strict=True, context=SonioxContextObject( general=[ SonioxContextGeneralItem(key="domain", value="Dental practice"), SonioxContextGeneralItem(key="topic", value="Booking an appointment"), ], terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], ), ), ) tts = SonioxTTSService(api_key=os.environ["SONIOX_API_KEY"]) llm = OpenAILLMService( api_key=os.environ["OPENAI_API_KEY"], settings=OpenAILLMService.Settings( system_instruction=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), ), ) llm.register_function("check_availability", check_availability) llm.register_function("book_appointment", book_appointment) @llm.event_handler("on_function_calls_started") async def on_function_calls_started(service, calls): for call in calls: if call.function_name == "check_availability": await tts.queue_frame(TTSSpeakFrame("Let me check the schedule.")) elif call.function_name == "book_appointment": await tts.queue_frame(TTSSpeakFrame("Booking that for you now.")) context = LLMContext(tools=tools) user_aggregator, assistant_aggregator = LLMContextAggregatorPair(context) pipeline = Pipeline( [ transport.input(), stt, user_aggregator, llm, tts, transport.output(), assistant_aggregator, ] ) task = PipelineTask( pipeline, params=PipelineParams(enable_metrics=True, enable_usage_metrics=True) ) @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): context.add_message( { "role": "developer", "content": "Greet the caller and ask how you can help.", } ) await task.queue_frames([LLMRunFrame()]) @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): await task.cancel() runner = PipelineRunner(handle_sigint=runner_args.handle_sigint) await runner.run(task) async def bot(runner_args: RunnerArguments): transport = await create_transport(runner_args, transport_params) await run_bot(transport, runner_args) if __name__ == "__main__": from pipecat.runner.run import main main() ``` ## Structuring with Pipecat Flows [Pipecat Flows](https://github.com/pipecat-ai/pipecat-flows) is a separate package that models a conversation as a graph of nodes. Each node has its own focused prompt and its own subset of tools. Each handler decides which node comes next. The LLM still phrases everything, but it cannot skip steps. ```bash pip install pipecat-ai-flows ``` ### The mental model A flow is a graph of **nodes**. At any moment, the bot is in exactly one node, and that node defines two things: what the LLM should be doing (its prompt) and which tools it is allowed to call. The LLM never sees tools from other nodes, so it cannot accidentally jump ahead and book an appointment while it is still collecting the patient's name. Transitions between nodes happen in code, not in the prompt. Each tool is wired to a Python **handler**, and that handler returns the next node along with the tool's result. The LLM phrases the conversation, but the handler decides where the conversation goes next. Branching becomes an `if` statement: send urgent cases to triage and everyone else to slot proposal. Flows does not replace the pipeline. It is a layer on top of the LLM service that swaps the prompt and the tool list whenever the conversation moves to a new node. A `FlowManager` object hooks into the LLM and the context aggregators, and you start the conversation by handing it the initial node. ### Handlers and schemas Each tool still needs a **handler** and a **schema**, the same as in the previous stage. Two things change: * Handlers in Flows return `tuple[result, next_node]` instead of calling a `result_callback`. The first element is what the LLM sees; the second element is the node the conversation moves to next. * Schemas use `FlowsFunctionSchema` instead of `FunctionSchema`. The shape is identical (`name`, `description`, `properties`, `required`), with one extra field, `handler`, that ties the schema to its Python function. Branching happens inside the handler. Pick the next node with normal Python, based on the LLM's arguments or external state: ```python # Branch on LLM args. async def collect_reason(args: FlowArgs): urgent = args.get("urgent", False) next_node = create_triage_node() if urgent else create_propose_slots_node() return {"reason": args["reason"], "urgent": urgent}, next_node # Branch on external state. async def propose_slots(args: FlowArgs): slots = await calendar.find_slots(args["preferred_date"]) if slots: return {"slots": slots}, create_confirm_node(slots) return {"slots": []}, create_no_availability_node(args["preferred_date"]) ``` Cycles work the same way. A handler that returns a node the conversation has already visited just sends the user back to that step. A schema looks the same as a regular `FunctionSchema` plus a `handler` reference: ```python reason_schema = FlowsFunctionSchema( name="collect_reason", description="Record the reason for the visit.", properties={ "reason": {"type": "string", "description": "e.g. cleaning, toothache, checkup"}, "urgent": {"type": "boolean", "description": "True if pain, swelling, or trauma."}, }, required=["reason"], handler=collect_reason, ) ``` The dentist flow has five handlers and five schemas in total. The full set is in the bot file at the end of this section. ### Nodes Each node-creator function returns a `NodeConfig` for one step. Parameters such as `name` or `slots` flow from one step to the next through these factories. The initial node is plain: ```python def create_initial_node() -> NodeConfig: return NodeConfig( name="greet", role_message=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), task_messages=[{ "role": "developer", "content": "Greet the caller and ask for their full name.", }], functions=[name_schema], ) ``` A later node accepts data from the previous step and bakes it into its prompt: ```python def create_reason_node(name: str) -> NodeConfig: return NodeConfig( name="reason", task_messages=[{ "role": "developer", "content": ( f"You now have the patient's name: {name}. Ask what brings " "them in. Set urgent=True if they mention pain, swelling, or " "an injury." ), }], functions=[reason_schema], ) ``` The dentist flow has seven nodes (`greet`, `reason`, `triage`, `propose_slots`, `confirm`, `no_availability`, `end`). Each one follows the same shape. The full set is in the bot file below. ### Wiring it into the pipeline The pipeline is the same as in stage 1. The two new pieces are a `FlowManager` built on top of the aggregator pair, and an `on_client_connected` that hands it the initial node: ```python flow_manager = FlowManager( task=task, llm=llm, context_aggregator=context_aggregator, transport=transport, ) @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): await flow_manager.initialize(create_initial_node()) ``` There are no `register_function` calls and no `tools` argument on the context. Flows manages the tool surface per node, so the LLM only sees `book_appointment` once the conversation reaches the `confirm` node. ### What this buys you * **Tool isolation.** `book_appointment` is not in the LLM's tool list during the `greet` node, so it cannot be invoked there. With a single prompt, that constraint depends on the LLM choosing to follow instructions. * **Deterministic transitions.** Step ordering is a Python expression in a handler, not a sentence in a prompt. The LLM still phrases the conversation, but it cannot skip steps. * **Branchable logic.** The `urgent` field routes to `triage` instead of `propose_slots` from the same handler. Adding a new branch is one extra `if` and one extra node. * **Cycles.** `no_availability` returns the patient to `propose_slots` until they pick an open day or end the call. Cycles are common in voice flows. ```python import os from datetime import date from typing import TypedDict from dotenv import load_dotenv from pipecat_flows import FlowArgs, FlowManager, FlowsFunctionSchema, NodeConfig from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineParams, PipelineTask from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.aggregators.llm_response_universal import LLMContextAggregatorPair from pipecat.runner.types import RunnerArguments from pipecat.runner.utils import create_transport from pipecat.services.openai.llm import OpenAILLMService from pipecat.services.soniox.stt import ( SonioxContextObject, SonioxContextGeneralItem, SonioxSTTService, ) from pipecat.services.soniox.tts import SonioxTTSService from pipecat.transcriptions.language import Language from pipecat.transports.base_transport import BaseTransport, TransportParams from pipecat.transports.daily.transport import DailyParams from pipecat.transports.websocket.fastapi import FastAPIWebsocketParams load_dotenv(override=True) # Replace this with your real calendar or booking system. class DentalCalendar: booked: set[str] = {"2026-05-12T10:30"} async def find_slots(self, date: str) -> list[str]: all_slots = [f"{date}T{t}" for t in ("09:00", "10:30", "14:00", "15:30")] return [s for s in all_slots if s not in self.booked] async def book(self, name: str, slot: str, reason: str) -> str: # name and reason unused in mock self.booked.add(slot) return f"DENT-{abs(hash(slot)) % 10000:04d}" calendar = DentalCalendar() class NameResult(TypedDict): name: str class ReasonResult(TypedDict): reason: str urgent: bool class SlotsResult(TypedDict): slots: list[str] class BookingResult(TypedDict): confirmation_id: str # Handlers: each returns (result, next_node). async def collect_name(args: FlowArgs) -> tuple[NameResult, NodeConfig]: return {"name": args["name"]}, create_reason_node(args["name"]) async def collect_reason(args: FlowArgs) -> tuple[ReasonResult, NodeConfig]: urgent = args.get("urgent", False) next_node = create_triage_node() if urgent else create_propose_slots_node() return {"reason": args["reason"], "urgent": urgent}, next_node async def propose_slots(args: FlowArgs) -> tuple[SlotsResult, NodeConfig]: slots = await calendar.find_slots(args["preferred_date"]) if slots: return {"slots": slots}, create_confirm_node(slots) return {"slots": []}, create_no_availability_node(args["preferred_date"]) async def book_appointment(args: FlowArgs) -> tuple[BookingResult, NodeConfig]: cid = await calendar.book(args["name"], args["slot"], args["reason"]) return {"confirmation_id": cid}, create_end_node(cid) async def end_conversation(args: FlowArgs) -> tuple[None, NodeConfig]: return None, create_end_node(None) # Schemas: a handler reference plus the same shape as FunctionSchema. name_schema = FlowsFunctionSchema( name="collect_name", description="Record the patient's full name once provided.", properties={"name": {"type": "string"}}, required=["name"], handler=collect_name, ) reason_schema = FlowsFunctionSchema( name="collect_reason", description="Record the reason for the visit.", properties={ "reason": {"type": "string", "description": "e.g. cleaning, toothache, checkup"}, "urgent": {"type": "boolean", "description": "True if pain, swelling, or trauma."}, }, required=["reason"], handler=collect_reason, ) propose_schema = FlowsFunctionSchema( name="propose_slots", description="Look up open appointment slots for the patient's preferred date.", properties={"preferred_date": {"type": "string", "description": "ISO date"}}, required=["preferred_date"], handler=propose_slots, ) book_schema = FlowsFunctionSchema( name="book_appointment", description="Book the confirmed appointment. Only after the patient has explicitly confirmed the slot.", properties={ "name": {"type": "string"}, "slot": {"type": "string"}, "reason": {"type": "string"}, }, required=["name", "slot", "reason"], handler=book_appointment, ) end_schema = FlowsFunctionSchema( name="end_conversation", description="End the call once the patient is satisfied.", properties={}, required=[], handler=end_conversation, ) # Nodes: one factory per step. def create_initial_node() -> NodeConfig: return NodeConfig( name="greet", role_message=( "You are a friendly receptionist at Bright Smile Dental. " "Keep replies short and natural. They will be spoken aloud." ), task_messages=[ { "role": "developer", "content": "Greet the caller and ask for their full name.", } ], functions=[name_schema], ) def create_reason_node(name: str) -> NodeConfig: return NodeConfig( name="reason", task_messages=[ { "role": "developer", "content": ( f"You now have the patient's name: {name}. Ask what brings " "them in. Set urgent=True if they mention pain, swelling, or " "an injury." ), } ], functions=[reason_schema], ) def create_triage_node() -> NodeConfig: today = date.today().isoformat() return NodeConfig( name="triage", task_messages=[ { "role": "developer", "content": ( "This is urgent. Tell the patient you are flagging it as " "urgent and will offer the earliest available slot. Then " f"call propose_slots with preferred_date={today}." ), } ], functions=[propose_schema], ) def create_propose_slots_node() -> NodeConfig: return NodeConfig( name="propose_slots", task_messages=[ { "role": "developer", "content": "Ask what date works best, then call propose_slots.", } ], functions=[propose_schema], ) def create_confirm_node(slots: list[str]) -> NodeConfig: slot_list = ", ".join(slots) return NodeConfig( name="confirm", task_messages=[ { "role": "developer", "content": ( f"Available slots: {slot_list}. Read them aloud, ask the " "patient to pick one, and read back the date and time before " "calling book_appointment." ), } ], functions=[book_schema], ) def create_no_availability_node(date: str) -> NodeConfig: return NodeConfig( name="no_availability", task_messages=[ { "role": "developer", "content": (f"No slots are open on {date}. Apologize and ask for another date."), } ], functions=[propose_schema, end_schema], ) def create_end_node(confirmation_id: str | None) -> NodeConfig: msg = ( f"Confirm booking ID {confirmation_id} and thank them." if confirmation_id else "Thank them politely and end the call." ) return NodeConfig( name="end", task_messages=[{"role": "developer", "content": msg}], post_actions=[{"type": "end_conversation"}], ) transport_params = { "daily": lambda: DailyParams(audio_in_enabled=True, audio_out_enabled=True), "twilio": lambda: FastAPIWebsocketParams(audio_in_enabled=True, audio_out_enabled=True), "webrtc": lambda: TransportParams(audio_in_enabled=True, audio_out_enabled=True), } async def run_bot(transport: BaseTransport, runner_args: RunnerArguments): stt = SonioxSTTService( api_key=os.environ["SONIOX_API_KEY"], vad_force_turn_endpoint=False, settings=SonioxSTTService.Settings( language_hints=[Language.EN], language_hints_strict=True, context=SonioxContextObject( general=[ SonioxContextGeneralItem(key="domain", value="Dental practice"), SonioxContextGeneralItem(key="topic", value="Booking an appointment"), ], terms=["Bright Smile Dental", "checkup", "cavity", "crown", "X-ray"], ), ), ) tts = SonioxTTSService(api_key=os.environ["SONIOX_API_KEY"]) llm = OpenAILLMService(api_key=os.environ["OPENAI_API_KEY"]) context_aggregator = LLMContextAggregatorPair(LLMContext()) pipeline = Pipeline( [ transport.input(), stt, context_aggregator.user(), llm, tts, transport.output(), context_aggregator.assistant(), ] ) task = PipelineTask( pipeline, params=PipelineParams(enable_metrics=True, enable_usage_metrics=True) ) flow_manager = FlowManager( task=task, llm=llm, context_aggregator=context_aggregator, transport=transport, ) @transport.event_handler("on_client_connected") async def on_client_connected(transport, client): await flow_manager.initialize(create_initial_node()) @transport.event_handler("on_client_disconnected") async def on_client_disconnected(transport, client): await task.cancel() runner = PipelineRunner(handle_sigint=runner_args.handle_sigint) await runner.run(task) async def bot(runner_args: RunnerArguments): transport = await create_transport(runner_args, transport_params) await run_bot(transport, runner_args) if __name__ == "__main__": from pipecat.runner.run import main main() ``` ## What to read next # Retell AI URL: /integrations/retell Use Soniox Speech-to-Text as the ASR provider for Retell AI voice agents to get accurate, multilingual, real-time transcription with code-switching on phone and web calls. import { LinkCards } from "@/components/link-card"; ## Overview [Retell AI](https://www.retellai.com/) is a platform for building, testing, and deploying voice AI agents that answer and make phone calls. Retell agents combine speech recognition (ASR), a large language model, and text-to-speech, while Retell handles telephony, turn-taking, and call orchestration. Soniox is available as a built-in ASR provider in Retell, delivering accurate real-time speech recognition across a broad range of languages, including support for code-switching within conversations. ## Set up Soniox in Retell Setup and configuration are documented by Retell: The Soniox ASR provider in Retell is built and maintained by Retell. For questions about Retell configuration, billing, or behavior, contact [Retell support](https://www.retellai.com/). # TanStack AI SDK URL: /integrations/tanstack-ai-sdk Soniox transcription adapter for the TanStack AI SDK. import Image from "next/image"; import { LinkCards } from "@/components/link-card"; ## Overview [TanStack AI](https://tanstack.com/ai) is a TypeScript toolkit for building AI applications. It provides a unified API that abstracts away the differences between various AI providers, allowing developers to switch models with just a few lines of code. This package (`@soniox/tanstack-ai-adapter`) implements the SDK's transcription adapter, enabling you to use Soniox's Speech-to-Text models directly within the standard TanStack AI workflow. ## Installation ```bash npm install @soniox/tanstack-ai-adapter ``` ## Authentication Set `SONIOX_API_KEY` in your environment or pass `apiKey` when creating the adapter. Get your API key from the [Soniox Console](https://console.soniox.com). ## Example ```ts import { generateTranscription } from '@tanstack/ai'; import { sonioxTranscription } from '@soniox/tanstack-ai-adapter'; const result = await generateTranscription({ adapter: sonioxTranscription('stt-async-v4'), audio: new URL( 'https://soniox.com/media/examples/coffee_shop.mp3', ), modelOptions: { enableLanguageIdentification: true, enableSpeakerDiarization: true, }, }); console.log(result.text); console.log(result.segments); // Timestamped segments with speaker info ``` ## Adapter configuration Use `createSonioxTranscription` to customize the adapter instance: ```ts import { createSonioxTranscription } from '@soniox/tanstack-ai-adapter'; const adapter = createSonioxTranscription('stt-async-v4', process.env.SONIOX_API_KEY!, { baseUrl: 'https://api.soniox.com', pollingIntervalMs: 1000, timeout: 180000, }); ``` Options: * `apiKey`: override `SONIOX_API_KEY` (required when using `createSonioxTranscription`). * `baseUrl`: custom API base URL. See list of regional API endpoints [here](/data-residency#regional-endpoints). Default is `https://api.soniox.com`. * `headers`: additional request headers. * `timeout`: transcription timeout in milliseconds. Default is 180000ms (3 minutes). * `pollingIntervalMs`: transcription polling interval in milliseconds. Default is 1000ms. ## Transcription options Per-request options are passed via `modelOptions`: ```ts const result = await generateTranscription({ adapter: sonioxTranscription('stt-async-v4'), audio, modelOptions: { languageHints: ['en', 'es'], enableLanguageIdentification: true, enableSpeakerDiarization: true, context: { terms: ['Soniox', 'TanStack'], }, }, }); ``` Available options: * `languageHints` - Array of ISO language codes to bias recognition. If you pass the TanStack `language` option, this adapter will merge it into `languageHints` for convenience. * `languageHintsStrict` - When true, rely more heavily on language hints (note: not supported by all models) * `enableLanguageIdentification` - Automatically detect spoken language * `enableSpeakerDiarization` - Identify and separate different speakers * `context` - Additional context to improve accuracy * `clientReferenceId` - Optional client-defined reference ID * `webhookUrl` - Webhook URL for transcription completion notifications * `webhookAuthHeaderName` - Webhook authentication header name * `webhookAuthHeaderValue` - Webhook authentication header value * `translation` - Translation configuration For more information on the available options, see the [Speech-to-Text API reference](/api-reference/stt/transcriptions/create_transcription). ## Accessing raw tokens When using translation or working with multilingual audio, you may need access to raw tokens with per-token language information and translation status. The adapter attaches a non-standard `providerMetadata` field at runtime: ```ts const result = await generateTranscription({ adapter: sonioxTranscription('stt-async-v4'), audio, modelOptions: { translation: { type: 'one_way', targetLanguage: 'es' }, }, }); // Access raw Soniox tokens with full metadata const rawTokens = (result as any).providerMetadata?.soniox?.tokens; if (rawTokens) { rawTokens.forEach((token) => { // token.text - token text // token.start_ms - start time in milliseconds // token.end_ms - end time in milliseconds // token.language - detected language for this token // token.translation_status - translation status (if translation enabled) // token.speaker - speaker identifier // token.confidence - confidence score }); } ``` **Note:** When using translation, the API returns both transcription tokens (original) and translation tokens. The `segments` array always includes only transcription tokens. To access translation tokens, filter by `translation_status === 'translation'`. # Telnyx URL: /integrations/telnyx Use Soniox Speech-to-Text and Text-to-Speech in Telnyx Voice AI Assistants, Voice API, and TeXML for accurate, multilingual, real-time voice agents and phone calls. import { LinkCards } from "@/components/link-card"; ## Overview [Telnyx](https://telnyx.com/) is a communications platform with its own global carrier network, offering programmable voice, messaging, and SIP trunking. Its **Voice AI** products, including no-code AI Assistants, the Voice API, and TeXML, let you build voice agents that answer and make phone calls with low latency. Soniox is available on Telnyx as both a **speech-to-text** and a **text-to-speech** provider, so you can use Soniox for both listening to and speaking with callers in your Telnyx voice agents. ## Services The Soniox integration in Telnyx is built and maintained by Telnyx. For questions about Telnyx configuration, billing, or integration behavior, contact [Telnyx support](https://telnyx.com/). # Speech-to-Text URL: /integrations/telnyx/stt Use Soniox real-time Speech-to-Text as the transcription provider in Telnyx Voice AI Assistants, WebSocket streaming, and the Voice API. import { LinkCards } from "@/components/link-card"; ## Overview Soniox is available as a real-time speech-to-text provider in Telnyx Voice AI, enabling accurate transcription through AI Assistants, WebSocket, or the Voice API, with automatic language detection, interim results, end-of-turn detection, and context-aware recognition of domain-specific terms. ## Telnyx documentation The Soniox integration in Telnyx is built and maintained by Telnyx. For questions about Telnyx configuration, billing, or integration behavior, contact [Telnyx support](https://telnyx.com/). # Text-to-Speech URL: /integrations/telnyx/tts Use Soniox Text-to-Speech voices with Telnyx Voice AI Assistants, TTS APIs, Call Control, and TeXML for natural, multilingual voice experiences. import { LinkCards } from "@/components/link-card"; ## Overview Soniox is available as a text-to-speech provider in Telnyx Voice AI, delivering low-latency streaming, precise alphanumeric pronunciation, and seamless multilingual speech with the same voice across all supported languages, including language mixing. ## Telnyx documentation The Soniox integration in Telnyx is built and maintained by Telnyx. For questions about Telnyx configuration, billing, or integration behavior, contact [Telnyx support](https://telnyx.com/). # Twilio URL: /integrations/twilio Stream Twilio call audio to Soniox Speech-to-Text API and get real-time transcriptions. import Image from "next/image"; import { LinkCards } from "@/components/link-card"; ## Overview This guide demonstrates how to stream live Twilio call audio to the Soniox Speech-to-Text API and receive real-time transcription via WebSockets. If you want to see a complete example, check out this GitHub repository: ## Preparation ### Create a Twilio account To get started, you'll need a Twilio account. If you don't have one, you can [sign up](https://www.twilio.com/try-twilio). You will also need two phone numbers to test the integration: * One from a phone number you own, which needs to be verified by Twilio. * The other one is a Twilio-owned phone number that you can use for testing. ### Get your Soniox API key To use Soniox Speech-to-Text API in your application, you'll need to obtain an API key. You can get one by signing up at [Soniox Console](https://console.soniox.com/). ## Running the example ### Clone the repository Clone the repository and install the dependencies: ```bash git clone https://github.com/soniox/soniox-twilio-realtime-transcription.git cd soniox-twilio-realtime-transcription pip install -r requirements.txt ``` ### Configure server environment Copy the `.env.example` file to `.env` and update the values with your Twilio account credentials and Soniox API key: ```bash cp .env.example .env ``` ### Run the server and expose it to Twilio Run the server: ```bash python server.py ``` This will start the server and listen for incoming Twilio calls. You will specify where phone call recording is streamed later. To expose the server to Twilio, you can use [ngrok](https://ngrok.com/). ```bash ngrok http 5000 ``` Note the forwarding URL that ngrok provides. It should look like `https://.ngrok.io` or `https://.ngrok-free.app`. ### Run the client Edit `client.html` and set `WEBSOCKET_URL` to your ngrok URL with `/client` at the end, e.g. `wss://xxxxx.ngrok.io/client`. Open `client.html` in your browser to view live call transcriptions. ### Start a Twilio call You can configure Twilio calls with `TwiML Bin` files. More information about streaming can be found in the [Twilio documentation](https://www.twilio.com/docs/voice/twiml/stream). Here is an example `TwiML Bin` file calls you phone number and streams the audio to your websocket server: ```xml USER_PHONE_NUMBER "Hello, this is a test call. How are you?" "Thank you, bye!" ``` To start, we recommend using the provided `call_me.py` script to start a Twilio call. Simply set the following environment variables: * `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` (from Twilio) * `TWILIO_PHONE_NUMBER` (your Twilio number, rented on Twilio) * `WEBSOCKET_URL` with your ngrok URL with `/twilio` at the end, e.g. `wss://xxxxx.ngrok.io/twilio`. * `USER_PHONE_NUMBER` with your Twilio-verified phone number. ```bash python call_me.py ``` You should hear a voice message saying "Hello, this is a test call. How are you?" and then a message saying "Thank you, bye!". Simultaneously, you should see the transcription in the browser. # Vapi URL: /integrations/vapi Use Soniox Speech-to-Text as the transcriber for Vapi voice AI agents to get low-latency, multilingual, real-time transcription on phone and web calls. import { LinkCards } from "@/components/link-card"; ## Overview [Vapi](https://vapi.ai/) is a developer platform for building, testing, and deploying voice AI agents. A Vapi assistant handles phone and web calls by combining a speech-to-text transcriber, a large language model, and a text-to-speech voice, while Vapi manages telephony, turn-taking, and call orchestration. Soniox is available as a built-in transcriber provider in Vapi, giving assistants low-latency, multilingual real-time speech recognition with automatic language detection and mid-conversation language switching. ## Set up Soniox in Vapi Setup and configuration are documented by Vapi: The Soniox transcriber in Vapi is built and maintained by Vapi. For questions about Vapi configuration, billing, or behavior, contact [Vapi support](https://vapi.ai/). # Vercel AI SDK URL: /integrations/vercel-ai-sdk Soniox transcription provider for the Vercel AI SDK. import Image from "next/image"; import { LinkCards } from "@/components/link-card"; ## Overview [Vercel AI SDK](https://sdk.vercel.ai/) is a TypeScript toolkit for building AI applications. It provides a unified API that abstracts away the differences between various AI providers, allowing developers to switch models with just a few lines of code. The [`@soniox/vercel-ai-sdk-provider`](https://www.npmjs.com/package/@soniox/vercel-ai-sdk-provider) package implements the SDK's Transcription Interface, enabling you to use Soniox's Speech-to-Text models directly within the standard Vercel AI workflow. Learn more about the Soniox provider in the [Vercel AI SDK Community Providers documentation](https://ai-sdk.dev/providers/community-providers/soniox). ## Installation ```bash npm install @soniox/vercel-ai-sdk-provider ``` ## Authentication Set `SONIOX_API_KEY` in your environment or pass `apiKey` when creating the provider. ## Example ```ts import { soniox } from '@soniox/vercel-ai-sdk-provider'; import { experimental_transcribe as transcribe } from 'ai'; const { text } = await transcribe({ model: soniox.transcription('stt-async-v4'), audio: new URL( 'https://soniox.com/media/examples/coffee_shop.mp3', ), }); ``` ## Provider options Use `createSoniox` to customize the provider instance: ```ts import { createSoniox } from '@soniox/vercel-ai-sdk-provider'; const soniox = createSoniox({ apiKey: process.env.SONIOX_API_KEY, apiBaseUrl: 'https://api.soniox.com', }); ``` Options: * `apiKey`: override `SONIOX_API_KEY`. * `apiBaseUrl`: custom API base URL. See list of regional API endpoints [here](/data-residency#regional-endpoints). * `headers`: additional request headers. * `fetch`: custom fetch implementation. * `pollingIntervalMs`: transcription polling interval in milliseconds. Default is 1000ms. ## Transcription options Per-request options are passed via `providerOptions`: ```ts const { text } = await transcribe({ model: soniox.transcription('stt-async-v4'), audio, providerOptions: { soniox: { languageHints: ['en', 'es'], enableLanguageIdentification: true, enableSpeakerDiarization: true, context: { terms: ["Soniox", "Vercel"] }, }, }, }); ``` Available options: * `languageHints` - Array of ISO language codes to bias recognition * `languageHintsStrict` - When true, rely more heavily on language hints (note: not supported by all models) * `enableLanguageIdentification` - Automatically detect spoken language * `enableSpeakerDiarization` - Identify and separate different speakers * `context` - Additional context to improve accuracy * `clientReferenceId` - Optional client-defined reference ID * `webhookUrl` - Webhook URL for transcription completion notifications * `webhookAuthHeaderName` - Webhook authentication header name * `webhookAuthHeaderValue` - Webhook authentication header value * `translation` - Translation configuration For more information on the available options, see the [Speech-to-Text API reference](/api-reference/stt/transcriptions/create_transcription). # SDKs URL: /sdk Official Soniox SDKs for Speech-to-Text and Text-to-Speech across Python, Node.js, browser, React, and React Native. import { LinkCards } from "@/components/link-card"; Soniox SDKs give you fully typed access to our STT and TTS REST and real-time APIs across the languages and runtimes you already use. Pick the SDK that matches your stack to get started quickly with transcription, translation, and speech generation, without writing low-level WebSocket or REST plumbing. # Node SDK URL: /sdk/node-SDK Build speech-to-text and text-to-speech workflows in Node with async and real-time APIs. The Soniox [Node SDK](https://github.com/soniox/soniox-js) gives you fully typed access to our Async and Real-time Speech-to-Text APIs and Text-to-Speech APIs. ## Quickstart ### Install Install via your preferred package manager: ```bash tab npm install @soniox/node ``` ```bash tab yarn add @soniox/node ``` ```bash tab pnpm add @soniox/node ``` ```bash tab bun add @soniox/node ``` ### Set your API key ```sh title="Terminal" export SONIOX_API_KEY= ``` Create a [Soniox account](https://console.soniox.com/signup) and log in to the [Console](https://console.soniox.com) to get your API key. See all available environment variables in the [SDK reference](/sdk/node-SDK/reference#environment-variables). ### Environment variables The client reads the following env vars as fallbacks when the matching client option is not provided: | Variable | Maps to option | | --------------------- | ---------------------- | | `SONIOX_API_KEY` | `api_key` | | `SONIOX_REGION` | `region` | | `SONIOX_BASE_DOMAIN` | `base_domain` | | `SONIOX_API_BASE_URL` | `base_url` | | `SONIOX_WS_URL` | `realtime.ws_base_url` | | `SONIOX_TTS_API_URL` | `tts_api_url` | | `SONIOX_TTS_WS_URL` | `realtime.tts_ws_url` | Resolution precedence: explicit option → env var → `base_domain` → `region` → US root default. `region` is shorthand for `base_domain: '{region}.soniox.com'`, so setting it resolves every host family (`api.*`, `stt-rt.*`, `tts-rt.*`) to the regional variant. See [Full SDK reference → Environment variables](/sdk/node-SDK/reference#environment-variables) for the full table and notes. ### Client options The client also accepts options for selecting a regional endpoint or overriding individual service URLs. All fields are optional — see [`SonioxNodeClientOptions`](/sdk/node-SDK/reference/types#sonioxnodeclientoptions) for the full type. ```ts import { SonioxNodeClient } from "@soniox/node"; const client = new SonioxNodeClient({ api_key: process.env.SONIOX_API_KEY, // Shorthand for selecting a regional deployment. // Valid values: 'eu' | 'jp' | 'in'. Leave undefined for the US (no region prefix). region: "eu", // Or override individual service URLs directly: // base_url: 'https://api.eu.soniox.com', // REST API // tts_api_url: 'https://tts-rt.eu.soniox.com', // TTS REST // realtime: { // ws_base_url: 'wss://stt-rt.eu.soniox.com/transcribe-websocket', // tts_ws_url: 'wss://tts-rt.eu.soniox.com/tts-websocket', // }, }); ``` ### Create your first real-time session ```ts import { SonioxNodeClient } from "@soniox/node"; const stream = await createFakeAudioStream(); // Create a Soniox client // The API key is read from the SONIOX_API_KEY environment variable. const client = new SonioxNodeClient(); // Create a real-time session const session = client.realtime.stt({ model: "stt-rt-v5", }); // Listen for transcription results session.on("result", (result) => { const text = result.tokens.map((t) => t.text).join(""); if (text) console.log(text); }); // Listen for errors session.on("error", (err) => console.error("Error:", err)); // Connect to Soniox and stream audio await session.connect(); // Stream audio in chunks and wait for the session to finish. // The server auto-detects common audio formats (e.g. mp3). await session.sendStream(stream, { pace_ms: 60, // Throttle sending by 60 ms per chunk to simulate a live source finish: true, // Signal end of audio and wait for remaining results }); // Demo helper: fetch an MP3 and return its body as an async-iterable stream. // In a real app you'd stream audio from a microphone or other live source. async function createFakeAudioStream() { const res = await fetch("https://soniox.com/media/examples/coffee_shop.mp3"); if (!res.ok) throw new Error(`Request failed: ${res.status} ${res.statusText}`); if (!res.body) throw new Error("No response body"); return res.body; } ``` Learn more about [Real-time transcription](/sdk/node-SDK/stt/realtime-transcription). ### Create your first async transcription ```ts import { SonioxNodeClient } from '@soniox/node'; import { readFile } from 'node:fs/promises'; const audio = await readFile('audio.mp3'); const client = new SonioxNodeClient(); const transcription = await client.stt.transcribe({ model: 'stt-async-v5', file: audio, filename: 'audio.mp3', wait: true, }); console.log(transcription.transcript?.text); ``` Learn more about [Async transcription](/sdk/node-SDK/stt/async-transcription). ### Generate your first speech ```ts import { SonioxNodeClient } from "@soniox/node"; const client = new SonioxNodeClient(); const bytesWritten = await client.tts.generateToFile("hello.wav", { text: "Hello from Soniox text-to-speech.", voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "wav", }); console.log(`Wrote ${bytesWritten} bytes`); ``` Learn more about [REST speech generation](/sdk/node-SDK/tts/rest-speech-generation) and [Real-time speech generation](/sdk/node-SDK/tts/realtime-speech-generation). ## Next steps * [Real-time transcription](/sdk/node-SDK/stt/realtime-transcription) * [Async transcription](/sdk/node-SDK/stt/async-transcription) * [Real-time speech generation](/sdk/node-SDK/tts/realtime-speech-generation) * [REST speech generation](/sdk/node-SDK/tts/rest-speech-generation) * [Webhooks](/sdk/node-SDK/stt/webhooks) * [Files and models](/sdk/node-SDK/stt/files) * [Full SDK reference](/sdk/node-SDK/reference) ## Package links * [GitHub repository](https://github.com/soniox/soniox-js) * [NPM package](https://www.npmjs.com/package/@soniox/node) # Classes URL: /sdk/node-SDK/reference/classes Soniox Node SDK — Class Reference ## SonioxNodeClient Soniox Node Client
### Example ```typescript import { SonioxNodeClient } from '@soniox/node'; // Default (US) region const client = new SonioxNodeClient({ api_key: 'your-api-key' }); // EU region const client = new SonioxNodeClient({ api_key: 'your-api-key', region: 'eu' }); // REST TTS const audio = await client.tts.generate({ text: 'Hello', voice: 'Adrian', language: 'en', }); // WebSocket TTS const stream = await client.realtime.tts({ model: 'tts-rt-v2', voice: 'Adrian', language: 'en', audio_format: 'wav', }); ``` ### Constructor ```ts new SonioxNodeClient(options): SonioxNodeClient; ``` **Parameters** | Parameter | Type | | --------- | ---------------------------------------------------------- | | `options` | [`SonioxNodeClientOptions`](types#sonioxnodeclientoptions) | **Returns** `SonioxNodeClient` ### Properties | Property | Type | | ------------------- | ------------------------------------------------------------------ | | `auth` | [`SonioxAuthAPI`](classes#sonioxauthapi) | | `concurrencyLimits` | [`SonioxConcurrencyLimitsAPI`](classes#sonioxconcurrencylimitsapi) | | `files` | [`SonioxFilesAPI`](classes#sonioxfilesapi) | | `models` | [`SonioxModelsAPI`](classes#sonioxmodelsapi) | | `realtime` | [`SonioxRealtimeApi`](classes#sonioxrealtimeapi) | | `stt` | [`SonioxSttApi`](classes#sonioxsttapi) | | `tts` | [`SonioxTtsApi`](classes#sonioxttsapi) | | `usageLogs` | [`SonioxUsageLogsAPI`](classes#sonioxusagelogsapi) | | `webhooks` | [`SonioxWebhooksAPI`](classes#sonioxwebhooksapi) | *** ## SonioxFilesAPI ### count() ```ts count(options): Promise; ``` Returns the total number of files, split by source. **Parameters** | Parameter | Type | Description | | ----------------- | ------------------------------ | --------------------------------- | | `options` | \{ `signal?`: `AbortSignal`; } | Optional cancellation parameters. | | `options.signal?` | `AbortSignal` | - | **Returns** `Promise`\<[`FilesCountResponse`](types#filescountresponse)> Total file counts for Playground, Public API, and all sources. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const counts = await client.files.count(); console.log(counts.total); ``` *** ### delete() ```ts delete(file, signal?): Promise; ``` Permanently deletes a file. This operation is idempotent - succeeds even if the file doesn't exist. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------- | --------------------------------------------- | | `file` | [`FileIdentifier`](types#fileidentifier) | The UUID of the file or a SonioxFile instance | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript // Delete by ID await client.files.delete('550e8400-e29b-41d4-a716-446655440000'); // Or delete a file instance const file = await client.files.get('550e8400-e29b-41d4-a716-446655440000'); if (file) { await client.files.delete(file); } // Or just use the instance method await file.delete(); ``` *** ### delete\_all() ```ts delete_all(options): Promise; ``` Permanently deletes all uploaded files. Iterates through all pages of files and deletes each one. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------------ | -------------------------------------- | | `options` | [`DeleteAllFilesOptions`](types#deleteallfilesoptions) | Optional signal and progress callback. | **Returns** `Promise`\<`void`> The number of files deleted. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` If the operation is aborted via signal. **Example** ```typescript // Delete all files await client.files.delete_all(); console.log(`Deleted all files.`); // With cancellation const controller = new AbortController(); await client.files.delete_all({ signal: controller.signal }); ``` *** ### get() ```ts get(file, signal?): Promise; ``` Retrieve metadata for an uploaded file. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------- | --------------------------------------------- | | `file` | [`FileIdentifier`](types#fileidentifier) | The UUID of the file or a SonioxFile instance | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation | **Returns** `Promise`\<[`SonioxFile`](classes#sonioxfile) | `null`> The file instance, or null if not found **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript const file = await client.files.get('550e8400-e29b-41d4-a716-446655440000'); if (file) { console.log(file.filename, file.size); } ``` *** ### list() ```ts list(options): Promise; ``` Retrieves list of uploaded files The returned result is async iterable - use `for await...of` **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------- | ----------------------------------------------- | | `options` | [`ListFilesOptions`](types#listfilesoptions) | Optional pagination and cancellation parameters | **Returns** `Promise`\<[`FileListResult`](classes#filelistresult)> FileListResult **Throws** [SonioxHttpError](classes#sonioxhttperror) **Example** ```typescript const result = await client.files.list(); // Automatic paging - iterates through ALL files across all pages for await (const file of result) { console.log(file.filename, file.size); } // Or access just the first page for (const file of result.files) { console.log(file.filename); } // Check if there are more pages if (result.isPaged()) { console.log('More pages available'); } // Manual paging using cursor const page1 = await client.files.list({ limit: 10 }); if (page1.next_page_cursor) { const page2 = await client.files.list({ cursor: page1.next_page_cursor }); } // With cancellation const controller = new AbortController(); const result = await client.files.list({ signal: controller.signal }); ``` *** ### upload() ```ts upload(file, options): Promise; ``` Uploads a file to Soniox for transcription **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------- | ------------------------------------------- | | `file` | [`UploadFileInput`](types#uploadfileinput) | Buffer, Uint8Array, Blob, or ReadableStream | | `options` | [`UploadFileOptions`](types#uploadfileoptions) | Upload options | **Returns** `Promise`\<[`SonioxFile`](classes#sonioxfile)> The uploaded file metadata **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors **Throws** `Error` On validation errors (file too large, invalid input) **Examples** ```typescript import * as fs from 'node:fs'; const buffer = await fs.promises.readFile('/path/to/audio.mp3'); const file = await client.files.upload(buffer, { filename: 'audio.mp3' }); ``` ```typescript const file = await client.files.upload(Bun.file('/path/to/audio.mp3')); ``` ```typescript const file = await client.files.upload(buffer, { filename: 'audio.mp3', client_reference_id: 'order-12345', }); ``` ```typescript const controller = new AbortController(); setTimeout(() => controller.abort(), 30000); const file = await client.files.upload(buffer, { filename: 'audio.mp3', signal: controller.signal, }); ``` *** ## SonioxSttApi ### count() ```ts count(signal?): Promise; ``` Returns the total number of transcriptions, split by request scope. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ---------------------------------------------- | | `signal?` | `AbortSignal` | Optional AbortSignal for request cancellation. | **Returns** `Promise`\<[`TranscriptionsCountResponse`](types#transcriptionscountresponse)> Total transcription counts for Playground, Public API, and all scopes. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const counts = await client.stt.count(); console.log(counts.total); ``` *** ### create() ```ts create(options, signal?): Promise; ``` Creates a new transcription from audio\_url or file\_id **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------------------------- | ------------------------------------------------------- | | `options` | [`CreateTranscriptionOptions`](types#createtranscriptionoptions) | Transcription options including model and audio source. | | `signal?` | `AbortSignal` | - | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription)> The created transcription. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript // Transcribe from URL const transcription = await client.stt.create({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', }); // Transcribe from uploaded file const file = await client.files.upload(buffer); const transcription = await client.stt.create({ model: 'stt-async-v5', file_id: file.id, }); // With speaker diarization const transcription = await client.stt.create({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', enable_speaker_diarization: true, }); ``` *** ### delete() ```ts delete(id, signal?): Promise; ``` Permanently deletes a transcription. This operation is idempotent - succeeds even if the transcription doesn't exist. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------------------- | --------------------------------------------------------------- | | `id` | [`TranscriptionIdentifier`](types#transcriptionidentifier) | The UUID of the transcription or a SonioxTranscription instance | | `signal?` | `AbortSignal` | - | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript // Delete by ID await client.stt.delete('550e8400-e29b-41d4-a716-446655440000'); // Or delete a transcription instance const transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); if (transcription) { await client.stt.delete(transcription); } ``` *** ### delete\_all() ```ts delete_all(options): Promise; ``` Permanently deletes all transcriptions. Iterates through all pages of transcriptions and deletes each one. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------------------------------ | ---------------- | | `options` | [`DeleteAllTranscriptionsOptions`](types#deletealltranscriptionsoptions) | Optional signal. | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` If the operation is aborted via signal. **Example** ```typescript // Delete all transcriptions await client.stt.delete_all(); console.log(`Deleted all transcriptions.`); // With cancellation const controller = new AbortController(); await client.stt.delete_all({ signal: controller.signal }); ``` *** ### destroy() ```ts destroy(id): Promise; ``` Permanently deletes a transcription and its associated file (if any). This operation is idempotent - succeeds even if resources don't exist. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------------------- | --------------------------------------------------------------- | | `id` | [`TranscriptionIdentifier`](types#transcriptionidentifier) | The UUID of the transcription or a SonioxTranscription instance | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript // Clean up both transcription and uploaded file const transcription = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, wait: true, }); // ... use transcription ... await client.stt.destroy(transcription); // Deletes both // Or by ID await client.stt.destroy('550e8400-e29b-41d4-a716-446655440000'); ``` *** ### destroy\_all() ```ts destroy_all(options): Promise; ``` Permanently deletes all transcriptions and their associated files. Iterates through all pages of transcriptions and calls [destroy](#destroy) on each one, removing both the transcription and its uploaded file. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------------------------------ | -------------------------------------- | | `options` | [`DeleteAllTranscriptionsOptions`](types#deletealltranscriptionsoptions) | Optional signal and progress callback. | **Returns** `Promise`\<`void`> The number of transcriptions destroyed. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` If the operation is aborted via signal. **Example** ```typescript // Destroy all transcriptions and their files await client.stt.destroy_all(); console.log(`Destroyed all transcriptions and their files.`); // With cancellation const controller = new AbortController(); await client.stt.destroy_all({ signal: controller.signal }); ``` *** ### get() ```ts get(id, signal?): Promise; ``` Retrieves a transcription by ID **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------------------- | ---------------------------------------------------------------- | | `id` | [`TranscriptionIdentifier`](types#transcriptionidentifier) | The UUID of the transcription or a SonioxTranscription instance. | | `signal?` | `AbortSignal` | - | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription) | `null`> The transcription, or null if not found. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404). **Example** ```typescript const transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); if (transcription) { console.log(transcription.status, transcription.model); } ``` *** ### getTranscript() ```ts getTranscript(id, signal?): Promise; ``` Retrieves the full transcript text and tokens for a completed transcription. Only available for successfully completed transcriptions. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------------------- | --------------------------------------------------------------- | | `id` | [`TranscriptionIdentifier`](types#transcriptionidentifier) | The UUID of the transcription or a SonioxTranscription instance | | `signal?` | `AbortSignal` | - | **Returns** `Promise`\<[`SonioxTranscript`](classes#sonioxtranscript) | `null`> The transcript with text and detailed tokens, or null if not found **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript const transcript = await client.stt.getTranscript('550e8400-e29b-41d4-a716-446655440000'); if (transcript) { console.log(transcript.text); for (const token of transcript.tokens) { console.log(token.text, token.start_ms, token.end_ms, token.confidence); } } ``` *** ### list() ```ts list(options, signal?): Promise; ``` Retrieves list of transcriptions The returned result is async iterable - use `for await...of` to iterate through all pages **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------------------------- | ------------------------------------------ | | `options` | [`ListTranscriptionsOptions`](types#listtranscriptionsoptions) | Optional pagination and filter parameters. | | `signal?` | `AbortSignal` | - | **Returns** `Promise`\<[`TranscriptionListResult`](classes#transcriptionlistresult)> TranscriptionListResult with async iteration support. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const result = await client.stt.list(); // Automatic paging - iterates through ALL transcriptions across all pages for await (const transcription of result) { console.log(transcription.id, transcription.status); } // Or access just the first page for (const transcription of result.transcriptions) { console.log(transcription.id); } // Check if there are more pages if (result.isPaged()) { console.log('More pages available'); } ``` *** ### transcribe() ```ts transcribe(options): Promise; ``` Unified transcribe method - supports direct file upload When `file` is provided, uploads it first then creates a transcription When `wait: true`, waits for completion before returning When `cleanup` is specified (requires `wait: true`), cleans up resources after completion or on error/timeout **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------- | -------------------------------------------------------------------- | | `options` | [`TranscribeOptions`](types#transcribeoptions) | Transcribe options including model, audio source, and wait settings. | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription)> The transcription (completed if wait=true, otherwise in queued/processing state). **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` On validation errors or wait timeout. **Example** ```typescript // Transcribe from URL and wait for completion const result = await client.stt.transcribe({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', wait: true, }); // Upload file and transcribe in one call const result = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, // or Blob, ReadableStream filename: 'meeting.mp3', enable_speaker_diarization: true, wait: true, }); // With wait progress callback const result = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, wait: true, wait_options: { interval_ms: 2000, on_status_change: (status) => console.log(`Status: ${status}`), }, }); // Auto-cleanup uploaded file after transcription const result = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, wait: true, cleanup: ['file'], // Deletes uploaded file, keeps transcription record }); // Auto-cleanup everything after transcription const result = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, wait: true, cleanup: ['file', 'transcription'], // Deletes both file and transcription record }); ``` *** ### transcribeFromFile() ```ts transcribeFromFile(file, options): Promise; ``` Wrapper to transcribe from raw file data. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------------------------- | ------------------------------------------- | | `file` | [`UploadFileInput`](types#uploadfileinput) | Buffer, Uint8Array, Blob, or ReadableStream | | `options` | [`TranscribeFromFileOptions`](types#transcribefromfileoptions) | Transcription options (excluding file) | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription)> The transcription (completed if wait=true, otherwise in queued/processing state). *** ### transcribeFromFileId() ```ts transcribeFromFileId(file_id, options): Promise; ``` Wrapper to transcribe from an uploaded file ID. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------------------------ | ------------------------------------------ | | `file_id` | `string` | ID of a previously uploaded file | | `options` | [`TranscribeFromFileIdOptions`](types#transcribefromfileidoptions) | Transcription options (excluding file\_id) | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription)> The transcription (completed if wait=true, otherwise in queued/processing state). *** ### transcribeFromUrl() ```ts transcribeFromUrl(audio_url, options): Promise; ``` Wrapper to transcribe from a URL. **Parameters** | Parameter | Type | Description | | ----------- | ------------------------------------------------------------ | -------------------------------------------- | | `audio_url` | `string` | Publicly accessible audio URL | | `options` | [`TranscribeFromUrlOptions`](types#transcribefromurloptions) | Transcription options (excluding audio\_url) | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription)> The transcription (completed if wait=true, otherwise in queued/processing state). *** ### translate() ```ts translate(options): Promise; ``` Starts a translation job. Sugar around [SonioxSttApi.transcribe](#transcribe): configures translation from the supplied [TranslateMode](types#translatemode) (`{ to }`, `{ to, from }`, or `{ between }`) and returns a [SonioxTranslationJob](classes#sonioxtranslationjob). With `wait: true`, waits for completion before returning, mirroring [SonioxSttApi.transcribe](#transcribe). Method-owned fields (cannot be set by the caller): * `translation` — derived from `to` / `between`. * `language_hints` + `language_hints_strict: true` — derived from `from` / `between`. * `enable_language_identification: true` — always. The reshape step relies on every token carrying a `language` field to group originals with their translations. * `fetch_transcript` — derived from `fetch_translation` when `wait=true`. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------- | --------------------------------------------- | | `options` | [`TranslateOptions`](types#translateoptions) | Mode, audio source, and pass-through options. | **Returns** `Promise`\<[`SonioxTranslationJob`](classes#sonioxtranslationjob)> The translation job. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` On validation errors or wait timeout. **Example** ```typescript // One-way: detect any source language, translate to Spanish. const job = await client.stt.translate({ audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', to: 'es', }); const completed = await job.wait(); const result = await completed.getTranslation(); console.log(result?.translation_text); // One-way with explicit source language. const explicitJob = await client.stt.translate({ file: buffer, filename: 'meeting.mp3', from: 'en', to: 'es', wait: true, }); console.log(explicitJob.translation?.translation_text); // Two-way: bidirectional translation between two languages. const twoWayJob = await client.stt.translate({ audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', between: ['en', 'es'], enable_speaker_diarization: true, wait: true, }); for (const seg of twoWayJob.translation?.segments ?? []) { console.log(`[${seg.from}] ${seg.original_text}`); if (seg.translation_text) { console.log(` → [${seg.to}] ${seg.translation_text}`); } } ``` *** ### wait() ```ts wait(id, options?): Promise; ``` Waits for a transcription to complete **Parameters** | Parameter | Type | Description | | ---------- | ---------------------------------------------------------- | ---------------------------------------------------------------- | | `id` | [`TranscriptionIdentifier`](types#transcriptionidentifier) | The UUID of the transcription or a SonioxTranscription instance. | | `options?` | [`WaitOptions`](types#waitoptions) | Wait options including polling interval, timeout, and callbacks. | **Returns** `Promise`\<[`SonioxTranscription`](classes#sonioxtranscription)> The completed or errored transcription. **Throws** `Error` If the wait times out or is aborted. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const completed = await client.stt.wait('550e8400-e29b-41d4-a716-446655440000'); // With progress callback const completed = await client.stt.wait('id', { interval_ms: 2000, on_status_change: (status) => console.log(`Status: ${status}`), }); ``` *** ## SonioxModelsAPI ### list() ```ts list(signal?): Promise; ``` List of available models and their attributes. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ------------------------------------- | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation | **Returns** `Promise`\<[`SonioxModel`](types#sonioxmodel)\[]> List of available models and their attributes. **See** [https://soniox.com/docs/stt/api-reference/models/get\_models](https://soniox.com/docs/stt/api-reference/models/get_models) *** ## SonioxWebhooksAPI Webhook utilities API accessible via client.webhooks Provides methods for handling incoming Soniox webhook requests. When used via the client, results include lazy fetch helpers for transcripts. ### getAuthFromEnv() ```ts getAuthFromEnv(): WebhookAuthConfig | undefined; ``` Get webhook authentication configuration from environment variables. Reads `SONIOX_API_WEBHOOK_HEADER` and `SONIOX_API_WEBHOOK_SECRET` environment variables. Returns undefined if either variable is not set (both are required for authentication). **Returns** [`WebhookAuthConfig`](types#webhookauthconfig) | `undefined` *** ### handle() ```ts handle(options): WebhookHandlerResultWithFetch; ``` Framework-agnostic webhook handler **Parameters** | Parameter | Type | | --------- | ---------------------------------------------------- | | `options` | [`HandleWebhookOptions`](types#handlewebhookoptions) | **Returns** [`WebhookHandlerResultWithFetch`](types#webhookhandlerresultwithfetch) *** ### handleExpress() ```ts handleExpress(req, auth?): WebhookHandlerResultWithFetch; ``` Handle a webhook from an Express-like request **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `req` | [`ExpressLikeRequest`](types#expresslikerequest) | | `auth?` | [`WebhookAuthConfig`](types#webhookauthconfig) | **Returns** [`WebhookHandlerResultWithFetch`](types#webhookhandlerresultwithfetch) **Example** ```typescript app.post('/webhook', async (req, res) => { const result = soniox.webhooks.handleExpress(req); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } res.status(result.status).json({ received: true }); }); ``` *** ### handleFastify() ```ts handleFastify(req, auth?): WebhookHandlerResultWithFetch; ``` Handle a webhook from a Fastify request **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `req` | [`FastifyLikeRequest`](types#fastifylikerequest) | | `auth?` | [`WebhookAuthConfig`](types#webhookauthconfig) | **Returns** [`WebhookHandlerResultWithFetch`](types#webhookhandlerresultwithfetch) *** ### handleHono() ```ts handleHono(c, auth?): Promise; ``` Handle a webhook from a Hono context **Parameters** | Parameter | Type | | --------- | ---------------------------------------------- | | `c` | [`HonoLikeContext`](types#honolikecontext) | | `auth?` | [`WebhookAuthConfig`](types#webhookauthconfig) | **Returns** `Promise`\<[`WebhookHandlerResultWithFetch`](types#webhookhandlerresultwithfetch)> *** ### handleNestJS() ```ts handleNestJS(req, auth?): WebhookHandlerResultWithFetch; ``` Handle a webhook from a NestJS request **Parameters** | Parameter | Type | | --------- | ---------------------------------------------- | | `req` | [`NestJSLikeRequest`](types#nestjslikerequest) | | `auth?` | [`WebhookAuthConfig`](types#webhookauthconfig) | **Returns** [`WebhookHandlerResultWithFetch`](types#webhookhandlerresultwithfetch) *** ### handleRequest() ```ts handleRequest(request, auth?): Promise; ``` Handle a webhook from a Fetch API Request **Parameters** | Parameter | Type | | --------- | ---------------------------------------------- | | `request` | `Request` | | `auth?` | [`WebhookAuthConfig`](types#webhookauthconfig) | **Returns** `Promise`\<[`WebhookHandlerResultWithFetch`](types#webhookhandlerresultwithfetch)> *** ### isEvent() ```ts isEvent(payload): payload is WebhookEvent; ``` Type guard to check if a value is a valid WebhookEvent **Parameters** | Parameter | Type | | --------- | --------- | | `payload` | `unknown` | **Returns** `payload is WebhookEvent` *** ### parseEvent() ```ts parseEvent(payload): WebhookEvent; ``` Parse and validate a webhook event payload **Parameters** | Parameter | Type | | --------- | --------- | | `payload` | `unknown` | **Returns** [`WebhookEvent`](types#webhookevent) *** ### verifyAuth() ```ts verifyAuth(headers, auth): boolean; ``` Verify webhook authentication header **Parameters** | Parameter | Type | | --------- | ---------------------------------------------- | | `headers` | [`WebhookHeaders`](types#webhookheaders) | | `auth` | [`WebhookAuthConfig`](types#webhookauthconfig) | **Returns** `boolean` *** ## SonioxAuthAPI ### createTemporaryKey() ```ts createTemporaryKey(request, signal?): Promise; ``` Creates a temporary API key for client-side use. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------------------- | ---------------------------------------- | | `request` | [`TemporaryApiKeyRequest`](types#temporaryapikeyrequest) | Request parameters for the temporary key | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation | **Returns** `Promise`\<[`TemporaryApiKeyResponse`](types#temporaryapikeyresponse)> The temporary API key response **Example** ```typescript const sttKey = await client.auth.createTemporaryKey({ usage_type: 'transcribe_websocket', expires_in_seconds: 300, }); const ttsKey = await client.auth.createTemporaryKey({ usage_type: 'tts_rt', expires_in_seconds: 300, single_use: true, max_session_duration_seconds: 600, }); ``` *** ## SonioxConcurrencyLimitsAPI ### get() ```ts get(signal?): Promise; ``` Retrieves current concurrency counts and configured limits. Values are region-scoped according to the client's configured REST API endpoint. **Parameters** | Parameter | Type | Description | | --------- | ------------- | -------------------------------------- | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation. | **Returns** `Promise`\<[`ConcurrencyLimitsResponse`](types#concurrencylimitsresponse)> Current counts and configured limits for project and organization scopes. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const limits = await client.concurrencyLimits.get(); console.log(limits.project.current.transcribe_concurrent); console.log(limits.project.limits.transcribe_concurrent); ``` *** ### getHistory() ```ts getHistory(options): Promise; ``` Retrieves historical concurrent stream aggregates for the project. Returns every aggregation period in the requested window (no gaps). Periods with no recorded activity have every numeric field set to `0`. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | `options` | [`GetConcurrentStreamsHistoryOptions`](types#getconcurrentstreamshistoryoptions) | Required time window, aggregation period, stream kind, and optional cancellation. | **Returns** `Promise`\<[`ConcurrentStreamsHistoryResponse`](types#concurrentstreamshistoryresponse)> Concurrent streams history for the requested kind. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const history = await client.concurrencyLimits.getHistory({ start_time: '2026-04-28T09:00:00Z', end_time: '2026-04-28T10:00:00Z', period_sec: 60, kind: 'stt', }); for (const entry of history.entries) { console.log(entry.period_start, entry.sample_max); } ``` *** ## SonioxUsageLogsAPI ### getSummary() ```ts getSummary(options): Promise; ``` Retrieves an aggregated usage summary for the project over a time window. Returns totals across all models plus one entry per model that recorded usage. Per-day series are aligned to each entry's `days` array. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------------------- | ------------------------------------------------ | | `options` | [`GetUsageSummaryOptions`](types#getusagesummaryoptions) | Required time window plus optional cancellation. | **Returns** `Promise`\<[`UsageSummaryResponse`](types#usagesummaryresponse)> Aggregated usage summary. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const summary = await client.usageLogs.getSummary({ start_time: '2026-04-01T00:00:00Z', end_time: '2026-04-03T00:00:00Z', }); console.log(summary.total.total_cost_usd); for (const model of summary.models) { console.log(model.model, model.total_num_requests); } ``` *** ### list() ```ts list(options): Promise; ``` Retrieves per-request usage log entries for the project. The returned result is async iterable. Use `for await...of` to iterate through all pages. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------------- | ------------------------------------------------------------------------- | | `options` | [`ListUsageLogsOptions`](types#listusagelogsoptions) | Required time window plus optional pagination, sorting, and cancellation. | **Returns** `Promise`\<[`UsageLogListResult`](classes#usageloglistresult)> UsageLogListResult with async iteration support. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const result = await client.usageLogs.list({ start_time: '2026-04-28T09:00:00Z', end_time: '2026-04-29T09:00:00Z', sort: 'end_time_desc', }); for await (const log of result) { console.log(log.model, log.cost_usd); } ``` *** ## SonioxRealtimeApi Real-time API factory for creating STT sessions and TTS connections. ### Examples ```typescript const session = client.realtime.stt({ model: 'stt-rt-v5' }); await session.connect(); ``` ```typescript const stream = await client.realtime.tts({ model: 'tts-rt-v2', voice: 'Adrian', language: 'en', audio_format: 'wav', }); stream.sendText("Hello"); stream.finish(); for await (const chunk of stream) { ... } ``` ```typescript const conn = await client.realtime.tts.multiStream(); const stream = await conn.stream({ model: 'tts-rt-v2', voice: 'Adrian', language: 'en', audio_format: 'wav', }); ``` ### stt() ```ts stt(config, options?): RealtimeSttSession; ``` Create a new Speech-to-Text session. `config` is shallow-merged on top of `stt_defaults` from the client options; caller-provided fields override the defaults. **Parameters** | Parameter | Type | | ---------- | ---------------------------------------------- | | `config` | [`SttSessionConfig`](types#sttsessionconfig) | | `options?` | [`SttSessionOptions`](types#sttsessionoptions) | **Returns** [`RealtimeSttSession`](classes#realtimesttsession) ### Properties | Property | Type | | -------- | ------------ | | `tts` | `TtsFactory` | *** ## SonioxFile Uploaded file ### Constructor ```ts new SonioxFile(data, _http): SonioxFile; ``` **Parameters** | Parameter | Type | | --------- | ---------------------------------------- | | `data` | [`SonioxFileData`](types#sonioxfiledata) | | `_http` | [`HttpClient`](types#httpclient) | **Returns** `SonioxFile` ### delete() ```ts delete(signal?): Promise; ``` Permanently deletes this file. This operation is idempotent - succeeds even if the file doesn't exist. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ------------------------------------- | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript const file = await client.files.get('550e8400-e29b-41d4-a716-446655440000'); if (file) { await file.delete(); } ``` *** ### toJSON() ```ts toJSON(): SonioxFileData; ``` Returns the raw data for this file. **Returns** [`SonioxFileData`](types#sonioxfiledata) ### Properties | Property | Type | | --------------------- | ----------------------- | | `client_reference_id` | `string` \| `undefined` | | `created_at` | `string` | | `filename` | `string` | | `id` | `string` | | `size` | `number` | *** ## SonioxTranscription A Transcription instance ### Extended by * [`SonioxTranslationJob`](classes#sonioxtranslationjob) ### Constructor ```ts new SonioxTranscription( data, _http, transcript?): SonioxTranscription; ``` **Parameters** | Parameter | Type | | ------------- | ---------------------------------------------------------- | | `data` | [`SonioxTranscriptionData`](types#sonioxtranscriptiondata) | | `_http` | [`HttpClient`](types#httpclient) | | `transcript?` | [`SonioxTranscript`](classes#sonioxtranscript) \| `null` | **Returns** `SonioxTranscription` ### delete() ```ts delete(): Promise; ``` Permanently deletes this transcription. This operation is idempotent - succeeds even if the transcription doesn't exist. **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript const transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); await transcription.delete(); ``` *** ### destroy() ```ts destroy(): Promise; ``` Permanently deletes this transcription and its associated file (if any). This operation is idempotent - succeeds even if resources don't exist. **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript // Clean up both transcription and uploaded file const transcription = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, wait: true, }); // ... use transcription ... await transcription.destroy(); // Deletes both transcription and file ``` *** ### getTranscript() ```ts getTranscript(options?): Promise; ``` Retrieves the full transcript text and tokens for this transcription. Only available for successfully completed transcriptions. Returns cached transcript if available (when using `transcribe()` with `wait: true`). Use `force: true` to bypass the cache and fetch fresh data from the API. **Parameters** | Parameter | Type | Description | | ----------------- | --------------------------------------------------- | -------------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | Optional settings | | `options.force?` | `boolean` | If true, bypasses cached transcript and fetches from API | | `options.signal?` | `AbortSignal` | Optional AbortSignal for request cancellation | **Returns** `Promise`\<[`SonioxTranscript`](classes#sonioxtranscript) | `null`> The transcript with text and detailed tokens, or null if not found. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404). **Example** ```typescript const transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); if (transcription) { const transcript = await transcription.getTranscript(); if (transcript) { console.log(transcript.text); } } // Force re-fetch from API const freshTranscript = await transcription.getTranscript({ force: true }); ``` *** ### refresh() ```ts refresh(signal?): Promise; ``` Re-fetches this transcription to get the latest status. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ---------------------------------------------- | | `signal?` | `AbortSignal` | Optional AbortSignal for request cancellation. | **Returns** `Promise`\<`SonioxTranscription`> A new SonioxTranscription instance with updated data. **Throws** [SonioxHttpError](classes#sonioxhttperror) **Example** ```typescript let transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); transcription = await transcription.refresh(); console.log(transcription.status); ``` *** ### toJSON() ```ts toJSON(): SonioxTranscriptionData; ``` Returns the raw data for this transcription. **Returns** [`SonioxTranscriptionData`](types#sonioxtranscriptiondata) *** ### wait() ```ts wait(options): Promise; ``` Waits for the transcription to complete or fail. Polls the API at the specified interval until the status is 'completed' or 'error'. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------- | ---------------------------------------------------------------- | | `options` | [`WaitOptions`](types#waitoptions) | Wait options including polling interval, timeout, and callbacks. | **Returns** `Promise`\<`SonioxTranscription`> The completed or errored transcription. **Throws** `Error` If the wait times out or is aborted. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const transcription = await client.stt.create({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', }); // Simple wait const completed = await transcription.wait(); // Wait with progress callback const completed = await transcription.wait({ interval_ms: 2000, on_status_change: (status) => console.log(`Status: ${status}`), }); ``` ### Properties | Property | Type | Description | | -------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio_duration_ms` | `number` \| `null` \| `undefined` | Duration of the audio in milliseconds. Only available after processing begins. | | `audio_url` | `string` \| `null` \| `undefined` | URL of the audio file being transcribed. | | `client_reference_id` | `string` \| `null` \| `undefined` | Optional tracking identifier. | | `context` | \| [`TranscriptionContext`](types#transcriptioncontext) \| `null` \| `undefined` | Additional context provided for the transcription. | | `created_at` | `string` | UTC timestamp when the transcription was created. | | `enable_language_identification` | `boolean` | When true, language is detected for each part of the transcription. | | `enable_speaker_diarization` | `boolean` | When true, speakers are identified and separated in the transcription output. | | `error_message` | `string` \| `null` \| `undefined` | Error message if transcription failed. | | `error_type` | `string` \| `null` \| `undefined` | Error type if transcription failed. | | `file_id` | `string` \| `null` \| `undefined` | ID of the uploaded file being transcribed. | | `filename` | `string` | Name of the file being transcribed. | | `id` | `string` | Unique identifier of the transcription. | | `language_hints` | `string`\[] \| `undefined` | Expected languages in the audio. | | `model` | `string` | Speech-to-text model used. | | `status` | [`TranscriptionStatus`](types#transcriptionstatus) | Current status of the transcription. | | `transcript` | [`SonioxTranscript`](classes#sonioxtranscript) \| `null` \| `undefined` | Pre-fetched transcript. Only available when using `transcribe()` with `wait: true`, `fetch_transcript !== false`, and the transcription completed successfully | | `webhook_auth_header_name` | `string` \| `null` \| `undefined` | Name of the authentication header sent with webhook notifications. | | `webhook_auth_header_value` | `string` \| `null` \| `undefined` | Authentication header value (masked). | | `webhook_status_code` | `number` \| `null` \| `undefined` | HTTP status code received when webhook was delivered. | | `webhook_url` | `string` \| `null` \| `undefined` | URL to receive webhook notifications. | *** ## SonioxTranscript A Transcript result containing the transcribed text and tokens. ### Constructor ```ts new SonioxTranscript(data): SonioxTranscript; ``` **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `data` | [`TranscriptResponse`](types#transcriptresponse) | **Returns** `SonioxTranscript` ### segments() ```ts segments(options?): TranscriptSegment[]; ``` Groups tokens into segments based on specified grouping keys. A new segment starts when any of the `group_by` fields changes. **Parameters** | Parameter | Type | Description | | ---------- | ------------------------------------------------------------ | -------------------- | | `options?` | [`SegmentTranscriptOptions`](types#segmenttranscriptoptions) | Segmentation options | **Returns** [`TranscriptSegment`](types#transcriptsegment)\[] Array of segments with combined text and timing **Example** ```typescript const transcript = await transcription.getTranscript(); // Group by both speaker and language (default) const segments = transcript.segments(); // Group by speaker only const bySpeaker = transcript.segments({ group_by: ['speaker'] }); for (const s of segments) { console.log(`[Speaker ${s.speaker}] ${s.text}`); } ``` ### Properties | Property | Type | Description | | -------- | --------------------------------------------- | ------------------------------------------------------------------ | | `id` | `string` | Unique identifier of the transcription this transcript belongs to. | | `text` | `string` | Complete transcribed text content. | | `tokens` | [`TranscriptToken`](types#transcripttoken)\[] | List of detailed token information with timestamps and metadata. | *** ## FileListResult Result set for file listing ### Constructor ```ts new FileListResult( initialResponse, _http, _limit, _signal): FileListResult; ``` **Parameters** | Parameter | Type | Default value | | ----------------- | ------------------------------------------------------------------------------------------ | ------------- | | `initialResponse` | [`ListFilesResponse`](types#listfilesresponset)\<[`SonioxFileData`](types#sonioxfiledata)> | `undefined` | | `_http` | [`HttpClient`](types#httpclient) | `undefined` | | `_limit` | `number` \| `undefined` | `undefined` | | `_signal` | `AbortSignal` \| `undefined` | `undefined` | **Returns** `FileListResult` ### \[asyncIterator]\() ```ts asyncIterator: AsyncIterator; ``` Async iterator that automatically fetches all pages Use with `for await...of` to iterate through all files **Returns** `AsyncIterator`\<[`SonioxFile`](classes#sonioxfile)> *** ### isPaged() ```ts isPaged(): boolean; ``` Returns true if there are more pages of results beyond the first page **Returns** `boolean` *** ### toJSON() ```ts toJSON(): ListFilesResponse; ``` Returns the raw data for this list result. Also used by JSON.stringify() to prevent serialization of internal HTTP client. **Returns** [`ListFilesResponse`](types#listfilesresponset)\<[`SonioxFileData`](types#sonioxfiledata)> ### Properties | Property | Type | Description | | ------------------ | ------------------------------------- | ---------------------------------------------------------- | | `files` | [`SonioxFile`](classes#sonioxfile)\[] | Files from the first page of results | | `next_page_cursor` | `string` \| `null` | Pagination cursor for the next page. Null if no more pages | *** ## TranscriptionListResult Result set for transcription listing. ### Constructor ```ts new TranscriptionListResult( initialResponse, _http, _options, _signal?): TranscriptionListResult; ``` **Parameters** | Parameter | Type | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------ | | `initialResponse` | [`ListTranscriptionsResponse`](types#listtranscriptionsresponset)\<[`SonioxTranscriptionData`](types#sonioxtranscriptiondata)> | | `_http` | [`HttpClient`](types#httpclient) | | `_options` | [`ListTranscriptionsOptions`](types#listtranscriptionsoptions) | | `_signal?` | `AbortSignal` | **Returns** `TranscriptionListResult` ### \[asyncIterator]\() ```ts asyncIterator: AsyncIterator; ``` Async iterator that automatically fetches all pages. Use with `for await...of` to iterate through all transcriptions. **Returns** `AsyncIterator`\<[`SonioxTranscription`](classes#sonioxtranscription)> *** ### isPaged() ```ts isPaged(): boolean; ``` Returns true if there are more pages of results beyond the first page. **Returns** `boolean` *** ### toJSON() ```ts toJSON(): ListTranscriptionsResponse; ``` Returns the raw data for this list result **Returns** [`ListTranscriptionsResponse`](types#listtranscriptionsresponset)\<[`SonioxTranscriptionData`](types#sonioxtranscriptiondata)> ### Properties | Property | Type | Description | | ------------------ | ------------------------------------------------------- | ----------------------------------------------------------- | | `next_page_cursor` | `string` \| `null` | Pagination cursor for the next page. Null if no more pages. | | `transcriptions` | [`SonioxTranscription`](classes#sonioxtranscription)\[] | Transcriptions from the first page of results. | *** ## UsageLogListResult Result set for usage log listing. ### Constructor ```ts new UsageLogListResult( initialResponse, _http, _options): UsageLogListResult; ``` **Parameters** | Parameter | Type | | ----------------- | ------------------------------------------------------ | | `initialResponse` | [`ListUsageLogsResponse`](types#listusagelogsresponse) | | `_http` | [`HttpClient`](types#httpclient) | | `_options` | [`ListUsageLogsOptions`](types#listusagelogsoptions) | **Returns** `UsageLogListResult` ### \[asyncIterator]\() ```ts asyncIterator: AsyncIterator; ``` Async iterator that automatically fetches all pages. Use with `for await...of` to iterate through all usage logs. **Returns** `AsyncIterator`\<[`SonioxUsageLog`](types#sonioxusagelog)> *** ### isPaged() ```ts isPaged(): boolean; ``` Returns true if there are more pages of results beyond the first page. **Returns** `boolean` *** ### toJSON() ```ts toJSON(): ListUsageLogsResponse; ``` Returns the raw data for this list result. **Returns** [`ListUsageLogsResponse`](types#listusagelogsresponse) ### Properties | Property | Type | Description | | ------------------ | ------------------------------------------- | ----------------------------------------------------------- | | `next_page_cursor` | `string` \| `null` | Pagination cursor for the next page. Null if no more pages. | | `usage_logs` | [`SonioxUsageLog`](types#sonioxusagelog)\[] | Usage logs from the first page of results. | *** ## RealtimeSttSession Real-time Speech-to-Text session Provides WebSocket-based streaming transcription with support for: * Event-based and async iterator consumption * Pause/resume with automatic keepalive while paused * AbortSignal cancellation ### Example ```typescript const session = new RealtimeSttSession(apiKey, wsUrl, { model: 'stt-rt-v5' }); session.on('result', (result) => { console.log(result.tokens.map(t => t.text).join('')); }); await session.connect(); session.sendAudio(audioChunk); await session.finish(); ``` ### paused ```ts get paused(): boolean; ``` Whether the session is currently paused. **Returns** `boolean` *** ### state ```ts get state(): SttSessionState; ``` Current session state. **Returns** [`SttSessionState`](types#sttsessionstate) ### Constructor ```ts new RealtimeSttSession( apiKey, wsBaseUrl, config, options?): RealtimeSttSession; ``` **Parameters** | Parameter | Type | | ----------- | ---------------------------------------------- | | `apiKey` | `string` | | `wsBaseUrl` | `string` | | `config` | [`SttSessionConfig`](types#sttsessionconfig) | | `options?` | [`SttSessionOptions`](types#sttsessionoptions) | **Returns** `RealtimeSttSession` ### \[asyncIterator]\() ```ts asyncIterator: AsyncIterator; ``` Async iterator for consuming events. The returned iterator's `return()` resets the internal iterator-attach flag and drops any buffered events, so consumers that exit `for await` early (via `break` etc.) stop accruing memory while the session keeps running. **Returns** `AsyncIterator`\<[`RealtimeEvent`](types#realtimeevent)> *** ### close() ```ts close(): void; ``` Close (cancel) the session immediately without waiting **Returns** `void` *** ### connect() ```ts connect(): Promise; ``` Connect to the Soniox WebSocket API. **Returns** `Promise`\<`void`> **Throws** [AbortError](classes#aborterror) If aborted **Throws** [ConnectionError](classes#connectionerror) If connection fails **Throws** [StateError](classes#stateerror) If already connected *** ### finalize() ```ts finalize(options?): void; ``` Requests the server to finalize current transcription **Parameters** | Parameter | Type | | ------------------------------ | -------------------------------------- | | `options?` | \{ `trailing_silence_ms?`: `number`; } | | `options.trailing_silence_ms?` | `number` | **Returns** `void` *** ### finish() ```ts finish(): Promise; ``` Gracefully finish the session **Returns** `Promise`\<`void`> *** ### keepAlive() ```ts keepAlive(): void; ``` Send a keepalive message **Returns** `void` *** ### off() ```ts off(event, handler): this; ``` Remove an event handler **Type Parameters** | Type Parameter | | ---------------------------------------------------------------- | | `E` *extends* keyof [`SttSessionEvents`](types#sttsessionevents) | **Parameters** | Parameter | Type | | --------- | -------------------------------------------------- | | `event` | `E` | | `handler` | [`SttSessionEvents`](types#sttsessionevents)\[`E`] | **Returns** `this` *** ### on() ```ts on(event, handler): this; ``` Register an event handler **Type Parameters** | Type Parameter | | ---------------------------------------------------------------- | | `E` *extends* keyof [`SttSessionEvents`](types#sttsessionevents) | **Parameters** | Parameter | Type | | --------- | -------------------------------------------------- | | `event` | `E` | | `handler` | [`SttSessionEvents`](types#sttsessionevents)\[`E`] | **Returns** `this` *** ### once() ```ts once(event, handler): this; ``` Register a one-time event handler **Type Parameters** | Type Parameter | | ---------------------------------------------------------------- | | `E` *extends* keyof [`SttSessionEvents`](types#sttsessionevents) | **Parameters** | Parameter | Type | | --------- | -------------------------------------------------- | | `event` | `E` | | `handler` | [`SttSessionEvents`](types#sttsessionevents)\[`E`] | **Returns** `this` *** ### pause() ```ts pause(): void; ``` Pause audio transmission and starts automatic keepalive messages **Returns** `void` *** ### resume() ```ts resume(): void; ``` Resume audio transmission **Returns** `void` *** ### sendAudio() ```ts sendAudio(data): void; ``` Send audio data to the server **Parameters** | Parameter | Type | Description | | --------- | ----------- | --------------------------------------- | | `data` | `AudioData` | Audio data as Uint8Array or ArrayBuffer | **Returns** `void` **Throws** [AbortError](classes#aborterror) If aborted **Throws** [StateError](classes#stateerror) If not connected *** ### sendStream() ```ts sendStream(stream, options?): Promise; ``` Stream audio data from an async iterable source. **Parameters** | Parameter | Type | Description | | ---------- | ---------------------------------------------- | ---------------------------------------- | | `stream` | `AsyncIterable`\<`AudioData`> | Async iterable yielding audio chunks | | `options?` | [`SendStreamOptions`](types#sendstreamoptions) | Optional pacing and auto-finish settings | **Returns** `Promise`\<`void`> **Throws** [AbortError](classes#aborterror) If aborted during streaming **Throws** [StateError](classes#stateerror) If not connected *** ## RealtimeSegmentBuffer Rolling buffer for turning real-time results into stable segments. ### size ```ts get size(): number; ``` Number of tokens currently buffered. **Returns** `number` ### Constructor ```ts new RealtimeSegmentBuffer(options?): RealtimeSegmentBuffer; ``` **Parameters** | Parameter | Type | | ---------- | -------------------------------------------------------------------- | | `options?` | [`RealtimeSegmentBufferOptions`](types#realtimesegmentbufferoptions) | **Returns** `RealtimeSegmentBuffer` ### add() ```ts add(result): RealtimeSegment[]; ``` Add a real-time result and return stable segments. **Parameters** | Parameter | Type | | --------- | ---------------------------------------- | | `result` | [`RealtimeResult`](types#realtimeresult) | **Returns** [`RealtimeSegment`](types#realtimesegment)\[] *** ### flushAll() ```ts flushAll(): RealtimeSegment[]; ``` Flush all buffered tokens into segments and clear the buffer. Includes tokens that are not yet stable by final\_audio\_proc\_ms. **Returns** [`RealtimeSegment`](types#realtimesegment)\[] *** ### reset() ```ts reset(): void; ``` Clear all buffered tokens. **Returns** `void` *** ## RealtimeUtteranceBuffer Collects real-time results into utterances for endpoint-driven workflows. ### Constructor ```ts new RealtimeUtteranceBuffer(options?): RealtimeUtteranceBuffer; ``` **Parameters** | Parameter | Type | | ---------- | ------------------------------------------------------------------------ | | `options?` | [`RealtimeUtteranceBufferOptions`](types#realtimeutterancebufferoptions) | **Returns** `RealtimeUtteranceBuffer` ### addResult() ```ts addResult(result): RealtimeSegment[]; ``` Add a real-time result and collect stable segments. **Parameters** | Parameter | Type | | --------- | ---------------------------------------- | | `result` | [`RealtimeResult`](types#realtimeresult) | **Returns** [`RealtimeSegment`](types#realtimesegment)\[] *** ### markEndpoint() ```ts markEndpoint(): RealtimeUtterance | undefined; ``` Mark an endpoint and flush the current utterance. **Returns** [`RealtimeUtterance`](types#realtimeutterance) | `undefined` *** ### reset() ```ts reset(): void; ``` Clear buffered segments and tokens. **Returns** `void` *** ## SonioxError ### Extends * `Error` ### Extended by * [`SonioxHttpError`](classes#sonioxhttperror) * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | \| `string` & \{ } \| [`SonioxErrorCode`](types#sonioxerrorcode) | Error code describing the type of error. Typed as `string` at the base level to allow subclasses (e.g. HTTP errors) to use their own error code unions. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## SonioxHttpError HTTP error class for all HTTP-related failures (REST API). Thrown when HTTP requests fail due to network issues, timeouts, server errors, or response parsing failures. ### Extends * [`SonioxError`](classes#sonioxerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Overrides** [`SonioxError`](classes#sonioxerror).[`toJSON`](classes#sonioxerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Overrides** [`SonioxError`](classes#sonioxerror).[`toString`](classes#sonioxerror-tostring) ### Properties | Property | Type | Description | | ------------ | -------------------------------------------- | ------------------------------------------------------------------------------------ | | `bodyText` | `string` \| `undefined` | Response body text, capped at 4KB (only for http\_error/parse\_error) | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`HttpErrorCode`](types#httperrorcode) | Categorized HTTP error code | | `headers` | `Record`\<`string`, `string`> \| `undefined` | Response headers (only for http\_error) | | `method` | [`HttpMethod`](types#httpmethod) | HTTP method | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | | `url` | `string` | Request URL | *** ## RealtimeError Base error class for all real-time (WebSocket) SDK errors ### Extends * [`SonioxError`](classes#sonioxerror) ### Extended by * [`AuthError`](classes#autherror) * [`BadRequestError`](classes#badrequesterror) * [`QuotaError`](classes#quotaerror) * [`ConnectionError`](classes#connectionerror) * [`NetworkError`](classes#networkerror) * [`AbortError`](classes#aborterror) * [`StateError`](classes#stateerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Overrides** [`SonioxError`](classes#sonioxerror).[`toJSON`](classes#sonioxerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Overrides** [`SonioxError`](classes#sonioxerror).[`toString`](classes#sonioxerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## AuthError Authentication error (401). Thrown when the API key is invalid or expired. ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## BadRequestError Bad request error (400). Thrown for invalid configuration or parameters. ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## QuotaError Quota error (402, 429). Thrown when rate limits are exceeded or quota is exhausted. ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## ConnectionError Connection error. Thrown for WebSocket connection failures and transport errors. ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## NetworkError Network error. Thrown for server-side network issues (408, 500, 503). ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## AbortError Abort error. Thrown when an operation is cancelled via AbortSignal. ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## StateError State error. Thrown when an operation is attempted in an invalid state. ### Extends * [`RealtimeError`](classes#realtimeerror) ### toJSON() ```ts toJSON(): Record; ``` Converts to a plain object for logging/serialization **Returns** `Record`\<`string`, `unknown`> **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toJSON`](classes#realtimeerror-tojson) *** ### toString() ```ts toString(): string; ``` Creates a human-readable string representation **Returns** `string` **Inherited from** [`RealtimeError`](classes#realtimeerror).[`toString`](classes#realtimeerror-tostring) ### Properties | Property | Type | Description | | ------------ | ---------------------------------------------- | -------------------------------------------------------------------------------------------------- | | `cause` | `unknown` | The underlying error that caused this error, if any. | | `code` | [`RealtimeErrorCode`](types#realtimeerrorcode) | Real-time error code | | `raw` | `unknown` | Original response payload for debugging. Contains the raw WebSocket message that caused the error. | | `statusCode` | `number` \| `undefined` | HTTP status code when applicable (e.g., 401 for auth errors, 500 for server errors). | *** ## RealtimeTtsConnection WebSocket connection for real-time Text-to-Speech. Supports up to 5 concurrent streams multiplexed by `stream_id`. The connection automatically sends keepalive messages while open. ### Example ```typescript const conn = new RealtimeTtsConnection(apiKey, wsUrl, ttsDefaults); await conn.connect(); const s1 = conn.stream({ model, voice, language, audio_format }); s1.sendText("Hello"); s1.finish(); for await (const chunk of s1) { ... } conn.close(); ``` ### Extends * `TypedEmitter`\<[`TtsConnectionEvents`](types#ttsconnectionevents)> ### isConnected ```ts get isConnected(): boolean; ``` Whether the WebSocket is connected. **Returns** `boolean` ### Constructor ```ts new RealtimeTtsConnection( apiKey, wsUrl, ttsDefaults?, options?): RealtimeTtsConnection; ``` **Parameters** | Parameter | Type | | -------------- | ------------------------------------------------------ | | `apiKey` | `string` | | `wsUrl` | `string` | | `ttsDefaults?` | `Partial`\<[`TtsStreamConfig`](types#ttsstreamconfig)> | | `options?` | [`TtsConnectionOptions`](types#ttsconnectionoptions) | **Returns** `RealtimeTtsConnection` **Overrides** ```ts TypedEmitter.constructor ``` ### close() ```ts close(): void; ``` Close the WebSocket connection and terminate all active streams. **Returns** `void` *** ### connect() ```ts connect(): Promise; ``` Open the WebSocket connection and start keepalive. Called automatically by [stream](#stream) if not yet connected. **Returns** `Promise`\<`void`> *** ### emit() ```ts emit(event, ...args): void; ``` Emit an event to all registered handlers. Handler errors do not prevent other handlers from running. Errors are reported to an `error` event if present, otherwise rethrown async. **Type Parameters** | Type Parameter | | ---------------------------------------------------------------------- | | `E` *extends* keyof [`TtsConnectionEvents`](types#ttsconnectionevents) | **Parameters** | Parameter | Type | | --------- | ----------------------------------------------------------------------- | | `event` | `E` | | ...`args` | `Parameters`\<[`TtsConnectionEvents`](types#ttsconnectionevents)\[`E`]> | **Returns** `void` **Inherited from** ```ts TypedEmitter.emit ``` *** ### off() ```ts off(event, handler): this; ``` Remove an event handler. **Type Parameters** | Type Parameter | | ---------------------------------------------------------------------- | | `E` *extends* keyof [`TtsConnectionEvents`](types#ttsconnectionevents) | **Parameters** | Parameter | Type | | --------- | -------------------------------------------------------- | | `event` | `E` | | `handler` | [`TtsConnectionEvents`](types#ttsconnectionevents)\[`E`] | **Returns** `this` **Inherited from** ```ts TypedEmitter.off ``` *** ### on() ```ts on(event, handler): this; ``` Register an event handler. **Type Parameters** | Type Parameter | | ---------------------------------------------------------------------- | | `E` *extends* keyof [`TtsConnectionEvents`](types#ttsconnectionevents) | **Parameters** | Parameter | Type | | --------- | -------------------------------------------------------- | | `event` | `E` | | `handler` | [`TtsConnectionEvents`](types#ttsconnectionevents)\[`E`] | **Returns** `this` **Inherited from** ```ts TypedEmitter.on ``` *** ### once() ```ts once(event, handler): this; ``` Register a one-time event handler. **Type Parameters** | Type Parameter | | ---------------------------------------------------------------------- | | `E` *extends* keyof [`TtsConnectionEvents`](types#ttsconnectionevents) | **Parameters** | Parameter | Type | | --------- | -------------------------------------------------------- | | `event` | `E` | | `handler` | [`TtsConnectionEvents`](types#ttsconnectionevents)\[`E`] | **Returns** `this` **Inherited from** ```ts TypedEmitter.once ``` *** ### removeAllListeners() ```ts removeAllListeners(event?): void; ``` Remove all event handlers. **Parameters** | Parameter | Type | | --------- | ------------------------- | | `event?` | keyof TtsConnectionEvents | **Returns** `void` **Inherited from** ```ts TypedEmitter.removeAllListeners ``` *** ### stream() ```ts stream(input?): Promise; ``` Open a new TTS stream on this connection. Auto-connects if the WebSocket is not yet open. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------- | ------------------------------------------------ | | `input?` | [`TtsStreamInput`](types#ttsstreaminput) | Stream configuration (merged with tts\_defaults) | **Returns** `Promise`\<[`RealtimeTtsStream`](classes#realtimettsstream)> A ready-to-use stream handle *** ## RealtimeTtsStream Handle for one TTS stream on a WebSocket connection. Emits typed events and supports async iteration over decoded audio chunks. ### Examples ```typescript stream.on('audio', (chunk) => process(chunk)); stream.on('terminated', () => console.log('done')); stream.sendText("Hello world"); stream.finish(); ``` ```typescript stream.sendText("Hello world"); stream.finish(); for await (const chunk of stream) { process(chunk); } ``` ### Extends * `TypedEmitter`\<[`TtsStreamEvents`](types#ttsstreamevents)> ### state ```ts get state(): TtsStreamState; ``` Current stream lifecycle state. **Returns** [`TtsStreamState`](types#ttsstreamstate) ### \[asyncIterator]\() ```ts asyncIterator: AsyncIterator>; ``` Async iterator that yields decoded audio chunks. The returned iterator's `return()` resets the internal iterator-attach flag and drops any buffered audio, so consumers that exit `for await` early (via `break` etc.) stop accruing memory while the stream keeps receiving server audio. **Returns** `AsyncIterator`\<`Uint8Array`\<`ArrayBufferLike`>> *** ### cancel() ```ts cancel(): void; ``` Cancel this stream. The server will stop generating and send `terminated`. **Returns** `void` *** ### close() ```ts close(): void; ``` Close this stream. For single-stream usage (created via `tts(input)`), also closes the underlying WebSocket connection. **Returns** `void` *** ### emit() ```ts emit(event, ...args): void; ``` Emit an event to all registered handlers. Handler errors do not prevent other handlers from running. Errors are reported to an `error` event if present, otherwise rethrown async. **Type Parameters** | Type Parameter | | -------------------------------------------------------------- | | `E` *extends* keyof [`TtsStreamEvents`](types#ttsstreamevents) | **Parameters** | Parameter | Type | | --------- | --------------------------------------------------------------- | | `event` | `E` | | ...`args` | `Parameters`\<[`TtsStreamEvents`](types#ttsstreamevents)\[`E`]> | **Returns** `void` **Inherited from** ```ts TypedEmitter.emit ``` *** ### finish() ```ts finish(): void; ``` Signal that no more text will be sent for this stream. The server will finish generating audio and send `terminated`. **Returns** `void` *** ### off() ```ts off(event, handler): this; ``` Remove an event handler. **Type Parameters** | Type Parameter | | -------------------------------------------------------------- | | `E` *extends* keyof [`TtsStreamEvents`](types#ttsstreamevents) | **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `event` | `E` | | `handler` | [`TtsStreamEvents`](types#ttsstreamevents)\[`E`] | **Returns** `this` **Inherited from** ```ts TypedEmitter.off ``` *** ### on() ```ts on(event, handler): this; ``` Register an event handler. **Type Parameters** | Type Parameter | | -------------------------------------------------------------- | | `E` *extends* keyof [`TtsStreamEvents`](types#ttsstreamevents) | **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `event` | `E` | | `handler` | [`TtsStreamEvents`](types#ttsstreamevents)\[`E`] | **Returns** `this` **Inherited from** ```ts TypedEmitter.on ``` *** ### once() ```ts once(event, handler): this; ``` Register a one-time event handler. **Type Parameters** | Type Parameter | | -------------------------------------------------------------- | | `E` *extends* keyof [`TtsStreamEvents`](types#ttsstreamevents) | **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `event` | `E` | | `handler` | [`TtsStreamEvents`](types#ttsstreamevents)\[`E`] | **Returns** `this` **Inherited from** ```ts TypedEmitter.once ``` *** ### removeAllListeners() ```ts removeAllListeners(event?): void; ``` Remove all event handlers. **Parameters** | Parameter | Type | | --------- | --------------------- | | `event?` | keyof TtsStreamEvents | **Returns** `void` **Inherited from** ```ts TypedEmitter.removeAllListeners ``` *** ### sendStream() ```ts sendStream(source): Promise; ``` Pipe an async iterable of text chunks into the stream. Automatically calls [finish](#finish) when the iterable completes. Designed for concurrent use: call `sendStream()` and consume audio via `for await` or events simultaneously. **Parameters** | Parameter | Type | | --------- | -------------------------- | | `source` | `AsyncIterable`\<`string`> | **Returns** `Promise`\<`void`> **Example** ```typescript stream.sendStream(llmTokenStream); for await (const audio of stream) { forward(audio); } ``` *** ### sendText() ```ts sendText(text, options?): void; ``` Send one text chunk to the TTS stream. **Parameters** | Parameter | Type | Description | | -------------- | ----------------------- | --------------------------------------------- | | `text` | `string` | Text to synthesize | | `options?` | \{ `end?`: `boolean`; } | - | | `options.end?` | `boolean` | If true, signals this is the final text chunk | **Returns** `void` ### Properties | Property | Type | | ---------- | -------- | | `streamId` | `string` | *** ## SonioxTranslationJob A translation job. Mirrors [SonioxTranscription](classes#sonioxtranscription), with an additional translation mode and helpers that reshape the completed transcript into a [SonioxTranslation](types#sonioxtranslation). ### Extends * [`SonioxTranscription`](classes#sonioxtranscription) ### Constructor ```ts new SonioxTranslationJob( data, http, _mode, transcript?, translation?): SonioxTranslationJob; ``` **Parameters** | Parameter | Type | | -------------- | ------------------------------------------------------------------ | | `data` | [`SonioxTranscriptionData`](types#sonioxtranscriptiondata) | | `http` | [`HttpClient`](types#httpclient) | | `_mode` | [`TranslateFromTranscriptMode`](types#translatefromtranscriptmode) | | `transcript?` | [`SonioxTranscript`](classes#sonioxtranscript) \| `null` | | `translation?` | [`SonioxTranslation`](types#sonioxtranslation) \| `null` | **Returns** `SonioxTranslationJob` **Overrides** [`SonioxTranscription`](classes#sonioxtranscription).[`constructor`](classes#sonioxtranscription-constructor) ### delete() ```ts delete(): Promise; ``` Permanently deletes this transcription. This operation is idempotent - succeeds even if the transcription doesn't exist. **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript const transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); await transcription.delete(); ``` **Inherited from** [`SonioxTranscription`](classes#sonioxtranscription).[`delete`](classes#sonioxtranscription-delete) *** ### destroy() ```ts destroy(): Promise; ``` Permanently deletes this transcription and its associated file (if any). This operation is idempotent - succeeds even if resources don't exist. **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404) **Example** ```typescript // Clean up both transcription and uploaded file const transcription = await client.stt.transcribe({ model: 'stt-async-v5', file: buffer, wait: true, }); // ... use transcription ... await transcription.destroy(); // Deletes both transcription and file ``` **Inherited from** [`SonioxTranscription`](classes#sonioxtranscription).[`destroy`](classes#sonioxtranscription-destroy) *** ### fetchTranslation() ```ts fetchTranslation(options?): Promise; ``` Alias for [SonioxTranslationJob.getTranslation](#gettranslation). **Parameters** | Parameter | Type | | ----------------- | --------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | | `options.force?` | `boolean` | | `options.signal?` | `AbortSignal` | **Returns** `Promise`\<[`SonioxTranslation`](types#sonioxtranslation) | `null`> *** ### getTranscript() ```ts getTranscript(options?): Promise; ``` Retrieves the full transcript text and tokens for this transcription. Only available for successfully completed transcriptions. Returns cached transcript if available (when using `transcribe()` with `wait: true`). Use `force: true` to bypass the cache and fetch fresh data from the API. **Parameters** | Parameter | Type | Description | | ----------------- | --------------------------------------------------- | -------------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | Optional settings | | `options.force?` | `boolean` | If true, bypasses cached transcript and fetches from API | | `options.signal?` | `AbortSignal` | Optional AbortSignal for request cancellation | **Returns** `Promise`\<[`SonioxTranscript`](classes#sonioxtranscript) | `null`> The transcript with text and detailed tokens, or null if not found. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404). **Example** ```typescript const transcription = await client.stt.get('550e8400-e29b-41d4-a716-446655440000'); if (transcription) { const transcript = await transcription.getTranscript(); if (transcript) { console.log(transcript.text); } } // Force re-fetch from API const freshTranscript = await transcription.getTranscript({ force: true }); ``` **Inherited from** [`SonioxTranscription`](classes#sonioxtranscription).[`getTranscript`](classes#sonioxtranscription-gettranscript) *** ### getTranslation() ```ts getTranslation(options?): Promise; ``` Retrieves and reshapes the completed transcript into a structured translation result. Returns cached translation if available. Use `force: true` to bypass the cached translation and fetch a fresh transcript from the API. **Parameters** | Parameter | Type | | ----------------- | --------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | | `options.force?` | `boolean` | | `options.signal?` | `AbortSignal` | **Returns** `Promise`\<[`SonioxTranslation`](types#sonioxtranslation) | `null`> *** ### refresh() ```ts refresh(signal?): Promise; ``` Re-fetches this translation job to get the latest status. **Parameters** | Parameter | Type | | --------- | ------------- | | `signal?` | `AbortSignal` | **Returns** `Promise`\<`SonioxTranslationJob`> **Overrides** [`SonioxTranscription`](classes#sonioxtranscription).[`refresh`](classes#sonioxtranscription-refresh) *** ### toJSON() ```ts toJSON(): SonioxTranscriptionData; ``` Returns the raw data for this transcription. **Returns** [`SonioxTranscriptionData`](types#sonioxtranscriptiondata) **Inherited from** [`SonioxTranscription`](classes#sonioxtranscription).[`toJSON`](classes#sonioxtranscription-tojson) *** ### wait() ```ts wait(options): Promise; ``` Waits for the translation job to complete or fail. **Parameters** | Parameter | Type | | --------- | ---------------------------------- | | `options` | [`WaitOptions`](types#waitoptions) | **Returns** `Promise`\<`SonioxTranslationJob`> **Overrides** [`SonioxTranscription`](classes#sonioxtranscription).[`wait`](classes#sonioxtranscription-wait) ### Properties | Property | Type | Description | | -------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio_duration_ms` | `number` \| `null` \| `undefined` | Duration of the audio in milliseconds. Only available after processing begins. | | `audio_url` | `string` \| `null` \| `undefined` | URL of the audio file being transcribed. | | `client_reference_id` | `string` \| `null` \| `undefined` | Optional tracking identifier. | | `context` | \| [`TranscriptionContext`](types#transcriptioncontext) \| `null` \| `undefined` | Additional context provided for the transcription. | | `created_at` | `string` | UTC timestamp when the transcription was created. | | `enable_language_identification` | `boolean` | When true, language is detected for each part of the transcription. | | `enable_speaker_diarization` | `boolean` | When true, speakers are identified and separated in the transcription output. | | `error_message` | `string` \| `null` \| `undefined` | Error message if transcription failed. | | `error_type` | `string` \| `null` \| `undefined` | Error type if transcription failed. | | `file_id` | `string` \| `null` \| `undefined` | ID of the uploaded file being transcribed. | | `filename` | `string` | Name of the file being transcribed. | | `id` | `string` | Unique identifier of the transcription. | | `language_hints` | `string`\[] \| `undefined` | Expected languages in the audio. | | `model` | `string` | Speech-to-text model used. | | `status` | [`TranscriptionStatus`](types#transcriptionstatus) | Current status of the transcription. | | `transcript` | [`SonioxTranscript`](classes#sonioxtranscript) \| `null` \| `undefined` | Pre-fetched transcript. Only available when using `transcribe()` with `wait: true`, `fetch_transcript !== false`, and the transcription completed successfully | | `translation` | [`SonioxTranslation`](types#sonioxtranslation) \| `null` \| `undefined` | Pre-fetched translation result. Only available when using `translate()` with `wait: true`, `fetch_translation !== false`, and the job completed successfully. | | `webhook_auth_header_name` | `string` \| `null` \| `undefined` | Name of the authentication header sent with webhook notifications. | | `webhook_auth_header_value` | `string` \| `null` \| `undefined` | Authentication header value (masked). | | `webhook_status_code` | `number` \| `null` \| `undefined` | HTTP status code received when webhook was delivered. | | `webhook_url` | `string` \| `null` \| `undefined` | URL to receive webhook notifications. | *** ## SonioxTtsApi REST API for Text-to-Speech generation and TTS model listing. Accessed via `client.tts` on [SonioxNodeClient](classes#sonioxnodeclient). Inherits browser-safe `generate()` and `generateStream()` from `TtsRestClient` in `@soniox/core`, and adds Node-specific methods `generateToFile()` and `listModels()`. ### Extends * `TtsRestClient` ### Constructor ```ts new SonioxTtsApi( apiKey, ttsApiUrl, http): SonioxTtsApi; ``` **Parameters** | Parameter | Type | | ----------- | -------------------------------- | | `apiKey` | `string` | | `ttsApiUrl` | `string` | | `http` | [`HttpClient`](types#httpclient) | **Returns** `SonioxTtsApi` **Overrides** ```ts TtsRestClient.constructor ``` ### generate() ```ts generate(options): Promise>; ``` Generate speech audio from text. Returns the full audio as a `Uint8Array`. **Parameters** | Parameter | Type | | --------- | ------------------------------------------------------ | | `options` | [`GenerateSpeechOptions`](types#generatespeechoptions) | **Returns** `Promise`\<`Uint8Array`\<`ArrayBufferLike`>> **Throws** [SonioxHttpError](classes#sonioxhttperror) on non-2xx responses, network failures, or aborted requests. **Inherited from** ```ts TtsRestClient.generate ``` *** ### generateStream() ```ts generateStream(options): AsyncIterable>; ``` Generate speech audio from text as a streaming async iterable. Yields `Uint8Array` chunks as they arrive from the server response body. Lower time-to-first-audio than [generate](#generate). **Known limitation:** Mid-stream server errors (reported via HTTP trailers) cannot be detected through the `fetch` API. The iterator may end early without an explicit error. Use WebSocket TTS for reliable error detection. **Parameters** | Parameter | Type | | --------- | ------------------------------------------------------ | | `options` | [`GenerateSpeechOptions`](types#generatespeechoptions) | **Returns** `AsyncIterable`\<`Uint8Array`\<`ArrayBufferLike`>> **Throws** [SonioxHttpError](classes#sonioxhttperror) on non-2xx responses, network failures, or aborted requests (before the stream starts). **Inherited from** ```ts TtsRestClient.generateStream ``` *** ### generateToFile() ```ts generateToFile(output, options): Promise; ``` Generate speech audio and write to a file or writable stream. **Parameters** | Parameter | Type | Description | | --------- | --------------------------------------------------------------- | ---------------------------------------------------- | | `output` | `string` \| `WritableStream`\<`Uint8Array`\<`ArrayBufferLike`>> | File path (string) or a `WritableStream` | | `options` | [`GenerateSpeechOptions`](types#generatespeechoptions) | Generation options | **Returns** `Promise`\<`number`> Number of bytes written **Examples** ```typescript const bytes = await client.tts.generateToFile('output.wav', { text: 'Hello world', voice: 'Adrian', language: 'en', }); ``` ```typescript const bytes = await client.tts.generateToFile(writableStream, { text: 'Hello world', voice: 'Adrian', language: 'en', }); ``` *** ### listModels() ```ts listModels(signal?): Promise; ``` List available TTS models and their voices. **Parameters** | Parameter | Type | | --------- | ------------- | | `signal?` | `AbortSignal` | **Returns** `Promise`\<[`TtsModel`](types#ttsmodel)\[]> **Example** ```typescript const models = await client.tts.listModels(); for (const model of models) { console.log(model.id, model.voices.map(v => v.id)); } ``` ### Properties | Property | Type | Description | | -------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `voices` | [`SonioxVoicesAPI`](classes#sonioxvoicesapi) | Manage custom (cloned) voices: create, list, get, recompute, and delete. **Example** `const voice = await client.tts.voices.create({ name: 'My voice', file: buffer });` | *** ## SonioxVoice A custom (cloned) Text-to-Speech voice. Use a `ready` voice by passing its [id](#id) as the `voice` value in any TTS request (REST or realtime). ### Constructor ```ts new SonioxVoice(data, _http): SonioxVoice; ``` **Parameters** | Parameter | Type | | --------- | ------------------------------------------ | | `data` | [`SonioxVoiceData`](types#sonioxvoicedata) | | `_http` | [`HttpClient`](types#httpclient) | **Returns** `SonioxVoice` ### delete() ```ts delete(signal?): Promise; ``` Permanently deletes this voice and its embeddings. This operation is idempotent - succeeds even if the voice doesn't exist. **Parameters** | Parameter | Type | Description | | --------- | ------------- | -------------------------------------- | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation. | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404). **Example** ```typescript const voice = await client.tts.voices.get(voiceId); if (voice) { await voice.delete(); } ``` *** ### isReady() ```ts isReady(model): boolean; ``` Returns true if the voice is `ready` for the given model. **Parameters** | Parameter | Type | Description | | --------- | -------- | --------------------------- | | `model` | `string` | Name of the model to check. | **Returns** `boolean` **Example** ```typescript const voice = await client.tts.voices.get(voiceId); if (voice?.isReady('tts-rt-v2')) { const audio = await client.tts.generate({ text: 'Hi', voice: voice.id, language: 'en', model: 'tts-rt-v2' }); } ``` *** ### recompute() ```ts recompute(options): Promise; ``` Prepares this voice for use with available models it is not ready for yet. Models the voice is already prepared for are left unchanged. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------------ | ------------------------------------------------- | | `options` | [`RecomputeVoiceOptions`](types#recomputevoiceoptions) | Optional model to target and cancellation signal. | **Returns** `Promise`\<`SonioxVoice`> The updated voice. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const voice = await client.tts.voices.get(voiceId); const updated = await voice?.recompute(); ``` *** ### toJSON() ```ts toJSON(): SonioxVoiceData; ``` Returns the raw data for this voice. **Returns** [`SonioxVoiceData`](types#sonioxvoicedata) ### Properties | Property | Type | | ------------ | --------------------------------------------------------- | | `created_at` | `string` | | `filename` | `string` | | `id` | `string` | | `models` | [`VoiceModelStatusEntry`](types#voicemodelstatusentry)\[] | | `name` | `string` | *** ## SonioxVoicesAPI REST API for managing custom (cloned) Text-to-Speech voices. Accessed via `client.tts.voices` on `SonioxNodeClient`. Create a voice from a short reference clip, wait until it is `ready` for the model you intend to use, then pass its `id` as the `voice` value in any TTS request. ### Constructor ```ts new SonioxVoicesAPI(http): SonioxVoicesAPI; ``` **Parameters** | Parameter | Type | | --------- | -------------------------------- | | `http` | [`HttpClient`](types#httpclient) | **Returns** `SonioxVoicesAPI` ### count() ```ts count(options): Promise; ``` Returns the total number of voices in your project. **Parameters** | Parameter | Type | Description | | ----------------- | ------------------------------ | --------------------------------- | | `options` | \{ `signal?`: `AbortSignal`; } | Optional cancellation parameters. | | `options.signal?` | `AbortSignal` | - | **Returns** `Promise`\<[`VoicesCountResponse`](types#voicescountresponse)> The total voice count. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const { total } = await client.tts.voices.count(); ``` *** ### create() ```ts create(options): Promise; ``` Creates a new voice by uploading a reference audio clip. The voice begins processing in the background per model. Poll [SonioxVoicesAPI.get](#get) (or check [SonioxVoice.isReady](classes#sonioxvoice-isready)) until the model you need reports `ready`. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------ | ---------------------------------- | | `options` | [`CreateVoiceOptions`](types#createvoiceoptions) | The voice name and reference clip. | **Returns** `Promise`\<[`SonioxVoice`](classes#sonioxvoice)> The created voice. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` On validation errors (file too large, invalid input). **Example** ```typescript import * as fs from 'node:fs'; const buffer = await fs.promises.readFile('/path/to/reference.wav'); const voice = await client.tts.voices.create({ name: 'My narrator', file: buffer, filename: 'reference.wav', }); ``` *** ### delete() ```ts delete(voice, signal?): Promise; ``` Permanently deletes a voice and its embeddings. This operation is idempotent - succeeds even if the voice doesn't exist. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------ | ------------------------------------------------ | | `voice` | [`VoiceIdentifier`](types#voiceidentifier) | The UUID of the voice or a SonioxVoice instance. | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation. | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404). **Example** ```typescript await client.tts.voices.delete('550e8400-e29b-41d4-a716-446655440000'); ``` *** ### delete\_all() ```ts delete_all(options): Promise; ``` Permanently deletes all voices in your project. Iterates through all pages of voices and deletes each one. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------------------- | ----------------------------- | | `options` | [`DeleteAllVoicesOptions`](types#deleteallvoicesoptions) | Optional cancellation signal. | **Returns** `Promise`\<`void`> **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Throws** `Error` If the operation is aborted via signal. **Example** ```typescript await client.tts.voices.delete_all(); ``` *** ### get() ```ts get(voice, signal?): Promise; ``` Retrieve metadata for a voice. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------ | ------------------------------------------------ | | `voice` | [`VoiceIdentifier`](types#voiceidentifier) | The UUID of the voice or a SonioxVoice instance. | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation. | **Returns** `Promise`\<[`SonioxVoice`](classes#sonioxvoice) | `null`> The voice instance, or null if not found. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors (except 404). **Example** ```typescript const voice = await client.tts.voices.get('550e8400-e29b-41d4-a716-446655440000'); if (voice) { console.log(voice.name, voice.models); } ``` *** ### list() ```ts list(options): Promise; ``` Retrieves the list of voices in your project. The returned result is async iterable - use `for await...of`. **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------------------- | ------------------------------------------------ | | `options` | [`ListVoicesOptions`](types#listvoicesoptions) | Optional pagination and cancellation parameters. | **Returns** `Promise`\<[`VoiceListResult`](classes#voicelistresult)> VoiceListResult **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript const result = await client.tts.voices.list(); // Automatic paging - iterates through ALL voices across all pages for await (const voice of result) { console.log(voice.id, voice.name); } ``` *** ### recompute() ```ts recompute(voice, options): Promise; ``` Prepares a voice for use with available models it is not ready for yet. Use this after a new model is released to make an existing voice usable with it. Models the voice is already prepared for are left unchanged. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------------------------------ | ------------------------------------------------- | | `voice` | [`VoiceIdentifier`](types#voiceidentifier) | The UUID of the voice or a SonioxVoice instance. | | `options` | [`RecomputeVoiceOptions`](types#recomputevoiceoptions) | Optional model to target and cancellation signal. | **Returns** `Promise`\<[`SonioxVoice`](classes#sonioxvoice)> The updated voice. **Throws** [SonioxHttpError](classes#sonioxhttperror) On API errors. **Example** ```typescript // Prepare for every model the voice is not ready for yet await client.tts.voices.recompute(voiceId); // Or target a specific model await client.tts.voices.recompute(voiceId, { model: 'tts-rt-v2' }); ``` *** ## VoiceListResult Result set for voice listing. ### Constructor ```ts new VoiceListResult( initialResponse, _http, _limit, _signal): VoiceListResult; ``` **Parameters** | Parameter | Type | Default value | | ----------------- | ---------------------------------------------------------------------------------------------- | ------------- | | `initialResponse` | [`ListVoicesResponse`](types#listvoicesresponset)\<[`SonioxVoiceData`](types#sonioxvoicedata)> | `undefined` | | `_http` | [`HttpClient`](types#httpclient) | `undefined` | | `_limit` | `number` \| `undefined` | `undefined` | | `_signal` | `AbortSignal` \| `undefined` | `undefined` | **Returns** `VoiceListResult` ### \[asyncIterator]\() ```ts asyncIterator: AsyncIterator; ``` Async iterator that automatically fetches all pages. Use with `for await...of` to iterate through all voices. **Returns** `AsyncIterator`\<[`SonioxVoice`](classes#sonioxvoice)> *** ### isPaged() ```ts isPaged(): boolean; ``` Returns true if there are more pages of results beyond the first page. **Returns** `boolean` *** ### toJSON() ```ts toJSON(): ListVoicesResponse; ``` Returns the raw data for this list result. Also used by JSON.stringify() to prevent serialization of internal HTTP client. **Returns** [`ListVoicesResponse`](types#listvoicesresponset)\<[`SonioxVoiceData`](types#sonioxvoicedata)> ### Properties | Property | Type | Description | | ------------------ | --------------------------------------- | ----------------------------------------------------------- | | `next_page_cursor` | `string` \| `null` | Pagination cursor for the next page. Null if no more pages. | | `voices` | [`SonioxVoice`](classes#sonioxvoice)\[] | Voices from the first page of results. | # Full Node SDK reference URL: /sdk/node-SDK/reference Full SDK reference for the Node SDK ## Environment variables Environment variables configure the client when no explicit option is passed. Every variable has a matching option on `new SonioxNodeClient({ ... })` — see [`SonioxNodeClientOptions`](/sdk/node-SDK/reference/types#sonioxnodeclientoptions). | Variable | Maps to option | Default | | --------------------------- | --------------------------------------------------------------------- | ---------------------------------------------- | | `SONIOX_API_KEY` | `api_key` | - | | `SONIOX_REGION` | `region` | - (US root) | | `SONIOX_BASE_DOMAIN` | `base_domain` — derives all `{api,stt-rt,tts-rt}.{base_domain}` hosts | - | | `SONIOX_API_BASE_URL` | `base_url` (REST API) | `https://api.soniox.com` | | `SONIOX_WS_URL` | `realtime.ws_base_url` (STT WebSocket) | `wss://stt-rt.soniox.com/transcribe-websocket` | | `SONIOX_TTS_API_URL` | `tts_api_url` (TTS REST) | `https://tts-rt.soniox.com` | | `SONIOX_TTS_WS_URL` | `realtime.tts_ws_url` (TTS WebSocket) | `wss://tts-rt.soniox.com/tts-websocket` | | `SONIOX_API_WEBHOOK_HEADER` | Webhook auth header name | - | | `SONIOX_API_WEBHOOK_SECRET` | Webhook auth header value | - | ### Resolution precedence For every configurable host, the SDK resolves in this order: 1. Explicit option on `new SonioxNodeClient({ ... })` (e.g. `base_url`, `tts_api_url`, `realtime.ws_base_url`, `realtime.tts_ws_url`). 2. Matching environment variable (`SONIOX_API_BASE_URL`, `SONIOX_TTS_API_URL`, `SONIOX_WS_URL`, `SONIOX_TTS_WS_URL`). 3. `base_domain` / `SONIOX_BASE_DOMAIN` — derives all service endpoints from `{service}.{base_domain}`. 4. `region` / `SONIOX_REGION` — shorthand for `base_domain: '{region}.soniox.com'`. 5. Root US default (no region prefix). Setting `region: 'eu'`, `region: 'jp'`, or `region: 'in'` resolves every host family — `api.*`, `stt-rt.*`, and `tts-rt.*` — to the matching regional variant. Use `SONIOX_TTS_API_URL` / `SONIOX_TTS_WS_URL` (or the corresponding explicit options) only when you need to override just the TTS hosts while leaving the rest of the client at its default region. ## Client ### Available client methods | Method | Description | | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | | [`client.files.upload(file, options)`](/sdk/node-SDK/reference/classes#sonioxfilesapi-upload) | Upload file | | [`client.files.list(options)`](/sdk/node-SDK/reference/classes#sonioxfilesapi-list) | List files | | [`client.files.count(options)`](/sdk/node-SDK/reference/classes#sonioxfilesapi-count) | Count uploaded files by source | | [`client.files.get(id)`](/sdk/node-SDK/reference/classes#sonioxfilesapi-get) | Get file | | [`client.files.delete(id)`](/sdk/node-SDK/reference/classes#sonioxfilesapi-delete) | Delete file | | [`client.files.delete_all()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-delete_all) | Delete all files | | --- | --- | | [`client.stt.create(options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-create) | Create transcription | | [`client.stt.list(options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-list) | List transcriptions | | [`client.stt.count(signal?)`](/sdk/node-SDK/reference/classes#sonioxsttapi-count) | Count transcriptions by request scope | | [`client.stt.get(id)`](/sdk/node-SDK/reference/classes#sonioxsttapi-get) | Get transcription | | [`client.stt.getTranscript(id)`](/sdk/node-SDK/reference/classes#sonioxsttapi-gettranscript) | Get transcription transcript | | [`client.stt.delete(id)`](/sdk/node-SDK/reference/classes#sonioxsttapi-delete) | Delete transcription | | [`client.stt.destroy(id)`](/sdk/node-SDK/reference/classes#sonioxsttapi-destroy) | Delete transcription and its file | | [`client.stt.wait(id)`](/sdk/node-SDK/reference/classes#sonioxsttapi-wait) | Wait for transcription to complete | | [`client.stt.transcribe(options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-transcribe) | Transcribe audio | | [`client.stt.translate(options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-translate) | Translate audio asynchronously | | [`client.stt.transcribeFromUrl(url, options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-transcribefromurl) | Transcribe audio from URL | | [`client.stt.transcribeFromFile(file, options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-transcribefromfile) | Transcribe audio from file | | [`client.stt.transcribeFromFileId(id, options)`](/sdk/node-SDK/reference/classes#sonioxsttapi-transcribefromfileid) | Transcribe audio from file ID | | [`client.stt.delete_all()`](/sdk/node-SDK/reference/classes#sonioxsttapi-delete_all) | Delete all transcriptions | | [`client.stt.destroy_all()`](/sdk/node-SDK/reference/classes#sonioxsttapi-destroy_all) | Delete all transcriptions and their files | | --- | --- | | [`client.tts.generate(options)`](/sdk/node-SDK/reference/classes#sonioxttsapi-generate) | Generate speech audio from text | | [`client.tts.generateStream(options)`](/sdk/node-SDK/reference/classes#sonioxttsapi-generatestream) | Generate speech audio as a streaming async iterable | | [`client.tts.generateToFile(output, options)`](/sdk/node-SDK/reference/classes#sonioxttsapi-generatetofile) | Generate speech audio and write it to a file or writable stream | | [`client.tts.listModels()`](/sdk/node-SDK/reference/classes#sonioxttsapi-listmodels) | List available TTS models and voices | | [`client.tts.voices.create(options)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-create) | Create a custom (cloned) voice from a reference audio clip | | [`client.tts.voices.list(options)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-list) | List voices in your project | | [`client.tts.voices.count(options)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-count) | Count voices in your project | | [`client.tts.voices.get(voice, signal?)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-get) | Get voice metadata | | [`client.tts.voices.delete(voice, signal?)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-delete) | Delete a voice | | [`client.tts.voices.delete_all(options)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-delete_all) | Delete all voices | | [`client.tts.voices.recompute(voice, options)`](/sdk/node-SDK/reference/classes#sonioxvoicesapi-recompute) | Prepare a voice for additional TTS models | | --- | --- | | [`client.models.list()`](/sdk/node-SDK/reference/classes#sonioxmodelsapi-list) | List available models | | --- | --- | | [`client.usageLogs.list(options)`](/sdk/node-SDK/reference/classes#sonioxusagelogsapi-list) | List per-request usage and cost logs | | [`client.usageLogs.getSummary(options)`](/sdk/node-SDK/reference/classes#sonioxusagelogsapi-getsummary) | Get daily usage and cost aggregated per model | | --- | --- | | [`client.concurrencyLimits.get(signal?)`](/sdk/node-SDK/reference/classes#sonioxconcurrencylimitsapi-get) | Get region-scoped concurrency counts and limits | | [`client.concurrencyLimits.getHistory(options)`](/sdk/node-SDK/reference/classes#sonioxconcurrencylimitsapi-gethistory) | Get historical concurrent stream aggregates per period | | --- | --- | | [`client.webhooks.handle(options)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-handle) | Handle webhook | | [`client.webhooks.handleRequest(request, options)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-handlerequest) | Handle webhook with Fetch API | | [`client.webhooks.handleExpress(req, options)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-handleexpress) | Handle webhook with Express | | [`client.webhooks.handleFastify(req, options)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-handlefastify) | Handle webhook with Fastify | | [`client.webhooks.handleNestJS(req, options)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-handlenestjs) | Handle webhook with NestJS | | [`client.webhooks.handleHono(c, options)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-handlehono) | Handle webhook with Hono | | [`client.webhooks.getAuthFromEnv()`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-getauthfromenv) | Get webhook auth from environment variables | | [`client.webhooks.verifyAuth(headers, auth)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-verifyauth) | Verify webhook auth | | [`client.webhooks.parseEvent(body)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-parseevent) | Parse webhook event | | [`client.webhooks.isEvent(body)`](/sdk/node-SDK/reference/classes#sonioxwebhooksapi-isevent) | Check if body is a webhook event | | --- | --- | | [`client.auth.createTemporaryKey(options)`](/sdk/node-SDK/reference/classes#sonioxauthapi-createtemporarykey) | Create temporary API key | | --- | --- | | [`client.realtime.stt(options)`](/sdk/node-SDK/reference/classes#sonioxrealtimeapi-stt) | Create real-time STT session | | [`client.realtime.tts(input?)`](/sdk/node-SDK/reference/classes#realtimettsstream) | Create a single real-time TTS stream (opens its own WebSocket) | | [`client.realtime.tts.multiStream()`](/sdk/node-SDK/reference/classes#realtimettsconnection) | Open a TTS WebSocket connection that can host multiple streams | ## File ### Available file instance methods | Method | Description | | -------------------------------------------------------------------- | ----------- | | [`file.delete()`](/sdk/node-SDK/reference/classes#sonioxfile-delete) | Delete file | ## Transcription ### Available transcription instance methods | Method | Description | | ---------------------------------------------------------------------------------------------------- | ---------------------------------- | | [`transcription.getTranscript()`](/sdk/node-SDK/reference/classes#sonioxtranscription-gettranscript) | Get transcription transcript | | [`transcription.delete()`](/sdk/node-SDK/reference/classes#sonioxtranscription-delete) | Delete transcription | | [`transcription.destroy()`](/sdk/node-SDK/reference/classes#sonioxtranscription-destroy) | Delete transcription and its file | | [`transcription.wait()`](/sdk/node-SDK/reference/classes#sonioxtranscription-wait) | Wait for transcription to complete | | [`transcription.refresh()`](/sdk/node-SDK/reference/classes#sonioxtranscription-refresh) | Refresh transcription | ## Translation job ### Available translation job instance methods | Method | Description | | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- | | [`translationJob.getTranslation()`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-gettranslation) | Fetch and reshape the completed transcript into a translation result | | [`translationJob.fetchTranslation()`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-fetchtranslation) | Alias for `getTranslation()` | | [`translationJob.getTranscript()`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-gettranscript) | Get the underlying transcription transcript | | [`translationJob.wait()`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-wait) | Wait for the translation job to complete | | [`translationJob.refresh()`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-refresh) | Refresh translation job status | ## Voice ### Available voice instance methods | Method | Description | | ----------------------------------------------------------------------------------- | ------------------------------------------------- | | [`voice.delete()`](/sdk/node-SDK/reference/classes#sonioxvoice-delete) | Permanently delete this voice | | [`voice.isReady(model)`](/sdk/node-SDK/reference/classes#sonioxvoice-isready) | Check if the voice is ready for a given TTS model | | [`voice.recompute(options)`](/sdk/node-SDK/reference/classes#sonioxvoice-recompute) | Prepare this voice for additional TTS models | | [`voice.toJSON()`](/sdk/node-SDK/reference/classes#sonioxvoice-tojson) | Get raw voice metadata | ## Transcript | Method | Description | | ------------------------------------------------------------------------------------ | ----------------------- | | [`transcript.segments()`](/sdk/node-SDK/reference/classes#sonioxtranscript-segments) | Get transcript segments | | [`transcript.text`](/sdk/node-SDK/reference/classes#sonioxtranscript) | Transcript text | | [`transcript.tokens`](/sdk/node-SDK/reference/classes#sonioxtranscript) | Transcript tokens | ## Real-time STT Session | Method | Description | | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------ | | [`realtime.stt.connect()`](/sdk/node-SDK/reference/classes#realtimesttsession-connect) | Establish websocket connection | | [`realtime.stt.close()`](/sdk/node-SDK/reference/classes#realtimesttsession-close) | Close websocket connection | | [`realtime.stt.finalize()`](/sdk/node-SDK/reference/classes#realtimesttsession-finalize) | Request server to finalize current transcription | | [`realtime.stt.finish()`](/sdk/node-SDK/reference/classes#realtimesttsession-finish) | Gracefully finish the session | | [`realtime.stt.keepAlive()`](/sdk/node-SDK/reference/classes#realtimesttsession-keepalive) | Send keepalive message | | [`realtime.stt.off()`](/sdk/node-SDK/reference/classes#realtimesttsession-off) | Remove event handler | | [`realtime.stt.on()`](/sdk/node-SDK/reference/classes#realtimesttsession-on) | Register event handler | | [`realtime.stt.once()`](/sdk/node-SDK/reference/classes#realtimesttsession-once) | Register one-time event handler | | [`realtime.stt.sendAudio(audio)`](/sdk/node-SDK/reference/classes#realtimesttsession-sendaudio) | Send audio chunk | | [`realtime.stt.sendStream(stream, options)`](/sdk/node-SDK/reference/classes#realtimesttsession-sendstream) | Send audio stream | | [`realtime.stt.pause()`](/sdk/node-SDK/reference/classes#realtimesttsession-pause) | Pause audio transmission | | [`realtime.stt.resume()`](/sdk/node-SDK/reference/classes#realtimesttsession-resume) | Resume audio transmission | | [`realtime.stt.paused`](/sdk/node-SDK/reference/classes#realtimesttsession-paused) | Whether the session is currently paused | | [`realtime.stt.state`](/sdk/node-SDK/reference/classes#realtimesttsession-state) | Current session state | ## Real-time TTS Stream | Method | Description | | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | | [`stream.sendText(text, options?)`](/sdk/node-SDK/reference/classes#realtimettsstream-sendtext) | Send one text chunk to the TTS stream | | [`stream.sendStream(source)`](/sdk/node-SDK/reference/classes#realtimettsstream-sendstream) | Pipe an async iterable of text chunks into the stream | | [`stream.finish()`](/sdk/node-SDK/reference/classes#realtimettsstream-finish) | Signal that no more text will be sent | | [`stream.cancel()`](/sdk/node-SDK/reference/classes#realtimettsstream-cancel) | Cancel generation and terminate the stream | | [`stream.close()`](/sdk/node-SDK/reference/classes#realtimettsstream-close) | Close the stream (and the WebSocket for single-stream usage) | | [`stream.on()`](/sdk/node-SDK/reference/classes#realtimettsstream-on) | Register event handler | | [`stream.once()`](/sdk/node-SDK/reference/classes#realtimettsstream-once) | Register one-time event handler | | [`stream.off()`](/sdk/node-SDK/reference/classes#realtimettsstream-off) | Remove event handler | | [`stream.state`](/sdk/node-SDK/reference/classes#realtimettsstream-state) | Current stream lifecycle state | | [`stream.streamId`](/sdk/node-SDK/reference/classes#realtimettsstream-properties) | Identifier of this TTS stream | ## Real-time TTS Connection | Method | Description | | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | | [`connection.connect()`](/sdk/node-SDK/reference/classes#realtimettsconnection-connect) | Open the WebSocket connection | | [`connection.stream(input?)`](/sdk/node-SDK/reference/classes#realtimettsconnection-stream) | Open a new TTS stream on this connection | | [`connection.close()`](/sdk/node-SDK/reference/classes#realtimettsconnection-close) | Close the WebSocket connection and terminate all active streams | | [`connection.on()`](/sdk/node-SDK/reference/classes#realtimettsconnection-on) | Register event handler | | [`connection.once()`](/sdk/node-SDK/reference/classes#realtimettsconnection-once) | Register one-time event handler | | [`connection.off()`](/sdk/node-SDK/reference/classes#realtimettsconnection-off) | Remove event handler | | [`connection.isConnected`](/sdk/node-SDK/reference/classes#realtimettsconnection-isconnected) | Whether the WebSocket is currently connected | # Types URL: /sdk/node-SDK/reference/types Soniox Node SDK — Types Reference ## AudioData ```ts type AudioData = Buffer | Uint8Array | ArrayBuffer; ``` Audio data types accepted by sendAudio. In Node.js, Buffer is also accepted since Buffer extends Uint8Array. *** ## AudioFormat ```ts type AudioFormat = | "pcm_s8" | "pcm_s8le" | "pcm_s8be" | "pcm_s16le" | "pcm_s16be" | "pcm_s24le" | "pcm_s24be" | "pcm_s32le" | "pcm_s32be" | "pcm_u8" | "pcm_u8le" | "pcm_u8be" | "pcm_u16le" | "pcm_u16be" | "pcm_u24le" | "pcm_u24be" | "pcm_u32le" | "pcm_u32be" | "pcm_f32le" | "pcm_f32be" | "pcm_f64le" | "pcm_f64be" | "mulaw" | "alaw" | "aac" | "aiff" | "amr" | "asf" | "wav" | "mp3" | "flac" | "ogg" | "webm"; ``` Supported audio formats for real-time transcription. *** ## CleanupTarget ```ts type CleanupTarget = "file" | "transcription"; ``` Resource types that can be cleaned up after transcription completes. * `'file'` - The uploaded file * `'transcription'` - The transcription record *** ## ConcurrencyCurrentValues ```ts type ConcurrencyCurrentValues = { transcribe_concurrent: number; tts_concurrent: number; }; ``` Live concurrency counts. **Properties** | Property | Type | Description | | --------------------------------------------------------------------------------- | -------- | ---------------------------------------------------- | | `transcribe_concurrent` | `number` | Current number of concurrent transcription sessions. | | `tts_concurrent` | `number` | Current number of concurrent TTS sessions. | *** ## ConcurrencyLimitValues ```ts type ConcurrencyLimitValues = { transcribe_concurrent: number | null; tts_concurrent: number | null; }; ``` Configured concurrency limits. **Properties** | Property | Type | Description | | ------------------------------------------------------------------------------- | ------------------ | --------------------------------------------------------------------------- | | `transcribe_concurrent` | `number` \| `null` | Configured transcription concurrency limit. Null means no configured limit. | | `tts_concurrent` | `number` \| `null` | Configured TTS concurrency limit. Null means no configured limit. | *** ## ConcurrencyLimitsResponse ```ts type ConcurrencyLimitsResponse = { organization: ConcurrencyScopeValues; project: ConcurrencyScopeValues; }; ``` Current concurrent counts plus configured concurrency limits for the project and its organization. Values are region-scoped. **Properties** | Property | Type | Description | | ---------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------- | | `organization` | [`ConcurrencyScopeValues`](types#concurrencyscopevalues) | Organization-level concurrency counts and limits. | | `project` | [`ConcurrencyScopeValues`](types#concurrencyscopevalues) | Project-level concurrency counts and limits. | *** ## ConcurrencyScopeValues ```ts type ConcurrencyScopeValues = { current: ConcurrencyCurrentValues; limits: ConcurrencyLimitValues; }; ``` Current counts and configured limits for a concurrency scope. **Properties** | Property | Type | Description | | --------------------------------------------------- | ------------------------------------------------------------ | -------------------------------- | | `current` | [`ConcurrencyCurrentValues`](types#concurrencycurrentvalues) | Current live concurrency counts. | | `limits` | [`ConcurrencyLimitValues`](types#concurrencylimitvalues) | Configured concurrency limits. | *** ## ConcurrentStreamKind ```ts type ConcurrentStreamKind = "stt" | "tts"; ``` Stream kind for concurrent streams history. * `stt`: Speech-to-Text WebSocket sessions * `tts`: Text-to-Speech WebSocket streams and REST requests *** ## ConcurrentStreamsHistoryEntry ```ts type ConcurrentStreamsHistoryEntry = { period_sec: number; period_start: string; sample_count: number; sample_max: number; sample_min: number; sample_sum: number; total_count: number; }; ``` Per-period concurrent stream aggregate for the authenticated project. **Properties** | Property | Type | Description | | -------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `period_sec` | `number` | Aggregation period in seconds. | | `period_start` | `string` | Start of the aggregation period, UTC. Aligned to a multiple of `period_sec`. **Format** date-time | | `sample_count` | `number` | Number of values actually recorded in the period. For `period_sec=60` this is how many samples were taken during that minute, so it is usually larger than `total_count`. For hourly and daily periods it is the number of source periods that had data, at most `total_count`. `0` when the period had no activity. | | `sample_max` | `number` | Peak concurrent stream count in the period. Stays exact when periods are rolled up into hours and days. `0` when the period had no activity. | | `sample_min` | `number` | Lowest recorded concurrent stream count in the period. Always `0`, at every tier, because that is what the per-minute tier records. Use `sample_max` for the peak. | | `sample_sum` | `number` | Sum of the recorded concurrency values in the period. Divide by `sample_count` for the average while streams were active, or by `total_count` for the average across the whole period (idle slots as zero). | | `total_count` | `number` | Number of slots the period covers. `1` for `period_sec=60`, `60` for `3600` (minutes per hour), `24` for `86400` (hours per day). `0` when the period had no activity. | *** ## ConcurrentStreamsHistoryPeriodSec ```ts type ConcurrentStreamsHistoryPeriodSec = 60 | 3600 | 86400; ``` Aggregation period for concurrent streams history, in seconds. * `60`: per-minute * `3600`: hourly * `86400`: daily *** ## ConcurrentStreamsHistoryResponse ```ts type ConcurrentStreamsHistoryResponse = { entries: ConcurrentStreamsHistoryEntry[]; kind: ConcurrentStreamKind; }; ``` Concurrent streams history for the authenticated project. **Properties** | Property | Type | Description | | ------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `entries` | [`ConcurrentStreamsHistoryEntry`](types#concurrentstreamshistoryentry)\[] | Per-period aggregates ordered by `period_start` ascending. Every aggregation period in the requested window is returned, with no gaps. Periods with no recorded activity have every numeric field set to `0`. | | `kind` | [`ConcurrentStreamKind`](types#concurrentstreamkind) | Stream kind these entries describe (`stt` or `tts`). | *** ## ContextGeneralEntry ```ts type ContextGeneralEntry = { key: string; value: string; }; ``` Key-value pair for general context information. **Properties** | Property | Type | Description | | -------------------------------------------- | -------- | ------------------------------------------------------------------------ | | `key` | `string` | The key describing the context type (e.g., "domain", "topic", "doctor"). | | `value` | `string` | The value for the context key. | *** ## ContextTranslationTerm ```ts type ContextTranslationTerm = { source: string; target: string; }; ``` Custom translation term mapping. **Properties** | Property | Type | Description | | ------------------------------------------------- | -------- | ------------------------------------ | | `source` | `string` | The source term to translate. | | `target` | `string` | The target translation for the term. | *** ## CreateTranscriptionOptions ```ts type CreateTranscriptionOptions = { audio_url?: string; client_reference_id?: string; context?: TranscriptionContext; enable_language_identification?: boolean; enable_speaker_diarization?: boolean; file_id?: string; language_hints?: string[]; language_hints_strict?: boolean; model: string; translation?: TranslationConfig; webhook_auth_header_name?: string; webhook_auth_header_value?: string; webhook_url?: string; }; ``` Options for creating a transcription. **Properties** | Property | Type | Description | | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | `audio_url?` | `string` | URL of a publicly accessible audio file. **Max Length** 4096 | | `client_reference_id?` | `string` | Optional tracking identifier. **Max Length** 256 | | `context?` | [`TranscriptionContext`](types#transcriptioncontext) | Additional context to improve transcription accuracy and formatting of specialized terms. | | `enable_language_identification?` | `boolean` | Enable automatic language identification. | | `enable_speaker_diarization?` | `boolean` | Enable speaker diarization to identify different speakers. | | `file_id?` | `string` | ID of a previously uploaded file. **Format** uuid | | `language_hints?` | `string`\[] | Array of expected ISO language codes to bias recognition. | | `language_hints_strict?` | `boolean` | When true, model relies more heavily on language hints. | | `model` | `string` | Speech-to-text model to use. **Max Length** 32 | | `translation?` | [`TranslationConfig`](types#translationconfig) | Translation configuration. | | `webhook_auth_header_name?` | `string` | Name of the authentication header sent with webhook notifications. **Max Length** 256 | | `webhook_auth_header_value?` | `string` | Authentication header value sent with webhook notifications. **Max Length** 256 | | `webhook_url?` | `string` | URL to receive webhook notifications when transcription is completed or fails. **Max Length** 256 | *** ## CreateVoiceInput ```ts type CreateVoiceInput = UploadFileInput; ``` Supported input types for the reference audio clip. *** ## CreateVoiceOptions ```ts type CreateVoiceOptions = { file: CreateVoiceInput; filename?: string; name: string; signal?: AbortSignal; timeout_ms?: number; }; ``` Options for creating a voice. **Properties** | Property | Type | Description | | ------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------- | | `file` | [`CreateVoiceInput`](types#createvoiceinput) | The reference audio clip for the voice. Keep it up to 2 minutes and within 35 MB. | | `filename?` | `string` | Custom filename for the uploaded reference clip. | | `name` | `string` | A name for the voice, unique within your project. **Min Length** 1 **Max Length** 128 | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request. | | `timeout_ms?` | `number` | Request timeout in milliseconds. | *** ## DeleteAllFilesOptions ```ts type DeleteAllFilesOptions = { signal?: AbortSignal; }; ``` Options for purging all files. **Properties** | Property | Type | Description | | ------------------------------------------------- | ------------- | ----------------------------------------------------- | | `signal?` | `AbortSignal` | AbortSignal for cancelling the delete\_all operation. | *** ## DeleteAllTranscriptionsOptions ```ts type DeleteAllTranscriptionsOptions = { on_progress?: (transcription, index) => void; signal?: AbortSignal; }; ``` Options for deleting all transcriptions. **Properties** | Property | Type | Description | | -------------------------------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `on_progress?` | (`transcription`, `index`) => `void` | Callback invoked before each transcription is deleted. Receives the transcription data and its 0-based index. | | `signal?` | `AbortSignal` | AbortSignal for cancelling the delete\_all operation. | *** ## DeleteAllVoicesOptions ```ts type DeleteAllVoicesOptions = { signal?: AbortSignal; }; ``` Options for deleting all voices. **Properties** | Property | Type | Description | | -------------------------------------------------- | ------------- | ----------------------------------------------------- | | `signal?` | `AbortSignal` | AbortSignal for cancelling the delete\_all operation. | *** ## ExpressLikeRequest ```ts type ExpressLikeRequest = { body?: unknown; headers: Record; method: string; }; ``` Express/Connect-style request object **Properties** | Property | Type | | ----------------------------------------------- | ----------------------------------------------------------- | | `body?` | `unknown` | | `headers` | `Record`\<`string`, `string` \| `string`\[] \| `undefined`> | | `method` | `string` | *** ## FastifyLikeRequest ```ts type FastifyLikeRequest = { body?: unknown; headers: Record; method: string; }; ``` Fastify-style request object **Properties** | Property | Type | | ----------------------------------------------- | ----------------------------------------------------------- | | `body?` | `unknown` | | `headers` | `Record`\<`string`, `string` \| `string`\[] \| `undefined`> | | `method` | `string` | *** ## FileIdentifier ```ts type FileIdentifier = | string | { id: string; }; ``` File identifier - either a string ID or an object with an id property. *** ## FilesCountResponse ```ts type FilesCountResponse = { playground: number; public_api: number; total: number; }; ``` Total number of files, split by source. **Properties** | Property | Type | Description | | ----------------------------------------------------- | -------- | -------------------------------------------- | | `playground` | `number` | Number of files uploaded via the Playground. | | `public_api` | `number` | Number of files uploaded via Public API. | | `total` | `number` | Total number of files across all sources. | *** ## GenerateSpeechOptions ```ts type GenerateSpeechOptions = { audio_format?: string; bitrate?: number; client_reference_id?: string; language?: string; model?: string; reduce_silence?: boolean; sample_rate?: number; signal?: AbortSignal; speed?: number; text: string; voice: string; }; ``` Options for REST TTS generation (`generate` / `generateStream`). **Properties** | Property | Type | Description | | --------------------------------------------------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio_format?` | `string` | Output audio format **Default** `'wav'` | | `bitrate?` | `number` | Codec bitrate in bps (for compressed formats). | | `client_reference_id?` | `string` | Optional tracking identifier. Does not need to be unique. Ignored if the request authenticates with a temporary API key. **Max Length** 256 | | `language?` | `string` | Language code. **Default** `'en'` | | `model?` | `string` | Text-to-Speech model to use. **Default** `'tts-rt-v2'` | | `reduce_silence?` | `boolean` | Shorten pauses between words in the generated speech. `false` (default) keeps the model's natural pacing; `true` tightens delivery by reducing silence between words. | | `sample_rate?` | `number` | Output sample rate in Hz. Required for raw PCM formats. | | `signal?` | `AbortSignal` | Optional AbortSignal for cancellation. | | `speed?` | `number` | Speaking rate. `1.0` is the normal rate; values below `1.0` slow speech down and values above `1.0` speed it up. Supported range is `0.7`-`1.3`. Defaults to `1.0` when omitted. | | `text` | `string` | Input text to generate as speech. | | `voice` | `string` | Voice identifier. | *** ## GetConcurrentStreamsHistoryOptions ```ts type GetConcurrentStreamsHistoryOptions = { end_time: string; kind: ConcurrentStreamKind; period_sec: ConcurrentStreamsHistoryPeriodSec; signal?: AbortSignal; start_time: string; }; ``` Options for retrieving concurrent streams history. **Properties** | Property | Type | Description | | --------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `end_time` | `string` | End of the time window (exclusive). Must be an ISO 8601 timestamp in UTC and strictly after `start_time`. Filters by `period_start`. **Example** `'2026-04-28T10:00:00Z'` | | `kind` | [`ConcurrentStreamKind`](types#concurrentstreamkind) | Stream kind to return. | | `period_sec` | [`ConcurrentStreamsHistoryPeriodSec`](types#concurrentstreamshistoryperiodsec) | Aggregation period in seconds. Also caps how long the requested window may be: for `period_sec=60` the window must not exceed 7 days. A window longer than the cap for its period, or one that would return more than 20000 entries, is rejected with a `400 invalid_request` error. | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request. | | `start_time` | `string` | Start of the time window (inclusive). Must be an ISO 8601 timestamp in UTC. Filters by `period_start`. **Example** `'2026-04-28T09:00:00Z'` | *** ## GetUsageSummaryOptions ```ts type GetUsageSummaryOptions = { end_time: string; signal?: AbortSignal; start_time: string; }; ``` Options for retrieving an aggregated usage summary. Usage is aggregated by whole UTC day over the half-open window `[start_time, end_time)`: a day is included when the window covers any part of it. The window must not cover more than 366 UTC days. **Properties** | Property | Type | Description | | --------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `end_time` | `string` | End of the window (exclusive). Must be an ISO 8601 timestamp in UTC and strictly after `start_time`. Its UTC day is included unless it falls exactly on midnight. **Example** `'2026-04-03T00:00:00Z'` | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request. | | `start_time` | `string` | Start of the window (inclusive). Must be an ISO 8601 timestamp in UTC. Its UTC day is included. **Example** `'2026-04-01T00:00:00Z'` | *** ## HandleWebhookOptions ```ts type HandleWebhookOptions = { auth?: WebhookAuthConfig; body: unknown; headers: WebhookHeaders; method: string; }; ``` Options for the handleWebhook function **Properties** | Property | Type | Description | | ------------------------------------------------- | ---------------------------------------------- | ---------------------------------------- | | `auth?` | [`WebhookAuthConfig`](types#webhookauthconfig) | Optional authentication configuration | | `body` | `unknown` | Request body (parsed JSON or raw string) | | `headers` | [`WebhookHeaders`](types#webhookheaders) | Request headers | | `method` | `string` | HTTP method of the request | *** ## HonoLikeContext ```ts type HonoLikeContext = { req: { method: string; header: string | undefined; json: Promise; }; }; ``` Hono context object **Properties** | Property | Type | | ------------------------------------------------- | ------------------------------------------------------------------------------------------ | | `req` | \{ `method`: `string`; `header`: `string` \| `undefined`; `json`: `Promise`\<`unknown`>; } | | `req.method` | `string` | | `req.header` | `string` \| `undefined` | | `req.json` | `Promise`\<`unknown`> | *** ## HttpErrorCode ```ts type HttpErrorCode = "network_error" | "timeout" | "aborted" | "http_error" | "parse_error"; ``` Error codes for HTTP client errors *** ## HttpMethod ```ts type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD"; ``` HTTP methods supported by the client *** ## HttpRequestBody ```ts type HttpRequestBody = | string | Record | ArrayBuffer | Uint8Array | FormData | null; ``` Request body types *** ## HttpResponseType ```ts type HttpResponseType = "json" | "text" | "arrayBuffer"; ``` Response types *** ## ListFilesOptions ```ts type ListFilesOptions = { cursor?: string; limit?: number; signal?: AbortSignal; }; ``` Options for listing files. **Properties** | Property | Type | Description | | -------------------------------------------- | ------------- | ------------------------------------------------------------------------------------ | | `cursor?` | `string` | Pagination cursor for the next page of results. | | `limit?` | `number` | Maximum number of files to return. **Default** `1000` **Minimum** 1 **Maximum** 1000 | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request | *** ## ListFilesResponse\ ```ts type ListFilesResponse = { files: T[]; next_page_cursor: string | null; }; ``` Response from listing files. **Type Parameters** | Type Parameter | | -------------- | | `T` | **Properties** | Property | Type | Description | | ----------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------ | | `files` | `T`\[] | List of uploaded files. | | `next_page_cursor` | `string` \| `null` | A pagination token that references the next page of results. When null, no additional results are available. | *** ## ListTranscriptionsOptions ```ts type ListTranscriptionsOptions = { cursor?: string; limit?: number; }; ``` Options for listing transcriptions **Properties** | Property | Type | Description | | ----------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------- | | `cursor?` | `string` | Pagination cursor for the next page of results | | `limit?` | `number` | Maximum number of transcriptions to return. **Default** `1000` **Minimum** 1 **Maximum** 1000 | *** ## ListTranscriptionsResponse\ ```ts type ListTranscriptionsResponse = { next_page_cursor: string | null; transcriptions: T[]; }; ``` Response from listing transcriptions. **Type Parameters** | Type Parameter | | -------------- | | `T` | **Properties** | Property | Type | Description | | -------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `next_page_cursor` | `string` \| `null` | A pagination token that references the next page of results. When null, no additional results are available. TODO: potentially can be undefined? | | `transcriptions` | `T`\[] | List of transcriptions. | *** ## ListUsageLogsOptions ```ts type ListUsageLogsOptions = { cursor?: string; end_time: string; limit?: number; signal?: AbortSignal; sort?: UsageLogsSort; start_time: string; }; ``` Options for listing usage logs. **Properties** | Property | Type | Description | | ------------------------------------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `cursor?` | `string` | Pagination cursor for the next page of results. | | `end_time` | `string` | End of the time window (exclusive), filtering by request end time. Must be an ISO 8601 timestamp in UTC. **Example** `'2026-04-29T09:00:00Z'` | | `limit?` | `number` | Maximum number of usage log entries to return. **Default** `1000` **Minimum** 1 **Maximum** 1000 | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request. | | `sort?` | [`UsageLogsSort`](types#usagelogssort) | Sort order by end\_time. **Default** `'end_time_asc'` | | `start_time` | `string` | Start of the time window (inclusive), filtering by request end time. Must be an ISO 8601 timestamp in UTC. **Example** `'2026-04-28T09:00:00Z'` | *** ## ListUsageLogsResponse ```ts type ListUsageLogsResponse = { next_page_cursor: string | null; usage_logs: SonioxUsageLog[]; }; ``` Response from listing usage logs. **Properties** | Property | Type | Description | | -------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------- | | `next_page_cursor` | `string` \| `null` | Pagination cursor for the next page of results. Null if no more pages. | | `usage_logs` | [`SonioxUsageLog`](types#sonioxusagelog)\[] | Per-request usage log entries ordered by end\_time and UUID. | *** ## ListVoicesOptions ```ts type ListVoicesOptions = { cursor?: string; limit?: number; signal?: AbortSignal; }; ``` Options for listing voices. **Properties** | Property | Type | Description | | --------------------------------------------- | ------------- | ----------------------------------------------- | | `cursor?` | `string` | Pagination cursor for the next page of results. | | `limit?` | `number` | Maximum number of voices to return. | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request. | *** ## ListVoicesResponse\ ```ts type ListVoicesResponse = { next_page_cursor: string | null; voices: T[]; }; ``` Response from listing voices. **Type Parameters** | Type Parameter | | -------------- | | `T` | **Properties** | Property | Type | Description | | ------------------------------------------------------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------ | | `next_page_cursor` | `string` \| `null` | A pagination token that references the next page of results. When null, no additional results are available. | | `voices` | `T`\[] | List of voices. | *** ## NestJSLikeRequest ```ts type NestJSLikeRequest = { body?: unknown; headers: Record; method: string; }; ``` NestJS-style request object (uses Express under the hood by default) **Properties** | Property | Type | | ---------------------------------------------- | ----------------------------------------------------------- | | `body?` | `unknown` | | `headers` | `Record`\<`string`, `string` \| `string`\[] \| `undefined`> | | `method` | `string` | *** ## OneWayTranslation ```ts type OneWayTranslation = { duration_ms: number; from?: string; mode: "one_way"; original_text: string; segments: TranslationSegment[]; to: string; translation_text: string; }; ``` Result of a one-way translation (`{ to }` or `{ to, from }` mode). `original_text` and `translation_text` flatten the per-segment content across the whole audio, which is useful when the caller just wants two parallel strings. **Properties** | Property | Type | Description | | ---------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | `duration_ms` | `number` | Total audio duration in milliseconds. Equals the largest `end_ms` across all original tokens, or `0` when there are no original tokens. | | `from?` | `string` | Source language hint that was supplied via `from`. Undefined when only `to` was provided and the source language was auto-detected. | | `mode` | `"one_way"` | - | | `original_text` | `string` | Concatenated text of every original token across all segments. | | `segments` | [`TranslationSegment`](types#translationsegment)\[] | Per-utterance segments in audio order. | | `to` | `string` | Target language code (the `to` value passed in). | | `translation_text` | `string` | Concatenated text of every translation token across all segments. | *** ## OneWayTranslationConfig ```ts type OneWayTranslationConfig = { target_language: string; type: "one_way"; }; ``` One-way translation configuration. Translates all spoken languages into a single target language. **Properties** | Property | Type | Description | | -------------------------------------------------------------------- | ----------- | -------------------------------------------------------------- | | `target_language` | `string` | Target language code for translation (e.g., "fr", "es", "de"). | | `type` | `"one_way"` | Translation type. | *** ## QueryParams ```ts type QueryParams = Record; ``` Query parameters *** ## RealtimeClientOptions ```ts type RealtimeClientOptions = { api_key: string; default_session_options?: SttSessionOptions; stt_defaults?: Partial; tts_connection_options?: TtsConnectionOptions; tts_defaults?: Partial; tts_ws_url: string; ws_base_url: string; }; ``` Real-time API configuration options for the client. **Properties** | Property | Type | Description | | ----------------------------------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `api_key` | `string` | API key for real-time sessions. | | `default_session_options?` | [`SttSessionOptions`](types#sttsessionoptions) | Default session options applied to all real-time STT sessions. Can be overridden per-session. | | `stt_defaults?` | `Partial`\<[`SttSessionConfig`](types#sttsessionconfig)> | STT session config defaults. Merged as the base layer when opening STT sessions via `realtime.stt(config)`; caller fields override. | | `tts_connection_options?` | [`TtsConnectionOptions`](types#ttsconnectionoptions) | Default TTS connection options. | | `tts_defaults?` | `Partial`\<[`TtsStreamConfig`](types#ttsstreamconfig)> | TTS stream config defaults. Merged as the base layer when opening TTS streams via `realtime.tts(...)`; caller fields override. | | `tts_ws_url` | `string` | TTS WebSocket URL for real-time connections. **Default** `'wss://tts-rt.soniox.com/tts-websocket'` | | `ws_base_url` | `string` | STT WebSocket base URL for real-time connections. **Default** `'wss://stt-rt.soniox.com/transcribe-websocket'` | *** ## RealtimeErrorCode ```ts type RealtimeErrorCode = | "auth_error" | "bad_request" | "quota_exceeded" | "connection_error" | "network_error" | "aborted" | "state_error" | "realtime_error"; ``` Error codes for Real-time (WebSocket) API errors *** ## RealtimeEvent ```ts type RealtimeEvent = | { data: RealtimeResult; kind: "result"; } | { kind: "endpoint"; } | { kind: "finalized"; } | { kind: "finished"; }; ``` Typed event for async iterator consumption. *** ## RealtimeOptions ```ts type RealtimeOptions = { default_session_options?: SttSessionOptions; stt_defaults?: Partial; tts_connection_options?: TtsConnectionOptions; tts_defaults?: Partial; tts_ws_url?: string; ws_base_url?: string; }; ``` Real-time configuration options for the main client. **Properties** | Property | Type | Description | | ----------------------------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `default_session_options?` | [`SttSessionOptions`](types#sttsessionoptions) | Default session options applied to all real-time STT sessions. Can be overridden per-session. | | `stt_defaults?` | `Partial`\<[`SttSessionConfig`](types#sttsessionconfig)> | Default STT session config fields (model, language hints, context, etc.). Merged as the base layer when opening STT sessions via `client.realtime.stt(config)`. Fields on the caller-provided `config` override these defaults. Equivalent to SonioxConnectionConfig.stt\_defaults on the web/react clients. | | `tts_connection_options?` | [`TtsConnectionOptions`](types#ttsconnectionoptions) | Default TTS connection options (keepalive interval, connect timeout). | | `tts_defaults?` | `Partial`\<[`TtsStreamConfig`](types#ttsstreamconfig)> | Default TTS stream config fields (model, voice, language, audio\_format, etc.). Merged as the base layer when opening TTS streams via `client.realtime.tts(...)`. Fields on the caller-provided [TtsStreamInput](types#ttsstreaminput) override these defaults. Equivalent to SonioxConnectionConfig.tts\_defaults on the web/react clients. | | `tts_ws_url?` | `string` | TTS WebSocket URL for real-time connections. Falls back to SONIOX\_TTS\_WS\_URL environment variable, then to 'wss\://tts-rt.soniox.com/tts-websocket'. | | `ws_base_url?` | `string` | STT WebSocket base URL for real-time connections. Falls back to SONIOX\_WS\_URL environment variable, then to 'wss\://stt-rt.soniox.com/transcribe-websocket'. | *** ## RealtimeResult ```ts type RealtimeResult = { final_audio_proc_ms: number; finished?: boolean; tokens: RealtimeToken[]; total_audio_proc_ms: number; }; ``` A result message from the real-time WebSocket. **Properties** | Property | Type | Description | | ------------------------------------------------------------------- | ----------------------------------------- | -------------------------------------------------- | | `final_audio_proc_ms` | `number` | Milliseconds of audio that have been finalized. | | `finished?` | `boolean` | Whether this is the final result (session ending). | | `tokens` | [`RealtimeToken`](types#realtimetoken)\[] | Tokens in this result. | | `total_audio_proc_ms` | `number` | Total milliseconds of audio processed. | *** ## RealtimeSegment ```ts type RealtimeSegment = { end_ms?: number; language?: string; speaker?: string; start_ms?: number; text: string; tokens: RealtimeToken[]; }; ``` A segment of contiguous real-time tokens grouped by speaker/language. **Properties** | Property | Type | Description | | ----------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------- | | `end_ms?` | `number` | End time of the segment in milliseconds (from last token). | | `language?` | `string` | Detected language code (if language identification enabled). | | `speaker?` | `string` | Speaker identifier (if diarization enabled). | | `start_ms?` | `number` | Start time of the segment in milliseconds (from first token). | | `text` | `string` | Concatenated text of all tokens in this segment. | | `tokens` | [`RealtimeToken`](types#realtimetoken)\[] | Original tokens in this segment. | *** ## RealtimeSegmentBufferOptions ```ts type RealtimeSegmentBufferOptions = { final_only?: boolean; group_by?: SegmentGroupKey[]; max_ms?: number; max_tokens?: number; }; ``` Options for rolling real-time segmentation buffers. **Properties** | Property | Type | Description | | ---------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `final_only?` | `boolean` | When true, only tokens marked as final are buffered. **Default** `true` | | `group_by?` | [`SegmentGroupKey`](types#segmentgroupkey)\[] | Fields to group by. A new segment starts when any of these fields changes **Default** `['speaker', 'language']` | | `max_ms?` | `number` | Maximum time window to keep in milliseconds (requires token timings). | | `max_tokens?` | `number` | Maximum number of tokens to keep in the buffer. **Default** `2000` | *** ## RealtimeSegmentOptions ```ts type RealtimeSegmentOptions = { final_only?: boolean; group_by?: SegmentGroupKey[]; }; ``` Options for segmenting real-time tokens. **Properties** | Property | Type | Description | | ---------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `final_only?` | `boolean` | When true, only tokens marked as final are included. **Default** `false` | | `group_by?` | [`SegmentGroupKey`](types#segmentgroupkey)\[] | Fields to group by. A new segment starts when any of these fields changes **Default** `['speaker', 'language']` | *** ## RealtimeToken ```ts type RealtimeToken = { confidence: number; end_ms?: number; is_final: boolean; language?: string; source_language?: string; speaker?: string; start_ms?: number; text: string; translation_status?: "none" | "original" | "translation"; }; ``` A single token from the real-time transcription. **Properties** | Property | Type | Description | | ----------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------ | | `confidence` | `number` | Confidence score (0.0 to 1.0). | | `end_ms?` | `number` | End time in milliseconds relative to audio start. | | `is_final` | `boolean` | Whether this is a finalized token. | | `language?` | `string` | Detected language code (if language identification enabled). | | `source_language?` | `string` | Source language for translated tokens. | | `speaker?` | `string` | Speaker identifier (if diarization enabled). | | `start_ms?` | `number` | Start time in milliseconds relative to audio start. | | `text` | `string` | The transcribed text. | | `translation_status?` | `"none"` \| `"original"` \| `"translation"` | Translation status of this token. | *** ## RealtimeUtterance ```ts type RealtimeUtterance = { end_ms?: number; final_audio_proc_ms?: number; language?: string; segments: RealtimeSegment[]; speaker?: string; start_ms?: number; text: string; tokens: RealtimeToken[]; total_audio_proc_ms?: number; }; ``` A single utterance built from real-time segments. **Properties** | Property | Type | Description | | ----------------------------------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------- | | `end_ms?` | `number` | End time of the utterance in milliseconds (from last segment). | | `final_audio_proc_ms?` | `number` | Milliseconds of audio that have been finalized at flush time. | | `language?` | `string` | Detected language code when consistent across segments. | | `segments` | [`RealtimeSegment`](types#realtimesegment)\[] | Segments included in this utterance. | | `speaker?` | `string` | Speaker identifier when consistent across segments. | | `start_ms?` | `number` | Start time of the utterance in milliseconds (from first segment). | | `text` | `string` | Concatenated text of all segments in this utterance. | | `tokens` | [`RealtimeToken`](types#realtimetoken)\[] | Tokens included in this utterance. | | `total_audio_proc_ms?` | `number` | Total milliseconds of audio processed at flush time. | *** ## RealtimeUtteranceBufferOptions ```ts type RealtimeUtteranceBufferOptions = { final_only?: boolean; group_by?: SegmentGroupKey[]; max_ms?: number; max_tokens?: number; }; ``` Options for buffering real-time utterances. **Properties** | Property | Type | Description | | ------------------------------------------------------------------ | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `final_only?` | `boolean` | When true, only tokens marked as final are buffered. **Default** `true` | | `group_by?` | [`SegmentGroupKey`](types#segmentgroupkey)\[] | Fields to group by. A new segment starts when any of these fields changes **Default** `['speaker', 'language']` | | `max_ms?` | `number` | Maximum time window to keep in milliseconds (requires token timings). | | `max_tokens?` | `number` | Maximum number of tokens to keep in the buffer. **Default** `2000` | *** ## RecomputeVoiceOptions ```ts type RecomputeVoiceOptions = { model?: string | null; signal?: AbortSignal; }; ``` Options for recomputing a voice. **Properties** | Property | Type | Description | | ------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------- | | `model?` | `string` \| `null` | The model to prepare this voice for. If omitted, the voice is prepared for every available model it is not ready for yet. | | `signal?` | `AbortSignal` | AbortSignal for cancelling the request. | *** ## SegmentGroupKey ```ts type SegmentGroupKey = "speaker" | "language"; ``` Fields that can be used to group tokens into segments *** ## SegmentTranscriptOptions ```ts type SegmentTranscriptOptions = { group_by?: SegmentGroupKey[]; }; ``` Options for segmenting a transcript **Properties** | Property | Type | Description | | -------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `group_by?` | [`SegmentGroupKey`](types#segmentgroupkey)\[] | Fields to group by. A new segment starts when any of these fields changes **Default** `['speaker', 'language']` | *** ## SendStreamOptions ```ts type SendStreamOptions = { finish?: boolean; pace_ms?: number; }; ``` Options for streaming audio from an async iterable source. **Properties** | Property | Type | Description | | ----------------------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `finish?` | `boolean` | When true, calls finish() automatically after the stream ends. **Default** `false` | | `pace_ms?` | `number` | Delay in milliseconds between sending chunks. Useful for simulating real-time pace when streaming pre-recorded files. Not needed for live audio sources. | *** ## SonioxErrorCode ```ts type SonioxErrorCode = | RealtimeErrorCode | "soniox_error" | HttpErrorCode; ``` All possible SDK error codes (real-time + HTTP-specific codes) *** ## SonioxFileData ```ts type SonioxFileData = { client_reference_id?: string | null; created_at: string; filename: string; id: string; size: number; }; ``` Raw file metadata from the API. **Properties** | Property | Type | Description | | -------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------- | | `client_reference_id?` | `string` \| `null` | Optional tracking identifier string. | | `created_at` | `string` | UTC timestamp indicating when the file was uploaded. **Format** date-time | | `filename` | `string` | Name of the file. | | `id` | `string` | Unique identifier of the file. **Format** uuid | | `size` | `number` | Size of the file in bytes. | *** ## SonioxLanguage ```ts type SonioxLanguage = { code: string; name: string; }; ``` **Properties** | Property | Type | Description | | ------------------------------------- | -------- | ----------------------- | | `code` | `string` | 2-letter language code. | | `name` | `string` | Language name. | *** ## SonioxModel ```ts type SonioxModel = { aliased_model_id: string | null; context_version: number | null; endpoint_latency_adjustment_max_level: number; id: string; languages: SonioxLanguage[]; name: string; one_way_translation: string | null; supports_endpoint_latency_adjustment: boolean; supports_endpoint_sensitivity: boolean; supports_language_hints_strict: boolean; supports_max_endpoint_delay: boolean; transcription_mode: SonioxTranscriptionMode; translation_targets: SonioxTranslationTarget[]; two_way_translation: string | null; two_way_translation_pairs: string[]; }; ``` **Properties** | Property | Type | Description | | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `aliased_model_id` | `string` \| `null` | If this is an alias, the id of the aliased model. Null for non-alias models. | | `context_version` | `number` \| `null` | Version of context supported. | | `endpoint_latency_adjustment_max_level` | `number` | Maximum `endpoint_latency_adjustment_level` the model accepts. Valid levels are `0` (no adjustment) through this value; `0` means the feature is unsupported. | | `id` | `string` | Unique identifier of the model. | | `languages` | [`SonioxLanguage`](types#sonioxlanguage)\[] | List of languages supported by the model. | | `name` | `string` | Name of the model. | | `one_way_translation` | `string` \| `null` | When contains string 'all\_languages', any laguage from languages can be used | | `supports_endpoint_latency_adjustment` | `boolean` | Whether the model supports `endpoint_latency_adjustment_level` on real-time sessions. | | `supports_endpoint_sensitivity` | `boolean` | Whether the model supports endpoint sensitivity configuration. | | `supports_language_hints_strict` | `boolean` | Whether the model supports `language_hints_strict`. | | `supports_max_endpoint_delay` | `boolean` | Whether the model supports `max_endpoint_delay_ms` on real-time sessions. | | `transcription_mode` | [`SonioxTranscriptionMode`](types#sonioxtranscriptionmode) | Transcription mode of the model. | | `translation_targets` | [`SonioxTranslationTarget`](types#sonioxtranslationtarget)\[] | List of supported one-way translation targets. If list is empty, check for one\_way\_translation field | | `two_way_translation` | `string` \| `null` | When contains string 'all\_languages',' any laguage pair from languages can be used | | `two_way_translation_pairs` | `string`\[] | List of supported two-way translation pairs. If list is empty, check for two\_way\_translation field | *** ## SonioxNodeClientOptions ```ts type SonioxNodeClientOptions = { api_key?: string; base_domain?: string; base_url?: string; http_client?: HttpClient; realtime?: RealtimeOptions; region?: SonioxRegion; stt_defaults?: Partial; tts_api_url?: string; tts_defaults?: Partial; }; ``` **Properties** | Property | Type | Description | | --------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `api_key?` | `string` | API key for authentication. Falls back to SONIOX\_API\_KEY environment variable if not provided. | | `base_domain?` | `string` | Base domain for all Soniox service URLs. A single override that derives all service endpoints from the pattern `{service}.{base_domain}`. Takes precedence over `region`. Falls back to SONIOX\_BASE\_DOMAIN environment variable. Individual URL fields (`base_url`, `tts_api_url`, `realtime.ws_base_url`, `realtime.tts_ws_url`) still take final precedence. **Example** `'eu.soniox.com'` | | `base_url?` | `string` | Base URL for the REST API. Falls back to SONIOX\_API\_BASE\_URL environment variable, then to the region-derived URL, then to '[https://api.soniox.com](https://api.soniox.com)'. | | `http_client?` | [`HttpClient`](types#httpclient) | Custom HTTP client implementation. | | `realtime?` | [`RealtimeOptions`](types#realtimeoptions) | Real-time API configuration options. | | `region?` | `SonioxRegion` | Deployment region. Determines which regional endpoints are used for both the REST API and real-time WebSocket connections. Leave `undefined` for the default (US) region. Shorthand for `base_domain: '{region}.soniox.com'`. `base_domain` takes precedence when both are provided. **See** [https://soniox.com/docs/stt/data-residency](https://soniox.com/docs/stt/data-residency) | | `stt_defaults?` | `Partial`\<[`SttSessionConfig`](types#sttsessionconfig)> | Default STT session config fields applied to every real-time STT session opened via `client.realtime.stt(config)`. Caller-provided fields override. Equivalent to SonioxConnectionConfig.stt\_defaults on the web/react clients. Prefer this when you want the same defaults across your whole Node process. | | `tts_api_url?` | `string` | TTS REST API URL. Falls back to SONIOX\_TTS\_API\_URL environment variable, then to the region-derived URL, then to '[https://tts-rt.soniox.com](https://tts-rt.soniox.com)'. | | `tts_defaults?` | `Partial`\<[`TtsStreamConfig`](types#ttsstreamconfig)> | Default TTS stream config fields applied to every real-time TTS stream opened via `client.realtime.tts(...)`. Caller-provided fields override. Equivalent to SonioxConnectionConfig.tts\_defaults on the web/react clients. | *** ## SonioxTranscriptionData ```ts type SonioxTranscriptionData = { audio_duration_ms?: number | null; audio_url?: string | null; client_reference_id?: string | null; context?: TranscriptionContext | null; created_at: string; enable_language_identification: boolean; enable_speaker_diarization: boolean; error_message?: string | null; error_type?: string | null; file_id?: string | null; filename: string; id: string; language_hints?: string[] | null; model: string; status: TranscriptionStatus; webhook_auth_header_name?: string | null; webhook_auth_header_value?: string | null; webhook_status_code?: number | null; webhook_url?: string | null; }; ``` Raw transcription metadata from the API. **Properties** | Property | Type | Description | | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | | `audio_duration_ms?` | `number` \| `null` | Duration of the audio in milliseconds. Only available after processing begins. | | `audio_url?` | `string` \| `null` | URL of the audio file being transcribed. | | `client_reference_id?` | `string` \| `null` | Optional tracking identifier. **Max Length** 256 | | `context?` | [`TranscriptionContext`](types#transcriptioncontext) \| `null` | Additional context provided for the transcription. | | `created_at` | `string` | UTC timestamp when the transcription was created. **Format** date-time | | `enable_language_identification` | `boolean` | When true, language is detected for each part of the transcription. | | `enable_speaker_diarization` | `boolean` | When true, speakers are identified and separated in the transcription output. | | `error_message?` | `string` \| `null` | Error message if transcription failed. Null for successful or in-progress transcriptions. | | `error_type?` | `string` \| `null` | Error type if transcription failed. Null for successful or in-progress transcriptions. | | `file_id?` | `string` \| `null` | ID of the uploaded file being transcribed. **Format** uuid | | `filename` | `string` | Name of the file being transcribed. | | `id` | `string` | Unique identifier of the transcription. **Format** uuid | | `language_hints?` | `string`\[] \| `null` | Expected languages in the audio. If not specified, languages are automatically detected. | | `model` | `string` | Speech-to-text model used. | | `status` | [`TranscriptionStatus`](types#transcriptionstatus) | Current status of the transcription. | | `webhook_auth_header_name?` | `string` \| `null` | Name of the authentication header sent with webhook notifications. | | `webhook_auth_header_value?` | `string` \| `null` | Authentication header value. Always returned masked. | | `webhook_status_code?` | `number` \| `null` | HTTP status code received from your server when webhook was delivered. Null if not yet sent. | | `webhook_url?` | `string` \| `null` | URL to receive webhook notifications when transcription is completed or fails. | *** ## SonioxTranscriptionMode ```ts type SonioxTranscriptionMode = "real_time" | "async"; ``` Transcription mode of the model. *** ## SonioxTranslation ```ts type SonioxTranslation = | OneWayTranslation | TwoWayTranslation; ``` Discriminated translation result returned by [SonioxTranslationJob.getTranslation](classes#sonioxtranslationjob-gettranslation), [SonioxTranslationJob.fetchTranslation](classes#sonioxtranslationjob-fetchtranslation), and [translateFromTranscript](types#translatefromtranscript). *** ## SonioxTranslationTarget ```ts type SonioxTranslationTarget = { exclude_source_languages: string[]; source_languages: string[]; target_language: string; }; ``` **Properties** | Property | Type | | -------------------------------------------------------------------------------------- | ----------- | | `exclude_source_languages` | `string`\[] | | `source_languages` | `string`\[] | | `target_language` | `string` | *** ## SonioxUsageLog ```ts type SonioxUsageLog = { client_reference_id?: string | null; cost_usd: string; end_time: string; input_audio_cost_usd: string; input_audio_duration_ms: number; input_audio_tokens: number; input_cost_usd: string; input_text_cost_usd: string; input_text_tokens: number; model: string; output_audio_cost_usd: string; output_audio_duration_ms: number; output_audio_tokens: number; output_cost_usd: string; output_text_cost_usd: string; output_text_tokens: number; request_scope: string; start_time: string; uuid: string; }; ``` Per-request usage log entry. **Properties** | Property | Type | Description | | ----------------------------------------------------------------------------- | ------------------ | ----------------------------------------------------------------------- | | `client_reference_id?` | `string` \| `null` | Optional tracking identifier provided by the caller. | | `cost_usd` | `string` | Total request cost in USD, represented as a decimal string. | | `end_time` | `string` | UTC timestamp indicating when the request ended. **Format** date-time | | `input_audio_cost_usd` | `string` | Input audio cost in USD, represented as a decimal string. | | `input_audio_duration_ms` | `number` | Input audio duration in milliseconds. | | `input_audio_tokens` | `number` | Number of input audio tokens. | | `input_cost_usd` | `string` | Input cost in USD, represented as a decimal string. | | `input_text_cost_usd` | `string` | Input text cost in USD, represented as a decimal string. | | `input_text_tokens` | `number` | Number of input text tokens. | | `model` | `string` | Model used for the request. | | `output_audio_cost_usd` | `string` | Output audio cost in USD, represented as a decimal string. | | `output_audio_duration_ms` | `number` | Output audio duration in milliseconds. | | `output_audio_tokens` | `number` | Number of output audio tokens. | | `output_cost_usd` | `string` | Output cost in USD, represented as a decimal string. | | `output_text_cost_usd` | `string` | Output text cost in USD, represented as a decimal string. | | `output_text_tokens` | `number` | Number of output text tokens. | | `request_scope` | `string` | Request scope. | | `start_time` | `string` | UTC timestamp indicating when the request started. **Format** date-time | | `uuid` | `string` | Unique identifier of the request. **Format** uuid | *** ## SonioxVoiceData ```ts type SonioxVoiceData = { created_at: string; filename: string; id: string; models: VoiceModelStatusEntry[]; name: string; }; ``` Raw voice metadata from the API. **Properties** | Property | Type | Description | | -------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `created_at` | `string` | UTC timestamp indicating when the voice was created. **Format** date-time | | `filename` | `string` | Original file name of the uploaded audio clip. | | `id` | `string` | Unique identifier of the voice. **Format** uuid | | `models` | [`VoiceModelStatusEntry`](types#voicemodelstatusentry)\[] | Voice status for each available model. A model with status `not_computed` is not prepared yet (e.g. it was released after the voice was created); call recompute to prepare the voice for it. | | `name` | `string` | Name of the voice. | *** ## SttSessionConfig ```ts type SttSessionConfig = { audio_format?: "auto" | AudioFormat; client_reference_id?: string; context?: TranscriptionContext; enable_endpoint_detection?: boolean; enable_language_identification?: boolean; enable_speaker_diarization?: boolean; endpoint_latency_adjustment_level?: number; endpoint_sensitivity?: number; language_hints?: string[]; language_hints_strict?: boolean; max_endpoint_delay_ms?: number; model: string; num_channels?: number; sample_rate?: number; translation?: TranslationConfig; }; ``` Configuration sent to the Soniox WebSocket API when starting a session. **Properties** | Property | Type | Description | | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio_format?` | `"auto"` \| [`AudioFormat`](types#audioformat) | Audio format. Use 'auto' for automatic detection of container formats. For raw PCM formats, also set sample\_rate and num\_channels. **Default** `'auto'` | | `client_reference_id?` | `string` | Optional tracking identifier (max 256 chars). | | `context?` | [`TranscriptionContext`](types#transcriptioncontext) | Additional context to improve transcription accuracy. | | `enable_endpoint_detection?` | `boolean` | Enable endpoint detection for utterance boundaries. Useful for voice AI agents. | | `enable_language_identification?` | `boolean` | Enable automatic language detection. | | `enable_speaker_diarization?` | `boolean` | Enable speaker identification. | | `endpoint_latency_adjustment_level?` | `number` | Reduces endpoint latency compared to the default endpointing behavior. Higher values reduce endpoint latency more aggressively, which means endpoints are returned sooner and more endpoints may be emitted. This can split long speech into more segments and may slightly reduce word recognition accuracy because speech is finalized earlier. Allowed values are 0, 1, 2, and 3. The default value is 0 (default semantic endpointing behavior). | | `endpoint_sensitivity?` | `number` | Controls how aggressively endpoints are detected. Adjusts how likely the model is to emit an endpoint. Higher values make endpoints more likely, which can finalize segments sooner. Lower values make endpoints less likely, which can help the system wait longer before finalizing. Allowed values are between -1.0 and 1.0. The default value is 0.0. | | `language_hints?` | `string`\[] | Expected languages in the audio (ISO language codes). | | `language_hints_strict?` | `boolean` | When true, recognition is strongly biased toward language hints. Best-effort only, not a hard guarantee. | | `max_endpoint_delay_ms?` | `number` | Maximum delay between the end of speech and returned endpoint. Allowed values for maximum delay are between 500ms and 3000ms. The default value is 2000ms | | `model` | `string` | Speech-to-text model to use. | | `num_channels?` | `number` | Number of audio channels (required for raw audio formats). | | `sample_rate?` | `number` | Sample rate in Hz (required for PCM formats). | | `translation?` | [`TranslationConfig`](types#translationconfig) | Translation configuration. | *** ## SttSessionEvents ```ts type SttSessionEvents = { connected: () => void; disconnected: (reason?) => void; endpoint: () => void; error: (error) => void; finalized: () => void; finished: () => void; result: (result) => void; state_change: (update) => void; token: (token) => void; }; ``` Event handlers for the STT session. **Properties** | Property | Type | Description | | ------------------------------------------------------- | --------------------- | ------------------------------------------------- | | `connected` | () => `void` | Session connected and ready. | | `disconnected` | (`reason?`) => `void` | Session disconnected. | | `endpoint` | () => `void` | Endpoint detected (\ token). | | `error` | (`error`) => `void` | Error occurred. | | `finalized` | () => `void` | Finalization complete (\ token). | | `finished` | () => `void` | Session finished (server signaled end of stream). | | `result` | (`result`) => `void` | Parsed result received. | | `state_change` | (`update`) => `void` | Session state transition. | | `token` | (`token`) => `void` | Individual token received. | *** ## SttSessionOptions ```ts type SttSessionOptions = { connect_timeout_ms?: number; keepalive_interval_ms?: number; signal?: AbortSignal; }; ``` SDK-level session options (not sent to the server). **Properties** | Property | Type | Description | | --------------------------------------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `connect_timeout_ms?` | `number` | Maximum time to wait for the WebSocket connection to open (milliseconds). If the connection is not established within this time, a [ConnectionError](classes#connectionerror) with message "Connection timed out" is thrown. **Default** `20000` | | `keepalive_interval_ms?` | `number` | Interval for sending keepalive messages while paused (milliseconds). **Default** `5000` | | `signal?` | `AbortSignal` | AbortSignal for cancellation. | *** ## SttSessionState ```ts type SttSessionState = | "idle" | "connecting" | "connected" | "finishing" | "finished" | "canceled" | "closed" | "error"; ``` Session lifecycle states. *** ## TemporaryApiKeyRequest ```ts type TemporaryApiKeyRequest = { client_reference_id?: string; expires_in_seconds: number; max_session_duration_seconds?: number; single_use?: boolean; usage_type: TemporaryApiKeyUsageType; }; ``` **Properties** | Property | Type | Description | | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | | `client_reference_id?` | `string` | Optional tracking identifier string. Does not need to be unique **Max Length** 256 | | `expires_in_seconds` | `number` | Duration in seconds until the temporary API key expires **Minimum** 1 **Maximum** 3600 | | `max_session_duration_seconds?` | `number` | Maximum connection duration in seconds for WebSocket and TTS HTTP streaming endpoints. **Minimum** 1 **Maximum** 18000 | | `single_use?` | `boolean` | When true, restricts the temporary API key to a single use. | | `usage_type` | [`TemporaryApiKeyUsageType`](types#temporaryapikeyusagetype) | Intended usage of the temporary API key. | *** ## TemporaryApiKeyResponse ```ts type TemporaryApiKeyResponse = { api_key: string; expires_at: string; }; ``` **Properties** | Property | Type | Description | | ---------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------ | | `api_key` | `string` | Created temporary API key. | | `expires_at` | `string` | UTC timestamp indicating when generated temporary API key will expire **Format** date-time | *** ## TemporaryApiKeyUsageType ```ts type TemporaryApiKeyUsageType = "transcribe_websocket" | "tts_rt"; ``` *** ## TranscribeBaseOptions ```ts type TranscribeBaseOptions = { cleanup?: CleanupTarget[]; client_reference_id?: string; context?: TranscriptionContext; enable_language_identification?: boolean; enable_speaker_diarization?: boolean; fetch_transcript?: boolean; language_hints?: string[]; language_hints_strict?: boolean; model: string; signal?: AbortSignal; timeout_ms?: number; translation?: TranslationConfig; wait?: boolean; wait_options?: WaitOptions; webhook_auth_header_name?: string; webhook_auth_header_value?: string; webhook_query?: string | URLSearchParams | Record; webhook_url?: string; }; ``` Base options shared by all audio source variants. **Properties** | Property | Type | Description | | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cleanup?` | [`CleanupTarget`](types#cleanuptarget)\[] | Resources to clean up after transcription completes or on error/timeout. Only applies when `wait: true`. Cleanup runs in all cases when `wait: true`: - After successful completion - After transcription errors (status: 'error') - On timeout or abort This ensures no orphaned resources are left behind. **Example** `// Delete only the uploaded file cleanup: ['file'] // Delete only the transcription record cleanup: ['transcription'] // Delete both file and transcription cleanup: ['file', 'transcription']` | | `client_reference_id?` | `string` | Optional tracking identifier. **Max Length** 256 | | `context?` | [`TranscriptionContext`](types#transcriptioncontext) | Additional context to improve transcription accuracy and formatting of specialized terms. | | `enable_language_identification?` | `boolean` | Enable automatic language identification. | | `enable_speaker_diarization?` | `boolean` | Enable speaker diarization to identify different speakers. | | `fetch_transcript?` | `boolean` | When true (default), fetches the transcript and attaches it to the result when wait=true and the transcription completes successfully. Set to false to skip fetching the full transcript payload. **Default** `true` | | `language_hints?` | `string`\[] | Array of expected ISO language codes to bias recognition. | | `language_hints_strict?` | `boolean` | When true, model relies more heavily on language hints. | | `model` | `string` | Speech-to-text model to use. **Max Length** 32 | | `signal?` | `AbortSignal` | AbortSignal to cancel the operation | | `timeout_ms?` | `number` | Timeout in milliseconds | | `translation?` | [`TranslationConfig`](types#translationconfig) | Translation configuration. | | `wait?` | `boolean` | When true, waits for transcription to complete before returning. **Default** `false` | | `wait_options?` | [`WaitOptions`](types#waitoptions) | Options for waiting (only used when wait=true). | | `webhook_auth_header_name?` | `string` | Name of the authentication header sent with webhook notifications. **Max Length** 256 | | `webhook_auth_header_value?` | `string` | Authentication header value sent with webhook notifications. **Max Length** 256 | | `webhook_query?` | `string` \| `URLSearchParams` \| `Record`\<`string`, `string`> | Query parameters to append to the webhook URL. Useful for encoding metadata like transcription ID in the webhook callback. Can be a string, URLSearchParams, or Record\. | | `webhook_url?` | `string` | URL to receive webhook notifications when transcription is completed or fails. **Max Length** 256 | *** ## TranscribeFromFile ```ts type TranscribeFromFile = TranscribeBaseOptions & { audio_url?: never; file: UploadFileInput; file_id?: never; filename?: string; }; ``` Transcribe from a direct file upload (Buffer, Uint8Array, Blob, or ReadableStream) **Type Declaration** | Name | Type | Description | | ------------ | ------------------------------------------ | ----------------------------------- | | `audio_url?` | `never` | - | | `file` | [`UploadFileInput`](types#uploadfileinput) | File data to upload and transcribe. | | `file_id?` | `never` | - | | `filename?` | `string` | - | *** ## TranscribeFromFileId ```ts type TranscribeFromFileId = TranscribeBaseOptions & { audio_url?: never; file?: never; file_id: string; filename?: never; }; ``` Transcribe from a previously uploaded file **Type Declaration** | Name | Type | Description | | ------------ | -------- | ------------------------------------------------- | | `audio_url?` | `never` | - | | `file?` | `never` | - | | `file_id` | `string` | ID of a previously uploaded file. **Format** uuid | | `filename?` | `never` | - | *** ## TranscribeFromFileIdOptions ```ts type TranscribeFromFileIdOptions = Omit; ``` Options for transcribing from an uploaded file ID via `transcribeFromFileId`. *** ## TranscribeFromFileOptions ```ts type TranscribeFromFileOptions = Omit; ``` Options for transcribing from a file via `transcribeFromFile`. *** ## TranscribeFromUrl ```ts type TranscribeFromUrl = TranscribeBaseOptions & { audio_url: string; file?: never; file_id?: never; filename?: never; }; ``` Transcribe from a publicly accessible audio URL **Type Declaration** | Name | Type | Description | | ----------- | -------- | ------------------------------------------------------------ | | `audio_url` | `string` | URL of a publicly accessible audio file. **Max Length** 4096 | | `file?` | `never` | - | | `file_id?` | `never` | - | | `filename?` | `never` | - | *** ## TranscribeFromUrlOptions ```ts type TranscribeFromUrlOptions = Omit; ``` Options for transcribing from a URL via `transcribeFromUrl`. *** ## TranscribeOptions ```ts type TranscribeOptions = | TranscribeFromFile | TranscribeFromFileId | TranscribeFromUrl; ``` Options for the unified transcribe method Exactly one audio source must be provided: `file`, `file_id`, or `audio_url` *** ## TranscriptResponse ```ts type TranscriptResponse = { id: string; text: string; tokens: TranscriptToken[]; }; ``` Response from getting a transcription transcript. **Properties** | Property | Type | Description | | --------------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------- | | `id` | `string` | Unique identifier of the transcription this transcript belongs to. **Format** uuid | | `text` | `string` | Complete transcribed text content. | | `tokens` | [`TranscriptToken`](types#transcripttoken)\[] | List of detailed token information with timestamps and metadata. | *** ## TranscriptSegment ```ts type TranscriptSegment = { end_ms?: number; language?: string; speaker?: string; start_ms?: number; text: string; tokens: TranscriptToken[]; }; ``` A segment of contiguous tokens grouped by speaker and language **Properties** | Property | Type | Description | | ------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | `end_ms?` | `number` | End time of the segment in milliseconds (from last token). Absent for translation-only segments where the underlying tokens carry no timestamps. | | `language?` | `string` | Detected language code (if language identification was enabled). | | `speaker?` | `string` | Speaker identifier (if speaker diarization was enabled). | | `start_ms?` | `number` | Start time of the segment in milliseconds (from first token). Absent for translation-only segments where the underlying tokens carry no timestamps. | | `text` | `string` | Concatenated text of all tokens in this segment. | | `tokens` | [`TranscriptToken`](types#transcripttoken)\[] | Original tokens in this segment. | *** ## TranscriptToken ```ts type TranscriptToken = { confidence: number; end_ms?: number; is_audio_event?: boolean | null; language?: string | null; source_language?: string | null; speaker?: string | null; start_ms?: number; text: string; translation_status?: "none" | "original" | "translation" | null; }; ``` A single token from the transcript with timing and confidence information. **Properties** | Property | Type | Description | | ------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `confidence` | `number` | Confidence score for this token (0.0 to 1.0). | | `end_ms?` | `number` | End time of the token in milliseconds. Present on original tokens (`translation_status` of `'original'` or `'none'`) and absent on translation tokens (`translation_status: 'translation'`), which do not carry timing. | | `is_audio_event?` | `boolean` \| `null` | Whether this token represents an audio event. | | `language?` | `string` \| `null` | Language code for this token. For original tokens (`translation_status` of `'original'` or `'none'`) this is the spoken language. For translation tokens (`translation_status: 'translation'`) this is the target language. Present on every token whenever language identification or translation is configured. | | `source_language?` | `string` \| `null` | Source language for translation tokens (`translation_status: 'translation'`). Identifies the language being translated from. Not set on original or `'none'` tokens; their language is in [TranscriptToken.language](#language). | | `speaker?` | `string` \| `null` | Speaker identifier (if speaker diarization was enabled). | | `start_ms?` | `number` | Start time of the token in milliseconds. Present on original tokens (`translation_status` of `'original'` or `'none'`) and absent on translation tokens (`translation_status: 'translation'`), which do not carry timing. | | `text` | `string` | The text content of this token. | | `translation_status?` | `"none"` \| `"original"` \| `"translation"` \| `null` | Translation status for this token. | *** ## TranscriptionContext ```ts type TranscriptionContext = { general?: ContextGeneralEntry[]; terms?: string[]; text?: string; translation_terms?: ContextTranslationTerm[]; }; ``` Additional context to improve transcription and translation accuracy. All sections are optional - include only what's relevant for your use case. **Properties** | Property | Type | Description | | ---------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | `general?` | [`ContextGeneralEntry`](types#contextgeneralentry)\[] | Structured key-value pairs describing domain, topic, intent, participant names, etc. | | `terms?` | `string`\[] | Domain-specific or uncommon words to recognize. | | `text?` | `string` | Longer free-form background text, prior interaction history, reference documents, or meeting notes. | | `translation_terms?` | [`ContextTranslationTerm`](types#contexttranslationterm)\[] | Custom translations for ambiguous terms. | *** ## TranscriptionIdentifier ```ts type TranscriptionIdentifier = | string | { id: string; }; ``` Transcription identifier - either a string ID or an object with an id property. *** ## TranscriptionStatus ```ts type TranscriptionStatus = "queued" | "processing" | "completed" | "error"; ``` Status of a transcription request. *** ## TranscriptionsCountResponse ```ts type TranscriptionsCountResponse = { playground: number; public_api: number; total: number; }; ``` Total number of transcriptions, split by request scope. **Properties** | Property | Type | Description | | -------------------------------------------------------------- | -------- | ---------------------------------------------------- | | `playground` | `number` | Number of transcriptions created via the Playground. | | `public_api` | `number` | Number of transcriptions created via Public API. | | `total` | `number` | Total number of transcriptions across all scopes. | *** ## TranslateAudioSource ```ts type TranslateAudioSource = | { audio_url?: never; file: UploadFileInput; file_id?: never; filename?: string; } | { audio_url?: never; file?: never; file_id: string; filename?: never; } | { audio_url: string; file?: never; file_id?: never; filename?: never; }; ``` Audio source for [SonioxSttApi.translate](classes#sonioxsttapi-translate). Exactly one of `file`, `file_id`, or `audio_url` must be provided. **Type Declaration** ```ts { audio_url?: never; file: UploadFileInput; file_id?: never; filename?: string; } ``` | Name | Type | Description | | ------------ | ------------------------------------------ | ---------------------------------- | | `audio_url?` | `never` | - | | `file` | [`UploadFileInput`](types#uploadfileinput) | File data to upload and translate. | | `file_id?` | `never` | - | | `filename?` | `string` | - | ```ts { audio_url?: never; file?: never; file_id: string; filename?: never; } ``` | Name | Type | Description | | ------------ | -------- | ------------------------------------------------- | | `audio_url?` | `never` | - | | `file?` | `never` | - | | `file_id` | `string` | ID of a previously uploaded file. **Format** uuid | | `filename?` | `never` | - | ```ts { audio_url: string; file?: never; file_id?: never; filename?: never; } ``` | Name | Type | Description | | ----------- | -------- | ------------------------------------------------------------ | | `audio_url` | `string` | URL of a publicly accessible audio file. **Max Length** 4096 | | `file?` | `never` | - | | `file_id?` | `never` | - | | `filename?` | `never` | - | *** ## TranslateBaseOptions ```ts type TranslateBaseOptions = { cleanup?: CleanupTarget[]; client_reference_id?: string; context?: TranscriptionContext; enable_speaker_diarization?: boolean; fetch_translation?: boolean; model?: string; signal?: AbortSignal; timeout_ms?: number; wait?: boolean; wait_options?: WaitOptions; webhook_auth_header_name?: string; webhook_auth_header_value?: string; webhook_query?: string | URLSearchParams | Record; webhook_url?: string; }; ``` Common (non-mode, non-source) options shared by every translate call. **Properties** | Property | Type | Description | | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | `cleanup?` | [`CleanupTarget`](types#cleanuptarget)\[] | Resources to clean up after translation completes or on error/timeout. | | `client_reference_id?` | `string` | Optional tracking identifier. **Max Length** 256 | | `context?` | [`TranscriptionContext`](types#transcriptioncontext) | Additional context to improve transcription and translation accuracy. | | `enable_speaker_diarization?` | `boolean` | Enable speaker diarization to identify different speakers. | | `fetch_translation?` | `boolean` | When true (default), fetches and reshapes the translation result when `wait=true` and the job completes successfully. **Default** `true` | | `model?` | `string` | Speech-to-text model to use. **Default** `'stt-async-v5'` **Max Length** 32 | | `signal?` | `AbortSignal` | AbortSignal to cancel the operation. | | `timeout_ms?` | `number` | Timeout in milliseconds. | | `wait?` | `boolean` | When true, waits for translation to complete before returning. **Default** `false` | | `wait_options?` | [`WaitOptions`](types#waitoptions) | Options for waiting on completion. | | `webhook_auth_header_name?` | `string` | Name of the authentication header sent with webhook notifications. **Max Length** 256 | | `webhook_auth_header_value?` | `string` | Authentication header value sent with webhook notifications. **Max Length** 256 | | `webhook_query?` | `string` \| `URLSearchParams` \| `Record`\<`string`, `string`> | Query parameters to append to the webhook URL. | | `webhook_url?` | `string` | URL to receive webhook notifications when translation is completed or fails. **Max Length** 256 | *** ## TranslateFromTranscriptMode ```ts type TranslateFromTranscriptMode = | { from?: string; to: string; type: "one_way"; } | { language_a: string; language_b: string; type: "two_way"; }; ``` Mode parameter accepted by [translateFromTranscript](types#translatefromtranscript). The async `translate()` method stores this internally on the returned job; webhook handlers (and other callers that already have a transcript in hand) supply it directly. *** ## TranslateMode ```ts type TranslateMode = | { between?: never; from?: never; to: string; } | { between?: never; from: string; to: string; } | { between: [string, string]; from?: never; to?: never; }; ``` Shorthand specification of the translation direction(s) for [SonioxSttApi.translate](classes#sonioxsttapi-translate). Three mutually exclusive shapes: * `{ to }` — one-way translation into `to`. Source language(s) are detected automatically. * `{ to, from }` — one-way translation from `from` to `to`. The source language is hinted to the model. * `{ between: [a, b] }` — two-way translation between `a` and `b`. Each side is translated into the other; speech in any third language is passed through as-is. *** ## TranslateOptions ```ts type TranslateOptions = TranslateMode & TranslateAudioSource & TranslateBaseOptions; ``` Options for [SonioxSttApi.translate](classes#sonioxsttapi-translate). Combines a [TranslateMode](types#translatemode) (the translation direction shorthand), a [TranslateAudioSource](types#translateaudiosource) (file, file\_id, or audio\_url), and [TranslateBaseOptions](types#translatebaseoptions). *** ## TranslationConfig ```ts type TranslationConfig = | OneWayTranslationConfig | TwoWayTranslationConfig; ``` Translation configuration. *** ## TranslationSegment ```ts type TranslationSegment = { end_ms?: number; from: string; original_text: string; original_tokens: TranscriptToken[]; speaker?: string; start_ms?: number; to?: string; translation_text?: string; translation_tokens?: TranscriptToken[]; }; ``` A grouped pair of original speech and (optionally) its translation, derived from the underlying transcript tokens. In one-way mode every segment that originated from speech in the source language carries both `original_*` and `translation_*` fields. In two-way mode the same is true for the two configured languages; speech in a third language flows through with `translation_status: 'none'` and the translation fields are omitted. **Properties** | Property | Type | Description | | ---------------------------------------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `end_ms?` | `number` | End time of the segment in milliseconds, taken from the last original token. Absent when the segment has no original tokens. | | `from` | `string` | Source language code. Derived from `original_tokens[0].language` when originals are present, otherwise from `translation_tokens[0].source_language`. | | `original_text` | `string` | Concatenated text of `original_tokens`. | | `original_tokens` | [`TranscriptToken`](types#transcripttoken)\[] | Original tokens (`translation_status` of `'original'` or `'none'`) for this segment, in order. | | `speaker?` | `string` | Speaker identifier (when speaker diarization is enabled). | | `start_ms?` | `number` | Start time of the segment in milliseconds, taken from the first original token. Absent when the segment has no original tokens. | | `to?` | `string` | Target language code. Omitted when there are no translation tokens (e.g. third-language pass-through under `between`). | | `translation_text?` | `string` | Concatenated text of `translation_tokens`. Omitted when there are no translation tokens. | | `translation_tokens?` | [`TranscriptToken`](types#transcripttoken)\[] | Translation tokens (`translation_status: 'translation'`) for this segment, in order. Omitted when there are no translation tokens. | *** ## TtsAudioFormat ```ts type TtsAudioFormat = | "pcm_f32le" | "pcm_s16le" | "pcm_s16be" | "pcm_mulaw" | "pcm_alaw" | "wav" | "aac" | "mp3" | "opus" | "flac" | string & { }; ``` Supported audio formats for Text-to-Speech output. *** ## TtsConnectionEvents ```ts type TtsConnectionEvents = { close: () => void; error: (error) => void; }; ``` Events emitted by a TTS WebSocket connection. **Properties** | Property | Type | Description | | -------------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `close` | () => `void` | The WebSocket connection was closed. | | `error` | (`error`) => `void` | A connection-level error occurred. Always a [RealtimeError](classes#realtimeerror) subclass (e.g. [ConnectionError](classes#connectionerror), [NetworkError](classes#networkerror), [AuthError](classes#autherror)). | *** ## TtsConnectionOptions ```ts type TtsConnectionOptions = { connect_timeout_ms?: number; keepalive_interval_ms?: number; }; ``` Options for creating a TTS connection. **Properties** | Property | Type | Description | | ------------------------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------- | | `connect_timeout_ms?` | `number` | Maximum time to wait for the WebSocket connection to open (milliseconds). **Default** `20000` | | `keepalive_interval_ms?` | `number` | Interval for sending keepalive messages (milliseconds). **Default** `5000` **Minimum** 1000 | *** ## TtsEvent ```ts type TtsEvent = { audio?: string; audio_end?: boolean; error_code?: number; error_message?: string; stream_id?: string; terminated?: boolean; timestamps?: TtsTimestamps; }; ``` Raw JSON event received from the TTS WebSocket server. **Properties** | Property | Type | | -------------------------------------------------- | --------------- | | `audio?` | `string` | | `audio_end?` | `boolean` | | `error_code?` | `number` | | `error_message?` | `string` | | `stream_id?` | `string` | | `terminated?` | `boolean` | | `timestamps?` | `TtsTimestamps` | *** ## TtsLanguage ```ts type TtsLanguage = { code: string; name: string; }; ``` A language supported by a Text-to-Speech model. **Properties** | Property | Type | Description | | ---------------------------------- | -------- | ----------------------------- | | `code` | `string` | ISO language code. | | `name` | `string` | Human-readable language name. | *** ## TtsModel ```ts type TtsModel = { aliased_model_id: string | null; id: string; languages: TtsLanguage[]; name: string; speed_max: number; speed_min: number; supports_silence_reduction: boolean; supports_speed_adjustment: boolean; supports_timestamps?: boolean; voices: TtsVoice[]; }; ``` A Text-to-Speech model. **Properties** | Property | Type | Description | | --------------------------------------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------- | | `aliased_model_id` | `string` \| `null` | If this is an alias, the id of the aliased model. Null for non-alias models. | | `id` | `string` | Unique identifier of the model. | | `languages` | [`TtsLanguage`](types#ttslanguage)\[] | Languages supported by this model. | | `name` | `string` | Name of the model. | | `speed_max` | `number` | Maximum supported speaking rate. | | `speed_min` | `number` | Minimum supported speaking rate. | | `supports_silence_reduction` | `boolean` | Whether the model supports shortening pauses between words via the `reduce_silence` parameter. | | `supports_speed_adjustment` | `boolean` | Whether the model supports adjusting the speaking rate via the `speed` parameter. | | `supports_timestamps?` | `boolean` | Whether the model can return character-level audio timestamps via `return_timestamps`. | | `voices` | [`TtsVoice`](types#ttsvoice)\[] | Voices supported by this model. | *** ## TtsStreamConfig ```ts type TtsStreamConfig = { audio_format: string; bitrate?: number; language: string; model: string; reduce_silence?: boolean; return_timestamps?: boolean; sample_rate?: number; speed?: number; stream_id: string; voice: string; }; ``` Fully resolved TTS stream config sent over the WebSocket. All required fields are present after merging input with defaults. **Properties** | Property | Type | | ----------------------------------------------------------------- | --------- | | `audio_format` | `string` | | `bitrate?` | `number` | | `language` | `string` | | `model` | `string` | | `reduce_silence?` | `boolean` | | `return_timestamps?` | `boolean` | | `sample_rate?` | `number` | | `speed?` | `number` | | `stream_id` | `string` | | `voice` | `string` | *** ## TtsStreamEvents ```ts type TtsStreamEvents = { audio: (chunk, timestamps?) => void; audioEnd: () => void; error: (error) => void; terminated: () => void; }; ``` Events emitted by a TTS stream. **Properties** | Property | Type | Description | | -------------------------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio` | (`chunk`, `timestamps?`) => `void` | Decoded audio chunk received. When `return_timestamps` is enabled, the second argument carries the character-level alignment for this frame (it is `undefined` for audio-only frames). | | `audioEnd` | () => `void` | Server marked the final audio payload for this stream. | | `error` | (`error`) => `void` | A stream-level error occurred. Always a [RealtimeError](classes#realtimeerror) subclass mapped from the server `error_code` / `error_message`. | | `terminated` | () => `void` | Stream has been fully terminated by the server. | *** ## TtsStreamInput ```ts type TtsStreamInput = { audio_format?: TtsAudioFormat; bitrate?: number; language?: string; model?: string; reduce_silence?: boolean; return_timestamps?: boolean; sample_rate?: number; speed?: number; stream_id?: string; voice?: string; }; ``` Input for creating a TTS stream. All fields are optional and are merged with `tts_defaults` from the resolved connection config. After merging, `model`, `language`, `voice`, and `audio_format` must be present. **Properties** | Property | Type | Description | | ---------------------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio_format?` | [`TtsAudioFormat`](types#ttsaudioformat) | Output audio format **Example** `'wav'` | | `bitrate?` | `number` | Codec bitrate in bps (for compressed formats). | | `language?` | `string` | Language code for speech generation. **Example** `'en'` | | `model?` | `string` | Text-to-Speech model to use. **Example** `'tts-rt-v2'` | | `reduce_silence?` | `boolean` | Shorten pauses between words in the generated speech. `false` (default) keeps the model's natural pacing; `true` tightens delivery by reducing silence between words. | | `return_timestamps?` | `boolean` | Request character-level audio timestamps in the responses. When enabled, audio frames may carry a TtsTimestamps payload aligning each character of the spoken text to its start/end time in the audio. WebSocket (realtime) only — the REST endpoint streams raw audio bytes and ignores this flag. Timestamps map to the model's preprocessed text, not the raw input. Defaults to `false` when omitted. | | `sample_rate?` | `number` | Output sample rate in Hz. Required for raw PCM formats. | | `speed?` | `number` | Speaking rate. `1.0` is the normal rate; values below `1.0` slow speech down and values above `1.0` speed it up. Supported range is `0.7`-`1.3`. Defaults to `1.0` when omitted. | | `stream_id?` | `string` | Client-generated stream identifier. Must be unique among active streams on the same connection. Auto-generated if omitted. | | `voice?` | `string` | Voice identifier. **Example** `'Adrian'` | *** ## TtsStreamState ```ts type TtsStreamState = "active" | "finishing" | "ended" | "error"; ``` Lifecycle states for a TTS stream. *** ## TtsVoice ```ts type TtsVoice = { description: string; gender: TtsVoiceGender; id: string; }; ``` A Text-to-Speech voice. **Properties** | Property | Type | Description | | --------------------------------------------- | ---------------------------------------- | --------------------------------- | | `description` | `string` | Human-readable voice description. | | `gender` | [`TtsVoiceGender`](types#ttsvoicegender) | Voice gender metadata. | | `id` | `string` | Unique identifier of the voice. | *** ## TtsVoiceGender ```ts type TtsVoiceGender = "male" | "female" | "neutral"; ``` Voice gender metadata returned by the TTS models API. *** ## TwoWayTranslation ```ts type TwoWayTranslation = { duration_ms: number; language_a: string; language_b: string; mode: "two_way"; segments: TranslationSegment[]; }; ``` Result of a two-way translation (`{ between }` mode). No flat `original_text` / `translation_text` strings are exposed because which side is "original" depends on the segment. Read `segments` and filter / format per `from` / `to` as needed. **Properties** | Property | Type | Description | | ------------------------------------------------------ | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | `duration_ms` | `number` | Total audio duration in milliseconds. Equals the largest `end_ms` across all original tokens, or `0` when there are no original tokens. | | `language_a` | `string` | First configured language (the `between[0]` value). | | `language_b` | `string` | Second configured language (the `between[1]` value). | | `mode` | `"two_way"` | - | | `segments` | [`TranslationSegment`](types#translationsegment)\[] | Per-utterance segments in audio order. | *** ## TwoWayTranslationConfig ```ts type TwoWayTranslationConfig = { language_a: string; language_b: string; type: "two_way"; }; ``` Two-way translation configuration. Translates between two specified languages. **Properties** | Property | Type | Description | | ---------------------------------------------------------- | ----------- | --------------------- | | `language_a` | `string` | First language code. | | `language_b` | `string` | Second language code. | | `type` | `"two_way"` | Translation type. | *** ## UploadFileInput ```ts type UploadFileInput = | Buffer | Uint8Array | Blob | ReadableStream | NodeJS.ReadableStream; ``` Supported input types for file upload *** ## UploadFileOptions ```ts type UploadFileOptions = { client_reference_id?: string; filename?: string; signal?: AbortSignal; timeout_ms?: number; }; ``` Options for uploading a file **Properties** | Property | Type | Description | | ----------------------------------------------------------------------- | ------------- | ---------------------------------------------------------------------------------- | | `client_reference_id?` | `string` | Optional tracking identifier string. Does not need to be unique **Max Length** 256 | | `filename?` | `string` | Custom filename for the uploaded file | | `signal?` | `AbortSignal` | AbortSignal for cancelling the upload | | `timeout_ms?` | `number` | Request timeout in milliseconds | *** ## UsageLogsSort ```ts type UsageLogsSort = "end_time_asc" | "end_time_desc"; ``` Sort order for usage logs. *** ## UsageSummaryEntry ```ts type UsageSummaryEntry = { cost_usd: string[]; days: string[]; duration_cost_usd: string[]; duration_ms: number[]; input_audio_duration_ms: number[]; input_audio_tokens: number[]; input_cost_usd: string[]; input_text_tokens: number[]; model: string | null; num_requests: number[]; output_audio_duration_ms: number[]; output_audio_tokens: number[]; output_cost_usd: string[]; output_text_tokens: number[]; total_cost_usd: string; total_duration_cost_usd: string; total_duration_ms: number; total_input_audio_duration_ms: number; total_input_audio_tokens: number; total_input_cost_usd: string; total_input_text_tokens: number; total_num_requests: number; total_output_audio_duration_ms: number; total_output_audio_tokens: number; total_output_cost_usd: string; total_output_text_tokens: number; }; ``` Aggregated usage for a model (or the project total) over a time window. Per-day arrays are aligned to [UsageSummaryEntry.days](#days). **Properties** | Property | Type | Description | | -------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cost_usd` | `string`\[] | Cost per day, in USD, aligned to `days`. | | `days` | `string`\[] | One UTC day (`YYYY-MM-DD`) per element, in ascending order. Every day in the requested window is present, including days with no usage. **Format** date | | `duration_cost_usd` | `string`\[] | Duration-billed cost per day, in USD, aligned to `days`. | | `duration_ms` | `number`\[] | Billed session duration per day, in milliseconds, aligned to `days`. | | `input_audio_duration_ms` | `number`\[] | - | | `input_audio_tokens` | `number`\[] | - | | `input_cost_usd` | `string`\[] | Cost of input tokens per day, in USD, aligned to `days`. | | `input_text_tokens` | `number`\[] | - | | `model` | `string` \| `null` | Model identifier. `null` on the [UsageSummaryResponse.total](types#usagesummaryresponse-total) entry. | | `num_requests` | `number`\[] | Number of requests per day, aligned to `days`. | | `output_audio_duration_ms` | `number`\[] | - | | `output_audio_tokens` | `number`\[] | - | | `output_cost_usd` | `string`\[] | Cost of output tokens per day, in USD, aligned to `days`. | | `output_text_tokens` | `number`\[] | - | | `total_cost_usd` | `string` | Total cost over the window, in USD. Equals `total_input_cost_usd` + `total_output_cost_usd` + `total_duration_cost_usd`. | | `total_duration_cost_usd` | `string` | Total cost over the window for models billed by session duration rather than by tokens, in USD. `0` for Speech-to-Text and Text-to-Speech models. | | `total_duration_ms` | `number` | Billed session duration over the window, in milliseconds, for models billed by duration. `0` for Speech-to-Text and Text-to-Speech models. | | `total_input_audio_duration_ms` | `number` | - | | `total_input_audio_tokens` | `number` | - | | `total_input_cost_usd` | `string` | Total cost of input tokens over the window, in USD. | | `total_input_text_tokens` | `number` | - | | `total_num_requests` | `number` | Number of requests over the window. | | `total_output_audio_duration_ms` | `number` | - | | `total_output_audio_tokens` | `number` | - | | `total_output_cost_usd` | `string` | Total cost of output tokens over the window, in USD. | | `total_output_text_tokens` | `number` | - | *** ## UsageSummaryResponse ```ts type UsageSummaryResponse = { models: UsageSummaryEntry[]; total: UsageSummaryEntry; }; ``` Aggregated usage summary for the authenticated project. **Properties** | Property | Type | Description | | ----------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------- | | `models` | [`UsageSummaryEntry`](types#usagesummaryentry)\[] | One entry per model that recorded usage in the window. Empty when the project had no usage. | | `total` | [`UsageSummaryEntry`](types#usagesummaryentry) | Cost and activity across all models. Its `model` is `null`. | *** ## VoiceIdentifier ```ts type VoiceIdentifier = | string | { id: string; }; ``` Voice identifier - either a string ID or an object with an id property. *** ## VoiceModelStatus ```ts type VoiceModelStatus = "not_computed" | "processing" | "ready" | "failed"; ``` Processing status of a voice for a specific model. * `not_computed`: Not prepared for this model yet (e.g. the model was released after the voice was created). Call recompute to prepare it. * `processing`: Still being processed for this model. Wait and check again. * `ready`: Usable with this model. * `failed`: Processing failed permanently for this model. Fix the reference clip and create a new voice. *** ## VoiceModelStatusEntry ```ts type VoiceModelStatusEntry = { error_message?: string | null; error_type?: string | null; model: string; status: VoiceModelStatus; }; ``` Voice status for a single model. **Properties** | Property | Type | Description | | --------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `error_message?` | `string` \| `null` | Human-readable error message when status is `failed` (e.g. the reference audio is too long). `null` otherwise. | | `error_type?` | `string` \| `null` | Machine-readable error category when status is `failed`. Stable across releases — safe to use in control flow. `null` otherwise. | | `model` | `string` | Name of the model. | | `status` | [`VoiceModelStatus`](types#voicemodelstatus) | Has to be `ready` for the voice to be usable with this model. | *** ## VoicesCountResponse ```ts type VoicesCountResponse = { total: number; }; ``` Total number of voices in your project. **Properties** | Property | Type | Description | | -------------------------------------------- | -------- | --------------------------------------- | | `total` | `number` | Total number of voices in your project. | *** ## WaitOptions ```ts type WaitOptions = { interval_ms?: number; on_status_change?: (status, transcription) => void; signal?: AbortSignal; timeout_ms?: number; }; ``` Options for polling/waiting for transcription completion. **Properties** | Property | Type | Description | | ----------------------------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------- | | `interval_ms?` | `number` | Polling interval in milliseconds. **Default** `1000` **Minimum** 1000 | | `on_status_change?` | (`status`, `transcription`) => `void` | Callback invoked when status changes. | | `signal?` | `AbortSignal` | AbortSignal to cancel waiting. | | `timeout_ms?` | `number` | Maximum time to wait in milliseconds. **Default** `300000 (5 minutes)` | *** ## WebhookAuthConfig ```ts type WebhookAuthConfig = { name: string; value: string; }; ``` Authentication configuration for webhook verification **Properties** | Property | Type | Description | | ------------------------------------------ | -------- | -------------------------------------------------- | | `name` | `string` | Expected header name (case-insensitive comparison) | | `value` | `string` | Expected header value (exact match) | *** ## WebhookEvent ```ts type WebhookEvent = { id: string; status: WebhookEventStatus; }; ``` Webhook event payload sent by Soniox when a transcription completes or fails. **Properties** | Property | Type | Description | | --------------------------------------- | ------------------------------------------------ | -------------------------------- | | `id` | `string` | Transcription ID **Format** uuid | | `status` | [`WebhookEventStatus`](types#webhookeventstatus) | Transcription result status | *** ## WebhookEventStatus ```ts type WebhookEventStatus = "completed" | "error"; ``` Webhook event status values *** ## WebhookHandlerResult ```ts type WebhookHandlerResult = { error?: string; event?: WebhookEvent; ok: boolean; status: number; }; ``` Result of webhook handling **Properties** | Property | Type | Description | | ----------------------------------------------- | ------------------------------------ | ------------------------------------------------ | | `error?` | `string` | Error message (only present when ok=false) | | `event?` | [`WebhookEvent`](types#webhookevent) | Parsed webhook event (only present when ok=true) | | `ok` | `boolean` | Whether the webhook was handled successfully | | `status` | `number` | HTTP status code to return | *** ## WebhookHandlerResultWithFetch ```ts type WebhookHandlerResultWithFetch = WebhookHandlerResult & { fetchTranscript: | () => Promise | undefined; fetchTranscription: | () => Promise | undefined; }; ``` Result of webhook handling with lazy fetch capabilities. When using `client.webhooks.handleExpress()` (or other framework handlers), the result includes helper methods to fetch the transcript or transcription. **Type Declaration** | Name | Type | Description | | -------------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fetchTranscript` | \| () => `Promise`\<[`ISonioxTranscript`](types#isonioxtranscript) \| `null`> \| `undefined` | Fetch the transcript for a completed transcription. Only available when `ok=true` and `event.status='completed'`. **Example** `const result = soniox.webhooks.handleExpress(req); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); }` | | `fetchTranscription` | \| () => `Promise`\<[`ISonioxTranscription`](types#isonioxtranscription) \| `null`> \| `undefined` | Fetch the full transcription object. Useful for both completed (metadata) and error (error details) statuses. **Example** `const result = soniox.webhooks.handleExpress(req); if (result.ok && result.event.status === 'error') { const transcription = await result.fetchTranscription(); console.log(transcription?.error_message); }` | *** ## WebhookHeaders ```ts type WebhookHeaders = | Headers | Record | { get: string | null; }; ``` Headers object type - supports both standard headers and record types *** ## HttpClient Pluggable HTTP client interface **Methods** **request()** ```ts request(request): Promise>; ``` Perform an HTTP request **Type Parameters** | Type Parameter | | -------------- | | `T` | **Parameters** | Parameter | Type | Description | | --------- | ---------------------------------- | --------------------- | | `request` | [`HttpRequest`](types#httprequest) | Request configuration | **Returns** `Promise`\<[`HttpResponse`](types#httpresponset)\<`T`>> Promise resolving to the response **Throws** [SonioxHttpError](classes#sonioxhttperror) On network errors, timeouts, HTTP errors, or parse errors *** ## HttpErrorDetails Error details for SonioxHttpError **Properties** | Property | Type | Description | | ---------------------------------------------------- | -------------------------------------- | ---------------------------------- | | `bodyText?` | `string` | Response body text (capped at 4KB) | | `cause?` | `unknown` | - | | `code` | [`HttpErrorCode`](types#httperrorcode) | - | | `headers?` | `Record`\<`string`, `string`> | - | | `message` | `string` | - | | `method` | [`HttpMethod`](types#httpmethod) | - | | `statusCode?` | `number` | - | | `url` | `string` | - | *** ## HttpRequest HTTP request configuration **Properties** | Property | Type | Description | | --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `body?` | [`HttpRequestBody`](types#httprequestbody) | Request body | | `headers?` | `Record`\<`string`, `string`> | Request headers | | `method` | [`HttpMethod`](types#httpmethod) | HTTP method | | `path` | `string` | URL path (relative to baseUrl) or absolute URL | | `query?` | [`QueryParams`](types#queryparams) | Query parameters (will be URL-encoded) | | `responseType?` | [`HttpResponseType`](types#httpresponsetype) | Expected response type **Default** `'json'` | | `signal?` | `AbortSignal` | Optional AbortSignal for request cancellation If provided along with timeoutMs, both will be respected | | `timeoutMs?` | `number` | Request timeout in milliseconds If not specified, uses the client's default timeout | *** ## HttpResponse\ HTTP response from the client **Type Parameters** | Type Parameter | | -------------- | | `T` | **Properties** | Property | Type | Description | | ------------------------------------------ | ----------------------------- | ----------------------------------------------- | | `data` | `T` | Parsed response data | | `headers` | `Record`\<`string`, `string`> | Response headers (normalized to lowercase keys) | | `status` | `number` | HTTP status code | *** ## ISonioxTranscript Type contract for SonioxTranscript class. **See** SonioxTranscript for full documentation. **Methods** **segments()** ```ts segments(options?): TranscriptSegment[]; ``` **Parameters** | Parameter | Type | | ---------- | ------------------------------------------------------------ | | `options?` | [`SegmentTranscriptOptions`](types#segmenttranscriptoptions) | **Returns** [`TranscriptSegment`](types#transcriptsegment)\[] **Properties** | Property | Type | | -------------------------------------------- | --------------------------------------------- | | `id` | `string` | | `text` | `string` | | `tokens` | [`TranscriptToken`](types#transcripttoken)\[] | *** ## ISonioxTranscription Type contract for SonioxTranscription class. **See** SonioxTranscription for full documentation. **Extended by** * [`ISonioxTranslationJob`](types#isonioxtranslationjob) **Methods** **delete()** ```ts delete(): Promise; ``` **Returns** `Promise`\<`void`> *** **destroy()** ```ts destroy(): Promise; ``` **Returns** `Promise`\<`void`> *** **getTranscript()** ```ts getTranscript(options?): Promise; ``` **Parameters** | Parameter | Type | | ----------------- | --------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | | `options.force?` | `boolean` | | `options.signal?` | `AbortSignal` | **Returns** `Promise`\<[`ISonioxTranscript`](types#isonioxtranscript) | `null`> *** **refresh()** ```ts refresh(signal?): Promise; ``` **Parameters** | Parameter | Type | | --------- | ------------- | | `signal?` | `AbortSignal` | **Returns** `Promise`\<`ISonioxTranscription`> *** **toJSON()** ```ts toJSON(): SonioxTranscriptionData; ``` **Returns** [`SonioxTranscriptionData`](types#sonioxtranscriptiondata) *** **wait()** ```ts wait(options?): Promise; ``` **Parameters** | Parameter | Type | | ---------- | ---------------------------------- | | `options?` | [`WaitOptions`](types#waitoptions) | **Returns** `Promise`\<`ISonioxTranscription`> **Properties** | Property | Type | | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | `audio_duration_ms` | `number` \| `null` \| `undefined` | | `audio_url` | `string` \| `null` \| `undefined` | | `client_reference_id` | `string` \| `null` \| `undefined` | | `context` | \| [`TranscriptionContext`](types#transcriptioncontext) \| `null` \| `undefined` | | `created_at` | `string` | | `enable_language_identification` | `boolean` | | `enable_speaker_diarization` | `boolean` | | `error_message` | `string` \| `null` \| `undefined` | | `error_type` | `string` \| `null` \| `undefined` | | `file_id` | `string` \| `null` \| `undefined` | | `filename` | `string` | | `id` | `string` | | `language_hints` | `string`\[] \| `undefined` | | `model` | `string` | | `status` | [`TranscriptionStatus`](types#transcriptionstatus) | | `transcript` | [`ISonioxTranscript`](types#isonioxtranscript) \| `null` \| `undefined` | | `webhook_auth_header_name` | `string` \| `null` \| `undefined` | | `webhook_auth_header_value` | `string` \| `null` \| `undefined` | | `webhook_status_code` | `number` \| `null` \| `undefined` | | `webhook_url` | `string` \| `null` \| `undefined` | *** ## ISonioxTranslationJob Type contract for SonioxTranslationJob class. **Extends** * [`ISonioxTranscription`](types#isonioxtranscription) **Methods** **delete()** ```ts delete(): Promise; ``` **Returns** `Promise`\<`void`> **Inherited from** [`ISonioxTranscription`](types#isonioxtranscription).[`delete`](types#isonioxtranscription-delete) *** **destroy()** ```ts destroy(): Promise; ``` **Returns** `Promise`\<`void`> **Inherited from** [`ISonioxTranscription`](types#isonioxtranscription).[`destroy`](types#isonioxtranscription-destroy) *** **fetchTranslation()** ```ts fetchTranslation(options?): Promise; ``` **Parameters** | Parameter | Type | | ----------------- | --------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | | `options.force?` | `boolean` | | `options.signal?` | `AbortSignal` | **Returns** `Promise`\<[`SonioxTranslation`](types#sonioxtranslation) | `null`> *** **getTranscript()** ```ts getTranscript(options?): Promise; ``` **Parameters** | Parameter | Type | | ----------------- | --------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | | `options.force?` | `boolean` | | `options.signal?` | `AbortSignal` | **Returns** `Promise`\<[`ISonioxTranscript`](types#isonioxtranscript) | `null`> **Inherited from** [`ISonioxTranscription`](types#isonioxtranscription).[`getTranscript`](types#isonioxtranscription-gettranscript) *** **getTranslation()** ```ts getTranslation(options?): Promise; ``` **Parameters** | Parameter | Type | | ----------------- | --------------------------------------------------- | | `options?` | \{ `force?`: `boolean`; `signal?`: `AbortSignal`; } | | `options.force?` | `boolean` | | `options.signal?` | `AbortSignal` | **Returns** `Promise`\<[`SonioxTranslation`](types#sonioxtranslation) | `null`> *** **refresh()** ```ts refresh(signal?): Promise; ``` **Parameters** | Parameter | Type | | --------- | ------------- | | `signal?` | `AbortSignal` | **Returns** `Promise`\<`ISonioxTranslationJob`> **Overrides** [`ISonioxTranscription`](types#isonioxtranscription).[`refresh`](types#isonioxtranscription-refresh) *** **toJSON()** ```ts toJSON(): SonioxTranscriptionData; ``` **Returns** [`SonioxTranscriptionData`](types#sonioxtranscriptiondata) **Overrides** [`ISonioxTranscription`](types#isonioxtranscription).[`toJSON`](types#isonioxtranscription-tojson) *** **wait()** ```ts wait(options?): Promise; ``` **Parameters** | Parameter | Type | | ---------- | ---------------------------------- | | `options?` | [`WaitOptions`](types#waitoptions) | **Returns** `Promise`\<`ISonioxTranslationJob`> **Overrides** [`ISonioxTranscription`](types#isonioxtranscription).[`wait`](types#isonioxtranscription-wait) **Properties** | Property | Type | | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- | | `audio_duration_ms` | `number` \| `null` \| `undefined` | | `audio_url` | `string` \| `null` \| `undefined` | | `client_reference_id` | `string` \| `null` \| `undefined` | | `context` | \| [`TranscriptionContext`](types#transcriptioncontext) \| `null` \| `undefined` | | `created_at` | `string` | | `enable_language_identification` | `boolean` | | `enable_speaker_diarization` | `boolean` | | `error_message` | `string` \| `null` \| `undefined` | | `error_type` | `string` \| `null` \| `undefined` | | `file_id` | `string` \| `null` \| `undefined` | | `filename` | `string` | | `id` | `string` | | `language_hints` | `string`\[] \| `undefined` | | `model` | `string` | | `status` | [`TranscriptionStatus`](types#transcriptionstatus) | | `transcript` | [`ISonioxTranscript`](types#isonioxtranscript) \| `null` \| `undefined` | | `translation` | [`SonioxTranslation`](types#sonioxtranslation) \| `null` \| `undefined` | | `webhook_auth_header_name` | `string` \| `null` \| `undefined` | | `webhook_auth_header_value` | `string` \| `null` \| `undefined` | | `webhook_status_code` | `number` \| `null` \| `undefined` | | `webhook_url` | `string` \| `null` \| `undefined` | *** ## translateFromTranscript() ```ts function translateFromTranscript(transcript, mode): SonioxTranslation; ``` Reshape a transcript produced by a translation-enabled transcription into a structured [SonioxTranslation](types#sonioxtranslation) result. This is the same logic `SonioxTranslationJob.getTranslation()` applies. Use it directly in webhook handlers or anywhere else you already have a transcript in hand. **Parameters** | Parameter | Type | Description | | ------------ | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | | `transcript` | `TranscriptLike` | Transcript (or any object with a `tokens` array) emitted for a translation-enabled transcription. | | `mode` | [`TranslateFromTranscriptMode`](types#translatefromtranscriptmode) | Whether to reshape as one-way or two-way; the discriminator tells the helper which result shape to produce. | **Returns** [`SonioxTranslation`](types#sonioxtranslation) A [SonioxTranslation](types#sonioxtranslation) keyed on `mode`. **Example** ```typescript import { translateFromTranscript } from '@soniox/node'; // From a webhook handler that just received the transcript const result = translateFromTranscript(transcript, { type: 'one_way', to: 'es' }); console.log(result.translation_text); ``` # Async transcription with Node SDK URL: /sdk/node-SDK/stt/async-transcription Transcribe audio files asynchronously with the Soniox Node SDK Soniox Node SDK supports asynchronous transcription for audio files. This allows you to transcribe recordings without maintaining a live connection or streaming pipeline. You can either wait for completion or create a job and retrieve the results based on the webhook event. ## Quickstart SDK provides you a convenient method to transcribe audio from a local file, public URL, or previously uploaded file. The **[`transcribe`](/sdk/node-SDK/reference/classes#sonioxsttapi-transcribe) method will:** 1. Upload the file to Soniox if it's not already uploaded (if `file` is provided) 2. Transcribe the audio 3. Await for the transcription to complete (if `wait: true` is provided) 4. Return the transcription object and final transcript (you can disable this by setting `fetch_transcript: false` and fetch transcript later using [`getTranscript`](/sdk/node-SDK/reference/classes#sonioxsttapi-gettranscript) method) 5. Delete the file from Soniox if it was uploaded (configurable using `cleanup` option) Don't forget to remove files and transcriptions from Soniox after you're done with them if `cleanup` option is not set. **Transcribe from a local file and delete everything after transcription is complete** ```ts import { readFile } from 'node:fs/promises'; const audio = await readFile('audio.mp3'); // Buffer | Uint8Array | Blob | ReadableStream const transcription = await client.stt.transcribe({ model: 'stt-async-v5', file: audio, filename: 'audio.mp3', wait: true, cleanup: ['file', 'transcription'], }); ``` **Transcribe from a public URL and fetch the transcript later using [`getTranscript`](/sdk/node-SDK/reference/classes#sonioxsttapi-gettranscript) method** ```ts const transcription = await client.stt.transcribe({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', wait: true, }); const transcript = await transcription.getTranscript(); ``` **Transcribe from a previously uploaded file and setup a [webhook](/sdk/node-SDK/stt/webhooks) to get the transcription when it's complete** ```ts const transcription = await client.stt.transcribe({ model: 'stt-async-v5', file_id: file.id, wait: false, webhook_url: 'https://example.com/webhook', }); ``` Learn more about [testing webhooks locally](/sdk/node-SDK/stt/webhooks#testing-webhooks-locally). ## Retrieve list of transcriptions You can retrieve a list of transcriptions using [`list`](/sdk/node-SDK/reference/classes#sonioxsttapi-list) method. ```ts const transcriptions = await client.stt.list({ limit: 100, // page size — pagination continues automatically when iterated }); ``` The returned result is async iterable - use `for await...of` to iterate through all pages. ```ts for await (const transcription of transcriptions) { console.log(transcription.id, transcription.status); } ``` ## Count transcriptions Use [`count`](/sdk/node-SDK/reference/classes#sonioxsttapi-count) to retrieve the total number of transcriptions. ```ts const counts = await client.stt.count(); console.log(counts.public_api); console.log(counts.playground); console.log(counts.total); ``` ## Get transcription You can get a transcription by ID using [`get`](/sdk/node-SDK/reference/classes#sonioxsttapi-get) method. ```ts const transcription = await client.stt.get('transcription-id'); console.log(transcription.id, transcription.status); ``` ## Get transcription transcript You can get a transcription transcript using [`getTranscript`](/sdk/node-SDK/reference/classes#sonioxsttapi-gettranscript) method. ```ts const transcript = await transcription.getTranscript(); console.log(transcript.text); ``` Or get transcript by transcription ID. ```ts const transcript = await client.stt.getTranscript(transcription.id); console.log(transcript.text); ``` ## Segmenting transcripts Group tokens by speaker and language changes: ```ts const transcript = await transcription.getTranscript(); for (const segment of transcript?.segments() ?? []) { console.log(`[${segment.speaker}][${segment.language}] ${segment.text}`); } ``` ## Delete or destroy transcription You can delete or destroy a transcription using [`delete`](/sdk/node-SDK/reference/classes#sonioxsttapi-delete) or [`destroy`](/sdk/node-SDK/reference/classes#sonioxsttapi-destroy) method. **Delete transcription only** ```ts await client.stt.delete(transcription.id); ``` **Delete transcription and its file if it was uploaded** ```ts await client.stt.destroy(transcription.id); ``` ## Delete all transcriptions and files from your account ### Delete all transcriptions You can delete all transcriptions using [`stt.delete_all`](/sdk/node-SDK/reference/classes#sonioxsttapi-delete_all) method. ```ts await client.stt.delete_all(); ``` ### Delete all transcriptions and their files You can delete all transcriptions and their files using [`stt.destroy_all`](/sdk/node-SDK/reference/classes#sonioxsttapi-destroy_all) method. ```ts await client.stt.destroy_all(); ``` `delete_all` and `destroy_all` operations are irreversible and cannot be undone. # Async translation with Node SDK URL: /sdk/node-SDK/stt/async-translation Translate audio asynchronously with the Soniox Node SDK Soniox Node SDK supports asynchronous speech translation through [`client.stt.translate`](/sdk/node-SDK/reference/classes#sonioxsttapi-translate). It creates an async transcription job with translation enabled, then reshapes the completed transcript into a structured translation result. Use async translation when you want to translate uploaded files, public audio URLs, or previously uploaded files without maintaining a live connection. This method is just a syntactic sugar on top of [`client.stt.transcribe`](/sdk/node-SDK/stt/async-transcription). Use `transcribe` if you need more low level control on the output. ## Quickstart For simple one-way translation, provide `to` and one audio source: ```ts const job = await client.stt.translate({ audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', to: 'es', wait: true, }); console.log(job.translation?.translation_text); ``` ## Translation modes ### One-way translation Use `to` to translate any detected source language to a target language. ```ts const job = await client.stt.translate({ file: audio, filename: 'meeting.mp3', to: 'es', wait: true, }); const translation = job.translation; console.log(translation?.original_text); console.log(translation?.translation_text); ``` If you know the source language, provide `from`. The SDK forwards it as a language hint for the underlying async transcription job. ```ts const job = await client.stt.translate({ audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', from: 'en', to: 'es', wait: true, }); ``` ### Two-way translation Use `between` for [bidirectional translation](/translation/stt-translation#two-way-translation) between two languages. This is useful for conversations where either language can appear in the audio. ```ts const job = await client.stt.translate({ file: audio, filename: 'conversation.mp3', between: ['en', 'es'], enable_speaker_diarization: true, wait: true, }); for (const segment of job.translation?.segments ?? []) { console.log(`[${segment.from}] ${segment.original_text}`); if (segment.translation_text) { console.log(` -> [${segment.to}] ${segment.translation_text}`); } } ``` ## Wait later If you do not want to block until the job completes, omit `wait` and call [`wait`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-wait) or [`fetchTranslation`](/sdk/node-SDK/reference/classes#sonioxtranslationjob-fetchtranslation) later. ```ts const job = await client.stt.translate({ audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', to: 'es', }); const completed = await job.wait(); const translation = await completed.fetchTranslation(); console.log(translation?.translation_text); ``` ## Use with webhooks Async translation jobs are regular async transcription jobs with translation enabled, so you can use the same [webhooks](/sdk/node-SDK/stt/webhooks) flow. ```ts const job = await client.stt.translate({ file_id: file.id, to: 'es', webhook_url: 'https://example.com/webhook', }); ``` In the webhook handler, fetch the transcript and reshape it with [`translateFromTranscript`](/sdk/node-SDK/reference/types#translatefromtranscript). ```ts import { translateFromTranscript } from '@soniox/node'; const transcript = await client.stt.getTranscript(event.id); if (transcript) { const translation = translateFromTranscript(transcript, { type: 'one_way', to: 'es', }); console.log(translation.translation_text); } ``` ## Fetch transcript instead of translation `translate()` also keeps access to the underlying transcript. This is useful when you need both the original token stream and the reshaped translation. ```ts const job = await client.stt.translate({ file: audio, filename: 'meeting.mp3', to: 'es', wait: true, }); const transcript = await job.getTranscript(); const translation = await job.getTranslation(); ``` Translation tokens do not carry timestamps, so `TranscriptToken.start_ms`, `TranscriptToken.end_ms`, and matching segment timestamps can be `undefined` for translation-only tokens. # Handling files with Node SDK URL: /sdk/node-SDK/stt/files Upload audio files and manage them with the Soniox Node SDK Node SDK provides helpers to work with the [Files API](/api-reference/stt/files/upload_file) to upload audio for async transcription or to reuse files across multiple jobs. ## Upload [`upload()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-upload) accepts `Buffer`, `Uint8Array`, `Blob`, `ReadableStream`. ```ts import { readFile } from 'node:fs/promises'; const audio = await readFile('audio.mp3'); const file = await client.files.upload(audio, { filename: 'audio.mp3', client_reference_id: 'meeting-42', }); console.log(file.id, file.filename, file.size); ``` Read more about [Supported audio formats](/stt/async/async-transcription#audio-formats). ## List files [`list()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-list) returns a paginated list of all uploaded files. Use `for await...of` to iterate through all pages. ```ts const result = await client.files.list({ limit: 100 }); // Automatic pagination for await (const file of result) { console.log(file.id, file.filename); } ``` ## Count files [`count()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-count) returns the total number of uploaded files. ```ts const counts = await client.files.count(); console.log(counts.public_api); console.log(counts.playground); console.log(counts.total); ``` ## Get file Get a file by ID using [`get()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-get) method: ```ts const file = await client.files.get('file-id'); ``` ## Delete file Delete file via instance using [`file.delete()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-delete) method: ```ts const file = await client.files.get('file-id'); await file.delete(); ``` Or delete by ID using [`delete()`](/sdk/node-SDK/reference/classes#sonioxfilesapi-delete) method: ```ts await client.files.delete('file-id'); ``` ## Delete all files from your account You can delete all files using `files.delete_all` method. ```ts await client.files.delete_all(); ``` `delete_all` operation is irreversible and cannot be undone. # Real-time transcription with Node SDK URL: /sdk/node-SDK/stt/realtime-transcription Create and manage real-time speech-to-text sessions with the Soniox Node SDK Soniox Node SDK supports real-time streaming transcription over WebSocket. This allows you to transcribe live audio with low latency — ideal for voice agents, live captions, and interactive experiences. You can consume results via events, async iteration, or buffers that group tokens into utterances. SDK provides you helper methods to work both with direct and proxy streaming. ## Direct stream and temporary API keys Read more about [Direct stream](/guides/direct-stream) Node SDK provides you a helper method to issue [temporary API Keys](/api-reference/auth/create_temporary_api_key) to use with [Direct stream](/guides/direct-stream) from the client's browser. `client_reference_id` is optional — when set, every request authenticated with the key is recorded under that identifier in [usage logs](/guides/usage-logs). ```ts const { api_key, expires_at } = await client.auth.createTemporaryKey({ usage_type: "transcribe_websocket", expires_in_seconds: 3600, client_reference_id: "support-call-123", }); console.log(api_key, expires_at); ``` Soniox's [Web Library](/sdk/web-SDK) handles everything client-side — capturing microphone input, managing the WebSocket connection, and authenticating using temporary API keys. ## Proxy stream helpers Read more about [Proxy stream](/guides/proxy-stream) Use the SDK's real-time session for low-latency transcription, live captions, and voice agent experiences. ## Create a real-time session ```ts const session = client.realtime.stt({ model: "stt-rt-v5", audio_format: "pcm_s16le", sample_rate: 16000, num_channels: 1, enable_endpoint_detection: true, enable_speaker_diarization: true, language_hints: ["en"], context: { text: "Support call about billing", terms: ["invoice", "refund"], }, }); ``` ## Connect and stream Use [`sendAudio`](/sdk/node-SDK/reference/classes#realtimesttsession-sendaudio) to send audio chunks to the session. ```ts // audioStream: AsyncIterable // e.g. a Node fs ReadStream, fetch response body, or mic-capture iterable. await session.connect(); session.on("result", (result) => { process.stdout.write(result.tokens.map((t) => t.text).join("")); }); for await (const chunk of audioStream) { session.sendAudio(chunk); } await session.finish(); ``` See the full example with a demo stream in the quickstart: [Create your first real-time session](/sdk/node-SDK#create-your-first-real-time-session) ## Handle session events ```ts session.on("connected", () => console.log("connected")); session.on("disconnected", (reason) => console.log("disconnected:", reason)); session.on("error", (error) => console.error("error:", error)); session.on("result", (result) => console.log(result.tokens.map((t) => t.text).join("")), ); session.on("endpoint", () => console.log("endpoint")); // server-detected end of utterance session.on("finalized", () => console.log("finalized")); // fires after a manual `finalize()` request session.on("finished", () => console.log("finished")); // fires after `finish()` completes ``` ## Session lifecycle ```ts // Connect to the session await session.connect(); // idle -> connected // Send audio chunks to the session for await (const chunk of audioStream) { session.sendAudio(chunk); } // Gracefully end the session (Signal end of audio and wait for remaining results from the server) await session.finish(); // Or cancel immediately without waiting for final results: session.close(); ``` ## Endpoint detection and manual finalization Endpoint detection lets you know when a speaker has finished speaking. This is critical for real-time voice AI assistants, command-and-response systems, and conversational apps where you want to respond immediately without waiting for long silences. Read more about [Endpoint detection](/stt/rt/endpoint-detection) Enable endpoint detection by setting `enable_endpoint_detection: true` in the session configuration. ```ts const session = client.realtime.stt({ model: "stt-rt-v5", enable_endpoint_detection: true, }); ``` Manual finalization gives you precise control over when audio should be finalized — useful for Push-to-talk systems and client-side voice activity detection (VAD). Read more about [Manual finalization](/stt/rt/manual-finalization) ```ts session.finalize(); ``` ## Pause and resume ```ts session.pause(); // keeps connection alive, drops audio while paused session.resume(); // resume sending audio ``` You are billed for the full stream duration even when session is paused. In a typical voice agent loop, you pause the STT session while the agent is responding to avoid transcribing the agent's own audio or processing overlapping speech: ```ts session.on("endpoint", async () => { const utterance = utteranceBuffer.markEndpoint(); // Read more about utterance buffer below if (!utterance) return; // Pause STT while the agent processes and responds session.pause(); const response = await myAgent.respond(utterance.text); // ... send response audio to the client ... // Resume listening for the next utterance session.resume(); }); ``` SDK will `finalize` audio on pause. Make sure to adjust your VAD sensitivity to have enough silence before pause. Learn more about [Manual finalization](/stt/rt/manual-finalization#key-points) ## Keepalive Read more about [Connection keepalive](/stt/rt/connection-keepalive) While the session is paused via [`session.pause()`](/sdk/node-SDK/reference/classes#realtimesttsession-pause), the Node SDK **automatically sends** a keepalive every `keepalive_interval_ms` (default `5000` ms) to hold the WebSocket open. A manual call is only needed if you want to force a keepalive outside of that cadence: ```ts session.keepAlive(); ``` ## Detecting utterance for voice agents When building voice AI agents, you need to know when the user has finished speaking so you can process their input. The SDK provides [`RealtimeUtteranceBuffer`](/sdk/node-SDK/reference/classes#realtimeutterancebuffer) to collect streaming tokens into complete utterances, driven by the server's endpoint detection. ### How it works 1. Set `enable_endpoint_detection: true` in the session config – the server detects when the user stops speaking and emits an endpoint event. 2. Feed every result event into the buffer with [`addResult()`](/sdk/node-SDK/reference/classes#realtimeutterancebuffer-addresult). 3. When an endpoint fires, call [`markEndpoint()`](/sdk/node-SDK/reference/classes#realtimeutterancebuffer-markendpoint) to flush the buffer and get the complete utterance. ### Example ```ts import { SonioxNodeClient, RealtimeUtteranceBuffer } from "@soniox/node"; const client = new SonioxNodeClient(); // Call this for each new user/connection - each session needs its own buffer function createAgentSession(onUtterance: (text: string) => void) { const session = client.realtime.stt({ model: "stt-rt-v5", enable_endpoint_detection: true, }); // Each session gets its own buffer const utteranceBuffer = new RealtimeUtteranceBuffer({ final_only: true, }); session.on("result", (result) => { utteranceBuffer.addResult(result); }); session.on("endpoint", () => { const utterance = utteranceBuffer.markEndpoint(); if (utterance) { onUtterance(utterance.text); } }); return session; } // Usage: create a session per user connection const session = createAgentSession((text) => { console.log("User said:", text); // Pass to your LLM / agent pipeline }); await session.connect(); session.sendAudio(audioChunk); ``` ## Streaming audio from a file Use [`sendStream()`](/sdk/node-SDK/reference/classes#realtimesttsession-sendstream) to pipe audio directly from a file (or any async source) into a real-time session. It accepts any `AsyncIterable` – Node.js file streams, Web `ReadableStream`, Bun file streams, fetch response bodies, or custom async generators. ```ts import { createReadStream } from "node:fs"; await session.connect(); await session.sendStream(createReadStream("audio.mp3"), { pace_ms: 60, // Throttle to simulate real-time pace; omit for live audio finish: true, }); ``` ### Simulating real-time pace When streaming pre-recorded files, you can throttle sending with `pace_ms` to simulate how audio would arrive from a live source (e.g. a microphone). This isn't needed for live audio – it naturally arrives at real-time pace. Use [`sendAudio`](/sdk/node-SDK/stt/realtime-transcription#connect-and-stream) if you need more control. # Handling webhooks with Node SDK URL: /sdk/node-SDK/stt/webhooks Use webhooks to receive transcription results with the Soniox Node SDK SDK provides you a helper method to handle [Webhooks](/stt/async/webhooks) from the Soniox API and transform them into a typed object. ## Configure webhook delivery If webhook is enabled during [transcription creation](/sdk/node-SDK/stt/async-transcription#quickstart), Soniox will send a POST request to your webhook URL with the transcription result. ```ts await client.stt.transcribe({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', webhook_url: 'https://your-server.com/webhooks/soniox', webhook_auth_header_name: 'X-Webhook-Secret', webhook_auth_header_value: process.env.SONIOX_API_WEBHOOK_SECRET, }); ``` You can also append metadata as query parameters: ```ts await client.stt.transcribe({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', webhook_url: 'https://your-server.com/webhooks/soniox', webhook_query: { request_id: 'abc-123' }, }); ``` Learn more about [testing webhooks locally](/sdk/node-SDK/stt/webhooks#testing-webhooks-locally). ## Handling webhooks The SDK provides both framework-agnostic and framework-specific handlers that parse the request body, verify authentication, and return a typed [`WebhookHandlerResultWithFetch`](/sdk/node-SDK/reference/types#webhookhandlerresultwithfetch). All handlers return: * `ok` — whether the webhook was handled successfully * `status` — HTTP status code to return to Soniox * `event` — the parsed [`WebhookEvent`](/sdk/node-SDK/reference/types#webhookevent) (when `ok=true`) * `error` — error message (when `ok=false`) * `fetchTranscript()` — lazily fetch the full transcript (when `event.status === 'completed'`) * `fetchTranscription()` — lazily fetch the transcription object All handler snippets below assume you already have an initialized `client`, for example `const client = new SonioxNodeClient();`. ```ts import express from 'express'; const app = express(); app.use(express.json()); app.post('/webhooks/soniox', async (req, res) => { const result = client.webhooks.handleExpress(req); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } res.status(result.status).json({ received: true }); }); ``` ```ts import Fastify from 'fastify'; const app = Fastify(); app.post('/webhooks/soniox', async (request, reply) => { const result = client.webhooks.handleFastify(request); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } return reply.status(result.status).send({ received: true }); }); ``` ```ts import { Hono } from 'hono'; const app = new Hono(); app.post('/webhooks/soniox', async (c) => { const result = await client.webhooks.handleHono(c); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } return c.json({ received: true }, result.status); }); ``` `handleHono` is async because it reads the request body from the Hono context. ```ts import { Controller, Post, Req, Res } from '@nestjs/common'; import { Request, Response } from 'express'; @Controller('webhooks') export class WebhooksController { @Post('soniox') async handleSoniox(@Req() req: Request, @Res() res: Response) { const result = client.webhooks.handleNestJS(req); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } res.status(result.status).json({ received: true }); } } ``` Use `handleRequest` with any framework that provides a standard Fetch API `Request` object: ```ts export default { async fetch(request: Request) { if (new URL(request.url).pathname === '/webhooks/soniox') { const result = await client.webhooks.handleRequest(request); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } return Response.json({ received: true }, { status: result.status }); } return new Response('Not found', { status: 404 }); }, }; ``` `handleRequest` is async because it reads the request body from the `Request` object. The `handle` method is a framework-agnostic handler. You provide the method, headers, and parsed body directly: ```ts const result = client.webhooks.handle({ method: req.method, headers: req.headers, body: req.body, }); if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); console.log(transcript?.text); } if (result.ok && result.event.status === 'error') { const transcription = await result.fetchTranscription(); console.log(transcription?.error_message); } ``` See [`HandleWebhookOptions`](/sdk/node-SDK/reference/types#handlewebhookoptions) for all available options. ## Webhook auth helpers By default, webhook handlers read auth from `SONIOX_API_WEBHOOK_HEADER` and `SONIOX_API_WEBHOOK_SECRET`. You can override auth explicitly: ```ts const result = client.webhooks.handleExpress(req, { name: 'X-Webhook-Secret', value: process.env.SONIOX_API_WEBHOOK_SECRET, }); ``` Learn more info about [Environment Variables](/sdk/node-SDK/reference#environment-variables). But you can also verify the auth manually: ```ts const auth = client.webhooks.getAuthFromEnv(); if (!auth) { throw new Error('Missing webhook auth'); } const isValid = client.webhooks.verifyAuth(req.headers, auth); ``` ## Webhook event helpers ```ts const event = client.webhooks.parseEvent(req.body); const isValid = client.webhooks.isEvent(req.body); ``` ## Testing webhooks locally Since Soniox needs to reach your server over the internet, you'll need a tunnel to expose your local development server. You can use [Cloudflare Tunnel](https://developers.cloudflare.com/pages/how-to/preview-with-cloudflare-tunnel/) or [ngrok](https://ngrok.com/). [Cloudflare Tunnel](https://developers.cloudflare.com/pages/how-to/preview-with-cloudflare-tunnel/) provides a quick way to expose your local server — no account required. Install `cloudflared` and start a tunnel pointing to your local server: ```bash # macOS brew install cloudflared # Start a tunnel to your local server on port 3000 cloudflared tunnel --url http://localhost:3000 ``` The command will output a public URL like `https://random-name.trycloudflare.com`. [ngrok](https://ngrok.com/) creates a secure tunnel to your local server and provides a stable public URL. Install ngrok, authenticate, and start a tunnel: ```bash # macOS brew install ngrok # Authenticate (one-time setup) ngrok config add-authtoken # Start a tunnel to your local server on port 3000 ngrok http 3000 ``` The command will output a public URL like `https://abcd-1234.ngrok-free.app`. Once you have your public tunnel URL, use it as the `webhook_url` when creating a transcription: ```ts import express from 'express'; import { SonioxNodeClient } from '@soniox/node'; const client = new SonioxNodeClient(); const app = express(); app.use(express.json()); // Handle incoming webhook events app.post('/webhooks/soniox', async (req, res) => { const result = client.webhooks.handleExpress(req); // You will receive the webhook event when the transcription is completed if (result.ok && result.event.status === 'completed') { const transcript = await result.fetchTranscript(); // Lazy fetch the transcript console.log(transcript?.text); } res.status(result.status).json({ received: true }); }); app.listen(3000, () => console.log('Listening on port 3000')); // Start a transcription with the tunnel URL as webhook await client.stt.transcribe({ model: 'stt-async-v5', audio_url: 'https://soniox.com/media/examples/coffee_shop.mp3', webhook_url: 'https:///webhooks/soniox', }); ``` # Real-time speech generation with Node SDK URL: /sdk/node-SDK/tts/realtime-speech-generation Stream text to speech with the Soniox Node SDK over WebSocket The Soniox Node SDK supports real-time Text-to-Speech generation over WebSocket. You send text — all at once or incrementally — and receive decoded audio chunks as they are generated. This is the lowest-latency path for voice agents, LLM output narration, and any scenario where text arrives progressively. If you already have the full text up front and don't need chunk-by-chunk streaming, use [REST speech generation](/sdk/node-SDK/tts/rest-speech-generation) instead — it's a single HTTP request. ## Quickstart `client.realtime.tts()` creates a single-stream session: it opens a WebSocket, configures a stream, and returns a [`RealtimeTtsStream`](/sdk/node-SDK/reference/classes#realtimettsstream). Send text, then consume audio by async iteration. ```typescript import { writeFileSync } from "node:fs"; import { SonioxNodeClient } from "@soniox/node"; const client = new SonioxNodeClient(); const stream = await client.realtime.tts({ voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "wav", }); // Send all the text and mark the stream as finished. stream.sendText( "Hello from Soniox real-time text-to-speech. This is a single-stream example.", { end: true }, ); // Collect audio as it arrives. const chunks: Uint8Array[] = []; for await (const chunk of stream) { chunks.push(chunk); } const audio = Buffer.concat(chunks); writeFileSync("tts_realtime.wav", audio); console.log(`Wrote ${audio.byteLength} bytes`); ``` The stream closes itself (and the underlying WebSocket) once `terminated` fires. You never have to call `close()` in single-stream mode. ## Send text incrementally Use `sendText(text)` for each chunk as it becomes available, then either set `{ end: true }` on the last call or invoke `finish()` explicitly. This is the pattern for narrating an LLM response token-by-token. ```typescript const stream = await client.realtime.tts({ voice: "Adrian", model: "tts-rt-v2", audio_format: "wav", }); stream.sendText("Hello from Soniox "); stream.sendText("real-time TTS. "); stream.sendText("This is the final chunk.", { end: true }); for await (const chunk of stream) { playback(chunk); // play, buffer, or write the chunk somewhere } ``` Equivalent with an explicit `finish()`: ```typescript stream.sendText("Hello from Soniox real-time TTS."); stream.finish(); for await (const chunk of stream) { playback(chunk); } ``` ## Pipe from an async iterable `stream.sendStream(source)` pipes any `AsyncIterable` into the TTS session and auto-finishes when the iterable completes. This is the idiomatic way to connect an LLM token stream directly to speech output — sending and receiving run concurrently. ```typescript async function* tokensFromLlm(): AsyncIterable { const words = "Hello from Soniox real-time TTS.".split(" "); for (let i = 0; i < words.length; i++) { await new Promise((r) => setTimeout(r, 50)); yield i === 0 ? words[i] : " " + words[i]; } } const stream = await client.realtime.tts({ voice: "Adrian", model: "tts-rt-v2", audio_format: "wav", }); // Start piping text. Audio consumption runs concurrently below. void stream.sendStream(tokensFromLlm()); for await (const chunk of stream) { playback(chunk); } ``` ## Event-based consumption `RealtimeTtsStream` is also a [`TypedEmitter`](/sdk/node-SDK/reference/classes#realtimettsstream). When you prefer an event-driven style over async iteration, listen for [`TtsStreamEvents`](/sdk/node-SDK/reference/types#ttsstreamevents): | Event | Payload | Description | | ------------ | ------------ | ------------------------------------------------------ | | `audio` | `Uint8Array` | Decoded audio chunk. | | `audioEnd` | — | Server marked the final audio payload for this stream. | | `terminated` | — | Stream fully closed by the server. | | `error` | `Error` | Stream-level error. | ```typescript const stream = await client.realtime.tts({ voice: "Adrian", model: "tts-rt-v2", audio_format: "wav", }); stream.on("audio", (chunk) => playback(chunk)); stream.on("audioEnd", () => console.log("last audio payload received")); stream.on("error", (err) => console.error("Stream error:", err)); stream.on("terminated", () => console.log("stream done")); stream.sendText("Hello from event-based TTS.", { end: true }); ``` Choose either async iteration **or** event listeners — not both. The async iterator consumes `audio` events internally. ## Multi-stream connection A single WebSocket connection can carry up to 5 concurrent TTS streams. Use `client.realtime.tts.multiStream()` to open a [`RealtimeTtsConnection`](/sdk/node-SDK/reference/classes#realtimettsconnection), then call `connection.stream()` for each stream. Each stream has its own `streamId` and can have different voice, model, and audio format settings. ```typescript const connection = await client.realtime.tts.multiStream(); const streamA = await connection.stream({ voice: "Adrian", audio_format: "wav", }); const streamB = await connection.stream({ // Enumerate available voices via `client.tts.listModels()`. voice: "", audio_format: "wav", }); streamA.sendText("Hello from stream A.", { end: true }); streamB.sendText("Hello from stream B.", { end: true }); const [audioA, audioB] = await Promise.all([ collect(streamA), collect(streamB), ]); connection.close(); async function collect(stream: AsyncIterable): Promise { const chunks: Uint8Array[] = []; for await (const chunk of stream) { chunks.push(chunk); } return Buffer.concat(chunks); } ``` Call `connection.close()` when you're done — this ends all active streams and closes the WebSocket. ## Cancel, finish, and close | Method | Behavior | | -------------------- | --------------------------------------------------------------------------------------------------------- | | `stream.finish()` | Signals "no more text". The server finishes generating audio and sends `terminated`. | | `stream.cancel()` | Aborts generation immediately. The server stops producing audio and sends `terminated`. | | `stream.close()` | Terminates the stream. In single-stream mode (`client.realtime.tts(...)`) this also closes the WebSocket. | | `connection.close()` | Closes the WebSocket and terminates all streams on a multi-stream connection. | ```typescript // Graceful stop stream.finish(); // User-triggered cancel stream.cancel(); ``` ## Error handling A failed stream does not close the whole WebSocket connection by default. Stream-level errors finalize only that stream (`terminated` fires for the same `streamId`), while other streams on the same connection can continue. Connection-level failures end the whole connection and all active streams. ```typescript import { RealtimeError, SonioxError } from "@soniox/node"; try { const stream = await client.realtime.tts({ voice: "Adrian" }); stream.sendText("Hello!", { end: true }); for await (const _ of stream) { // consume audio } } catch (err) { if (err instanceof RealtimeError) { console.error(`Realtime TTS error (${err.code}):`, err.message); } else if (err instanceof SonioxError) { console.error("Soniox SDK error:", err.message); } else { throw err; } } ``` ## Server-driven defaults Set shared TTS fields once on the client via `tts_defaults` and they'll be merged as the base layer every time you open a stream. Caller-provided fields on `client.realtime.tts(...)` / `connection.stream(...)` override the defaults, so you never need to spread them manually. ```typescript import { SonioxNodeClient } from "@soniox/node"; const client = new SonioxNodeClient({ tts_defaults: { model: "tts-rt-v2", language: "en", voice: "Adrian", audio_format: "wav", }, }); // Inherits everything from tts_defaults. const stream = await client.realtime.tts(); // Overrides the default voice for this stream only. const customVoice = await client.realtime.tts({ voice: "" }); ``` `tts_defaults` is also accepted on [`RealtimeOptions`](/sdk/node-SDK/reference/types#realtimeoptions) if you want to scope defaults to a specific realtime namespace. On the Web and React SDKs, the equivalent is [`SonioxConnectionConfig.tts_defaults`](/sdk/web-SDK/reference/types#sonioxconnectionconfig) — return it from the async `config` resolver alongside the temporary `api_key` so the server owns the defaults. ## See also * [REST speech generation](/sdk/node-SDK/tts/rest-speech-generation) — single-request HTTP TTS. * [`RealtimeTtsStream` reference](/sdk/node-SDK/reference/classes#realtimettsstream) * [`RealtimeTtsConnection` reference](/sdk/node-SDK/reference/classes#realtimettsconnection) * [`TtsStreamInput`](/sdk/node-SDK/reference/types#ttsstreaminput), [`TtsStreamEvents`](/sdk/node-SDK/reference/types#ttsstreamevents) * [TTS WebSocket API](/api-reference/tts/websocket-api) # REST speech generation with Node SDK URL: /sdk/node-SDK/tts/rest-speech-generation Generate speech from text with the Soniox Node SDK over HTTP The Soniox Node SDK supports Text-to-Speech generation over HTTP with `SonioxNodeClient`. Use REST when you have the full text up front and don't need streaming from an LLM — the SDK can return audio bytes, stream them as an async iterable, or write the output directly to a file. Use [real-time speech generation](/sdk/node-SDK/tts/realtime-speech-generation) when you want the lowest latency to first audio or when text arrives incrementally (for example, streamed from an LLM). ## Quickstart The shortest path is `generateToFile` — the SDK calls the REST API, streams the response, and writes the output for you. ```typescript import { SonioxNodeClient } from "@soniox/node"; // The API key is read from the SONIOX_API_KEY environment variable. const client = new SonioxNodeClient(); const bytesWritten = await client.tts.generateToFile("hello.wav", { text: "Hello from the Soniox Node SDK text-to-speech example.", voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "wav", }); console.log(`Wrote ${bytesWritten} bytes`); ``` ## Generate to bytes Use `client.tts.generate()` when you want the full audio payload in memory — for custom storage, uploading to another service, or post-processing. ```typescript const audio = await client.tts.generate({ text: "This response is generated in memory.", voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "wav", }); console.log(`Received ${audio.byteLength} bytes`); // audio is a Uint8Array ``` ## Stream audio chunks Use `client.tts.generateStream()` to receive the response as an async iterable of `Uint8Array` chunks. This lets you start processing or playing audio before the full payload has arrived. ```typescript import { createWriteStream } from "node:fs"; const output = createWriteStream("streamed.wav"); let totalBytes = 0; for await (const chunk of client.tts.generateStream({ text: "Streaming audio as it arrives from the server.", voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "wav", })) { output.write(chunk); totalBytes += chunk.byteLength; } output.end(); console.log(`Received ${totalBytes} bytes`); ``` ## Write directly to a file `client.tts.generateToFile()` accepts either a file path (string) or any `WritableStream` and returns the total number of bytes written. This is the simplest option for common server-side workflows. ```typescript const bytesWritten = await client.tts.generateToFile("hello.pcm", { text: "Hello from Soniox.", voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "pcm_s16le", sample_rate: 24000, }); console.log(`Wrote ${bytesWritten} bytes`); ``` ## List available models `client.tts.listModels()` returns the set of available TTS models with their supported voices. ```typescript const models = await client.tts.listModels(); for (const model of models) { const voices = model.voices.map((v) => v.id).join(", "); console.log(`${model.id} (${model.name}): ${voices}`); } ``` ## Generation options All three generator methods accept the same [`GenerateSpeechOptions`](/sdk/node-SDK/reference/types#generatespeechoptions) shape: | Option | Type | Description | | -------------- | ---------------------------------------------------------------- | ------------------------------------------------------- | | `text` | `string` | Input text to synthesize. Required. | | `voice` | `string` | Voice identifier (e.g. `"Adrian"`). Required. | | `model` | `string` | TTS model. Default `"tts-rt-v2"`. | | `language` | `string` | Language code. Default `"en"`. | | `audio_format` | [`TtsAudioFormat`](/sdk/node-SDK/reference/types#ttsaudioformat) | Output audio format. Default `"wav"`. | | `sample_rate` | `number` | Output sample rate in Hz. Required for raw PCM formats. | | `bitrate` | `number` | Codec bitrate in bps (for compressed formats). | | `signal` | `AbortSignal` | Optional signal to cancel the request. | See [Available models](/tts/models) for the full list of TTS models, voices, and supported audio formats. ## Cancel a request Pass an `AbortSignal` to cancel a generation request — useful when the user changes their mind mid-request, or when you need a deadline. ```typescript import { SonioxHttpError } from "@soniox/node"; const controller = new AbortController(); setTimeout(() => controller.abort(), 5000); // abort after 5s try { const audio = await client.tts.generate({ text: "Some long text...", voice: "Adrian", signal: controller.signal, }); console.log(`Received ${audio.byteLength} bytes`); } catch (err) { if (err instanceof SonioxHttpError && err.code === "aborted") { console.log("Generation cancelled"); } else { throw err; } } ``` ## Error handling REST TTS requests can throw the following errors: | Error | When it's thrown | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `SonioxHttpError` | Covers all HTTP failures: non-2xx responses (`code: 'http_error'`), network failures (`code: 'network_error'`), timeouts (`code: 'timeout'`), aborted requests (`code: 'aborted'`), and parse errors (`code: 'parse_error'`). Inspect `code`, `statusCode`, `message`, and `bodyText`. | | `SonioxError` | Base class for all SDK errors (`SonioxHttpError` extends it). Catch this if you want a single branch for every Soniox-originated failure. | ```typescript import { SonioxHttpError, SonioxError } from "@soniox/node"; try { await client.tts.generateToFile("out.wav", { text: "Hello!", voice: "Adrian", }); } catch (err) { if (err instanceof SonioxHttpError) { console.error( `HTTP ${err.statusCode ?? "n/a"} (${err.code}): ${err.message}` ); } else if (err instanceof SonioxError) { console.error("Soniox SDK error:", err.message); } else { throw err; } } ``` For raw HTTP integration details, see the [TTS REST API reference](/api-reference/tts/generate_tts). ### Error handling limitations Once audio streaming has started, errors cannot be delivered to the client. For guaranteed error delivery, use the [realtime WebSocket TTS](/sdk/node-SDK/tts/realtime-speech-generation) instead. ## See also * [Real-time speech generation](/sdk/node-SDK/tts/realtime-speech-generation) — WebSocket-based streaming TTS for LLM token streaming and low-latency playback. * [`GenerateSpeechOptions` reference](/sdk/node-SDK/reference/types#generatespeechoptions) * [`TtsModel` reference](/sdk/node-SDK/reference/types#ttsmodel) and [`TtsAudioFormat`](/sdk/node-SDK/reference/types#ttsaudioformat) # Async Client URL: /sdk/python-SDK/Full-SDK-reference/async_client Soniox Python SDK - Async Client Reference *** > **Sync mirror:** the synchronous `SonioxClient` exposes the same API as `AsyncSonioxClient` below - drop `await` from each call and treat `AsyncIterator[X]` return types as plain `Iterator[X]`. Only the async surface is documented here to avoid duplicating an otherwise identical reference. Realtime sessions have genuinely different sync/async patterns and are documented in the [Realtime Client](./realtime_client.md) page. *** ## AsyncSonioxClient Asynchronous Soniox REST client exposing HTTP and realtime helpers. ### Constructor ```python AsyncSonioxClient(api_key: str | None = None, api_base_url: str | None = None, websocket_base_url: str | None = None, tts_api_base_url: str | None = None, tts_websocket_base_url: str | None = None, timeout_sec: float | None = None, webhook_secret: str | None = None, webhook_signature_header: str | None = None, **client_kwargs: Any) ``` **Parameters** | Parameter | Type | Description | | -------------------------- | --------------- | --------------------------------------------------------------- | | `api_key` | `str \| None` | API key used for authentication. | | `api_base_url` | `str \| None` | Base URL for Soniox REST API requests. | | `websocket_base_url` | `str \| None` | Base URL for Soniox realtime WebSocket endpoint. | | `tts_api_base_url` | `str \| None` | Base URL for Soniox Text-to-Speech REST API requests. | | `tts_websocket_base_url` | `str \| None` | Base URL for Soniox Text-to-Speech realtime WebSocket endpoint. | | `timeout_sec` | `float \| None` | Maximum wait time in seconds. | | `webhook_secret` | `str \| None` | Webhook secret used for signature verification. | | `webhook_signature_header` | `str \| None` | Webhook signature header name. | | `client_kwargs` | `Any` | Additional HTTP client keyword arguments. | **Returns** `None` ### Properties | Property | Type | Description | | -------------------- | --------------------------- | ----------------------------------------------------------------------- | | `files` | `AsyncFilesAPI` | File upload and management API namespace. | | `stt` | `AsyncSttAPI` | Speech-to-text API namespace. | | `tts` | `AsyncTtsAPI` | Text-to-Speech API namespace. | | `models` | `AsyncModelsAPI` | Speech-to-text model listing API namespace. | | `tts_models` | `AsyncTtsModelsAPI` | Text-to-Speech model listing API namespace. | | `voices` | `AsyncVoicesAPI` | Voice cloning, shared voice listing and voice management API namespace. | | `usage_logs` | `AsyncUsageLogsAPI` | Per-request usage log API namespace. | | `usage` | `AsyncUsageAPI` | Usage and cost summary API namespace. | | `concurrency_limits` | `AsyncConcurrencyLimitsAPI` | Concurrency limit API namespace. | | `auth` | `AsyncAuthAPI` | Authentication API namespace. | | `webhooks` | `AsyncSonioxWebhooksAPI` | Webhook utilities API namespace. | | `realtime` | `AsyncRealtimeAPI` | Realtime websocket API namespace (STT and TTS). | ### request() ```python request(method: str, path: str, *, params: Mapping[str, Any] | None = None, json: Any | None = None, data: Mapping[str, Any] | None = None, files: Mapping[str, Any] | None = None) -> httpx.Response ``` Perform a request against the configured Soniox REST endpoint. **Parameters** | Parameter | Type | Description | | --------- | --------------------------- | ----------------------------------- | | `method` | `str` | HTTP method to use for the request. | | `path` | `str` | Relative API path for the request. | | `params` | `Mapping[str, Any] \| None` | Query parameters for the request. | | `json` | `Any \| None` | JSON request payload. | | `data` | `Mapping[str, Any] \| None` | Form-encoded request payload. | | `files` | `Mapping[str, Any] \| None` | Multipart file payload mapping. | **Returns** `httpx.Response` *** ### aclose() ```python aclose() -> None ``` Close any outstanding async HTTP connections. **Returns** `None` *** ## AsyncFilesAPI ### Constructor ```python AsyncFilesAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### list() ```python list(limit: int = 100, cursor: str | None = None) -> GetFilesResponse ``` List uploaded files. Performs a GET request to `/files` with optional pagination. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ----------------------------------------------- | | `limit` | `int` | Maximum number of files to return. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | **Returns** `GetFilesResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### count() ```python count() -> GetFilesCountResponse ``` Return a breakdown of uploaded file counts. Performs a GET request to `/files/count`. **Returns** `GetFilesCountResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### list\_all() ```python list_all(limit: int = 100) -> AsyncGenerator[File, None] ``` Iterate through all uploaded files across all pages. **Parameters** | Parameter | Type | Description | | --------- | ----- | ---------------------------------- | | `limit` | `int` | Maximum number of files to return. | **Yields** `AsyncGenerator[File, None]` File: The next file object from the API. **Raises** * `SonioxAPIError` When the API returns an error. *** ### get() ```python get(file_id: str) -> File ``` Retrieve a file by ID. Performs a GET request to `/files/{file_id}`. **Parameters** | Parameter | Type | Description | | --------- | ----- | --------------------------------- | | `file_id` | `str` | ID of a previously uploaded file. | **Returns** `File` **Raises** * `SonioxAPIError` When the API returns an error. *** ### get\_or\_none() ```python get_or_none(file_id: str) -> File | None ``` Retrieve a file by ID. Returns `None` if the file does not exist. **Parameters** | Parameter | Type | Description | | --------- | ----- | --------------------------------- | | `file_id` | `str` | ID of a previously uploaded file. | **Returns** `File | None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete() ```python delete(file_id: str) -> None ``` Delete a file by ID. Performs a DELETE request to `/files/{file_id}`. **Parameters** | Parameter | Type | Description | | --------- | ----- | --------------------------------- | | `file_id` | `str` | ID of a previously uploaded file. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete\_if\_exists() ```python delete_if_exists(file_id: str) -> None ``` Delete a file by ID if it exists. Ignores missing files. **Parameters** | Parameter | Type | Description | | --------- | ----- | --------------------------------- | | `file_id` | `str` | ID of a previously uploaded file. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### upload() ```python upload(file: BinaryIO | bytes | Path | str, *, filename: str | None = None, client_reference_id: str | None = None) -> File ``` Upload a file. Performs a multipart POST request to `/files`. Uploaded files are automatically deleted 30 days after upload. **Parameters** | Parameter | Type | Description | | --------------------- | ---------------------------------- | --------------------------------------------------------------- | | `file` | `BinaryIO \| bytes \| Path \| str` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `client_reference_id` | `str \| None` | Optional tracking identifier string. Does not need to be unique | **Returns** `File` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete\_all() ```python delete_all(limit: int = 100) -> None ``` Delete all files. Iterates through all pages and deletes each file. Stops and raises on the first failed deletion. **Parameters** | Parameter | Type | Description | | --------- | ----- | ---------------------------------- | | `limit` | `int` | Maximum number of files to return. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ## AsyncSttAPI ### Constructor ```python AsyncSttAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### list() ```python list(limit: int = 100, cursor: str | None = None) -> GetTranscriptionsResponse ``` List transcriptions. Performs a GET request to `/transcriptions` with optional pagination. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ----------------------------------------------- | | `limit` | `int` | Maximum number of transcriptions to return. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | **Returns** `GetTranscriptionsResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### count() ```python count() -> GetTranscriptionsCountResponse ``` Return a breakdown of transcription counts. Performs a GET request to `/transcriptions/count`. **Returns** `GetTranscriptionsCountResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### list\_all() ```python list_all(limit: int = 100) -> AsyncGenerator[Transcription, None] ``` Iterate through all transcriptions across all pages. **Parameters** | Parameter | Type | Description | | --------- | ----- | ------------------------------------------- | | `limit` | `int` | Maximum number of transcriptions to return. | **Yields** `AsyncGenerator[Transcription, None]` File: The next transcription object from the API. **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete\_all() ```python delete_all(limit: int = 100) -> None ``` Delete all transcriptions. Iterates through all pages and deletes each transcription. Stops and raises on the first failed deletion. **Parameters** | Parameter | Type | Description | | --------- | ----- | ------------------------------------------- | | `limit` | `int` | Maximum number of transcriptions to return. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### create() ```python create(*, model: str = DEFAULT_MODEL, file_id: str | None = None, audio_url: str | None = None, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Create a transcription. Performs a POST request to `/transcriptions`. Transcriptions are automatically deleted 30 days after creation. **Parameters** | Parameter | Type | Description | | --------------------- | ----------------------------------- | ----------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. *** ### get() ```python get(transcription_id: str) -> Transcription ``` Retrieve a transcription by ID. Performs a GET request to `/transcriptions/{transcription_id}`. **Parameters** | Parameter | Type | Description | | ------------------ | ----- | ------------------------- | | `transcription_id` | `str` | Transcription identifier. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. *** ### get\_or\_none() ```python get_or_none(transcription_id: str) -> Transcription | None ``` Retrieve a transcription by ID. Returns `None` if the transcription does not exist. **Parameters** | Parameter | Type | Description | | ------------------ | ----- | ------------------------- | | `transcription_id` | `str` | Transcription identifier. | **Returns** `Transcription | None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete() ```python delete(transcription_id: str) -> None ``` Delete a transcription by ID. Performs a DELETE request to `/transcriptions/{transcription_id}`. **Parameters** | Parameter | Type | Description | | ------------------ | ----- | ------------------------- | | `transcription_id` | `str` | Transcription identifier. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete\_if\_exists() ```python delete_if_exists(transcription_id: str) -> None ``` Delete a transcription by ID if it exists. Ignores missing transcriptions. **Parameters** | Parameter | Type | Description | | ------------------ | ----- | ------------------------- | | `transcription_id` | `str` | Transcription identifier. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### destroy() ```python destroy(transcription_id: str) -> None ``` Delete a transcription and its associated uploaded file. **Parameters** | Parameter | Type | Description | | ------------------ | ----- | ------------------------- | | `transcription_id` | `str` | Transcription identifier. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### destroy\_all() ```python destroy_all(limit: int = 100) -> None ``` Delete all transcriptions and their associated files. Stops and raises on the first failed deletion. **Parameters** | Parameter | Type | Description | | --------- | ----- | ------------------------------------------- | | `limit` | `int` | Maximum number of transcriptions to return. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error during listing. *** ### get\_transcript() ```python get_transcript(transcription_id: str) -> TranscriptionTranscript ``` Retrieve the transcript for a transcription. Performs a GET request to `/transcriptions/{transcription_id}/transcript`. **Parameters** | Parameter | Type | Description | | ------------------ | ----- | ------------------------- | | `transcription_id` | `str` | Transcription identifier. | **Returns** `TranscriptionTranscript` **Raises** * `SonioxAPIError` When the API returns an error. *** ### wait() ```python wait(transcription_id: str, *, interval_sec: float = 5.0, timeout_sec: float | None = None) -> Transcription ``` Poll a transcription until it leaves the queued or processing state. **Parameters** | Parameter | Type | Description | | ------------------ | --------------- | ----------------------------- | | `transcription_id` | `str` | Transcription identifier. | | `interval_sec` | `float` | Polling interval in seconds. | | `timeout_sec` | `float \| None` | Maximum wait time in seconds. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `TimeoutError` Waiting for the transcription to finish exceeded `timeout_sec`. *** ### transcribe\_from\_url() ```python transcribe_from_url(*, model: str = DEFAULT_MODEL, audio_url: str, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Create a transcription from an audio URL. **Parameters** | Parameter | Type | Description | | --------------------- | ----------------------------------- | ----------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `audio_url` | `str` | Publicly accessible audio URL. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. *** ### transcribe\_from\_file\_id() ```python transcribe_from_file_id(*, model: str = DEFAULT_MODEL, file_id: str, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Create a transcription from an existing uploaded file. **Parameters** | Parameter | Type | Description | | --------------------- | ----------------------------------- | ----------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `file_id` | `str` | ID of a previously uploaded file. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. *** ### transcribe\_from\_file() ```python transcribe_from_file(*, model: str = DEFAULT_MODEL, file: BinaryIO | bytes | Path | str, filename: str | None = None, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Upload a file and create a transcription from it. **Parameters** | Parameter | Type | Description | | --------------------- | ----------------------------------- | -------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `file` | `BinaryIO \| bytes \| Path \| str` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. *** ### transcribe() ```python transcribe(*, model: str = DEFAULT_MODEL, audio_url: str | None = None, file_id: str | None = None, file: BinaryIO | bytes | Path | str | None = None, filename: str | None = None, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Create a transcription from a file, file ID, or audio URL. Validates mutually exclusive inputs before submission. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------ | -------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `file` | `BinaryIO \| bytes \| Path \| str \| None` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the payload fails validation. *** ### transcribe\_file\_with\_webhook() ```python transcribe_file_with_webhook(*, model: str = DEFAULT_MODEL, file: BinaryIO | bytes | Path | str, webhook_url: str, filename: str | None = None, client_reference_id: str | None = None, webhook_auth: WebhookAuthConfig | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Upload a file, configure a webhook, and start transcription. **Parameters** | Parameter | Type | Description | | --------------------- | ----------------------------------- | -------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `file` | `BinaryIO \| bytes \| Path \| str` | File input to upload or transcribe. | | `webhook_url` | `str` | URL to receive webhook notifications. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `webhook_auth` | `WebhookAuthConfig \| None` | Webhook authentication configuration. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. *** ### transcribe\_and\_wait() ```python transcribe_and_wait(*, model: str = DEFAULT_MODEL, audio_url: str | None = None, file_id: str | None = None, file: BinaryIO | bytes | Path | str | None = None, filename: str | None = None, client_reference_id: str | None = None, delete_after: bool = False, wait_interval_sec: float = 5.0, wait_timeout_sec: float | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Create a transcription and wait for completion. Returns a Transcription object after it is completed. Optionally deletes the transcription and the uploaded file after completion. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------ | ----------------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `file` | `BinaryIO \| bytes \| Path \| str \| None` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `delete_after` | `bool` | Whether to delete created resources after completion. | | `wait_interval_sec` | `float` | Polling interval in seconds while waiting. | | `wait_timeout_sec` | `float \| None` | Maximum wait time in seconds while polling. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the payload fails validation. * `TimeoutError` Waiting for the transcription to finish exceeded `timeout_sec`. *** ### transcribe\_and\_wait\_with\_tokens() ```python transcribe_and_wait_with_tokens(*, model: str = DEFAULT_MODEL, audio_url: str | None = None, file_id: str | None = None, file: BinaryIO | bytes | Path | str | None = None, filename: str | None = None, client_reference_id: str | None = None, delete_after: bool = False, wait_interval_sec: float = 5.0, wait_timeout_sec: float | None = None, config: CreateTranscriptionConfig | None = None) -> TranscriptionTranscript ``` Create a transcription, wait for completion, and return the transcript. Optionally deletes the transcription and uploaded file after completion. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------ | ----------------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `file` | `BinaryIO \| bytes \| Path \| str \| None` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `delete_after` | `bool` | Whether to delete created resources after completion. | | `wait_interval_sec` | `float` | Polling interval in seconds while waiting. | | `wait_timeout_sec` | `float \| None` | Maximum wait time in seconds while polling. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `TranscriptionTranscript` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the payload fails validation. * `TimeoutError` Waiting for the transcription to finish exceeded `timeout_sec`. *** ### translate\_from\_url() ```python translate_from_url(*, audio_url: str, to: LanguageCode | None = None, source: LanguageCode | None = None, between: tuple[LanguageCode, LanguageCode] | None = None, model: str = DEFAULT_MODEL, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Translate audio at a URL. Provide exactly one of `to` (one-way) or `between` (two-way). `source` is an optional language hint and is only valid with `to`. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------- | ----------------------------------------- | | `audio_url` | `str` | Publicly accessible audio URL. | | `to` | `LanguageCode \| None` | - | | `source` | `LanguageCode \| None` | The source term to translate. | | `between` | `tuple[LanguageCode, LanguageCode] \| None` | - | | `model` | `str` | Speech-to-text model to use. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the translate kwargs are invalid. *** ### translate\_from\_file\_id() ```python translate_from_file_id(*, file_id: str, to: LanguageCode | None = None, source: LanguageCode | None = None, between: tuple[LanguageCode, LanguageCode] | None = None, model: str = DEFAULT_MODEL, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Translate an already-uploaded file. Provide exactly one of `to` (one-way) or `between` (two-way). `source` is an optional language hint and is only valid with `to`. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------- | ----------------------------------------- | | `file_id` | `str` | ID of a previously uploaded file. | | `to` | `LanguageCode \| None` | - | | `source` | `LanguageCode \| None` | The source term to translate. | | `between` | `tuple[LanguageCode, LanguageCode] \| None` | - | | `model` | `str` | Speech-to-text model to use. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the translate kwargs are invalid. *** ### translate\_from\_file() ```python translate_from_file(*, file: BinaryIO | bytes | Path | str, to: LanguageCode | None = None, source: LanguageCode | None = None, between: tuple[LanguageCode, LanguageCode] | None = None, filename: str | None = None, model: str = DEFAULT_MODEL, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Upload a file and translate it. Provide exactly one of `to` (one-way) or `between` (two-way). `source` is an optional language hint and is only valid with `to`. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------- | -------------------------------------------- | | `file` | `BinaryIO \| bytes \| Path \| str` | File input to upload or transcribe. | | `to` | `LanguageCode \| None` | - | | `source` | `LanguageCode \| None` | The source term to translate. | | `between` | `tuple[LanguageCode, LanguageCode] \| None` | - | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `model` | `str` | Speech-to-text model to use. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the translate kwargs are invalid. *** ### translate() ```python translate(*, to: LanguageCode | None = None, source: LanguageCode | None = None, between: tuple[LanguageCode, LanguageCode] | None = None, audio_url: str | None = None, file_id: str | None = None, file: BinaryIO | bytes | Path | str | None = None, filename: str | None = None, model: str = DEFAULT_MODEL, client_reference_id: str | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Translate audio from a file, file ID, or URL. Provide exactly one of `to` (one-way) or `between` (two-way). `source` is an optional language hint and is only valid with `to`. Convenience over `transcribe()` that fills in the `translation` config and forces `enable_language_identification=True`. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------- | -------------------------------------------- | | `to` | `LanguageCode \| None` | - | | `source` | `LanguageCode \| None` | The source term to translate. | | `between` | `tuple[LanguageCode, LanguageCode] \| None` | - | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `file` | `BinaryIO \| bytes \| Path \| str \| None` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `model` | `str` | Speech-to-text model to use. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the payload or translate kwargs are invalid. *** ### translate\_and\_wait() ```python translate_and_wait(*, to: LanguageCode | None = None, source: LanguageCode | None = None, between: tuple[LanguageCode, LanguageCode] | None = None, audio_url: str | None = None, file_id: str | None = None, file: BinaryIO | bytes | Path | str | None = None, filename: str | None = None, model: str = DEFAULT_MODEL, client_reference_id: str | None = None, delete_after: bool = False, wait_interval_sec: float = 5.0, wait_timeout_sec: float | None = None, config: CreateTranscriptionConfig | None = None) -> Transcription ``` Translate and wait for completion. Returns the finished `Transcription`. Provide exactly one of `to` (one-way) or `between` (two-way). `source` is an optional language hint and is only valid with `to`. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------- | ----------------------------------------------------- | | `to` | `LanguageCode \| None` | - | | `source` | `LanguageCode \| None` | The source term to translate. | | `between` | `tuple[LanguageCode, LanguageCode] \| None` | - | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `file` | `BinaryIO \| bytes \| Path \| str \| None` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `model` | `str` | Speech-to-text model to use. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `delete_after` | `bool` | Whether to delete created resources after completion. | | `wait_interval_sec` | `float` | Polling interval in seconds while waiting. | | `wait_timeout_sec` | `float \| None` | Maximum wait time in seconds while polling. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `Transcription` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the payload or translate kwargs are invalid. * `TimeoutError` Waiting for the transcription to finish exceeded `wait_timeout_sec`. *** ### translate\_and\_wait\_with\_tokens() ```python translate_and_wait_with_tokens(*, to: LanguageCode | None = None, source: LanguageCode | None = None, between: tuple[LanguageCode, LanguageCode] | None = None, audio_url: str | None = None, file_id: str | None = None, file: BinaryIO | bytes | Path | str | None = None, filename: str | None = None, model: str = DEFAULT_MODEL, client_reference_id: str | None = None, delete_after: bool = False, wait_interval_sec: float = 5.0, wait_timeout_sec: float | None = None, config: CreateTranscriptionConfig | None = None) -> TranscriptionTranscript ``` Translate, wait for completion, and return the transcript with tokens. Provide exactly one of `to` (one-way) or `between` (two-way). `source` is an optional language hint and is only valid with `to`. Optionally deletes the transcription and uploaded file after completion. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------------------------------- | ----------------------------------------------------- | | `to` | `LanguageCode \| None` | - | | `source` | `LanguageCode \| None` | The source term to translate. | | `between` | `tuple[LanguageCode, LanguageCode] \| None` | - | | `audio_url` | `str \| None` | Publicly accessible audio URL. | | `file_id` | `str \| None` | ID of a previously uploaded file. | | `file` | `BinaryIO \| bytes \| Path \| str \| None` | File input to upload or transcribe. | | `filename` | `str \| None` | Filename associated with uploaded file data. | | `model` | `str` | Speech-to-text model to use. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | | `delete_after` | `bool` | Whether to delete created resources after completion. | | `wait_interval_sec` | `float` | Polling interval in seconds while waiting. | | `wait_timeout_sec` | `float \| None` | Maximum wait time in seconds while polling. | | `config` | `CreateTranscriptionConfig \| None` | Configuration options for this operation. | **Returns** `TranscriptionTranscript` **Raises** * `SonioxAPIError` When the API returns an error. * `SonioxValidationError` When the payload or translate kwargs are invalid. * `TimeoutError` Waiting for the transcription to finish exceeded `wait_timeout_sec`. *** ## AsyncTtsAPI ### Constructor ```python AsyncTtsAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### generate() ```python generate(*, text: str, voice: str, model: str = DEFAULT_MODEL, config: CreateTtsConfig | None = None, language: str | None = None, audio_format: TtsAudioFormat | None = None, sample_rate: TtsSampleRate | None = None, bitrate: TtsBitrate | None = None) -> bytes ``` Generate speech audio from text and return raw audio bytes. Performs a POST request to the TTS REST endpoint. `audio_format`/`sample_rate`/`bitrate` are deprecated; set them on `CreateTtsConfig` instead. Pass `language` explicitly — relying on the default ("en") is deprecated and `language` will be required in the next major release. **Parameters** | Parameter | Type | Description | | -------------- | ------------------------- | --------------------------------------------------------------------------------------------------- | | `text` | `str` | Longer free-form background text, prior interaction history, reference documents, or meeting notes. | | `voice` | `str` | Voice identifier to generate speech audio with. | | `model` | `str` | Speech-to-text model to use. | | `config` | `CreateTtsConfig \| None` | Configuration options for this operation. | | `language` | `str \| None` | Language code for Text-to-Speech (e.g., "en"). | | `audio_format` | `TtsAudioFormat \| None` | Audio format for realtime transcription. | | `sample_rate` | `TtsSampleRate \| None` | Audio sample rate in Hz. | | `bitrate` | `TtsBitrate \| None` | Output bitrate in bits-per-second for compressed formats. | **Returns** `bytes` **Raises** * `SonioxAPIError` When the API returns an error. *** ### generate\_to\_file() ```python generate_to_file(output: BinaryIO | Path | str, *, text: str, voice: str = DEFAULT_VOICE, model: str = DEFAULT_MODEL, config: CreateTtsConfig | None = None, language: str | None = None, audio_format: TtsAudioFormat | None = None, sample_rate: TtsSampleRate | None = None, bitrate: TtsBitrate | None = None) -> int ``` Generate speech audio from text and write the audio bytes to a file-like output. `audio_format`/`sample_rate`/`bitrate` are deprecated; set them on `CreateTtsConfig` instead. Pass `language` explicitly — relying on the default ("en") is deprecated and `language` will be required in the next major release. **Parameters** | Parameter | Type | Description | | -------------- | ------------------------- | --------------------------------------------------------------------------------------------------- | | `output` | `BinaryIO \| Path \| str` | - | | `text` | `str` | Longer free-form background text, prior interaction history, reference documents, or meeting notes. | | `voice` | `str` | Voice identifier to generate speech audio with. | | `model` | `str` | Speech-to-text model to use. | | `config` | `CreateTtsConfig \| None` | Configuration options for this operation. | | `language` | `str \| None` | Language code for Text-to-Speech (e.g., "en"). | | `audio_format` | `TtsAudioFormat \| None` | Audio format for realtime transcription. | | `sample_rate` | `TtsSampleRate \| None` | Audio sample rate in Hz. | | `bitrate` | `TtsBitrate \| None` | Output bitrate in bits-per-second for compressed formats. | **Returns** `int` Number of bytes written. *** ## AsyncTtsModelsAPI ### Constructor ```python AsyncTtsModelsAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### list() ```python list() -> GetTtsModelsResponse ``` List available Text-to-Speech models. Performs a GET request to `/tts-models`. **Returns** `GetTtsModelsResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ## AsyncVoicesAPI ### Constructor ```python AsyncVoicesAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### list() ```python list(limit: int = 100, cursor: str | None = None) -> GetVoicesResponse ``` List the voices you cloned in the project. For the built-in voices of a model, use `list_shared()`. Performs a GET request to `/voices` with optional pagination. **Parameters** | Parameter | Type | Description | | --------- | ------------- | ----------------------------------------------- | | `limit` | `int` | Maximum number of voices to return. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | **Returns** `GetVoicesResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### count() ```python count() -> GetVoicesCountResponse ``` Return the total number of voices in the project. Performs a GET request to `/voices/count`. **Returns** `GetVoicesCountResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### list\_all() ```python list_all(limit: int = 100) -> AsyncGenerator[Voice, None] ``` Iterate through all cloned voices across all pages. For the built-in voices of a model, use `list_all_shared()`. **Parameters** | Parameter | Type | Description | | --------- | ----- | ----------------------------------- | | `limit` | `int` | Maximum number of voices to return. | **Yields** `AsyncGenerator[Voice, None]` Voice: The next voice object from the API. **Raises** * `SonioxAPIError` When the API returns an error. *** ### list\_shared() ```python list_shared(model: str, *, gender: TtsVoiceGender | None = None, age: TtsVoiceAge | None = None, accent: str | None = None, use_case: list[str] | None = None, style: list[str] | None = None, limit: int = 100, cursor: str | None = None) -> GetSharedVoicesResponse ``` List the shared voices built into a Text-to-Speech model. Performs a GET request to `/shared-voices`. All given filters must match. For voices you cloned yourself, use `list()`. **Parameters** | Parameter | Type | Description | | ---------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | `model` | `str` | Id of the TTS model whose voices to return. | | `gender` | `TtsVoiceGender \| None` | Only return voices of this gender. | | `age` | `TtsVoiceAge \| None` | Only return voices of this age. | | `accent` | `str \| None` | Only return voices with this accent. | | `use_case` | `list[str] \| None` | Only return voices tagged with every listed use case. | | `style` | `list[str] \| None` | Only return voices tagged with every listed style. | | `limit` | `int` | Maximum number of voices to return (1-200). | | `cursor` | `str \| None` | Pagination cursor. Pass the same filters alongside it; the cursor points into the filtered list, not the whole catalogue. | **Returns** `GetSharedVoicesResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### list\_all\_shared() ```python list_all_shared(model: str, *, gender: TtsVoiceGender | None = None, age: TtsVoiceAge | None = None, accent: str | None = None, use_case: list[str] | None = None, style: list[str] | None = None, limit: int = 100) -> AsyncGenerator[TtsVoiceDetails, None] ``` Iterate through all shared voices of a Text-to-Speech model across all pages. Accepts the same filters as `list_shared()`; they are sent with every page. **Parameters** | Parameter | Type | Description | | ---------- | ------------------------ | ----------------------------------------------------- | | `model` | `str` | Id of the TTS model whose voices to return. | | `gender` | `TtsVoiceGender \| None` | Only return voices of this gender. | | `age` | `TtsVoiceAge \| None` | Only return voices of this age. | | `accent` | `str \| None` | Only return voices with this accent. | | `use_case` | `list[str] \| None` | Only return voices tagged with every listed use case. | | `style` | `list[str] \| None` | Only return voices tagged with every listed style. | | `limit` | `int` | Maximum number of voices to return. | **Yields** `AsyncGenerator[TtsVoiceDetails, None]` TtsVoiceDetails: The next voice matching the filters. **Raises** * `SonioxAPIError` When the API returns an error. *** ### get() ```python get(voice_id: str) -> Voice ``` Retrieve a voice by ID. Performs a GET request to `/voices/{voice_id}`. **Parameters** | Parameter | Type | Description | | ---------- | ----- | ----------------- | | `voice_id` | `str` | Voice identifier. | **Returns** `Voice` **Raises** * `SonioxAPIError` When the API returns an error. *** ### get\_or\_none() ```python get_or_none(voice_id: str) -> Voice | None ``` Retrieve a voice by ID. Returns `None` if the voice does not exist. **Parameters** | Parameter | Type | Description | | ---------- | ----- | ----------------- | | `voice_id` | `str` | Voice identifier. | **Returns** `Voice | None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### create() ```python create(file: BinaryIO | bytes | Path | str, *, name: str, filename: str | None = None) -> Voice ``` Create a cloned voice from a reference audio clip. Performs a multipart POST request to `/voices`. **Parameters** | Parameter | Type | Description | | ---------- | ---------------------------------- | -------------------------------------------- | | `file` | `BinaryIO \| bytes \| Path \| str` | File input to upload or transcribe. | | `name` | `str` | Name of the model. | | `filename` | `str \| None` | Filename associated with uploaded file data. | **Returns** `Voice` **Raises** * `SonioxAPIError` When the API returns an error. *** ### recompute() ```python recompute(voice_id: str, *, model: str | None = None) -> Voice ``` Prepare an existing voice for models it is not ready for yet. Performs a POST request to `/voices/{voice_id}/recompute`. When `model` is omitted, the voice is prepared for every available model it is not ready for; models it is already prepared for are left unchanged. **Parameters** | Parameter | Type | Description | | ---------- | ------------- | ----------------------------------------------------------------------------------- | | `voice_id` | `str` | Voice identifier. | | `model` | `str \| None` | Model to prepare the voice for. If None, prepares it for every not-yet-ready model. | **Returns** `Voice` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete() ```python delete(voice_id: str) -> None ``` Delete a voice by ID. Performs a DELETE request to `/voices/{voice_id}`. **Parameters** | Parameter | Type | Description | | ---------- | ----- | ----------------- | | `voice_id` | `str` | Voice identifier. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ### delete\_if\_exists() ```python delete_if_exists(voice_id: str) -> None ``` Delete a voice by ID if it exists. Ignores missing voices. **Parameters** | Parameter | Type | Description | | ---------- | ----- | ----------------- | | `voice_id` | `str` | Voice identifier. | **Returns** `None` **Raises** * `SonioxAPIError` When the API returns an error. *** ## AsyncModelsAPI ### Constructor ```python AsyncModelsAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### list() ```python list() -> GetModelsResponse ``` List available models. Performs a GET request to `/models`. **Returns** `GetModelsResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ## AsyncUsageLogsAPI ### Constructor ```python AsyncUsageLogsAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### list() ```python list(start_time: str, end_time: str, limit: int = 1000, sort: UsageLogsSort = 'end_time_asc', cursor: str | None = None) -> GetUsageLogsResponse ``` List usage-log entries for a time window. Performs a GET request to `/usage-logs`. **Parameters** | Parameter | Type | Description | | ------------ | --------------- | ------------------------------------------------------------- | | `start_time` | `str` | Start of the window (inclusive). Filters by request end time. | | `end_time` | `str` | End of the window (exclusive). Filters by request end time. | | `limit` | `int` | Maximum number of entries to return (1–1000). | | `sort` | `UsageLogsSort` | Sort order by end\_time. | | `cursor` | `str \| None` | Pagination cursor for the next page. | **Returns** `GetUsageLogsResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ### list\_all() ```python list_all(start_time: str, end_time: str, limit: int = 1000, sort: UsageLogsSort = 'end_time_asc') -> AsyncGenerator[UsageLogEntry, None] ``` Iterate through all usage-log entries across all pages. **Parameters** | Parameter | Type | Description | | ------------ | --------------- | ------------------------------------------------------------- | | `start_time` | `str` | Start of the window (inclusive). Filters by request end time. | | `end_time` | `str` | End of the window (exclusive). Filters by request end time. | | `limit` | `int` | Maximum number of entries to return (1–1000). | | `sort` | `UsageLogsSort` | Sort order by end\_time. | **Returns** `AsyncGenerator[UsageLogEntry, None]` *** ## AsyncUsageAPI ### Constructor ```python AsyncUsageAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### summary() ```python summary(start_time: str, end_time: str) -> GetUsageSummaryResponse ``` Return daily cost and activity for the project, per model and in total. Performs a GET request to `/usage/summary`. **Parameters** | Parameter | Type | Description | | ------------ | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `start_time` | `str` | Start of the window (inclusive), ISO 8601 UTC. | | `end_time` | `str` | End of the window (exclusive), ISO 8601 UTC. A UTC day is included when the window covers any part of it, so an `end_time` at exactly midnight leaves out its own day. At most 366 days. | **Returns** `GetUsageSummaryResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ## AsyncConcurrencyLimitsAPI ### Constructor ```python AsyncConcurrencyLimitsAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### get() ```python get() -> GetConcurrencyLimitsResponse ``` Get current concurrent sessions and configured limits. Performs a GET request to `/concurrency-limits`. **Returns** `GetConcurrencyLimitsResponse` Project- and organization-scoped current counts and configured limits for realtime STT and TTS sessions. **Raises** * `SonioxAPIError` When the API returns an error. *** ### history() ```python history(start_time: str, end_time: str, *, period_sec: ConcurrentStreamsPeriodSec, kind: ConcurrentStreamKind) -> GetConcurrentStreamsHistoryResponse ``` Get historical concurrent stream counts, aggregated per period. Performs a GET request to `/concurrent-streams-history`. **Parameters** | Parameter | Type | Description | | ------------ | ---------------------------- | ------------------------------------------------------------------------------------------------------- | | `start_time` | `str` | Start of the window (inclusive), ISO 8601 UTC. | | `end_time` | `str` | End of the window (exclusive), ISO 8601 UTC, after `start_time`. | | `period_sec` | `ConcurrentStreamsPeriodSec` | Aggregation period: 60, 3600, or 86400. Also caps the window length the server accepts (7 days for 60). | | `kind` | `ConcurrentStreamKind` | `stt` for Speech-to-Text sessions, `tts` for Text-to-Speech. | **Returns** `GetConcurrentStreamsHistoryResponse` **Raises** * `SonioxAPIError` When the API returns an error. *** ## AsyncAuthAPI ### Constructor ```python AsyncAuthAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### create\_temporary\_api\_key() ```python create_temporary_api_key(*, usage_type: TemporaryApiKeyUsageType = 'transcribe_websocket', expires_in_seconds: int = 5 * 60, client_reference_id: str | None = None, single_use: bool | None = None, max_session_duration_seconds: int | None = None) -> CreateTemporaryApiKeyResponse ``` Create a temporary API key. Performs a POST request to `/auth/temporary-api-key`. The API key needs the **Temporary API keys** permission and the permission for the service in `usage_type`. See [API key permissions](https://soniox.com/docs/guides/api-key-permissions#temporary-api-keys). **Parameters** | Parameter | Type | Description | | ------------------------------ | -------------------------- | -------------------------------------------------------------------------------------- | | `usage_type` | `TemporaryApiKeyUsageType` | Intended usage of the temporary API key. | | `expires_in_seconds` | `int` | Duration in seconds until the temporary API key expires | | `client_reference_id` | `str \| None` | Optional tracking identifier string. Does not need to be unique | | `single_use` | `bool \| None` | When true, restricts the temporary API key to a single use. | | `max_session_duration_seconds` | `int \| None` | Maximum connection duration in seconds for WebSocket and TTS HTTP streaming endpoints. | **Returns** `CreateTemporaryApiKeyResponse` **Raises** * `SonioxPermissionDeniedError` When the API key lacks one of those permissions. * `SonioxAPIError` When the API returns another error. *** ## AsyncSonioxWebhooksAPI # Errors URL: /sdk/python-SDK/Full-SDK-reference/errors Soniox Python SDK - Errors Reference *** Import errors from `soniox.errors`. Every exception subclasses `SonioxError`, and HTTP API failures subclass `SonioxAPIError`, which carries `status_code`, `request_id` and the parsed `api_error` (including its `error_type`). *** ## SonioxError Subclass of `Exception`. Base exception for the SDK. ### Constructor ```python SonioxError(message: str, *, response: httpx.Response | None = None) ``` **Parameters** | Parameter | Type | Description | | ---------- | ------------------------ | -------------------------------------------- | | `message` | `str` | Description of what went wrong. | | `response` | `httpx.Response \| None` | HTTP response that caused the error, if any. | **Returns** `None` ### Properties | Property | Type | Description | | ---------- | ------------------------ | -------------------------------------------- | | `response` | `httpx.Response \| None` | HTTP response that caused the error, if any. | *** ## SonioxAPIError Subclass of `SonioxError`. Raised when the Soniox API replies with a non-2xx payload. ### Constructor ```python SonioxAPIError(message: str, *, api_error: ApiError | None = None, response: httpx.Response | None = None) ``` **Parameters** | Parameter | Type | Description | | ----------- | ------------------------ | --------------------------------------------------------- | | `message` | `str` | Description of what went wrong. | | `api_error` | `ApiError \| None` | Parsed error body; its `error_type` identifies the error. | | `response` | `httpx.Response \| None` | HTTP response that caused the error. | **Returns** `None` ### Properties | Property | Type | Description | | ------------- | ------------------ | -------------------------------------------------------------- | | `api_error` | `ApiError \| None` | Structured representation of a non-2xx API response payload. | | `status_code` | `int \| None` | HTTP status code. | | `request_id` | `str \| None` | Unique identifier for the request, useful for troubleshooting. | ### from\_response() ```python from_response(response: httpx.Response) -> SonioxAPIError ``` Parse an `httpx.Response` into the matching SDK error. **Parameters** | Parameter | Type | Description | | ---------- | ---------------- | ------------------------------------------ | | `response` | `httpx.Response` | Non-2xx HTTP response from the Soniox API. | **Returns** `SonioxAPIError` *** ## SonioxInvalidRequestError Subclass of `SonioxAPIError`. Invalid request payloads (`400`). *** ## SonioxAuthenticationError Subclass of `SonioxAPIError`. Authentication failures (`401`/`403`). *** ## SonioxPermissionDeniedError Subclass of `SonioxAPIError`. The API key is valid but lacks the permission for this call (`403` with `error_type` `permission_denied`). Other `403` errors, such as an expired temporary API key session, raise `SonioxAuthenticationError`. REST calls only; over WebSocket a permission error arrives as a realtime error event. See [API key permissions](https://soniox.com/docs/guides/api-key-permissions). *** ## SonioxNotFoundError Subclass of `SonioxAPIError`. Resource not found (`404`). *** ## SonioxConflictError Subclass of `SonioxAPIError`. Conflict or invalid state, e.g. deleting while processing (`409`). *** ## SonioxRateLimitError Subclass of `SonioxAPIError`. Rate limit or usage limit exceeded (`429`). *** ## SonioxServerError Subclass of `SonioxAPIError`. Server errors (`5xx`). *** ## SonioxValidationError Subclass of `SonioxError`. Raised when Pydantic input validation fails on the client side. ### Constructor ```python SonioxValidationError(message: str, *, errors: ValidationError | None = None) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------------- | ------------------------------------------------- | | `message` | `str` | Description of what went wrong. | | `errors` | `ValidationError \| None` | The underlying Pydantic validation error, if any. | **Returns** `None` ### Properties | Property | Type | Description | | -------- | ------------------------- | ------------------------------------------------- | | `errors` | `ValidationError \| None` | The underlying Pydantic validation error, if any. | *** ## SonioxRealtimeError Subclass of `SonioxError`. Errors raised by realtime workflows. *** ## InvalidWebhookSignatureError Subclass of `SonioxError`. Raised when a webhook signature cannot be validated. # Realtime Client URL: /sdk/python-SDK/Full-SDK-reference/realtime_client Soniox Python SDK - Realtime Client Reference *** ## RealtimeAPI Entrypoint for realtime helpers on SonioxClient. ### Constructor ```python RealtimeAPI(client: SonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | -------------- | ----------------------- | | `client` | `SonioxClient` | Soniox client instance. | **Returns** `None` ### Properties | Property | Type | Description | | -------- | ------------------- | ----------------------------- | | `stt` | `RealtimeSTTClient` | Speech-to-text API namespace. | | `tts` | `RealtimeTTSClient` | Text-to-Speech API namespace | *** ## AsyncRealtimeAPI Entrypoint for async realtime helpers on AsyncSonioxClient. ### Constructor ```python AsyncRealtimeAPI(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### Properties | Property | Type | Description | | -------- | ------------------------ | ----------------------------- | | `stt` | `AsyncRealtimeSTTClient` | Speech-to-text API namespace. | | `tts` | `AsyncRealtimeTTSClient` | Text-to-Speech API namespace | *** ## RealtimeSTTClient Factory for creating synchronous realtime speech-to-text sessions. This class validates credentials and prepares session configuration, but does not itself manage WebSocket connections. ### Constructor ```python RealtimeSTTClient(client: SonioxClient) ``` Create a realtime STT client bound to an existing API client. **Parameters** | Parameter | Type | Description | | --------- | -------------- | ------------------------------------------------------------- | | `client` | `SonioxClient` | Parent Soniox client providing configuration and credentials. | **Returns** `None` ### connect() ```python connect(*, config: RealtimeSTTConfig, api_key: str | None = None, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) -> RealtimeSTTSession ``` Create a new realtime STT session. The returned session is not connected until entered as a context manager. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | --------------------------------------------------------------------------------- | | `config` | `RealtimeSTTConfig` | Realtime transcription configuration. | | `api_key` | `str \| None` | Optional API key override. If not provided, the client's default API key is used. | | `connect_timeout_sec` | `float` | Maximum seconds to wait for the WebSocket handshake. Defaults to 10 seconds. | **Returns** `RealtimeSTTSession` A new RealtimeSTTSession instance. **Raises** * `SonioxValidationError` If no API key is available. *** ## AsyncRealtimeSTTClient Factory for creating asynchronous realtime speech-to-text sessions. This class validates credentials and prepares session configuration, but does not itself manage WebSocket connections. ### Constructor ```python AsyncRealtimeSTTClient(client: AsyncSonioxClient) ``` Create a realtime STT client bound to an existing API client. **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ------------------------------------------------------------- | | `client` | `AsyncSonioxClient` | Parent Soniox client providing configuration and credentials. | **Returns** `None` ### connect() ```python connect(*, config: RealtimeSTTConfig, api_key: str | None = None, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) -> AsyncRealtimeSTTSession ``` Create a new realtime STT session. The returned session is not connected until entered as an async context manager. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | --------------------------------------------------------------------------------- | | `config` | `RealtimeSTTConfig` | Realtime transcription configuration. | | `api_key` | `str \| None` | Optional API key override. If not provided, the client's default API key is used. | | `connect_timeout_sec` | `float` | Maximum seconds to wait for the WebSocket handshake. Defaults to 10 seconds. | **Returns** `AsyncRealtimeSTTSession` A new AsyncRealtimeSTTSession instance. **Raises** * `SonioxValidationError` If no API key is available. *** ## RealtimeSTTSession Synchronous WebSocket session for a single real-time speech-to-text stream. This class manages the full lifecycle of a real-time transcription session: connecting to the WebSocket endpoint, streaming audio data, receiving events, and gracefully closing the stream. A session is stateful and represents exactly one streaming interaction with the Soniox realtime API. Instances are designed to be used as context managers. ### Constructor ```python RealtimeSTTSession(url: str, config: RealtimeSTTConfig, api_key: str, *, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) ``` Create a new realtime STT session. This does not open a network connection. The WebSocket connection is established when entering the context manager. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | ---------------------------------------------------------------------------------------- | | `url` | `str` | WebSocket URL for the realtime transcription endpoint. | | `config` | `RealtimeSTTConfig` | Configuration describing the audio format and transcription behavior for this session. | | `api_key` | `str` | API key sent on the WebSocket handshake. | | `connect_timeout_sec` | `float` | Maximum seconds to wait for the WebSocket handshake to complete. Defaults to 10 seconds. | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | ----------------------- | --------------------------------------------------------- | | `config` | `RealtimeSTTConfig` | Return the configuration used to initialize this session. | | `paused` | `bool` | Return True if the session is currently paused. | | `last_message` | `RealtimeEvent \| None` | Return the most recently received realtime event, if any. | ### close() ```python close() -> None ``` Close the realtime session and release the WebSocket. Signals end-of-audio to the server and clears the underlying connection. Subsequent calls are no-ops. Called automatically when exiting the context manager. **Returns** `None` *** ### send\_byte\_chunk() ```python send_byte_chunk(chunk: bytes) -> None ``` Send a single chunk of raw audio bytes to the realtime stream. The audio data must match the format declared in the session configuration (sample rate, channels, encoding). **Parameters** | Parameter | Type | Description | | --------- | ------- | ------------------------ | | `chunk` | `bytes` | Raw audio bytes to send. | **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected or the send operation fails. *** ### send\_bytes() ```python send_bytes(chunks: bytes | Iterator[bytes], *, finish: bool = True) -> None ``` Send audio data to the realtime stream. Accepts either a single bytes object or an iterator yielding byte chunks (e.g. from `throttle_audio`). If `finish=True` (the default), an end-of-audio signal is sent after the last chunk; pass `finish=False` when you intend to send more audio later in the same session. **Parameters** | Parameter | Type | Description | | --------- | -------------------------- | ------------------------------------------------------------ | | `chunks` | `bytes \| Iterator[bytes]` | Raw bytes or an iterator of byte chunks. | | `finish` | `bool` | If True (default), signal end-of-audio after the last chunk. | **Returns** `None` *** ### send\_control\_message() ```python send_control_message(control_type: RealtimeControlType) -> None ``` Send a control message to the realtime session. Control messages modify the state of the stream, such as signaling end-of-audio or requesting finalization. **Parameters** | Parameter | Type | Description | | -------------- | --------------------- | ------------------------------------ | | `control_type` | `RealtimeControlType` | The type of control message to send. | **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected or the message cannot be sent. *** ### finish() ```python finish() -> None ``` Signal end-of-audio. The server finalizes any pending tokens and closes the connection. Continue iterating `receive_events()` to consume the remaining tokens. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keep-alive message to prevent the session from timing out. **Returns** `None` *** ### finalize() ```python finalize() -> None ``` Finalize all outstanding non-final tokens while keeping the session open. Subsequent tokens will be delivered with `is_final=True`. **Returns** `None` *** ### recv\_bytes() ```python recv_bytes() -> bytes ``` Receive a raw message from the WebSocket connection. **Returns** `bytes` The received message as bytes. An empty bytes object indicates that the connection has been closed. *** ### parse\_event() ```python parse_event(raw: str | bytes) -> RealtimeEvent ``` Parse a raw WebSocket message into a structured realtime event. **Parameters** | Parameter | Type | Description | | --------- | -------------- | --------------------------------------------- | | `raw` | `str \| bytes` | Raw message payload received from the server. | **Returns** `RealtimeEvent` A validated RealtimeEvent instance. *** ### receive\_event() ```python receive_event() -> RealtimeEvent | None ``` Receive and parse the next realtime event from the server. **Returns** `RealtimeEvent | None` The next RealtimeEvent, or None if the connection has closed. **Raises** * `SonioxRealtimeError` If the session is not connected. *** ### receive\_events() ```python receive_events() -> Iterator[RealtimeEvent] ``` Yield realtime events as they are received from the server. Iteration stops automatically when the connection is closed. **Returns** `Iterator[RealtimeEvent]` *** ### handle\_events() ```python handle_events(handler: Callable[[RealtimeEvent], None]) -> None ``` Receive realtime events and dispatch them to a handler callback. **Parameters** | Parameter | Type | Description | | --------- | --------------------------------- | ------------------------------------------------- | | `handler` | `Callable[[RealtimeEvent], None]` | Callable invoked for each received RealtimeEvent. | **Returns** `None` *** ### pause() ```python pause(*, finalize: bool = True) -> None ``` Pause the session, suppressing outgoing audio and starting a background keepalive thread. While paused, calls to `send_byte_chunk` are silently dropped. A background thread sends a keepalive message every `KEEP_ALIVE_INTERVAL_SEC` seconds to prevent the server from timing out the session. Calling `pause` on an already-paused session is a no-op. **Parameters** | Parameter | Type | Description | | ---------- | ------ | ---------------------------------------------------- | | `finalize` | `bool` | If True (default), call `finalize()` before pausing. | **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected. *** ### resume() ```python resume() -> None ``` Resume a paused session, stopping the keepalive thread and allowing audio to be sent again. Calling `resume` on a session that is not paused is a no-op. **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected. *** ## AsyncRealtimeSTTSession Asynchronous WebSocket session for a single real-time speech-to-text stream. This class manages the full lifecycle of a real-time transcription session: connecting to the WebSocket endpoint, streaming audio data, receiving events, and gracefully closing the stream. A session is stateful and represents exactly one streaming interaction with the Soniox realtime API. Instances are designed to be used as async context managers. ### Constructor ```python AsyncRealtimeSTTSession(url: str, config: RealtimeSTTConfig, api_key: str, *, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) ``` Create a new realtime STT session. This does not open a network connection. The WebSocket connection is established when entering the async context manager. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | ---------------------------------------------------------------------------------------- | | `url` | `str` | WebSocket URL for the realtime transcription endpoint. | | `config` | `RealtimeSTTConfig` | Configuration describing the audio format and transcription behavior for this session. | | `api_key` | `str` | API key sent on the WebSocket handshake. | | `connect_timeout_sec` | `float` | Maximum seconds to wait for the WebSocket handshake to complete. Defaults to 10 seconds. | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | ----------------------- | --------------------------------------------------------- | | `config` | `RealtimeSTTConfig` | Return the configuration used to initialize this session. | | `paused` | `bool` | Return True if the session is currently paused. | | `last_message` | `RealtimeEvent \| None` | Return the most recently received realtime event, if any. | ### close() ```python close() -> None ``` Close the realtime session and release the WebSocket. Signals end-of-audio to the server and clears the underlying connection. Subsequent calls are no-ops. Called automatically when exiting the async context manager. **Returns** `None` *** ### send\_byte\_chunk() ```python send_byte_chunk(chunk: bytes) -> None ``` Send a single chunk of raw audio bytes to the realtime stream. The audio data must match the format declared in the session configuration (sample rate, channels, encoding). **Parameters** | Parameter | Type | Description | | --------- | ------- | ------------------------ | | `chunk` | `bytes` | Raw audio bytes to send. | **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected or the send operation fails. *** ### send\_bytes() ```python send_bytes(chunks: bytes | AsyncIterator[bytes], *, finish: bool = True) -> None ``` Send audio data to the realtime stream. Accepts either a single bytes object or an async iterator yielding byte chunks (e.g. from `throttle_audio_async`). If `finish=True` (the default), an end-of-audio signal is sent after the last chunk; pass `finish=False` when you intend to send more audio later in the same session. **Parameters** | Parameter | Type | Description | | --------- | ------------------------------- | ------------------------------------------------------------ | | `chunks` | `bytes \| AsyncIterator[bytes]` | Raw bytes or an async iterator of byte chunks. | | `finish` | `bool` | If True (default), signal end-of-audio after the last chunk. | **Returns** `None` *** ### send\_control\_message() ```python send_control_message(control_type: RealtimeControlType) -> None ``` Send a control message to the realtime session. Control messages modify the state of the stream, such as signaling end-of-audio or requesting finalization. **Parameters** | Parameter | Type | Description | | -------------- | --------------------- | ------------------------------------ | | `control_type` | `RealtimeControlType` | The type of control message to send. | **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected or the message cannot be sent. *** ### finish() ```python finish() -> None ``` Signal end-of-audio. The server finalizes any pending tokens and closes the connection. Continue iterating `receive_events()` to consume the remaining tokens. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keep-alive message to prevent the session from timing out. **Returns** `None` *** ### finalize() ```python finalize() -> None ``` Finalize all outstanding non-final tokens while keeping the session open. Subsequent tokens will be delivered with `is_final=True`. **Returns** `None` *** ### recv\_bytes() ```python recv_bytes() -> bytes ``` Receive a raw message from the WebSocket connection. **Returns** `bytes` The received message as bytes. An empty bytes object indicates that the connection has been closed. *** ### parse\_event() ```python parse_event(raw: str | bytes) -> RealtimeEvent ``` Parse a raw WebSocket message into a structured realtime event. **Parameters** | Parameter | Type | Description | | --------- | -------------- | --------------------------------------------- | | `raw` | `str \| bytes` | Raw message payload received from the server. | **Returns** `RealtimeEvent` A validated RealtimeEvent instance. *** ### receive\_event() ```python receive_event() -> RealtimeEvent | None ``` Receive and parse the next realtime event from the server. **Returns** `RealtimeEvent | None` The next RealtimeEvent, or None if the connection has closed. **Raises** * `SonioxRealtimeError` If the session is not connected. *** ### receive\_events() ```python receive_events() -> AsyncIterator[RealtimeEvent] ``` Yield realtime events as they are received from the server. Iteration stops automatically when the connection is closed. **Returns** `AsyncIterator[RealtimeEvent]` *** ### handle\_events() ```python handle_events(handler: Callable[[RealtimeEvent], Awaitable[None]]) -> None ``` Receive realtime events and dispatch them to a handler callback. **Parameters** | Parameter | Type | Description | | --------- | -------------------------------------------- | ------------------------------------------------- | | `handler` | `Callable[[RealtimeEvent], Awaitable[None]]` | Callable invoked for each received RealtimeEvent. | **Returns** `None` *** ### pause() ```python pause(*, finalize: bool = True) -> None ``` Pause the session, suppressing outgoing audio and starting a background keepalive task. While paused, calls to `send_byte_chunk` are silently dropped. A background task sends a keepalive message every `KEEP_ALIVE_INTERVAL_SEC` seconds to prevent the server from timing out the session. Calling `pause` on an already-paused session is a no-op. **Parameters** | Parameter | Type | Description | | ---------- | ------ | ---------------------------------------------------- | | `finalize` | `bool` | If True (default), call `finalize()` before pausing. | **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected. *** ### resume() ```python resume() -> None ``` Resume a paused session, stopping the keepalive task and allowing audio to be sent again. Calling `resume` on a session that is not paused is a no-op. **Returns** `None` **Raises** * `SonioxRealtimeError` If the session is not connected. *** ## RealtimeTTSClient Factory for synchronous realtime Text-to-Speech connections and streams. ### Constructor ```python RealtimeTTSClient(client: SonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | -------------- | ----------------------- | | `client` | `SonioxClient` | Soniox client instance. | **Returns** `None` ### connect() ```python connect(*, config: RealtimeTTSConfig, api_key: str | None = None, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) -> RealtimeTTSConnection ``` Create a single-stream realtime Text-to-Speech connection. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | ----------------------------------------- | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | | `api_key` | `str \| None` | API key used for authentication. | | `connect_timeout_sec` | `float` | - | **Returns** `RealtimeTTSConnection` *** ### connect\_multi\_stream() ```python connect_multi_stream(*, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) -> RealtimeTTSMultiplexedConnection ``` Create a multiplexed realtime Text-to-Speech connection. **Parameters** | Parameter | Type | Description | | --------------------- | ------- | ----------- | | `connect_timeout_sec` | `float` | - | **Returns** `RealtimeTTSMultiplexedConnection` *** ## AsyncRealtimeTTSClient Factory for asynchronous realtime Text-to-Speech connections and streams. ### Constructor ```python AsyncRealtimeTTSClient(client: AsyncSonioxClient) ``` **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------- | | `client` | `AsyncSonioxClient` | Soniox client instance. | **Returns** `None` ### connect() ```python connect(*, config: RealtimeTTSConfig, api_key: str | None = None, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) -> AsyncRealtimeTTSConnection ``` Create a single-stream realtime Text-to-Speech connection. **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | ----------------------------------------- | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | | `api_key` | `str \| None` | API key used for authentication. | | `connect_timeout_sec` | `float` | - | **Returns** `AsyncRealtimeTTSConnection` *** ### connect\_multi\_stream() ```python connect_multi_stream(*, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) -> AsyncRealtimeTTSMultiplexedConnection ``` Create a multiplexed realtime Text-to-Speech connection. **Parameters** | Parameter | Type | Description | | --------------------- | ------- | ----------- | | `connect_timeout_sec` | `float` | - | **Returns** `AsyncRealtimeTTSMultiplexedConnection` *** ## RealtimeTTSConnection Synchronous WebSocket connection for one realtime Text-to-Speech stream. ### Constructor ```python RealtimeTTSConnection(url: str, config: RealtimeTTSConfig, api_key: str, *, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) ``` **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | ----------------------------------------- | | `url` | `str` | WebSocket URL for realtime transcription. | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | | `api_key` | `str` | API key used for authentication. | | `connect_timeout_sec` | `float` | - | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | -------------------------- | -------------------------------------------------- | | `config` | `RealtimeTTSConfig` | Configuration used to initialize this connection. | | `paused` | `bool` | Return True if the connection is currently paused. | | `last_message` | `RealtimeTTSEvent \| None` | Most recently received realtime event, if any. | ### close() ```python close() -> None ``` Close the realtime Text-to-Speech connection. **Returns** `None` *** ### send\_text\_chunk() ```python send_text_chunk(text: str, *, text_end: bool = False) -> None ``` Send one text chunk to the realtime stream. **Parameters** | Parameter | Type | Description | | ---------- | ------ | --------------------------------------------------------------- | | `text` | `str` | Text chunk to generate into speech. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### send\_text\_chunks() ```python send_text_chunks(chunks: str | Iterator[str], *, text_end: bool = True) -> None ``` Send text data to the realtime stream. **Parameters** | Parameter | Type | Description | | ---------- | ---------------------- | --------------------------------------------------------------- | | `chunks` | `str \| Iterator[str]` | Audio chunks to stream to realtime transcription. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### finish() ```python finish() -> None ``` Signal that no more text will be sent for this stream. **Returns** `None` *** ### cancel() ```python cancel() -> None ``` Cancel the realtime Text-to-Speech stream. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keep-alive message to prevent the session from timing out. **Returns** `None` *** ### pause() ```python pause() -> None ``` Pause outgoing text and start periodic keep-alive messages. **Returns** `None` *** ### resume() ```python resume() -> None ``` Resume outgoing text and stop periodic keep-alive messages. **Returns** `None` *** ### recv\_bytes() ```python recv_bytes() -> bytes ``` Receive one raw websocket message payload as bytes. **Returns** `bytes` *** ### parse\_event() ```python parse_event(raw: str | bytes) -> RealtimeTTSEvent ``` Parse a raw websocket message into a realtime event. **Parameters** | Parameter | Type | Description | | --------- | -------------- | ---------------------------------------- | | `raw` | `str \| bytes` | Raw event payload from the realtime API. | **Returns** `RealtimeTTSEvent` *** ### receive\_event() ```python receive_event() -> RealtimeTTSEvent | None ``` Receive and parse the next realtime event. **Returns** `RealtimeTTSEvent | None` *** ### receive\_events() ```python receive_events() -> Iterator[RealtimeTTSEvent] ``` Yield realtime events until the stream ends or closes. **Returns** `Iterator[RealtimeTTSEvent]` *** ### receive\_audio\_chunks() ```python receive_audio_chunks() -> Iterator[bytes] ``` Yield decoded audio chunks from incoming realtime events. **Returns** `Iterator[bytes]` *** ## AsyncRealtimeTTSConnection Asynchronous WebSocket connection for one realtime Text-to-Speech stream. ### Constructor ```python AsyncRealtimeTTSConnection(url: str, config: RealtimeTTSConfig, api_key: str, *, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) ``` **Parameters** | Parameter | Type | Description | | --------------------- | ------------------- | ----------------------------------------- | | `url` | `str` | WebSocket URL for realtime transcription. | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | | `api_key` | `str` | API key used for authentication. | | `connect_timeout_sec` | `float` | - | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | -------------------------- | -------------------------------------------------- | | `config` | `RealtimeTTSConfig` | Configuration used to initialize this connection. | | `paused` | `bool` | Return True if the connection is currently paused. | | `last_message` | `RealtimeTTSEvent \| None` | Most recently received realtime event, if any. | ### close() ```python close() -> None ``` Close the realtime Text-to-Speech connection. **Returns** `None` *** ### send\_text\_chunk() ```python send_text_chunk(text: str, *, text_end: bool = False) -> None ``` Send one text chunk to the realtime stream. **Parameters** | Parameter | Type | Description | | ---------- | ------ | --------------------------------------------------------------- | | `text` | `str` | Text chunk to generate into speech. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### send\_text\_chunks() ```python send_text_chunks(chunks: str | AsyncIterator[str], *, text_end: bool = True) -> None ``` Send text data to the realtime stream. **Parameters** | Parameter | Type | Description | | ---------- | --------------------------- | --------------------------------------------------------------- | | `chunks` | `str \| AsyncIterator[str]` | Audio chunks to stream to realtime transcription. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### finish() ```python finish() -> None ``` Signal that no more text will be sent for this stream. **Returns** `None` *** ### cancel() ```python cancel() -> None ``` Cancel the realtime Text-to-Speech stream. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keep-alive message to prevent the session from timing out. **Returns** `None` *** ### pause() ```python pause() -> None ``` Pause outgoing text and start periodic keep-alive messages. **Returns** `None` *** ### resume() ```python resume() -> None ``` Resume outgoing text and stop periodic keep-alive messages. **Returns** `None` *** ### recv\_bytes() ```python recv_bytes() -> bytes ``` Receive one raw websocket message payload as bytes. **Returns** `bytes` *** ### parse\_event() ```python parse_event(raw: str | bytes) -> RealtimeTTSEvent ``` Parse a raw websocket message into a realtime event. **Parameters** | Parameter | Type | Description | | --------- | -------------- | ---------------------------------------- | | `raw` | `str \| bytes` | Raw event payload from the realtime API. | **Returns** `RealtimeTTSEvent` *** ### receive\_event() ```python receive_event() -> RealtimeTTSEvent | None ``` Receive and parse the next realtime event. **Returns** `RealtimeTTSEvent | None` *** ### receive\_events() ```python receive_events() -> AsyncIterator[RealtimeTTSEvent] ``` Yield realtime events until the stream ends or closes. **Returns** `AsyncIterator[RealtimeTTSEvent]` *** ### receive\_audio\_chunks() ```python receive_audio_chunks() -> AsyncIterator[bytes] ``` Yield decoded audio chunks from incoming realtime events. **Returns** `AsyncIterator[bytes]` *** ### handle\_events() ```python handle_events(handler: Callable[[RealtimeTTSEvent], Awaitable[None]]) -> None ``` Receive events and pass each one to `handler`. **Parameters** | Parameter | Type | Description | | --------- | ----------------------------------------------- | ------------------------------------------------------------------ | | `handler` | `Callable[[RealtimeTTSEvent], Awaitable[None]]` | Event payload received from the realtime Text-to-Speech websocket. | **Returns** `None` *** ## RealtimeTTSMultiplexedConnection Synchronous websocket connection that can host multiple Text-to-Speech streams. ### Constructor ```python RealtimeTTSMultiplexedConnection(url: str, api_key: str, *, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) ``` **Parameters** | Parameter | Type | Description | | --------------------- | ------- | ----------------------------------------- | | `url` | `str` | WebSocket URL for realtime transcription. | | `api_key` | `str` | API key used for authentication. | | `connect_timeout_sec` | `float` | - | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | -------------------------- | -------------------------------------------------- | | `last_message` | `RealtimeTTSEvent \| None` | Most recently received realtime event, if any. | | `paused` | `bool` | Return True if the connection is currently paused. | ### close() ```python close() -> None ``` Close the websocket and clear the stream state. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keep-alive message to prevent the session from timing out. **Returns** `None` *** ### pause() ```python pause() -> None ``` Pause outgoing text and start periodic keep-alive messages. **Returns** `None` *** ### resume() ```python resume() -> None ``` Resume outgoing text and stop periodic keep-alive messages. **Returns** `None` *** ### open\_stream() ```python open_stream(*, config: RealtimeTTSConfig) -> RealtimeTTSStream ``` Register and start a new stream on the shared websocket. **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------------------------- | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | **Returns** `RealtimeTTSStream` *** ## AsyncRealtimeTTSMultiplexedConnection Asynchronous websocket connection that can host multiple TTS streams. ### Constructor ```python AsyncRealtimeTTSMultiplexedConnection(url: str, api_key: str, *, connect_timeout_sec: float = DEFAULT_CONNECT_TIMEOUT_SEC) ``` **Parameters** | Parameter | Type | Description | | --------------------- | ------- | ----------------------------------------- | | `url` | `str` | WebSocket URL for realtime transcription. | | `api_key` | `str` | API key used for authentication. | | `connect_timeout_sec` | `float` | - | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | -------------------------- | -------------------------------------------------- | | `last_message` | `RealtimeTTSEvent \| None` | Most recently received realtime event, if any. | | `paused` | `bool` | Return True if the connection is currently paused. | ### close() ```python close() -> None ``` Close the websocket and clear the stream state. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keep-alive message to prevent the session from timing out. **Returns** `None` *** ### pause() ```python pause() -> None ``` Pause outgoing text and start periodic keep-alive messages. **Returns** `None` *** ### resume() ```python resume() -> None ``` Resume outgoing text and stop periodic keep-alive messages. **Returns** `None` *** ### open\_stream() ```python open_stream(*, config: RealtimeTTSConfig) -> AsyncRealtimeTTSStream ``` Register and start a new stream on the shared websocket. **Parameters** | Parameter | Type | Description | | --------- | ------------------- | ----------------------------------------- | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | **Returns** `AsyncRealtimeTTSStream` *** ## RealtimeTTSStream Handle for one stream on a multiplexed realtime TTS connection. ### Constructor ```python RealtimeTTSStream(connection: RealtimeTTSMultiplexedConnection, config: RealtimeTTSConfig) ``` **Parameters** | Parameter | Type | Description | | ------------ | ---------------------------------- | ------------------------------------------------------------------------------- | | `connection` | `RealtimeTTSMultiplexedConnection` | Synchronous websocket connection that can host multiple Text-to-Speech streams. | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | -------------------------- | ----------------------------------------------------- | | `config` | `RealtimeTTSConfig` | Stream configuration. | | `stream_id` | `str` | Stream identifier. | | `last_message` | `RealtimeTTSEvent \| None` | Most recently received event for this stream, if any. | ### send\_text\_chunk() ```python send_text_chunk(text: str, *, text_end: bool = False) -> None ``` Send one text chunk for this stream. **Parameters** | Parameter | Type | Description | | ---------- | ------ | --------------------------------------------------------------- | | `text` | `str` | Text chunk to generate into speech. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### send\_text\_chunks() ```python send_text_chunks(chunks: str | Iterator[str], *, text_end: bool = True) -> None ``` Send text chunks for this stream. **Parameters** | Parameter | Type | Description | | ---------- | ---------------------- | --------------------------------------------------------------- | | `chunks` | `str \| Iterator[str]` | Audio chunks to stream to realtime transcription. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### finish() ```python finish() -> None ``` Signal that no more text will be sent for this stream. **Returns** `None` *** ### cancel() ```python cancel() -> None ``` Cancel this stream. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keepalive message on the underlying shared connection. **Returns** `None` *** ### pause() ```python pause() -> None ``` Pause the underlying shared connection and start keepalive. **Returns** `None` *** ### resume() ```python resume() -> None ``` Resume the underlying shared connection and stop keepalive. **Returns** `None` *** ### receive\_event() ```python receive_event() -> RealtimeTTSEvent | None ``` Receive the next event for this stream. **Returns** `RealtimeTTSEvent | None` *** ### receive\_events() ```python receive_events() -> Iterator[RealtimeTTSEvent] ``` Yield events for this stream until it ends. **Returns** `Iterator[RealtimeTTSEvent]` *** ### receive\_audio\_chunks() ```python receive_audio_chunks() -> Iterator[bytes] ``` Yield decoded audio chunks for this stream. **Returns** `Iterator[bytes]` *** ## AsyncRealtimeTTSStream Handle for one stream on a multiplexed realtime TTS connection. ### Constructor ```python AsyncRealtimeTTSStream(connection: AsyncRealtimeTTSMultiplexedConnection, config: RealtimeTTSConfig) ``` **Parameters** | Parameter | Type | Description | | ------------ | --------------------------------------- | --------------------------------------------------------------------- | | `connection` | `AsyncRealtimeTTSMultiplexedConnection` | Asynchronous websocket connection that can host multiple TTS streams. | | `config` | `RealtimeTTSConfig` | Configuration options for this operation. | **Returns** `None` ### Properties | Property | Type | Description | | -------------- | -------------------------- | ----------------------------------------------------- | | `config` | `RealtimeTTSConfig` | Stream configuration. | | `stream_id` | `str` | Stream identifier. | | `last_message` | `RealtimeTTSEvent \| None` | Most recently received event for this stream, if any. | ### send\_text\_chunk() ```python send_text_chunk(text: str, *, text_end: bool = False) -> None ``` Send one text chunk for this stream. **Parameters** | Parameter | Type | Description | | ---------- | ------ | --------------------------------------------------------------- | | `text` | `str` | Text chunk to generate into speech. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### send\_text\_chunks() ```python send_text_chunks(chunks: str | AsyncIterator[str], *, text_end: bool = True) -> None ``` Send text chunks for this stream. **Parameters** | Parameter | Type | Description | | ---------- | --------------------------- | --------------------------------------------------------------- | | `chunks` | `str \| AsyncIterator[str]` | Audio chunks to stream to realtime transcription. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | **Returns** `None` *** ### finish() ```python finish() -> None ``` Signal that no more text will be sent for this stream. **Returns** `None` *** ### cancel() ```python cancel() -> None ``` Cancel this stream. **Returns** `None` *** ### keep\_alive() ```python keep_alive() -> None ``` Send a keepalive message on the underlying shared connection. **Returns** `None` *** ### pause() ```python pause() -> None ``` Pause the underlying shared connection and start keepalive. **Returns** `None` *** ### resume() ```python resume() -> None ``` Resume the underlying shared connection and stop keepalive. **Returns** `None` *** ### receive\_event() ```python receive_event() -> RealtimeTTSEvent | None ``` Receive the next event for this stream. **Returns** `RealtimeTTSEvent | None` *** ### receive\_events() ```python receive_events() -> AsyncIterator[RealtimeTTSEvent] ``` Yield events for this stream until it ends. **Returns** `AsyncIterator[RealtimeTTSEvent]` *** ### receive\_audio\_chunks() ```python receive_audio_chunks() -> AsyncIterator[bytes] ``` Yield decoded audio chunks for this stream. **Returns** `AsyncIterator[bytes]` # Types URL: /sdk/python-SDK/Full-SDK-reference/types Soniox Python SDK - Types Reference *** ## Token Token metadata emitted during realtime streaming transcriptions. ### Properties | Property | Type | Description | | -------------------- | --------------- | ------------------------------------------------------------ | | `text` | `str` | The transcribed text. | | `start_ms` | `int \| None` | Start time in milliseconds relative to audio start. | | `end_ms` | `int \| None` | End time in milliseconds relative to audio start. | | `confidence` | `float \| None` | Confidence score (0.0 to 1.0). | | `is_final` | `bool \| None` | Whether this is a finalized token. | | `speaker` | `str \| None` | Speaker identifier (if diarization enabled). | | `translation_status` | `str \| None` | Translation status of this token. | | `language` | `str \| None` | Detected language code (if language identification enabled). | | `source_language` | `str \| None` | Source language for translated tokens. | *** ## ApiError Structured representation of a non-2xx API response payload. ### Properties | Property | Type | Description | | ------------------- | ------------------------------- | ------------------------------------------------------------------------------------------ | | `status_code` | `int` | HTTP status code. | | `error_type` | `str` | High-level error code (e.g., 'bad\_request', 'quota\_exceeded') for programmatic handling. | | `message` | `str` | Detailed error message describing the failure. | | `validation_errors` | `list[ApiErrorValidationError]` | List of specific field validation failures, if applicable. | | `request_id` | `str \| None` | Unique identifier for the request, useful for troubleshooting. | | `more_info` | `str \| None` | Optional URL pointing to documentation for resolving this error. | *** ## ApiErrorValidationError Details a single validation error reported by the Soniox API. ### Properties | Property | Type | Description | | ------------ | ----- | -------------------------------------------------------- | | `error_type` | `str` | The category of validation error. | | `location` | `str` | The location of the error, e.g. \['body', 'audio\_url']. | | `message` | `str` | A human-readable description of the validation failure. | *** ## CreateTemporaryApiKeyPayload Payload for requesting a temporary API key (e.g., websocket). ### Properties | Property | Type | Description | | ------------------------------ | -------------------------- | -------------------------------------------------------------------------------------- | | `usage_type` | `TemporaryApiKeyUsageType` | Intended usage of the temporary API key. | | `expires_in_seconds` | `int` | Duration in seconds until the temporary API key expires | | `client_reference_id` | `str \| None` | Optional tracking identifier string. Does not need to be unique | | `single_use` | `bool \| None` | When true, restricts the temporary API key to a single use. | | `max_session_duration_seconds` | `int \| None` | Maximum connection duration in seconds for WebSocket and TTS HTTP streaming endpoints. | *** ## CreateTemporaryApiKeyResponse Response data for a temp API key request. ### Properties | Property | Type | Description | | ------------ | ---------- | --------------------------------------------------------------------- | | `api_key` | `str` | Created temporary API key. | | `expires_at` | `datetime` | UTC timestamp indicating when generated temporary API key will expire | *** ## CreateTtsPayload Payload sent to generate speech audio from text via REST. ### Properties | Property | Type | Description | | ---------------- | ----------------------- | -------------------------------------------------------------------------------------- | | `model` | `str` | Text-to-Speech model to use. | | `language` | `str` | Language code for Text-to-Speech (e.g., "en"). | | `voice` | `str` | Voice identifier to generate speech audio with. | | `audio_format` | `TtsAudioFormat` | Requested output audio format. | | `sample_rate` | `TtsSampleRate \| None` | Output sample rate in Hz. | | `bitrate` | `TtsBitrate \| None` | Output bitrate in bits-per-second for compressed formats. | | `speed` | `float \| None` | Speaking rate multiplier from 0.7 to 1.3; 1.0 (default) is normal speed. | | `reduce_silence` | `bool \| None` | Shorten the pauses between words. Only for models with 'supports\_silence\_reduction'. | | `text` | `str` | Input text to generate into speech. | *** ## ConcurrencyCurrentValues Live counts of concurrent sessions. ### Properties | Property | Type | Description | | ----------------------- | ----- | ------------------------------------------------------------ | | `transcribe_concurrent` | `int` | Number of concurrent realtime STT sessions currently active. | | `tts_concurrent` | `int` | Number of concurrent realtime TTS sessions currently active. | *** ## ConcurrencyLimitValues Configured concurrency limits. None means no limit. ### Properties | Property | Type | Description | | ----------------------- | ------------- | --------------------------------------------------------------- | | `transcribe_concurrent` | `int \| None` | Maximum concurrent realtime STT sessions, or None if unlimited. | | `tts_concurrent` | `int \| None` | Maximum concurrent realtime TTS sessions, or None if unlimited. | *** ## ConcurrencyScopeValues Current and limit values for a single scope (project or organization). ### Properties | Property | Type | Description | | --------- | -------------------------- | ------------------------------- | | `current` | `ConcurrencyCurrentValues` | Live counts of active sessions. | | `limits` | `ConcurrencyLimitValues` | Configured limits. | *** ## CreateTtsConfig Helper config used when building Text-to-Speech payloads. ### Properties | Property | Type | Description | | ---------------- | ------------------------ | -------------------------------------------------------------------------------------- | | `model` | `str \| None` | Deprecated: pass `model` to generate()/generate\_to\_file() instead. | | `language` | `str \| None` | Deprecated: pass `language` to generate()/generate\_to\_file() instead. | | `voice` | `str \| None` | Deprecated: pass `voice` to generate()/generate\_to\_file() instead. | | `audio_format` | `TtsAudioFormat \| None` | Requested output audio format. | | `sample_rate` | `TtsSampleRate \| None` | Output sample rate in Hz. | | `bitrate` | `TtsBitrate \| None` | Output bitrate in bits-per-second for compressed formats. | | `speed` | `float \| None` | Speaking rate multiplier from 0.7 to 1.3; 1.0 (default) is normal speed. | | `reduce_silence` | `bool \| None` | Shorten the pauses between words. Only for models with 'supports\_silence\_reduction'. | *** ## CreateTranscriptionPayload Payload sent to create an asynchronous transcription job. ### Properties | Property | Type | Description | | -------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `audio_url` | `str \| None` | URL of a publicly accessible audio file. | | `file_id` | `str \| None` | ID of a previously uploaded file (UUID). | | `language_hints` | `list[LanguageCode] \| None` | Array of expected ISO language codes to bias recognition. | | `language_hints_strict` | `bool \| None` | When true, model relies more heavily on language hints (best results with one language hint set). | | `enable_speaker_diarization` | `bool \| None` | Enable speaker diarization to identify different speakers. | | `enable_language_identification` | `bool \| None` | Enable automatic language identification. | | `translation` | `TranslationConfigInput \| None` | Translation configuration. | | `context` | `StructuredContextInput \| None` | Additional context to improve transcription accuracy and formatting of specialized terms. | | `webhook_url` | `str \| None` | URL to receive webhook notifications when transcription is completed or fails. | | `webhook_auth_header_name` | `str \| None` | Name of the authentication header sent with webhook notifications | | `webhook_auth_header_value` | `str \| None` | Authentication header value sent with webhook notifications. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | *** ## CreateTranscriptionConfig Helper config used when building transcription payloads. ### Properties | Property | Type | Description | | -------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------- | | `model` | `str \| None` | Deprecated: pass `model` to the create call instead. | | `language_hints` | `list[LanguageCode] \| None` | Array of expected ISO language codes to bias recognition. | | `language_hints_strict` | `bool \| None` | When true, model relies more heavily on language hints. | | `enable_speaker_diarization` | `bool \| None` | Enable speaker diarization to identify different speakers. | | `enable_language_identification` | `bool \| None` | Enable automatic language identification | | `translation` | `TranslationConfigInput \| None` | Translation configuration | | `context` | `StructuredContextInput \| None` | Additional context to improve transcription accuracy and formatting of specialized terms. | | `webhook_url` | `str \| None` | URL to receive webhook notifications when transcription is completed or fails. | | `webhook_auth_header_name` | `str \| None` | Name of the authentication header sent with webhook notifications | | `webhook_auth_header_value` | `str \| None` | Authentication header value sent with webhook notifications | | `client_reference_id` | `str \| None` | Deprecated: pass `client_reference_id` to the create call instead. | *** ## File Metadata describing an uploaded file in the Soniox API. Uploaded files are automatically deleted 30 days after upload. ### Properties | Property | Type | Description | | --------------------- | ------------- | ---------------------------------------------------- | | `id` | `str` | Unique identifier of the file (UUID). | | `filename` | `str` | Name of the file. | | `size` | `int` | Size of the file in bytes. | | `created_at` | `datetime` | UTC timestamp indicating when the file was uploaded. | | `client_reference_id` | `str \| None` | Optional tracking identifier string. | *** ## GetConcurrencyLimitsResponse Response returned when fetching concurrency limits. ### Properties | Property | Type | Description | | -------------- | ------------------------ | --------------------------------------------------------- | | `project` | `ConcurrencyScopeValues` | Project-scoped current counts and configured limits. | | `organization` | `ConcurrencyScopeValues` | Organization-scoped current counts and configured limits. | *** ## GetFilesCountResponse Breakdown of uploaded file counts by source. ### Properties | Property | Type | Description | | ------------ | ----- | -------------------------------------------- | | `total` | `int` | Total number of files across all sources. | | `public_api` | `int` | Number of files uploaded via Public API. | | `playground` | `int` | Number of files uploaded via the Playground. | *** ## GetFilesPayload Parameters accepted by the file listing endpoint. ### Properties | Property | Type | Description | | -------- | ------------- | ----------------------------------------------- | | `limit` | `int` | Maximum number of files to return. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | *** ## GetFilesResponse Paginated response returned when listing uploaded files. ### Properties | Property | Type | Description | | ------------------ | ------------- | ------------------------------------------------------------------------------------------------------------ | | `files` | `list[File]` | List of uploaded files. | | `next_page_cursor` | `str \| None` | A pagination token that references the next page of results. When None, no additional results are available. | *** ## GetModelsResponse Response returned when listing available models. ### Properties | Property | Type | Description | | -------- | ------------- | ----------------------------- | | `models` | `list[Model]` | List of all available models. | *** ## GetSharedVoicesPayload Parameters for listing the shared voices of a Text-to-Speech model. ### Properties | Property | Type | Description | | ---------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------- | | `model` | `str` | Id of the TTS model whose voices to return. | | `gender` | `TtsVoiceGender \| None` | Only return voices of this gender. | | `age` | `TtsVoiceAge \| None` | Only return voices of this age. | | `accent` | `str \| None` | Only return voices with this accent. | | `use_case` | `list[Annotated[str, Field(max_length=40)]] \| None` | Only return voices tagged with every listed use case. | | `style` | `list[Annotated[str, Field(max_length=40)]] \| None` | Only return voices tagged with every listed style. | | `limit` | `int` | Maximum number of voices to return. | | `cursor` | `str \| None` | Pagination cursor. Pass the same filters alongside it; it points into the filtered list. | *** ## GetSharedVoicesResponse Response returned when listing the shared voices of a Text-to-Speech model. ### Properties | Property | Type | Description | | ------------------ | ----------------------- | ---------------------------------------------------------------------------- | | `voices` | `list[TtsVoiceDetails]` | List of voices matching the filters. | | `next_page_cursor` | `str \| None` | Pagination token for the next page of results, or None when no more results. | *** ## GetTTSModelsResponse ```python GetTTSModelsResponse = GetTtsModelsResponse ``` *** ## GetTtsModelsResponse Response returned when listing available Text-to-Speech models. ### Properties | Property | Type | Description | | -------- | ---------------- | ---------------------------------------- | | `models` | `list[TtsModel]` | List of available Text-to-Speech models. | *** ## GetTranscriptionsCountResponse Breakdown of transcription counts by scope. ### Properties | Property | Type | Description | | ------------ | ----- | ---------------------------------------------------- | | `total` | `int` | Total number of transcriptions across all scopes. | | `public_api` | `int` | Number of transcriptions created via Public API. | | `playground` | `int` | Number of transcriptions created via the Playground. | *** ## GetTranscriptionsPayload Parameters for listing transcription jobs. ### Properties | Property | Type | Description | | -------- | ------------- | ----------------------------------------------- | | `limit` | `int` | Maximum number of transcriptions to return. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | *** ## GetTranscriptionsResponse Paginated response for transcription listings. ### Properties | Property | Type | Description | | ------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------ | | `transcriptions` | `list[Transcription]` | List of transcriptions. | | `next_page_cursor` | `str \| None` | A pagination token that references the next page of results. When None, no additional results are available. | *** ## GetUsageLogsPayload Parameters accepted by the usage logs listing endpoint. ### Properties | Property | Type | Description | | ------------ | --------------- | ---------------------------------------------------------------------------------- | | `start_time` | `str` | Start of the time window (inclusive). Filters by request end time. | | `end_time` | `str` | End of the time window (exclusive). Filters by request end time. | | `limit` | `int` | Maximum number of usage log entries to return. | | `sort` | `UsageLogsSort` | Sort order by end\_time. Use `end_time_desc` to get the most recent entries first. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | *** ## GetUsageLogsResponse Paginated response for usage-log listings. ### Properties | Property | Type | Description | | ------------------ | --------------------- | ---------------------------------------------------------------------- | | `usage_logs` | `list[UsageLogEntry]` | Per-request usage log entries ordered by end\_time. | | `next_page_cursor` | `str \| None` | Pagination cursor for the next page of results. None if no more pages. | *** ## GetConcurrentStreamsHistoryPayload Parameters accepted by the concurrent streams history endpoint. ### Properties | Property | Type | Description | | ------------ | ---------------------------- | --------------------------------------------------------------------------------- | | `start_time` | `str` | Start of the window (inclusive), ISO 8601 UTC. Filters by `period_start`. | | `end_time` | `str` | End of the window (exclusive), ISO 8601 UTC. Must be strictly after `start_time`. | | `period_sec` | `ConcurrentStreamsPeriodSec` | Aggregation period. Also caps how long the requested window may be. | | `kind` | `ConcurrentStreamKind` | Stream kind to return. | *** ## GetConcurrentStreamsHistoryResponse Per-period concurrent stream aggregates for a project. ### Properties | Property | Type | Description | | --------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `ConcurrentStreamKind` | Stream kind these entries describe. | | `entries` | `list[ConcurrentStreamsHistoryEntry]` | Aggregates ordered by `period_start` ascending. Every period in the window is present with no gaps; periods without activity have every field set to 0. | *** ## GetUsageSummaryPayload Parameters accepted by the usage summary endpoint. ### Properties | Property | Type | Description | | ------------ | ----- | ------------------------------------------------------------------------------- | | `start_time` | `str` | Start of the time window (inclusive), ISO 8601 UTC. | | `end_time` | `str` | End of the time window (exclusive), ISO 8601 UTC. At most 366 days after start. | *** ## GetUsageSummaryResponse Daily cost and activity for a project, per model and across all models. ### Properties | Property | Type | Description | | -------- | ------------------------- | ------------------------------------------------------------------------- | | `total` | `UsageSummaryEntry` | Totals across all models. Its `model` is None. | | `models` | `list[UsageSummaryEntry]` | One entry per model that recorded usage. Empty when the project had none. | *** ## GetVoicesCountResponse Total number of voices in the project. ### Properties | Property | Type | Description | | -------- | ----- | -------------------------------------- | | `total` | `int` | Total number of voices in the project. | *** ## GetVoicesPayload Parameters for listing voices. ### Properties | Property | Type | Description | | -------- | ------------- | ----------------------------------------------- | | `limit` | `int` | Maximum number of voices to return. | | `cursor` | `str \| None` | Pagination cursor for the next page of results. | *** ## GetVoicesResponse Response returned when listing voices. ### Properties | Property | Type | Description | | ------------------ | ------------- | ---------------------------------------------------------------------------- | | `voices` | `list[Voice]` | List of voices. | | `next_page_cursor` | `str \| None` | Pagination token for the next page of results, or None when no more results. | *** ## Language Deprecated alias for :class:`SupportedLanguage`. *** ## LanguageCode ```python LanguageCode = Annotated[str, Field(min_length=2, max_length=2)] ``` ISO 639-1 two-letter language code (e.g. `"en"`, `"fr"`). *** ## SupportedLanguage Represents a supported language for transcription or translation. ### Properties | Property | Type | Description | | -------- | ----- | ------------------------------------ | | `code` | `str` | 2-letter language code (ISO format). | | `name` | `str` | Language name. | *** ## Model Describes a Soniox transcription model. ### Properties | Property | Type | Description | | --------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------- | | `id` | `str` | Unique identifier of the model. | | `aliased_model_id` | `str \| None` | If this is an alias, the id of the aliased model. None for non-alias models. | | `name` | `str` | Name of the model. | | `context_version` | `int \| None` | Version of context supported. | | `transcription_mode` | `TranscriptionMode` | Transcription mode of the model. | | `languages` | `list[SupportedLanguage]` | List of languages supported by the model. | | `supports_language_hints_strict` | `bool` | If model supports 'language\_hints\_strict' option. | | `supports_max_endpoint_delay` | `bool` | If model supports 'max\_endpoint\_delay\_ms' option. | | `supports_endpoint_sensitivity` | `bool` | If model supports the 'endpoint\_sensitivity' option. | | `supports_endpoint_latency_adjustment` | `bool` | If model supports the 'endpoint\_latency\_adjustment\_level' option. | | `endpoint_latency_adjustment_max_level` | `int` | Maximum endpoint\_latency\_adjustment\_level the model accepts (0 means unsupported). | | `translation_targets` | `list[TranslationTarget]` | List of supported one-way translation targets. If list is empty, check for one\_way\_translation field. | | `two_way_translation_pairs` | `list[str]` | List of supported two-way translation pairs. If list is empty, check for one\_way\_translation field. | | `one_way_translation` | `str \| None` | When contains string 'all\_languages', any language from languages can be used | | `two_way_translation` | `str \| None` | When contains string 'all\_languages',' any language pair from languages can be used | *** ## RealtimeSTTAudioFormat ```python RealtimeSTTAudioFormat = Literal["auto"] | RealtimeSTTHeaderFormat | RealtimeSTTRawFormat ``` Audio formats accepted by the realtime STT websocket. *** ## RealtimeSTTHeaderFormat ```python RealtimeSTTHeaderFormat = Literal[ "aac", "aiff", "amr", "asf", "flac", "mp3", "ogg", "wav", "webm", ] ``` Container formats whose header carries sample rate and channels. *** ## RealtimeSTTRawFormat ```python RealtimeSTTRawFormat = Literal[ "pcm_s8", "pcm_s16le", "pcm_s16be", "pcm_s24le", "pcm_s24be", "pcm_s32le", "pcm_s32be", "pcm_u8", "pcm_u16le", "pcm_u16be", "pcm_u24le", "pcm_u24be", "pcm_u32le", "pcm_u32be", "pcm_f32le", "pcm_f32be", "pcm_f64le", "pcm_f64be", "mulaw", "alaw", ] ``` Raw formats with no header - require `sample_rate` and `num_channels`. *** ## RecomputeVoicePayload Body for preparing a voice for additional models. ### Properties | Property | Type | Description | | -------- | ------------- | ----------------------------------------------------------------------------------- | | `model` | `str \| None` | Model to prepare the voice for. If None, prepares it for every not-yet-ready model. | *** ## StructuredContext Optional structured context provided to the transcription engine. For ergonomics, `general` and `translation_terms` also accept a plain dict in addition to the typed item lists: * `general={"domain": "Healthcare"}` (dict of key -> value) * `translation_terms={"Mr. Smith": "Sr. Smith"}` (dict of source -> target) ### Properties | Property | Type | Description | | ------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | | `general` | `Annotated[StructuredContextGeneralInput, Field(union_mode='left_to_right')] \| None` | Structured key-value pairs describing domain, topic, intent, participant names, etc. | | `text` | `str \| None` | Longer free-form background text, prior interaction history, reference documents, or meeting notes. | | `terms` | `list[str] \| None` | Domain-specific or uncommon words to recognize. | | `translation_terms` | `Annotated[StructuredContextTranslationTermsInput, Field(union_mode='left_to_right')] \| None` | Custom translations for ambiguous terms. | *** ## StructuredContextGeneralInput ```python StructuredContextGeneralInput = list[StructuredContextGeneralItem] | dict[str, str] ``` Accepted input shapes for `StructuredContext.general`. *** ## StructuredContextGeneralItem Single general context key/value pair for transcription context. ### Properties | Property | Type | Description | | -------- | ----- | ------------------------------------------------------------------------ | | `key` | `str` | The key describing the context type (e.g., "domain", "topic", "doctor"). | | `value` | `str` | The value for the context key. | *** ## StructuredContextInput ```python StructuredContextInput = StructuredContext | dict[str, Any] ``` Accepted input for the `context` field - typed object or a plain dict. *** ## StructuredContextTranslationTerm Defines a translation term mapping used in structured context. ### Properties | Property | Type | Description | | -------- | ----- | ------------------------------------ | | `source` | `str` | The source term to translate. | | `target` | `str` | The target translation for the term. | *** ## StructuredContextTranslationTermsInput ```python StructuredContextTranslationTermsInput = list[StructuredContextTranslationTerm] | dict[str, str] ``` Accepted input shapes for `StructuredContext.translation_terms`. *** ## Transcription Represents a transcription job tracked by Soniox. Transcriptions are automatically deleted 30 days after creation. ### Properties | Property | Type | Description | | -------------------------------- | --------------------- | -------------------------------------------------------------------------------------------- | | `id` | `str` | Unique identifier of the transcription (UUID). | | `status` | `TranscriptionStatus` | Current status of the transcription. | | `created_at` | `datetime` | UTC timestamp when the transcription was created. | | `model` | `str` | Speech-to-text model used. | | `audio_url` | `str \| None` | URL of the audio file being transcribed. | | `file_id` | `str \| None` | ID of the uploaded file being transcribed (UUID). | | `filename` | `str` | Name of the file being transcribed. | | `language_hints` | `list[str] \| None` | Expected languages in the audio. If not specified, languages are automatically detected. | | `enable_speaker_diarization` | `bool` | When true, speakers are identified and separated in the transcription output. | | `enable_language_identification` | `bool` | When true, language is detected for each part of the transcription. | | `audio_duration_ms` | `int \| None` | Duration of the audio in milliseconds. Only available after processing begins. | | `error_type` | `str \| None` | Error type if transcription failed. None for successful or in-progress transcriptions. | | `error_message` | `str \| None` | Error message if transcription failed. None for successful or in-progress transcriptions. | | `webhook_url` | `str \| None` | URL to receive webhook notifications when transcription is completed or fails. | | `webhook_auth_header_name` | `str \| None` | Name of the authentication header sent with webhook notifications. | | `webhook_auth_header_value` | `str \| None` | Authentication header value. Always returned masked. | | `webhook_status_code` | `int \| None` | HTTP status code received from your server when webhook was delivered. None if not yet sent. | | `client_reference_id` | `str \| None` | Optional tracking identifier. | *** ## TranscriptionStatus ```python TranscriptionStatus = Literal["queued", "processing", "completed", "error"] ``` Current status of the transcription job. *** ## TranscriptionTranscript Transcript data including the full text and tokens. ### Properties | Property | Type | Description | | -------- | ------------- | ------------------------------------------------------------------------- | | `id` | `str` | Unique identifier of the transcription this transcript belongs to (UUID). | | `text` | `str` | Complete transcribed text content. | | `tokens` | `list[Token]` | List of detailed token information with timestamps and metadata. | *** ## TranslationConfig Configuration describing how translation should be performed. ### Properties | Property | Type | Description | | ----------------- | ---------------------- | ------------------------------------------------------------------------- | | `type` | `TranslationType` | Translation type. | | `target_language` | `LanguageCode \| None` | Target language code for translation (e.g., "fr", "es", "de") (one\_way). | | `language_a` | `LanguageCode \| None` | First language code (two\_way). | | `language_b` | `LanguageCode \| None` | Second language code (two\_way). | ### validate\_logic() ```python validate_logic() -> TranslationConfig ``` **Returns** `TranslationConfig` *** ## TranslationConfigInput ```python TranslationConfigInput = TranslationConfig | dict[str, Any] ``` Accepted input for the `translation` field - typed object or a plain dict. *** ## TranslationTarget Describes translation targets offered by a model. ### Properties | Property | Type | Description | | -------------------------- | ----------- | ------------------------------------------------------------------------- | | `target_language` | `str` | Target language code for translation (e.g., "fr", "es", "de") (one\_way). | | `source_languages` | `list[str]` | List of source language codes. | | `exclude_source_languages` | `list[str]` | Source language codes excluded for this target. | *** ## TranslationType ```python TranslationType = Literal["one_way", "two_way"] ``` Supported translation configuration types. *** ## TTSModel ```python TTSModel = TtsModel ``` *** ## TTSVoice ```python TTSVoice = TtsVoice ``` *** ## TTSVoiceAge ```python TTSVoiceAge = TtsVoiceAge ``` *** ## TTSVoiceDetails ```python TTSVoiceDetails = TtsVoiceDetails ``` *** ## TtsAudioFormat ```python TtsAudioFormat = Literal[ "pcm_f32le", "pcm_s16le", "pcm_mulaw", "pcm_alaw", "wav", "aac", "mp3", "opus", "flac", ] ``` Allowed audio formats for Text-to-Speech output. *** ## TtsBitrate ```python TtsBitrate = Literal[32000, 64000, 96000, 128000, 192000, 256000, 320000] ``` Allowed output bitrates in bits-per-second for compressed Text-to-Speech formats. *** ## TtsModel Represents a Text-to-Speech model. ### Properties | Property | Type | Description | | ------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------- | | `id` | `str` | Unique identifier of the model. | | `aliased_model_id` | `str \| None` | If this is an alias, the id of the aliased model. None for non-alias models. | | `name` | `str` | Name of the model. | | `voices` | `list[TtsVoice]` | Voices supported by this model. | | `languages` | `list[SupportedLanguage]` | Languages supported by this model. | | `supports_timestamps` | `bool` | If model supports character-to-audio timestamps ('return\_timestamps'). | | `supports_voice_cloning` | `bool` | If model supports cloned voices created with `client.voices.create()`. | | `voice_cloning_max_audio_duration_ms` | `int \| None` | Maximum reference clip duration for voice cloning (None when cloning is unsupported). | | `supports_speed_adjustment` | `bool` | If model supports adjusting the speaking rate via the 'speed' parameter. | | `speed_min` | `float \| None` | Minimum supported speaking rate (None when speed adjustment is unsupported). | | `speed_max` | `float \| None` | Maximum supported speaking rate (None when speed adjustment is unsupported). | | `supports_silence_reduction` | `bool` | If model supports shortening pauses between words via 'reduce\_silence'. | *** ## TtsSampleRate ```python TtsSampleRate = Literal[8000, 16000, 24000, 44100, 48000] ``` Allowed output sample rates in Hz for Text-to-Speech. *** ## TtsVoice Represents a Text-to-Speech voice. ### Properties | Property | Type | Description | | ------------- | ---------------- | ------------------------------- | | `id` | `str` | Unique identifier of the voice. | | `description` | `str` | Description of the voice. | | `gender` | `TtsVoiceGender` | Gender of the voice. | *** ## TtsVoiceAge ```python TtsVoiceAge = Literal["young", "middle_aged", "old"] ``` Perceived age of a Text-to-Speech voice. *** ## TtsVoiceDetails A shared Text-to-Speech voice with its descriptive tags. ### Properties | Property | Type | Description | | ------------- | ---------------- | --------------------------------------------------------------------------------- | | `id` | `str` | Unique identifier of the voice. | | `description` | `str` | Description of the voice. | | `gender` | `TtsVoiceGender` | Gender of the voice. | | `age` | `TtsVoiceAge` | Perceived age of the speaker. | | `accent` | `str` | Accent of the voice, e.g. 'american', 'british'. | | `use_case` | `list[str]` | Tags describing what the voice is suited for, e.g. 'narration', 'conversational'. | | `style` | `list[str]` | Tags describing how the voice sounds, e.g. 'warm', 'energetic'. | *** ## TtsVoiceGender ```python TtsVoiceGender = Literal["male", "female", "neutral"] ``` Reported gender of a Text-to-Speech voice. *** ## TemporaryApiKeyUsageType ```python TemporaryApiKeyUsageType = Literal["transcribe_websocket", "tts_rt"] ``` Intended usage for temporary API keys. *** ## UploadFilePayload Optional metadata supplied at upload time. ### Properties | Property | Type | Description | | --------------------- | ------------- | --------------------------------------------------------------- | | `client_reference_id` | `str \| None` | Optional tracking identifier string. Does not need to be unique | *** ## UsageLogEntry A single usage-log entry describing one API request. ### Properties | Property | Type | Description | | -------------------------- | ---------- | --------------------------------------------------------------------------- | | `uuid` | `str` | Unique identifier of the request. | | `request_scope` | `str` | Scope of the request (api / playground). | | `client_reference_id` | `str` | Client reference ID supplied on the original request. Empty string if none. | | `model` | `str` | Model identifier. | | `start_time` | `datetime` | When the request started. | | `end_time` | `datetime` | When the request ended. | | `input_text_tokens` | `int` | - | | `input_audio_tokens` | `int` | - | | `input_audio_duration_ms` | `int` | - | | `output_text_tokens` | `int` | - | | `output_audio_tokens` | `int` | - | | `output_audio_duration_ms` | `int` | - | | `cost_usd` | `str` | - | | `input_cost_usd` | `str` | - | | `input_text_cost_usd` | `str` | - | | `input_audio_cost_usd` | `str` | - | | `output_cost_usd` | `str` | - | | `output_text_cost_usd` | `str` | - | | `output_audio_cost_usd` | `str` | - | *** ## ConcurrentStreamKind ```python ConcurrentStreamKind = Literal["stt", "tts"] ``` Stream kind: `stt` for Speech-to-Text sessions, `tts` for Text-to-Speech streams. *** ## ConcurrentStreamsHistoryEntry Concurrent stream counts aggregated over one period. ### Properties | Property | Type | Description | | -------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | `period_start` | `datetime` | Start of the aggregation period, UTC. Aligned to a multiple of `period_sec`. | | `period_sec` | `int` | Aggregation period in seconds. | | `sample_min` | `int` | Lowest recorded count in the period. Always 0; use `sample_max` for the peak. | | `sample_max` | `int` | Peak concurrent stream count in the period. Exact even when rolled up to hours or days. | | `sample_sum` | `int` | Sum of recorded concurrency values. Divide by `sample_count` for the average while streams were active, or by `total_count` to count idle slots as zero. | | `sample_count` | `int` | Number of values actually recorded in the period. 0 when the period had no activity. | | `total_count` | `int` | Number of slots the period covers: 1 for per-minute, 60 for hourly, 24 for daily. | *** ## ConcurrentStreamsPeriodSec ```python ConcurrentStreamsPeriodSec = Literal[60, 3600, 86400] ``` Aggregation period in seconds: per-minute, hourly, or daily. *** ## UsageLogsSort ```python UsageLogsSort = Literal["end_time_asc", "end_time_desc"] ``` *** ## UsageSummaryEntry Daily usage rolled up for one model, or for all models when `model` is None. The per-day lists are aligned by index with `days`; every day in the window is present, so days without usage are zeros. ### Properties | Property | Type | Description | | -------------------------------- | ------------- | -------------------------------------------------------------------- | | `model` | `str \| None` | Model identifier, or None for the entry totalling all models. | | `days` | `list[date]` | UTC dates covered, ascending. Indexes into every per-day list below. | | `total_cost_usd` | `str` | - | | `total_input_cost_usd` | `str` | - | | `total_output_cost_usd` | `str` | - | | `total_duration_cost_usd` | `str` | - | | `cost_usd` | `list[str]` | - | | `input_cost_usd` | `list[str]` | - | | `output_cost_usd` | `list[str]` | - | | `duration_cost_usd` | `list[str]` | - | | `total_num_requests` | `int` | - | | `total_input_text_tokens` | `int` | - | | `total_input_audio_tokens` | `int` | - | | `total_input_audio_duration_ms` | `int` | - | | `total_output_text_tokens` | `int` | - | | `total_output_audio_tokens` | `int` | - | | `total_output_audio_duration_ms` | `int` | - | | `total_duration_ms` | `int` | - | | `num_requests` | `list[int]` | - | | `input_text_tokens` | `list[int]` | - | | `input_audio_tokens` | `list[int]` | - | | `input_audio_duration_ms` | `list[int]` | - | | `output_text_tokens` | `list[int]` | - | | `output_audio_tokens` | `list[int]` | - | | `output_audio_duration_ms` | `list[int]` | - | | `duration_ms` | `list[int]` | - | *** ## Voice A cloned Text-to-Speech voice created from a reference audio clip. ### Properties | Property | Type | Description | | ------------ | ------------------ | ---------------------------------------------------- | | `id` | `str` | Unique identifier of the voice. | | `name` | `str` | Name of the voice, unique within the project. | | `filename` | `str` | Original file name of the uploaded reference clip. | | `created_at` | `datetime` | UTC timestamp indicating when the voice was created. | | `models` | `list[VoiceModel]` | Voice readiness status for each available model. | *** ## VoiceModel Per-model readiness status of a voice. ### Properties | Property | Type | Description | | --------------- | ------------------ | ------------------------------------------------------------------------ | | `model` | `str` | Name of the model. | | `status` | `VoiceModelStatus` | Has to be 'ready' for the voice to be usable with this model. | | `error_type` | `str \| None` | Machine-readable error category when status is 'failed'; None otherwise. | | `error_message` | `str \| None` | Human-readable error message when status is 'failed'; None otherwise. | *** ## VoiceModelStatus ```python VoiceModelStatus = Literal["not_computed", "processing", "ready", "failed"] ``` Readiness of a voice for a given model. Must be 'ready' to use the voice with that model. *** ## RealtimeEvent Event payload received from the realtime STT websocket. ### Properties | Property | Type | Description | | --------------------- | ------------- | -------------------------------------------------- | | `tokens` | `list[Token]` | Tokens in this result. | | `final_audio_proc_ms` | `int \| None` | Milliseconds of audio that have been finalized. | | `total_audio_proc_ms` | `int \| None` | Total milliseconds of audio processed. | | `finished` | `bool` | Whether this is the final result (session ending). | | `error_code` | `int \| None` | Error code if the realtime operation failed. | | `error_message` | `str \| None` | Human-readable description of the error. | ### validate\_event() ```python validate_event(raw: str | bytes) -> RealtimeEvent ``` **Parameters** | Parameter | Type | Description | | --------- | -------------- | ---------------------------------------- | | `raw` | `str \| bytes` | Raw event payload from the realtime API. | **Returns** `RealtimeEvent` *** ## RealtimeSTTConfig Configuration for initiating a realtime transcription session. ### Properties | Property | Type | Description | | ----------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model` | `str` | Speech-to-text model to use. | | `audio_format` | `RealtimeSTTAudioFormat` | Audio format. Use 'auto' for automatic detection of container formats. | | `num_channels` | `int \| None` | Number of audio channels (required for raw audio formats). | | `sample_rate` | `int \| None` | Sample rate in Hz (required for PCM formats). | | `language_hints` | `list[LanguageCode] \| None` | Expected languages in the audio (ISO language codes). | | `language_hints_strict` | `bool \| None` | When true, recognition is strongly biased toward language hints (best results when using one language in language\_hints). | | `context` | `StructuredContextInput \| None` | Additional context to improve transcription accuracy. | | `enable_speaker_diarization` | `bool \| None` | Enable speaker identification. | | `enable_language_identification` | `bool \| None` | Enable automatic language detection. | | `enable_endpoint_detection` | `bool \| None` | Enable endpoint detection for utterance boundaries. | | `max_endpoint_delay_ms` | `int \| None` | Maximum delay between the end of speech and returned endpoint. Allowed values for maximum delay are between 500ms and 3000ms. The default value is 2000ms | | `endpoint_sensitivity` | `float \| None` | Adjusts how likely the model is to emit an endpoint. Higher values make endpoints more likely (finalizing sooner); lower values make them less likely. Allowed values are between -1.0 and 1.0; the default is 0.0. Introduced in the Soniox v5 model; earlier models reject it. | | `endpoint_latency_adjustment_level` | `int \| None` | Fine-tunes the latency/accuracy trade-off of endpoint detection. Allowed values are integers from 0 to 3. | | `translation` | `TranslationConfigInput \| None` | Translation configuration. | | `client_reference_id` | `str \| None` | Optional tracking identifier (max 256 chars). | *** ## RealtimeTTSConfig Configuration for initiating a realtime Text-to-Speech stream. ### Properties | Property | Type | Description | | ------------------- | ----------------------- | -------------------------------------------------------------------------------------- | | `stream_id` | `str` | Client stream identifier unique among active streams on a connection. | | `model` | `str` | Text-to-Speech model to use. | | `language` | `str` | Language code for Text-to-Speech (e.g., "en"). | | `voice` | `str` | Voice identifier to generate speech audio with. | | `audio_format` | `TtsAudioFormat` | Requested output audio format. | | `sample_rate` | `TtsSampleRate \| None` | Output sample rate in Hz. | | `bitrate` | `TtsBitrate \| None` | Output bitrate in bits-per-second for compressed formats. | | `speed` | `float \| None` | Speaking rate multiplier from 0.7 to 1.3; 1.0 (default) is normal speed. | | `reduce_silence` | `bool \| None` | Shorten the pauses between words. Only for models with 'supports\_silence\_reduction'. | | `return_timestamps` | `bool \| None` | Request character-to-audio timestamps on response events. Defaults to false. | *** ## RealtimeTTSEvent Event payload received from the realtime Text-to-Speech websocket. ### Properties | Property | Type | Description | | --------------- | ----------------------- | ----------------------------------------------------------------------------- | | `stream_id` | `str \| None` | Stream identifier associated with this event. | | `audio` | `str \| None` | Base64 encoded audio chunk, when present. | | `audio_end` | `bool` | Whether this event contains the last audio payload for the stream. | | `terminated` | `bool` | Whether the stream has been fully terminated. | | `error_code` | `int \| None` | Error code if the Text-to-Speech stream failed. | | `error_message` | `str \| None` | Human-readable error message. | | `timestamps` | `TtsTimestamps \| None` | Character-to-audio alignment for this chunk, when `return_timestamps` is set. | ### validate\_event() ```python validate_event(raw: str | bytes) -> RealtimeTTSEvent ``` **Parameters** | Parameter | Type | Description | | --------- | -------------- | ---------------------------------------- | | `raw` | `str \| bytes` | Raw event payload from the realtime API. | **Returns** `RealtimeTTSEvent` *** ### audio\_bytes() ```python audio_bytes() -> bytes | None ``` Decode and return the audio bytes for this event, if present. **Returns** `bytes | None` *** ## RealtimeTTSTextMessage Text chunk message sent over realtime Text-to-Speech websocket. ### Properties | Property | Type | Description | | ----------- | ------ | --------------------------------------------------------------- | | `text` | `str` | Text chunk to generate into speech. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | | `stream_id` | `str` | Stream identifier the chunk belongs to. | *** ## TtsTimestamps Character-to-audio alignment attached to realtime Text-to-Speech events. The three arrays are parallel and equal-length: each index maps one character of the (preprocessed) spoken text to the audio span that pronounces it. ### Properties | Property | Type | Description | | ------------------------------- | ------------- | --------------------------------------------------------------- | | `characters` | `list[str]` | One entry per character (Unicode codepoint) of the spoken text. | | `character_start_times_seconds` | `list[float]` | Start time of each character, in seconds. | | `character_end_times_seconds` | `list[float]` | End time of each character, in seconds. | *** ## Headers ```python Headers = Mapping[str, str] ``` *** ## WebhookAuthConfig Configuration for webhook authentication headers. ### Properties | Property | Type | Description | | -------- | ----- | --------------------------------------------------- | | `name` | `str` | Expected header name (case-insensitive comparison). | | `value` | `str` | Expected header value (exact match). | *** ## WebhookEvent Basic webhook event metadata. ### Properties | Property | Type | Description | | -------- | ------------------------------- | ---------------------------- | | `id` | `str` | Transcription ID (UUID). | | `status` | `Literal['completed', 'error']` | Transcription result status. | # Helpers URL: /sdk/python-SDK/Full-SDK-reference/utils Soniox Python SDK - Helper Functions Reference *** ## output\_file\_for\_audio\_format() ```python output_file_for_audio_format(audio_format: str, prefix: str) -> Path ``` Build an output file path with the correct extension for the audio format. **Parameters** | Parameter | Type | Description | | -------------- | ----- | ------------------------------------------------------------------------------------------------------------- | | `audio_format` | `str` | Audio format name (e.g. `"wav"`, `"mp3"`, `"pcm_s16le"`). | | `prefix` | `str` | Filename prefix without extension. The chosen extension is appended to this prefix to form the returned path. | **Returns** `Path` *** ## render\_tokens() ```python render_tokens(final_tokens: list[Token], non_final_tokens: list[Token]) -> str ``` Build a human-friendly transcript from token metadata. **Parameters** | Parameter | Type | Description | | ------------------ | ------------- | ---------------------------------------------------------------- | | `final_tokens` | `list[Token]` | Token metadata emitted during realtime streaming transcriptions. | | `non_final_tokens` | `list[Token]` | Token metadata emitted during realtime streaming transcriptions. | **Returns** `str` *** ## start\_audio\_thread() ```python start_audio_thread(session: RealtimeSTTSession, chunks: bytes | Iterator[bytes], *, name: str | None = None, daemon: bool = True) -> threading.Thread ``` Stream audio into the session on a background thread. **Parameters** | Parameter | Type | Description | | --------- | -------------------------- | --------------------------------------------------------------------------- | | `session` | `RealtimeSTTSession` | Synchronous WebSocket session for a single real-time speech-to-text stream. | | `chunks` | `bytes \| Iterator[bytes]` | Audio chunks to stream to realtime transcription. | | `name` | `str \| None` | Name of the model. | | `daemon` | `bool` | - | **Returns** `threading.Thread` *** ## start\_text\_thread() ```python start_text_thread(session: RealtimeTTSConnection | RealtimeTTSStream, chunks: str | Iterator[str], *, text_end: bool = True, name: str | None = None, daemon: bool = True) -> threading.Thread ``` Stream text into a realtime TTS session on a background thread. **Parameters** | Parameter | Type | Description | | ---------- | -------------------------------------------- | ------------------------------------------------------------------------ | | `session` | `RealtimeTTSConnection \| RealtimeTTSStream` | Synchronous WebSocket connection for one realtime Text-to-Speech stream. | | `chunks` | `str \| Iterator[str]` | Audio chunks to stream to realtime transcription. | | `text_end` | `bool` | Whether this message marks the final text chunk for the stream. | | `name` | `str \| None` | Name of the model. | | `daemon` | `bool` | - | **Returns** `threading.Thread` *** ## stream\_audio() ```python stream_audio(file: Path | str | BinaryIO | bytes, *, chunk_size_bytes: int = 4 * 1024) -> Iterator[bytes] ``` Yield fixed-size chunks from an audio source. Supports bytes, file paths, or binary streams and slices them into `chunk_size_bytes` blocks for realtime transmission. **Parameters** | Parameter | Type | Description | | ------------------ | ---------------------------------- | ----------------------------------- | | `file` | `Path \| str \| BinaryIO \| bytes` | File input to upload or transcribe. | | `chunk_size_bytes` | `int` | - | **Returns** `Iterator[bytes]` *** ## stream\_audio\_async() ```python stream_audio_async(file: Path | str | BinaryIO | bytes, *, chunk_size_bytes: int = 4 * 1024) -> AsyncIterator[bytes] ``` Asynchronously yield fixed-size chunks from an audio source. Mirrors `stream_audio` but produces an async iterator for later consumption. **Parameters** | Parameter | Type | Description | | ------------------ | ---------------------------------- | ----------------------------------- | | `file` | `Path \| str \| BinaryIO \| bytes` | File input to upload or transcribe. | | `chunk_size_bytes` | `int` | - | **Returns** `AsyncIterator[bytes]` *** ## throttle\_audio() ```python throttle_audio(file: Path | str | BinaryIO | bytes, *, chunk_size_bytes: int = 4096, delay_seconds: float = 0.0) -> Iterator[bytes] ``` Yield audio chunks at a regulated pace, optionally sleeping between yields. **Parameters** | Parameter | Type | Description | | ------------------ | ---------------------------------- | ----------------------------------- | | `file` | `Path \| str \| BinaryIO \| bytes` | File input to upload or transcribe. | | `chunk_size_bytes` | `int` | - | | `delay_seconds` | `float` | - | **Returns** `Iterator[bytes]` *** ## throttle\_audio\_async() ```python throttle_audio_async(file: Path | str | BinaryIO | bytes, *, chunk_size_bytes: int = 32 * 1024, delay_seconds: float = 0.0) -> AsyncIterator[bytes] ``` Async counterpart of `throttle_audio`, yielding chunks with optional delay. **Parameters** | Parameter | Type | Description | | ------------------ | ---------------------------------- | ----------------------------------- | | `file` | `Path \| str \| BinaryIO \| bytes` | File input to upload or transcribe. | | `chunk_size_bytes` | `int` | - | | `delay_seconds` | `float` | - | **Returns** `AsyncIterator[bytes]` # Python SDK URL: /sdk/python-SDK Python SDK for Soniox REST and realtime APIs. Soniox [Python SDK](https://github.com/soniox/soniox-python) gives you fully typed access to our Speech-to-Text and Text-to-Speech REST and realtime APIs. ## Quickstart ### Install ```bash pip install soniox ``` ### Set your API key ```bash export SONIOX_API_KEY= ``` Create a [Soniox account](https://console.soniox.com/signup) and log in to the [Console](https://console.soniox.com) to get your API key. ### Create your first real-time Speech-to-Text session ```python from soniox import SonioxClient from soniox.types import RealtimeSTTConfig, Token from soniox.utils import render_tokens, throttle_audio, start_audio_thread # Grab the demo file from: # https://github.com/soniox/soniox_examples/raw/refs/heads/master/speech_to_text/assets/coffee_shop.mp3 AUDIO_FILE = "coffee_shop.mp3" client = SonioxClient() config = RealtimeSTTConfig(model="stt-rt-v5", audio_format="mp3") final_tokens: list[Token] = [] non_final_tokens: list[Token] = [] def realtime(): # Create new real-time websocket session with client.realtime.stt.connect(config=config) as session: # Stream audio to websocket start_audio_thread(session, throttle_audio(AUDIO_FILE, delay_seconds=0.1)) # Receive events from Soniox Real-time STT for event in session.receive_events(): for token in event.tokens: if token.is_final: final_tokens.append(token) else: non_final_tokens.append(token) print(render_tokens(final_tokens, non_final_tokens)) non_final_tokens.clear() realtime() ``` Learn more about [Real-time transcription](/sdk/python-SDK/stt/realtime-transcription). ### Create your first async Speech-to-Text transcription ```python from soniox import SonioxClient client = SonioxClient() # Create new transcription from `audio_url` transcription = client.stt.transcribe( audio_url="https://soniox.com/media/examples/coffee_shop.mp3", ) # Wait until transcription processing is finished client.stt.wait(transcription.id) # Get transcription transcript and print it transcript = client.stt.get_transcript(transcription.id) print(transcript.text) ``` Learn more about [Async transcription](/sdk/python-SDK/stt/async-transcription). ### Create your first REST Text-to-Speech generation ```python from soniox import SonioxClient client = SonioxClient() written = client.tts.generate_to_file( "hello.wav", text="Hello from Soniox Python SDK text-to-speech.", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) print(f"Wrote {written} bytes") ``` Learn more about [REST speech generation](/sdk/python-SDK/tts/rest-speech-generation). ### Create your first real-time Text-to-Speech session ```python from uuid import uuid4 from soniox import SonioxClient from soniox.types import RealtimeTTSConfig client = SonioxClient() config = RealtimeTTSConfig( stream_id=f"tts-{uuid4()}", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) audio_chunks: list[bytes] = [] with client.realtime.tts.connect(config=config) as session: session.send_text_chunks(["Hello from Soniox real-time TTS."], terminate=True) for chunk in session.receive_audio_chunks(): audio_chunks.append(chunk) with open("hello-realtime.wav", "wb") as f: f.write(b"".join(audio_chunks)) ``` Learn more about [Real-time speech generation](/sdk/python-SDK/tts/realtime-speech-generation). ## Next steps * [REST speech generation](/sdk/python-SDK/tts/rest-speech-generation) * [Real-time speech generation](/sdk/python-SDK/tts/realtime-speech-generation) * [Real-time streaming](/sdk/python-SDK/stt/realtime-transcription) * [Async transcription](/sdk/python-SDK/stt/async-transcription) * [Webhooks](/sdk/python-SDK/stt/webhooks) * [Files and models](/sdk/python-SDK/stt/files) * [Sync vs async clients](/sdk/python-SDK/sync-vs-async-clients) ## Package links * [GitHub repository](https://github.com/soniox/soniox-python) * [PyPi package](https://pypi.org/project/soniox/) # Async transcription with Python SDK URL: /sdk/python-SDK/stt/async-transcription Transcribe audio files asynchronously with the Soniox Python SDK Soniox Python SDK supports asynchronous transcription for audio files. This allows you to transcribe recordings without maintaining a live connection or streaming pipeline. You can either wait for completion or create a job and retrieve the results based on the webhook event. ## Quickstart The SDK provides a convenient `transcribe` method that accepts a local file, public URL, or previously uploaded file ID. It will upload the file (if provided) and create the transcription job. Don't forget to remove files and transcriptions from Soniox after you're done with them. I am working on SDK and docs now, after finishing it, I will do a few minor updates (as I proceed with docs, probably will find somethin else): 1. service: GET /v1/models should respect model type (stt or tts) 2. asr-lb: POST /tts should return the same structure of error response, ass stt ```python from soniox import SonioxClient client = SonioxClient() # Transcribe from a local file transcription = client.stt.transcribe( model="stt-async-v5", file="audio.mp3", ) # Transcribe from a public URL and fetch the transcript later transcription = client.stt.transcribe( model="stt-async-v5", audio_url="https://soniox.com/media/examples/coffee_shop.mp3", ) # Transcribe from a previously uploaded file transcription = client.stt.transcribe( model="stt-async-v5", file_id="uploaded-file-id", ) ``` After creating the job, you can poll the status with `client.stt.get` or wait for completion with `client.stt.wait`. To get the final transcript, call `client.stt.get_transcript`. ```python # Check status transcription = client.stt.get("transcription-id") print(transcription.status) # Wait for completion client.stt.wait("transcription-id") # Fetch transcript transcript = client.stt.get_transcript("transcription-id") print(transcript.text) ``` Don't forget to delete files and transcriptions from Soniox after you're done with them. ## Get transcription You can get a transcription by ID using `get` method. ```python transcription = client.stt.get("transcription-id") print(transcription.id, transcription.status) ``` Get a transcription or return `None` if it doesn't exist: ```python transcription = client.stt.get_or_none("transcription-id") if transcription is None: print("Transcription not found") ``` ## Get transcription transcript If you want to receive text or tokens from a transcription, fetch the transcription transcript with `get_transcript`. ```python transcript = client.stt.get_transcript("transcription-id") print(transcript.text) ``` ## Retrieve list of transcriptions You can retrieve a list of transcriptions using `list` method. ```python from soniox import SonioxClient client = SonioxClient() response = client.stt.list(limit=100) for transcription in response.transcriptions: print(transcription.id, transcription.status) # Use pagination to list more transcriptions while response.next_page_cursor: response = client.stt.list( limit=100, cursor=response.next_page_cursor, ) for transcription in response.transcriptions: print(transcription.id, transcription.status) ``` ## Delete or destroy transcription You can delete or destroy a transcription using `delete` or `destroy` method. **Delete transcription only:** ```python client.stt.delete("transcription-id") ``` **Delete a transcription only if it exists:** ```python client.stt.delete_if_exists("transcription-id") ``` **Delete transcription and its file if it was uploaded:** ```python client.stt.destroy("transcription-id") ``` ## Delete all transcriptions and files from your account You have limited space for files and transcriptions, see: [Limits and quotas](/stt/async/limits-and-quotas). These operations are irreversible and cannot be undone. ### Delete all transcriptions You can delete all transcriptions using `transcriptions.delete_all`. ```python client.stt.delete_all() ``` ### Delete all files You can delete all files using `files.delete_all`. ```python client.files.delete_all() ``` ### Delete all transcriptions and its files You can delete all transcriptions and its files (if it exist) using `files.destroy_all`. ```python client.files.destroy_all() ``` # Handling files with Python SDK URL: /sdk/python-SDK/stt/files Upload audio files and manage them with the Soniox Python SDK Use the Files API to upload audio for async transcription or to reuse files across multiple jobs. ## Upload `upload()` accepts `bytes`, file paths (`str` or `Path`), or a file-like object (`BinaryIO`). ```python from soniox import SonioxClient client = SonioxClient() file = client.files.upload("audio.mp3") print(file.id, file.filename, file.size) ``` Read more about [Supported audio formats](/stt/async/async-transcription#audio-formats). ## Get file Get a file by ID, throws `SonioxNotFoundError` if file does not exist: ```python file = client.files.get("file-id") print(file.id, file.filename) ``` Get file or none: ```python file = client.files.get_or_none("file-id") if file is None: print("File not found") ``` ## List files List files returns a paginated response. Use `next_page_cursor` to fetch additional pages until it is `None`. ```python from soniox import SonioxClient client = SonioxClient() response = client.files.list(limit=100) for file in response.files: print(file.id, file.filename) # Pagination while response.next_page_cursor: response = client.files.list(limit=100, cursor=response.next_page_cursor) for file in response.files: print(file.id, file.filename) ``` ## Delete file Delete file by ID, throws `SonioxNotFoundError` if file does not exist: ```python client.files.delete("file-id") ``` Delete file only if exists: ```python client.files.delete_if_exists("file-id") ``` ## Delete all files Delete all files iterates through every page and removes each file. ```python client.files.delete_all() ``` # Real-time transcription with Python SDK URL: /sdk/python-SDK/stt/realtime-transcription Create and connect to Soniox real-time speech-to-text sessions with the Python SDK Soniox Python SDK supports transcribing audio in real-time with **low latency** and **high accuracy**. This makes it ideal for voice assistants, live captions, and conversational AI. ## Connect to a real-time session Example below streams audio from live radio to the Soniox real-time API. If you want to stream from a file instead, see: [Create your first real-time session](/sdk/python-SDK#create-your-first-real-time-speech-to-text-session). ```python from typing import Iterator from soniox import SonioxClient from soniox.types import ( RealtimeSTTConfig, Token, StructuredContext, StructuredContextGeneralItem, ) from soniox.utils import render_tokens, start_audio_thread import httpx AUDIO_URL = "https://npr-ice.streamguys1.com/live.mp3?ck=1742897559135" # Fetch audio from a live radio stream and yield it in chunks. def stream_audio_from_url(audio_url) -> Iterator[bytes]: with httpx.Client() as client: with client.stream("GET", audio_url) as response: response.raise_for_status() for chunk in response.iter_bytes(4096): if chunk: yield chunk client = SonioxClient() # Create config, see below for all parameters config = RealtimeSTTConfig( model="stt-rt-v5", audio_format="mp3", enable_endpoint_detection=True, enable_speaker_diarization=True, language_hints=["en"], context=StructuredContext( general=[StructuredContextGeneralItem(key="domain", value="live radio / news broadcast")], text="Live NPR news and talk radio stream, including interviews, music, and commentary.", terms=["NPR", "news", "interview", "music", "commentary", "report", "broadcast", "anchor"], ), ) final_tokens: list[Token] = [] non_final_tokens: list[Token] = [] def realtime(): # Create new real-time websocket session with client.realtime.stt.connect(config=config) as session: # Stream audio from live radio to websocket start_audio_thread(session, stream_audio_from_url(AUDIO_URL)) # Receive events from Soniox Real-time STT for event in session.receive_events(): for token in event.tokens: if token.is_final: final_tokens.append(token) else: non_final_tokens.append(token) print(render_tokens(final_tokens, non_final_tokens)) non_final_tokens.clear() realtime() ``` For config options see: [WebSocket API](/api-reference/stt/websocket-api#configuration) or [RealtimeSTTConfig reference](/sdk/python-SDK/Full-SDK-reference/types#realtimesttconfig-properties). ## Endpoint detection Endpoint detection lets you know when a speaker has finished speaking. This is critical for real-time voice AI assistants, command-and-response systems, and conversational apps where you want to respond immediately without waiting for long silences. Read more about [Endpoint detection](/stt/rt/endpoint-detection) Enable endpoint detection by setting `enable_endpoint_detection=True` in the session config. You will receive special token `` when speech ends. ```python # Enable endpoint detection config = RealtimeSTTConfig( enable_endpoint_detection=True, ... ) # When receiving events, check for special token for event in session.receive_events(): for token in event.tokens: if token.text == "": print("Endpoint detected") ``` ## Manual finalization Manual finalization gives you precise control over when audio should be finalized. When you know the user stopped talking (push-to-talk or client-side VAD), call `finalize` to mark all outstanding tokens as final. Read more about [Manual finalization](/stt/rt/manual-finalization) ```python # Finalize current buffered audio without closing the session. session.finalize() ``` ## Pause and resume ```python session.pause(); // keeps connection alive, drops audio while paused session.resume(); // resume sending audio ``` You are billed for the full stream duration even when session is paused. ## Keepalive Soniox terminates your session if no audio arrives for \~20 seconds. To keep the connection alive, send a keepalive control message or run a background keepalive loop. Python SDK **automatically sends** keepalive messages when session is paused via `session.pause()`. ```python # Sends keepalive message manually session.keep_alive() ``` Read more about [Connection keepalive](/stt/rt/connection-keepalive) ## Streaming audio from a file Use `stream_audio()` with `start_audio_thread()` to stream from a file while receiving events. If you are streaming live audio (microphone, client stream, etc.), you can feed raw chunks without throttling. If you are streaming a prerecorded file, throttle chunks to simulate real-time delivery. ```python from soniox.utils import stream_audio, start_audio_thread, throttle_audio ... with client.realtime.stt.connect(config=config) as session: # Start streaming audio on a background thread. start_audio_thread(session, stream_audio("audio.wav")) # Or throttle local audio file to simulate streaming (sends chunk every 100 ms) start_audio_thread(session, throttle_audio("audio.wav", delay_seconds=0.1)) ... ``` Use [`send_bytes`](/sdk/python-SDK/Full-SDK-reference/realtime_client#send_bytes) if you need more control ## Direct stream and proxy stream Read more about [Direct stream](/guides/direct-stream) and [Proxy stream](/guides/proxy-stream). For direct streaming from a client, issue a temporary API key and pass it to the browser or device that will open the WebSocket connection. `client_reference_id` is optional — when set, every request authenticated with the key is recorded under that identifier in [usage logs](/guides/usage-logs). ```python from soniox import SonioxClient client = SonioxClient() key = client.auth.create_temporary_api_key( expires_in_seconds=3600, client_reference_id="support-call-123", ) print(key.api_key, key.expires_at) ``` For proxy streaming, keep the WebSocket connection on your server and stream audio through your backend. # Handling webhooks with Python SDK URL: /sdk/python-SDK/stt/webhooks Use webhooks to receive transcription results with the Soniox Python SDK Python SDK provides helper functions to work with [Webhooks](/stt/async/webhooks). ## Configure webhook delivery If webhook is enabled during transcription creation, Soniox will send a POST request to your webhook URL with the [transcription status result](/stt/async/webhooks#example). ```python from soniox import SonioxClient from soniox.types import CreateTranscriptionConfig client = SonioxClient() config = CreateTranscriptionConfig( webhook_url="https://your-server.com/webhooks/soniox", webhook_auth_header_name="X-Webhook-Secret", webhook_auth_header_value="your-secret", ) transcription = client.stt.transcribe( audio_url="https://soniox.com/media/examples/coffee_shop.mp3", config=config, ) ``` For `transcribe`, you must pass `webhook_auth_header_name` and `webhook_auth_header_value` explicitly in the config. Environment variables (`SONIOX_API_WEBHOOK_HEADER` and `SONIOX_API_WEBHOOK_SECRET`) are only used by webhook helpers and verification (see below). You can also append additional metadata as query parameters: ```python config = CreateTranscriptionConfig( webhook_url="https://your-server.com/webhooks/soniox?request_id=abc-123", ) ``` If you are uploading a local file, you can also use the convenience helper (reads webhook secret and header automatically from environment if present): ```python from soniox import SonioxClient from soniox.types import WebhookAuthConfig client = SonioxClient() transcription = client.stt.transcribe_file_with_webhook( model="stt-async-v5", file="audio.mp3", webhook_url="https://your-server.com/webhooks/soniox", ) ``` ## Example (FastAPI + ngrok) Expose your local server (for example with [ngrok](https://ngrok.com/)), then create a transcription that points to the public ngrok URL and verify the webhook payload on your FastAPI server: ```python from fastapi import FastAPI, Request from soniox import SonioxClient from soniox.errors import InvalidWebhookSignatureError from soniox.types import CreateTranscriptionConfig, WebhookAuthConfig app = FastAPI() client = SonioxClient() # Replace with your public ngrok URL. NGROK_URL = "https://your-subdomain.ngrok-free.app" WEBHOOK_SECRET_NAME = "X-Webhook-Secret" WEBHOOK_SECRET_VALUE = "your-secret" # When creating transcript you must provide correct webhook secret name and value # config = CreateTranscriptionConfig( # webhook_url=f"{NGROK_URL}/webhooks/soniox", # webhook_auth_header_name=WEBHOOK_SECRET_NAME, # webhook_auth_header_value=WEBHOOK_SECRET_VALUE, # ) # client.stt.transcribe( # model="stt-async-v5", # audio_url="https://soniox.com/media/examples/coffee_shop.mp3", # config=config, # ) @app.post("/webhooks/soniox") async def soniox_webhook(request: Request): payload = await request.body() headers = dict(request.headers) try: event = client.webhooks.unwrap( payload, headers, # This can be omitted if you have set env variables SONOIX_API_WEBHOOK_SECRET and SONIOX_API_WEBHOOK_HEADER auth=WebhookAuthConfig( name=WEBHOOK_SECRET_NAME, value=WEBHOOK_SECRET_VALUE, ), ) except InvalidWebhookSignatureError: print("InvalidWebhookSignatureError") return if event.status == "completed": transcript = client.stt.get_transcript(event.id) print(transcript.text) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8080) ``` ## Webhook verification Verify webhook signatures to ensure the request really came from Soniox (and not a third party posting to your endpoint). You can verify signatures manually: ```python from soniox import SonioxClient from soniox.types import WebhookAuthConfig client = SonioxClient() client.webhooks.verify_signature( headers={"X-Webhook-Secret": "your-secret"}, ) ``` Or rely on `unwrap` to validate and parse in one step: ```python from soniox import SonioxClient from soniox.types import WebhookAuthConfig client = SonioxClient() event = client.webhooks.unwrap( payload=request_body, headers={"X-Webhook-Secret": "your-secret"}, ) print(event.id, event.status) ``` If you prefer, you can also use `client.stt.transcribe_file_with_webhook` and `client.webhooks` with `SONIOX_API_WEBHOOK_HEADER` and `SONIOX_API_WEBHOOK_SECRET` set in your environment. # Sync vs async clients URL: /sdk/python-SDK/sync-vs-async-clients Choose between SonioxClient and AsyncSonioxClient based on your app. Soniox Python SDK provides two clients. * `SonioxClient` for synchronous code (scripts, CLIs, simple services) * `AsyncSonioxClient` for asyncio apps (FastAPI, aiohttp, background workers) The `files`, `stt`, `tts`, `models`, `auth`, `webhooks`, and `realtime` APIs accept the same parameters and return the same types in both clients. ## Speech-to-text examples ### Sync client (`SonioxClient`) ```python from soniox import SonioxClient client = SonioxClient() file = client.files.upload("audio.mp3") transcription = client.stt.transcribe( audio_url="https://soniox.com/media/examples/coffee_shop.mp3" ) print(file.id, transcription.id) ``` ### Async client (`AsyncSonioxClient`) ```python import asyncio from soniox import AsyncSonioxClient async def main(): client = AsyncSonioxClient() file = await client.files.upload("audio.mp3") transcription = await client.stt.transcribe( audio_url="https://soniox.com/media/examples/coffee_shop.mp3" ) print(file.id, transcription.id) await client.aclose() asyncio.run(main()) ``` ## Text-to-speech examples ### Sync client (`SonioxClient`) ```python from soniox import SonioxClient client = SonioxClient() written = client.tts.generate_to_file( "./audio.wav", text="Hello from Soniox!", voice="Adrian", ) print(f"Wrote {written} bytes.") ``` ### Async client (`AsyncSonioxClient`) ```python import asyncio from soniox import AsyncSonioxClient async def main() -> None: client = AsyncSonioxClient() written = await client.tts.generate_to_file( "./audio.wav", text="Hello from Soniox!", voice="Adrian", ) print(f"Wrote {written} bytes.") await client.aclose() asyncio.run(main()) ``` # Real-time speech generation with Python SDK URL: /sdk/python-SDK/tts/realtime-speech-generation Convert text to speech with the Python SDK Soniox Python SDK supports real-time Text-to-Speech generation with low latency streaming output. You send text chunks over WebSocket and receive audio chunks as they are generated. ## Connect to a real-time session ```python from uuid import uuid4 from soniox import SonioxClient from soniox.types import RealtimeTTSConfig TEXT_CHUNKS = [ "This is a test of Soniox real-time text to speech. ", "Audio is streamed back as it is generated. ", "Each chunk is sent as soon as it is ready.", ] client = SonioxClient() config = RealtimeTTSConfig( stream_id=f"sync-{uuid4()}", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) audio_chunks: list[bytes] = [] with client.realtime.tts.connect(config=config) as session: session.send_text_chunks(TEXT_CHUNKS, text_end=True) for chunk in session.receive_audio_chunks(): audio_chunks.append(chunk) audio = b"".join(audio_chunks) with open("tts_realtime_sync_output.wav", "wb") as f: f.write(audio) print(f"Wrote {len(audio)} bytes") print("Captured final message:", session.last_message) ``` For config options see: [TTS WebSocket API](/api-reference/tts/websocket-api) and [RealtimeTTSConfig reference](/sdk/python-SDK/Full-SDK-reference/types#realtimettsconfig-properties). ## Async real-time session ```python import asyncio from collections.abc import AsyncIterator from uuid import uuid4 from soniox import AsyncSonioxClient from soniox.types import RealtimeTTSConfig TEXT_CHUNKS = [ "This is a test of Soniox real-time text to speech. ", "Audio is streamed back as it is generated. ", "Each chunk is sent as soon as it is ready.", ] async def iter_text_chunks(chunks: list[str]) -> AsyncIterator[str]: for chunk in chunks: yield chunk async def main() -> None: client = AsyncSonioxClient() config = RealtimeTTSConfig( stream_id=f"async-{uuid4()}", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) audio_chunks: list[bytes] = [] async with client.realtime.tts.connect(config=config) as session: await session.send_text_chunks(iter_text_chunks(TEXT_CHUNKS), text_end=True) async for chunk in session.receive_audio_chunks(): audio_chunks.append(chunk) audio = b"".join(audio_chunks) with open("tts_realtime_async_output.wav", "wb") as f: f.write(audio) print(f"Wrote {len(audio)} bytes") print("Captured final message:", session.last_message) await client.aclose() asyncio.run(main()) ``` ## Send text incrementally Use `send_text_chunk` when text arrives dynamically (for example from an LLM stream). Set `text_end=True` on the final chunk, or call `finish()`. ```python with client.realtime.tts.connect(config=config) as session: session.send_text_chunk("Hello ", text_end=False) session.send_text_chunk("from Soniox ", text_end=False) session.send_text_chunk("real-time TTS.", text_end=True) ``` Equivalent explicit finalization: ```python with client.realtime.tts.connect(config=config) as session: session.send_text_chunk("Hello from Soniox real-time TTS.", text_end=False) session.finish() ``` ## Receive events vs audio chunks `receive_audio_chunks()` yields decoded audio bytes directly and stops after finalization. Use `receive_events()` when you want access to raw event metadata like `audio_end`, `terminated`, and errors. ```python with client.realtime.tts.connect(config=config) as session: session.send_text_chunk("Hello!", text_end=True) for event in session.receive_events(): if event.audio is not None: print("Audio chunk received") if event.audio_end: print("Server marked final audio payload") if event.terminated: print("Stream terminated") break ``` ## Multiple streams on one connection A single WebSocket connection can carry up to 5 concurrent streams. Use `connect_multi_stream()` to open a multiplexed connection, then call `open_stream()` for each stream. Each stream has its own `stream_id` and operates independently — you can send text and receive audio on all streams in parallel. ### Async multi-stream ```python import asyncio from collections.abc import AsyncIterator from uuid import uuid4 from soniox import AsyncSonioxClient from soniox.types import RealtimeTTSConfig STREAM_TEXTS = { "a": ["Hello from stream A. ", "Stream A shares a connection with B. ", "Goodbye from A."], "b": ["Hello from stream B. ", "Stream B shares a connection with A. ", "Goodbye from B."], } async def iter_text(chunks: list[str]) -> AsyncIterator[str]: for chunk in chunks: yield chunk async def collect_audio(stream) -> bytes: chunks: list[bytes] = [] async for chunk in stream.receive_audio_chunks(): chunks.append(chunk) return b"".join(chunks) async def main() -> None: client = AsyncSonioxClient() async with client.realtime.tts.connect_multi_stream() as connection: # Open two streams on the same WebSocket. streams = {} for key in STREAM_TEXTS: config = RealtimeTTSConfig( stream_id=f"multi-{key}-{uuid4()}", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) streams[key] = await connection.open_stream(config=config) # Start receiving audio from each stream concurrently. receiver_tasks = { key: asyncio.create_task(collect_audio(stream)) for key, stream in streams.items() } # Send text to each stream concurrently. sender_tasks = [ asyncio.create_task( stream.send_text_chunks(iter_text(STREAM_TEXTS[key]), text_end=True) ) for key, stream in streams.items() ] await asyncio.gather(*sender_tasks) # Wait for all audio to arrive. for key, task in receiver_tasks.items(): audio = await task with open(f"tts_multi_{key}.wav", "wb") as f: f.write(audio) print(f"Stream {key}: wrote {len(audio)} bytes") await client.aclose() asyncio.run(main()) ``` ### Sync multi-stream In synchronous code, use threads to send text and receive audio from each stream concurrently. ```python import threading from uuid import uuid4 from soniox import SonioxClient from soniox.types import RealtimeTTSConfig STREAM_TEXTS = { "a": ["Hello from stream A. ", "Stream A shares a connection with B. ", "Goodbye from A."], "b": ["Hello from stream B. ", "Stream B shares a connection with A. ", "Goodbye from B."], } def collect_audio(stream, results: dict, key: str) -> None: results[key] = b"".join(stream.receive_audio_chunks()) client = SonioxClient() with client.realtime.tts.connect_multi_stream() as connection: # Open two streams on the same WebSocket. streams = {} for key in STREAM_TEXTS: config = RealtimeTTSConfig( stream_id=f"multi-{key}-{uuid4()}", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) streams[key] = connection.open_stream(config=config) audio_results: dict[str, bytes] = {} # Start receiving audio from each stream in background threads. receivers = [] for key, stream in streams.items(): t = threading.Thread(target=collect_audio, args=(stream, audio_results, key)) t.start() receivers.append(t) # Send text to each stream (threads handle concurrent receiving). for key, stream in streams.items(): stream.send_text_chunks(STREAM_TEXTS[key], text_end=True) # Wait for all audio to arrive. for t in receivers: t.join() for key, audio in sorted(audio_results.items()): with open(f"tts_multi_{key}.wav", "wb") as f: f.write(audio) print(f"Stream {key}: wrote {len(audio)} bytes") client.close() ``` ## Error handling A failed stream does not close the whole WebSocket connection by default. Stream-level errors finalize only that stream (`terminated=True` for the same `stream_id`), while other streams on the same connection can continue. Connection-level failures end the whole connection and all streams. ```python from soniox.errors import SonioxRealtimeError try: with client.realtime.tts.connect(config=config) as session: session.send_text_chunk("Hello!", text_end=True) for _chunk in session.receive_audio_chunks(): pass except SonioxRealtimeError as exc: print("Realtime TTS error:", exc) ``` # REST speech generation with Python SDK URL: /sdk/python-SDK/tts/rest-speech-generation Convert text to speech with the Soniox Python SDK Soniox Python SDK supports asynchronous Text-to-Speech generation with `AsyncSonioxClient`. You can generate speech directly to audio bytes or write output to a file. ## Quickstart The SDK provides a convenient `generate_to_file` method for writing audio output directly to disk. ```python import asyncio from soniox import AsyncSonioxClient async def main() -> None: client = AsyncSonioxClient() try: written = await client.tts.generate_to_file( "tts_async_output.wav", text="Hello from the Soniox Python SDK async TTS example.", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) print(f"Wrote {written} bytes") finally: await client.aclose() asyncio.run(main()) ``` ## Generate to bytes Use `generate` when you want audio bytes in memory (for custom storage, streaming, or post-processing). ```python import asyncio from soniox import AsyncSonioxClient async def main() -> None: client = AsyncSonioxClient() try: audio = await client.tts.generate( text="This response is generated in memory.", model="tts-rt-v2", language="en", voice="Adrian", audio_format="wav", ) print(f"Received {len(audio)} bytes") finally: await client.aclose() asyncio.run(main()) ``` ## Generate to file Use `generate_to_file` when you want the SDK to write output for you. ```python import asyncio from soniox import AsyncSonioxClient async def main() -> None: client = AsyncSonioxClient() try: written = await client.tts.generate_to_file( "hello.pcm", text="Hello from Soniox async text to speech.", model="tts-rt-v2", language="en", voice="Adrian", audio_format="pcm_s16le", sample_rate=24000, ) print(f"Wrote {written} bytes") finally: await client.aclose() asyncio.run(main()) ``` ## Use typed config (`CreateTtsConfig`) You can pass generation options through `CreateTtsConfig`. ```python import asyncio from soniox import AsyncSonioxClient from soniox.types import CreateTtsConfig async def main() -> None: client = AsyncSonioxClient() try: written = await client.tts.generate_to_file( "typed-config.wav", text="Typed configuration example.", voice="Adrian", config=CreateTtsConfig( model="tts-rt-v2", language="en", audio_format="wav", sample_rate=24000, ), ) print(f"Wrote {written} bytes") finally: await client.aclose() asyncio.run(main()) ``` ## Error handling Handle `SonioxAPIError` to inspect API-level failures. For raw HTTP integration details, see [TTS REST API error handling](/api-reference/tts/generate_tts). ```python import asyncio from soniox import AsyncSonioxClient from soniox.errors import SonioxAPIError async def main() -> None: client = AsyncSonioxClient() try: await client.tts.generate_to_file( "error-case.wav", text="Hello from Soniox!", voice="Adrian", ) except SonioxAPIError as exc: print("Soniox API error:", exc) if exc.request_id: print("request_id:", exc.request_id) finally: await client.aclose() asyncio.run(main()) ``` # React SDK URL: /sdk/react-SDK Build speech-to-text and text-to-speech workflows in React with real-time APIs. import { LinkCards } from "@/components/link-card"; Soniox [React SDK](https://www.npmjs.com/package/@soniox/react) provides React hooks and components for real-time speech-to-text and text-to-speech, built on top of the [Web SDK](/sdk/web-SDK). It lets you: * Capture audio from the user's microphone with a single hook * Stream audio to Soniox in real time * Receive transcription and translation results as reactive state * Generate speech from text with a single `useTts` hook ## Quickstart ### Install Install via your preferred package manager: ```bash tab npm install @soniox/react ``` ```bash tab yarn add @soniox/react ``` ```bash tab pnpm add @soniox/react ``` ```bash tab bun add @soniox/react ``` ### Set up your temporary API key endpoint In client environment (browser, mobile app, React Native, etc.), you don't want to expose your API key to the client. For this reason, you can create a temporary API key endpoint on your server and use it to issue temporary API keys for the client. For example, you can use our [Node SDK](/sdk/node-SDK) to create a temporary API key endpoint. ```ts import express from 'express'; import { SonioxNodeClient } from '@soniox/node'; const app = express(); const client = new SonioxNodeClient(); // reads SONIOX_API_KEY from env // Create a temporary API key endpoint app.post('/tmp-key', async (_req, res) => { try { const { api_key, expires_at } = await client.auth.createTemporaryKey({ usage_type: 'transcribe_websocket', expires_in_seconds: 300, // 1..3600 }); res.json({ api_key, expires_at }); } catch (err) { res.status(500).json({ error: err instanceof Error ? err.message : 'Failed to create temporary key' }); } }); app.listen(3000, () => { console.log('Server listening on http://localhost:3000'); }); ``` Read more about our [Node SDK](/sdk/node-SDK) and [Temporary API keys](/guides/temporary-api-keys). ### Create your first real-time session ```tsx import { SonioxProvider, useRecording } from "@soniox/react"; // Fetch a temporary API key (and optional region / URL overrides) from your server async function fetchSttConfig() { const res = await fetch("/tmp-key", { method: "POST" }); const { api_key } = await res.json(); return { api_key }; } function App() { return ( // Wrap your app with a SonioxProvider and pass a config resolver ); } function Transcription() { // Create a recording session const { state, finalText, partialText, start, stop } = useRecording({ model: "stt-rt-v5", }); return (

{finalText} {partialText}

State: {state}

{state === "recording" || state === "connecting" || state === "starting" ? ( ) : ( )}
); } ``` Learn more about [Real-time transcription](/sdk/react-SDK/stt/realtime-transcription) ### Generate your first speech ```tsx import { useRef } from "react"; import { useTts } from "@soniox/react"; async function fetchTtsConfig() { // Your server should issue a temporary key with usage_type: 'tts_rt' const res = await fetch("/tts-tmp-key"); const { api_key } = await res.json(); return { api_key }; } function SpeakButton() { const audioRef = useRef([]); const { speak, isSpeaking } = useTts({ config: fetchTtsConfig, voice: "Adrian", audio_format: "wav", onAudio: (chunk) => audioRef.current.push(chunk), onTerminated: () => { const blob = new Blob(audioRef.current, { type: "audio/wav" }); new Audio(URL.createObjectURL(blob)).play(); audioRef.current = []; }, }); return ( ); } ``` Learn more about [Real-time speech generation](/sdk/react-SDK/tts/realtime-speech-generation). ## Next steps * [Real-time transcription](/sdk/react-SDK/stt/realtime-transcription) * [Real-time speech generation](/sdk/react-SDK/tts/realtime-speech-generation) * [Full SDK reference](/sdk/react-SDK/reference) ## Package links * [GitHub repository](https://github.com/soniox/soniox-js) * [NPM package](https://www.npmjs.com/package/@soniox/react) # Full React SDK reference URL: /sdk/react-SDK/reference Full SDK reference for the React SDK ## Components | Component | Description | | ----------------------------------------------------------------- | --------------------------------------------------------------------- | | [`SonioxProvider`](/sdk/react-SDK/reference/types#sonioxprovider) | Provider component for the Soniox client | | [`AudioLevel`](/sdk/react-SDK/reference/types#audiolevel) | Component to display the audio level (not available for React Native) | ### `SonioxProvider` props `@soniox/react` exports three related prop types so you can split provider props in wrapper HOCs without re-deriving them: | Type | Description | | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | [`SonioxProviderProps`](/sdk/react-SDK/reference/types#sonioxproviderprops) | Discriminated union consumed by `SonioxProvider`. Pass either `config` (config-driven) or `client` (client-driven) — never both. | | [`SonioxProviderConfigProps`](/sdk/react-SDK/reference/types#sonioxproviderprops) | The config-driven leaf of the union. Use when you want the provider to construct a `SonioxClient` internally from `SonioxConnectionConfig`. | | [`SonioxProviderClientProps`](/sdk/react-SDK/reference/types#sonioxproviderprops) | The client-driven leaf of the union. Use when you already own a `SonioxClient` instance and just want to expose it through context. | ## Hooks | Hook | Description | | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | [`useRecording`](/sdk/react-SDK/reference/types#userecording) | Main hook for real-time speech-to-text session | | [`useTts`](/sdk/react-SDK/reference/types#usetts) | Main hook for real-time text-to-speech session | | [`useMicrophonePermission`](/sdk/react-SDK/reference/types#usemicrophonepermission) | Hook for checking microphone permission | | [`useAudioLevel`](/sdk/react-SDK/reference/types#useaudiolevel) | Hook for real-time audio volume and spectrum data (not available for React Native) | | [`useSoniox`](/sdk/react-SDK/reference/types#usesoniox) | Hook toaccess the SonioxClient from context | # Types URL: /sdk/react-SDK/reference/types Soniox React SDK — Types Reference ## SonioxProviderProps ```ts type SonioxProviderProps = { children: ReactNode; } & SonioxProviderConfigProps | SonioxProviderClientProps; ``` Props for SonioxProvider. Supply either a pre-built `client` instance or configuration props
**Type Declaration** | Name | Type | | ---------- | ----------- | | `children` | `ReactNode` | *** ## TtsState ```ts type TtsState = "idle" | "connecting" | "speaking" | "stopping" | "error"; ``` Aggregate state for the TTS hook. *** ## UnsupportedReason ```ts type UnsupportedReason = "ssr" | "no-mediadevices" | "no-getusermedia" | "insecure-context"; ``` Reason why the built-in browser `MicrophoneSource` is unavailable: * `'ssr'` — `navigator` is undefined (SSR, React Native, or other non-browser JS runtimes). * `'no-mediadevices'` — `navigator` exists but `navigator.mediaDevices` is missing. * `'no-getusermedia'` — `navigator.mediaDevices` exists but `getUserMedia` is not a function. * `'insecure-context'` — the page is not served over HTTPS. This only reflects whether the **default** `MicrophoneSource` can work. Custom `AudioSource` implementations (e.g. for React Native) bypass this check entirely and can record regardless of this value. *** ## AudioLevelProps **Extends** * [`UseAudioLevelOptions`](types#useaudioleveloptions) **Properties** | Property | Type | Description | | ------------------------------------------------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `active?` | `boolean` | Whether volume metering is active. When false, resources are released. | | `bands?` | `number` | Number of frequency bands to return. When set, the `bands` array is populated with per-band levels (0-1). Useful for spectrum/equalizer visualizations. | | `children` | (`state`) => `ReactNode` | - | | `fftSize?` | `number` | FFT size for the AnalyserNode. Must be a power of 2. Higher values give more frequency resolution (more bins per band) but update less frequently. **Default** `256` | | `smoothing?` | `number` | Exponential smoothing factor (0-1). Higher = smoother/slower decay. **Default** `0.85` | *** ## AudioSupportResult **Properties** | Property | Type | | ------------------------------------------------------- | ---------------------------------------------- | | `isSupported` | `boolean` | | `reason?` | [`UnsupportedReason`](types#unsupportedreason) | *** ## MicrophonePermissionState **Properties** | Property | Type | Description | | -------------------------------------------------------------- | ------------------------ | ---------------------------------------------------------------------- | | `canRequest` | `boolean` | Whether the permission can be requested (e.g., via a prompt). | | `check` | () => `Promise`\<`void`> | Check (or re-check) the microphone permission. No-op when unsupported. | | `isDenied` | `boolean` | `status === 'denied'`. | | `isGranted` | `boolean` | `status === 'granted'`. | | `isSupported` | `boolean` | Whether permission checking is available. | | `status` | `MicPermissionStatus` | Current permission status. | *** ## RecordingSnapshot Immutable snapshot of the recording state exposed to React. **Extended by** * [`UseRecordingReturn`](types#userecordingreturn) **Properties** | Property | Type | Description | | ---------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `error` | `Error` \| `null` | Latest error, if any. | | `finalText` | `string` | Accumulated finalized text. | | `finalTokens` | readonly `RealtimeToken`\[] | All finalized tokens in chronological order. Useful for rendering per-token metadata (language, speaker, etc.) in the order tokens were spoken. Pair with `partialTokens` for the complete ordered stream. | | `groups` | `Readonly`\<`Record`\<`string`, `TokenGroup`>> | Tokens grouped by the active `groupBy` strategy. Auto-populated when `translation` config is provided: - `one_way` → keys: `"original"`, `"translation"` - `two_way` → keys: language codes (e.g. `"en"`, `"es"`) Empty `{}` when no grouping is active. | | `isActive` | `boolean` | `true` when state is not idle/stopped/canceled/error. | | `isPaused` | `boolean` | `true` when `state === 'paused'`. | | `isReconnecting` | `boolean` | `true` when `state === 'reconnecting'`. | | `isRecording` | `boolean` | `true` when `state === 'recording'`. | | `isSourceMuted` | `boolean` | `true` when the audio source is muted externally (e.g. OS-level or hardware mute). | | `partialText` | `string` | Text from current non-final tokens. | | `partialTokens` | readonly `RealtimeToken`\[] | Non-final tokens from the latest result. | | `reconnectAttempt` | `number` | Current reconnection attempt number (0 when not reconnecting). | | `result` | `RealtimeResult` \| `null` | Latest raw result from the server. | | `segments` | readonly `RealtimeSegment`\[] | Accumulated final segments. | | `state` | `RecordingState` | Current recording lifecycle state. | | `text` | `string` | Full transcript: `finalText + partialText`. | | `tokens` | readonly `RealtimeToken`\[] | Tokens from the latest result message. | | `utterances` | readonly `RealtimeUtterance`\[] | Accumulated utterances (one per endpoint). | *** ## TtsSnapshot Immutable snapshot of the TTS state exposed to React. **Extended by** * [`UseTtsReturn`](types#usettsreturn) **Properties** | Property | Type | | -------------------------------------------------- | ---------------------------- | | `error` | `Error` \| `null` | | `isConnecting` | `boolean` | | `isSpeaking` | `boolean` | | `state` | [`TtsState`](types#ttsstate) | *** ## UseAudioLevelOptions **Extended by** * [`AudioLevelProps`](types#audiolevelprops) **Properties** | Property | Type | Description | | ------------------------------------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `active?` | `boolean` | Whether volume metering is active. When false, resources are released. | | `bands?` | `number` | Number of frequency bands to return. When set, the `bands` array is populated with per-band levels (0-1). Useful for spectrum/equalizer visualizations. | | `fftSize?` | `number` | FFT size for the AnalyserNode. Must be a power of 2. Higher values give more frequency resolution (more bins per band) but update less frequently. **Default** `256` | | `smoothing?` | `number` | Exponential smoothing factor (0-1). Higher = smoother/slower decay. **Default** `0.85` | *** ## UseAudioLevelReturn **Properties** | Property | Type | Description | | ---------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------ | | `bands` | readonly `number`\[] | Per-band frequency levels, each 0-1. Empty array when the `bands` option is not set. | | `volume` | `number` | Current volume level, 0 to 1. Updated every animation frame. | *** ## UseMicrophonePermissionOptions **Properties** | Property | Type | Description | | ---------------------------------------------------------------- | --------- | ---------------------------------------- | | `autoCheck?` | `boolean` | Automatically check permission on mount. | *** ## UseRecordingConfig Configuration for useRecording. Extends the STT session config (model, language\_hints, etc.) with recording-specific and React-specific options. Can be used **with or without** a ``: * **With Provider:** omit `config`/`apiKey` — the client is read from context. * **Without Provider:** pass `config` (or legacy `apiKey`) — a client is created internally. **Extends** * `SttSessionConfig` **Properties** | Property | Type | Description | | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ~~`apiKey?`~~ | `ApiKeyConfig` | API key — string or async function that fetches a temporary key. Required when not using ``. **Deprecated** Use `config` instead. | | `audio_format?` | `"auto"` \| `AudioFormat` | Audio format. Use 'auto' for automatic detection of container formats. For raw PCM formats, also set sample\_rate and num\_channels. **Default** `'auto'` | | `auto_reconnect?` | `boolean` | Enable automatic reconnection on retriable errors. **Default** `false` | | `buffer_queue_size?` | `number` | Maximum audio chunks to buffer during connection setup. | | `client_reference_id?` | `string` | Optional tracking identifier (max 256 chars). | | `config?` | \| `SonioxConnectionConfig` \| (`context?`) => `Promise`\<`SonioxConnectionConfig`> | Connection configuration — sync object or async function. Required when not using ``. | | `context?` | `TranscriptionContext` | Additional context to improve transcription accuracy. | | `enable_endpoint_detection?` | `boolean` | Enable endpoint detection for utterance boundaries. Useful for voice AI agents. | | `enable_language_identification?` | `boolean` | Enable automatic language detection. | | `enable_speaker_diarization?` | `boolean` | Enable speaker identification. | | `endpoint_latency_adjustment_level?` | `number` | Reduces endpoint latency compared to the default endpointing behavior. Higher values reduce endpoint latency more aggressively, which means endpoints are returned sooner and more endpoints may be emitted. This can split long speech into more segments and may slightly reduce word recognition accuracy because speech is finalized earlier. Allowed values are 0, 1, 2, and 3. The default value is 0 (default semantic endpointing behavior). | | `endpoint_sensitivity?` | `number` | Controls how aggressively endpoints are detected. Adjusts how likely the model is to emit an endpoint. Higher values make endpoints more likely, which can finalize segments sooner. Lower values make endpoints less likely, which can help the system wait longer before finalizing. Allowed values are between -1.0 and 1.0. The default value is 0.0. | | `groupBy?` | `"translation"` \| `"language"` \| `"speaker"` \| (`token`) => `string` | Group tokens by a key for easy splitting (e.g. translation, language, speaker). - `'translation'` — group by `translation_status`: keys `"original"` and `"translation"` - `'language'` — group by token `language` field: keys are language codes - `'speaker'` — group by token `speaker` field: keys are speaker identifiers - `(token) => string` — custom grouping function **Auto-defaults** when `translation` config is provided: - `one_way` → `'translation'` - `two_way` → `'language'` | | `language_hints?` | `string`\[] | Expected languages in the audio (ISO language codes). | | `language_hints_strict?` | `boolean` | When true, recognition is strongly biased toward language hints. Best-effort only, not a hard guarantee. | | `max_endpoint_delay_ms?` | `number` | Maximum delay between the end of speech and returned endpoint. Allowed values for maximum delay are between 500ms and 3000ms. The default value is 2000ms | | `max_reconnect_attempts?` | `number` | Maximum consecutive reconnection attempts before giving up. **Default** `3` | | `model` | `string` | Speech-to-text model to use. | | `num_channels?` | `number` | Number of audio channels (required for raw audio formats). | | `onConnected?` | () => `void` | Called when the WebSocket connects. | | `onEndpoint?` | () => `void` | Called when an endpoint is detected. | | `onError?` | (`error`) => `void` | Called when an error occurs. | | `onFinalized?` | () => `void` | Called when the server acknowledges a finalize request (see [UseRecordingReturn](types#userecordingreturn)). | | `onFinished?` | () => `void` | Called when the recording session finishes. | | `onReconnected?` | (`event`) => `void` | Called after a successful reconnection. | | `onReconnecting?` | (`event`) => `void` | Called before a reconnection attempt. Call `preventDefault()` to cancel. | | `onResult?` | (`result`) => `void` | Called on each result from the server. | | `onSourceMuted?` | () => `void` | Called when the audio source is muted externally (e.g. OS-level or hardware mute). | | `onSourceUnmuted?` | () => `void` | Called when the audio source is unmuted after an external mute. | | `onStateChange?` | (`update`) => `void` | Called on each state transition. | | `onToken?` | (`token`) => `void` | Called for each token received from the server (both final and non-final). | | `permissions?` | `PermissionResolver` \| `null` | Permission resolver override (only used when creating an inline client). Pass `null` to explicitly disable. | | `reconnect_base_delay_ms?` | `number` | Base delay in milliseconds for exponential backoff. **Default** `1000` | | `reset_transcript_on_reconnect?` | `boolean` | Clear accumulated transcript state on reconnect. Window-tracking state is always reset regardless. **Default** `false` | | `resetOnStart?` | `boolean` | Reset transcript state when `start()` is called. **Default** `true` | | `sample_rate?` | `number` | Sample rate in Hz (required for PCM formats). | | `session_options?` | `SttSessionOptions` | SDK-level session options (signal, etc.). | | `sessionConfig?` | (`resolved`) => `SttSessionConfig` | Function that receives the resolved connection config (including `stt_defaults` from the server) and returns session config overrides. When provided, its return value is used as the session config for the recording, and any flat session config fields on this object are ignored. **Example** `const { start } = useRecording({ config: asyncConfigFn, sessionConfig: (resolved) => ({ ...resolved.stt_defaults, enable_endpoint_detection: true, }), });` | | `source?` | `AudioSource` | Custom audio source (bypasses default MicrophoneSource). | | `translation?` | `TranslationConfig` | Translation configuration. | | ~~`wsBaseUrl?`~~ | `string` | WebSocket URL override (only used when `apiKey` is provided). **Deprecated** Use `config.stt_ws_url` or `config.region` instead. | *** ## UseRecordingReturn Immutable snapshot of the recording state exposed to React. **Extends** * [`RecordingSnapshot`](types#recordingsnapshot) **Properties** | Property | Type | Description | | ------------------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cancel` | () => `void` | Immediately cancel — does not wait for final results. | | `clearTranscript` | () => `void` | Clear transcript state (finalText, partialText, utterances, segments). | | `error` | `Error` \| `null` | Latest error, if any. | | `finalize` | (`options?`) => `void` | Request the server to finalize current non-final tokens. | | `finalText` | `string` | Accumulated finalized text. | | `finalTokens` | readonly `RealtimeToken`\[] | All finalized tokens in chronological order. Useful for rendering per-token metadata (language, speaker, etc.) in the order tokens were spoken. Pair with `partialTokens` for the complete ordered stream. | | `groups` | `Readonly`\<`Record`\<`string`, `TokenGroup`>> | Tokens grouped by the active `groupBy` strategy. Auto-populated when `translation` config is provided: - `one_way` → keys: `"original"`, `"translation"` - `two_way` → keys: language codes (e.g. `"en"`, `"es"`) Empty `{}` when no grouping is active. | | `isActive` | `boolean` | `true` when state is not idle/stopped/canceled/error. | | `isPaused` | `boolean` | `true` when `state === 'paused'`. | | `isReconnecting` | `boolean` | `true` when the WebSocket is reconnecting after a drop. | | `isRecording` | `boolean` | `true` when `state === 'recording'`. | | `isSourceMuted` | `boolean` | `true` when the audio source is muted externally (e.g. OS-level or hardware mute). | | `isSupported` | `boolean` | Whether the built-in browser `MicrophoneSource` is available. Custom `AudioSource` implementations work regardless of this value. | | `partialText` | `string` | Text from current non-final tokens. | | `partialTokens` | readonly `RealtimeToken`\[] | Non-final tokens from the latest result. | | `pause` | () => `void` | Pause recording — pauses audio capture and activates keepalive. | | `reconnect` | () => `void` | Force a reconnection — tears down the current session and audio encoder, then establishes a new session. Requires `auto_reconnect`. Call this from platform lifecycle handlers (e.g. web `visibilitychange`, React Native `AppState`) to recover from stale connections after sleep/wake or backgrounding. | | `reconnectAttempt` | `number` | Current reconnection attempt number (0 when not reconnecting). | | `result` | `RealtimeResult` \| `null` | Latest raw result from the server. | | `resume` | () => `void` | Resume recording after pause. | | `segments` | readonly `RealtimeSegment`\[] | Accumulated final segments. | | `start` | () => `void` | Start a new recording. Aborts any in-flight recording first. | | `state` | `RecordingState` | Current recording lifecycle state. | | `stop` | () => `Promise`\<`void`> | Gracefully stop — waits for final results from the server. | | `text` | `string` | Full transcript: `finalText + partialText`. | | `tokens` | readonly `RealtimeToken`\[] | Tokens from the latest result message. | | `unsupportedReason` | [`UnsupportedReason`](types#unsupportedreason) \| `undefined` | Why the built-in `MicrophoneSource` is unavailable, if applicable. Custom `AudioSource` implementations bypass this check entirely. | | `utterances` | readonly `RealtimeUtterance`\[] | Accumulated utterances (one per endpoint). | *** ## UseTtsConfig Configuration for useTts. Extends TtsStreamInput — flat TTS fields (model, voice, language, audio\_format) are merged on top of server-provided `tts_defaults`. Can be used **with or without** a ``: * **With Provider:** omit `config` — the client is read from context. * **Without Provider:** pass `config` — a client is created internally. In `'rest'` mode, `voice` is required — the REST TTS endpoint (`GenerateSpeechOptions.voice`) has no default. Discover available voices via `client.tts.listModels()`. **Extends** * `TtsStreamInput` **Properties** | Property | Type | Description | | -------------------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `audio_format?` | `TtsAudioFormat` | Output audio format **Example** `'wav'` | | `bitrate?` | `number` | Codec bitrate in bps (for compressed formats). | | `config?` | \| `SonioxConnectionConfig` \| (`context?`) => `Promise`\<`SonioxConnectionConfig`> | Connection configuration — sync object or async function. Required when not using ``. | | `language?` | `string` | Language code for speech generation. **Example** `'en'` | | `mode?` | `"websocket"` \| `"rest"` | Transport mode for TTS generation. - `'websocket'` (default): Real-time streaming via WebSocket. Supports incremental text input (`sendText`/`finish`) and streaming from LLM. - `'rest'`: HTTP request/response via the TTS REST endpoint. Sends full text at once, streams audio back. Simpler but no incremental text input. **Default** `'websocket'` | | `model?` | `string` | Text-to-Speech model to use. **Example** `'tts-rt-v2'` | | `onAudio?` | (`chunk`, `timestamps?`) => `void` | Called when an audio chunk is received. In WebSocket mode with `return_timestamps` enabled, the second argument carries the character-level alignment for that frame (`undefined` for audio-only frames). REST mode never provides timestamps. | | `onAudioEnd?` | () => `void` | Called when the server marks the final audio payload. | | `onError?` | (`error`) => `void` | Called on error. | | `onStateChange?` | (`event`) => `void` | Called on each state transition. | | `onTerminated?` | () => `void` | Called when generation is complete. | | `reduce_silence?` | `boolean` | Shorten pauses between words in the generated speech. `false` (default) keeps the model's natural pacing; `true` tightens delivery by reducing silence between words. | | `return_timestamps?` | `boolean` | Request character-level audio timestamps in the responses. When enabled, audio frames may carry a TtsTimestamps payload aligning each character of the spoken text to its start/end time in the audio. WebSocket (realtime) only — the REST endpoint streams raw audio bytes and ignores this flag. Timestamps map to the model's preprocessed text, not the raw input. Defaults to `false` when omitted. | | `sample_rate?` | `number` | Output sample rate in Hz. Required for raw PCM formats. | | `speed?` | `number` | Speaking rate. `1.0` is the normal rate; values below `1.0` slow speech down and values above `1.0` speed it up. Supported range is `0.7`-`1.3`. Defaults to `1.0` when omitted. | | `stream_id?` | `string` | Client-generated stream identifier. Must be unique among active streams on the same connection. Auto-generated if omitted. | | `voice?` | `string` | Voice identifier. **Example** `'Adrian'` | *** ## UseTtsReturn Immutable snapshot of the TTS state exposed to React. **Extends** * [`TtsSnapshot`](types#ttssnapshot) **Properties** | Property | Type | Description | | --------------------------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------- | | `cancel` | () => `void` | Cancel the current generation immediately. | | `error` | `Error` \| `null` | - | | `finish` | () => `void` | Signal that no more text will be sent. WebSocket mode only. | | `isConnecting` | `boolean` | - | | `isSpeaking` | `boolean` | - | | `sendText` | (`text`) => `void` | Send one text chunk without finishing. WebSocket mode only. | | `speak` | (`text`) => `void` | Start TTS. Sends text (or pipes an async iterable in WebSocket mode) and generates audio. | | `state` | [`TtsState`](types#ttsstate) | - | | `stop` | () => `Promise`\<`void`> | Gracefully stop — sends finish and waits for completion. | *** ## AudioLevel() ```ts function AudioLevel(__namedParameters): ReactNode; ``` **Parameters** | Parameter | Type | | ------------------- | ------------------------------------------ | | `__namedParameters` | [`AudioLevelProps`](types#audiolevelprops) | **Returns** `ReactNode` *** ## SonioxProvider() ```ts function SonioxProvider(props): ReactNode; ``` **Parameters** | Parameter | Type | | --------- | -------------------------------------------------- | | `props` | [`SonioxProviderProps`](types#sonioxproviderprops) | **Returns** `ReactNode` *** ## checkAudioSupport() ```ts function checkAudioSupport(): AudioSupportResult; ``` Check whether the current environment supports the built-in browser `MicrophoneSource` (which uses `navigator.mediaDevices.getUserMedia`). This does **not** reflect general recording capability — custom `AudioSource` implementations (e.g. for React Native) bypass this check entirely and can record regardless of the result. **Returns** [`AudioSupportResult`](types#audiosupportresult) **Platform** browser *** ## useAudioLevel() ```ts function useAudioLevel(options?): UseAudioLevelReturn; ``` **Parameters** | Parameter | Type | | ---------- | ---------------------------------------------------- | | `options?` | [`UseAudioLevelOptions`](types#useaudioleveloptions) | **Returns** [`UseAudioLevelReturn`](types#useaudiolevelreturn) *** ## useMicrophonePermission() ```ts function useMicrophonePermission(options?): MicrophonePermissionState; ``` **Parameters** | Parameter | Type | | ---------- | ------------------------------------------------------------------------ | | `options?` | [`UseMicrophonePermissionOptions`](types#usemicrophonepermissionoptions) | **Returns** [`MicrophonePermissionState`](types#microphonepermissionstate) *** ## useRecording() ```ts function useRecording(config): UseRecordingReturn; ``` **Parameters** | Parameter | Type | | --------- | ------------------------------------------------ | | `config` | [`UseRecordingConfig`](types#userecordingconfig) | **Returns** [`UseRecordingReturn`](types#userecordingreturn) *** ## useSoniox() ```ts function useSoniox(): SonioxClient; ``` Returns the `SonioxClient` instance provided by the nearest `SonioxProvider` **Returns** `SonioxClient` **Throws** Error if called outside a `SonioxProvider` *** ## useTts() ```ts function useTts(config): UseTtsReturn; ``` **Parameters** | Parameter | Type | | --------- | ------------------------------------ | | `config` | [`UseTtsConfig`](types#usettsconfig) | **Returns** [`UseTtsReturn`](types#usettsreturn) # Real-time transcription with React SDK URL: /sdk/react-SDK/stt/realtime-transcription Create and manage real-time speech-to-text sessions with the Soniox React SDK import { LinkCards } from "@/components/link-card"; Soniox React SDK supports real-time transcription via React hooks, built on top of the [@soniox/client](/sdk/web-SDK) Web SDK. This allows you to transcribe live audio with low latency — ideal for live captions, voice input, and interactive experiences. You can capture audio from the user's microphone, receive transcription results as reactive state, and control sessions with simple `start`/`stop` calls. ## Soniox Provider [`SonioxProvider`](/sdk/react-SDK/reference/types#sonioxprovider) creates and shares a single [`SonioxClient`](/sdk/web-SDK/reference/classes#sonioxclient) instance via React context. Place it near the root of your component tree. ### With configuration props ```tsx import { SonioxProvider } from "@soniox/react"; function App() { return ( { const res = await fetch("/api/get-temporary-key", { method: "POST" }); const { api_key } = await res.json(); return { api_key }; }} > {children} ); } ``` The `config` resolver runs once per recording session and can return any [`SonioxConnectionConfig`](/sdk/web-SDK/reference/types#sonioxclientoptions) fields — for example `region`, `stt_ws_url`, or `tts_ws_url` — alongside the `api_key`. ### With a pre-built client ```tsx import { SonioxClient } from "@soniox/client"; import { SonioxProvider } from "@soniox/react"; const client = new SonioxClient({ config: async () => { const { api_key } = await fetchKey(); return { api_key }; }, }); function App() { return {children}; } ``` ## `useRecording` `useRecording` is the primary hook for real-time speech-to-text. Returns reactive transcript state and control methods. Returns [`UseRecordingReturn`](/sdk/react-SDK/reference/types#userecordingreturn) which contains reactive state and control methods. ```tsx function Transcriber() { const recording = useRecording({ model: "stt-rt-v5", language_hints: ["en", "es"], enable_endpoint_detection: true, }); return (

State: {recording.state}

{recording.text}

); } ``` ### Handle session events | Callback | Signature | Description | | ------------------ | --------------------------------------------------------------- | ---------------------------------------------------------------------- | | `onResult` | `(result: RealtimeResult) => void` | Called on each result from the server. | | `onToken` | `(token: RealtimeToken) => void` | Called once per token, in addition to `onResult`. | | `onEndpoint` | `() => void` | Called when an endpoint is detected. | | `onError` | `(error: Error) => void` | Called when an error occurs. | | `onStateChange` | `(update: { old_state, new_state, reason? }) => void` | Called on each state transition. | | `onFinished` | `() => void` | Called when the recording session finishes. | | `onConnected` | `() => void` | Called when the WebSocket connects. | | `onReconnecting` | `({ attempt, max_attempts, delay_ms, preventDefault }) => void` | Called before each reconnect attempt (requires `auto_reconnect`). | | `onReconnected` | `({ attempt }) => void` | Called after a successful reconnect. | | `onSessionRestart` | `({ reset_transcript }) => void` | Called when a new STT session is started (initial or after reconnect). | | `onSourceMuted` | `() => void` | Called when the audio source is muted externally. | | `onSourceUnmuted` | `() => void` | Called when the audio source is unmuted. | ### Session lifecycle #### Recording state | Field | Type | Description | | --------------- | ---------------- | -------------------------------------------------------------------- | | `state` | `RecordingState` | Current lifecycle state (`'idle'`, `'recording'`, `'paused'`, etc.). | | `isActive` | `boolean` | `true` when state is not `idle`/`stopped`/`canceled`/`error`. | | `isRecording` | `boolean` | `true` when `state === 'recording'`. | | `isPaused` | `boolean` | `true` when `state === 'paused'`. | | `isSourceMuted` | `boolean` | `true` when the audio source is muted externally. | #### Available methods | Method | Signature | Description | | ----------------- | --------------------- | ------------------------------------------------------------------------ | | `start` | `() => void` | Start a new recording. Aborts any in-flight recording first. | | `stop` | `() => Promise` | Gracefully stop — waits for final results from the server. | | `cancel` | `() => void` | Immediately cancel — does not wait for final results. | | `pause` | `() => void` | Pause audio capture (keepalive keeps connection open). | | `resume` | `() => void` | Resume after pause. | | `finalize` | `(options?) => void` | Request the server to finalize current non-final tokens. | | `clearTranscript` | `() => void` | Clear transcript state (`finalText`, `partialText`, `utterances`, etc.). | ### Endpoint detection and manual finalization Endpoint detection lets you know when a speaker has finished speaking. This is critical for real-time voice AI assistants, command-and-response systems, and conversational apps where you want to respond immediately without waiting for long silences. Read more about [Endpoint detection](/stt/rt/endpoint-detection) Enable endpoint detection by setting `enable_endpoint_detection: true` in the hook configuration. Use the `onEndpoint` callback to know when a speaker has finished speaking. ```tsx const { start, stop, text } = useRecording({ model: "stt-rt-v5", enable_endpoint_detection: true, onEndpoint: () => { console.log("--- speaker finished ---"); }, }); ``` Manual finalization gives you precise control over when audio should be finalized — useful for push-to-talk systems and client-side voice activity detection (VAD). Read more about [Manual finalization](/stt/rt/manual-finalization) The finalize function is returned by useRecording and can be called at any time during an active recording: ```tsx const { start, stop, finalize } = useRecording({}); // Later, when you want to force finalization: finalize(); ``` ### Pause, resume and muting audio source The pause and resume functions are returned by `useRecording`. The `isPaused` flag reflects the current pause state reactively. ```tsx const { start, stop, pause, resume, isPaused } = useRecording({}); pause(); // keeps connection alive, drops audio while paused resume(); // resume sending audio ``` SDK will `finalize` audio on pause. Make sure to adjust your VAD sensitivity to have enough silence before pause. Learn more about [Manual finalization](/stt/rt/manual-finalization#key-points) The hook also tracks system-level mute events via `isSourceMuted`. When the audio source is muted externally (e.g. OS-level or hardware mute), keepalive messages are sent automatically to keep the session alive. You can listen for mute state changes with the `onSourceMuted` and `onSourceUnmuted` callbacks. ```tsx const { isSourceMuted } = useRecording({ onSourceMuted: () => { console.log("Microphone muted externally"); }, onSourceUnmuted: () => { console.log("Microphone unmuted"); }, }); ``` You are billed for the full stream duration even when the session is paused. ### Auto-reconnect `useRecording` can transparently recover from transient network drops. Opt in with `auto_reconnect: true` — on a retriable error, the hook tears down the current WebSocket and audio encoder, re-resolves the connection config, and starts a new session with exponential backoff. Audio captured during the reconnect is buffered and flushed on resume. ```tsx const { start, stop, state, isReconnecting, reconnectAttempt } = useRecording({ model: "stt-rt-v5", auto_reconnect: true, max_reconnect_attempts: 3, // default: 3 reconnect_base_delay_ms: 1000, // exponential backoff: 1s, 2s, 4s, ... onReconnecting: ({ attempt, max_attempts, delay_ms, preventDefault }) => { console.log(`Reconnect attempt ${attempt}/${max_attempts} in ${delay_ms}ms`); // preventDefault() cancels this attempt (e.g. for manual backoff control). }, onReconnected: ({ attempt }) => { console.log(`Reconnected after ${attempt} attempt(s)`); }, }); ``` #### Options | Option | Type | Default | Description | | ------------------------------- | --------- | ------- | ----------------------------------------------------------- | | `auto_reconnect` | `boolean` | `false` | Enable automatic reconnection on retriable errors. | | `max_reconnect_attempts` | `number` | `3` | Maximum consecutive attempts before surfacing the error. | | `reconnect_base_delay_ms` | `number` | `1000` | Base delay in ms for exponential backoff (1x, 2x, 4x, ...). | | `reset_transcript_on_reconnect` | `boolean` | `false` | Clear accumulated transcript state on reconnect. | #### Return values | Field | Type | Description | | ------------------ | --------- | -------------------------------------------------------------------- | | `isReconnecting` | `boolean` | `true` while the hook is in the `reconnecting` state. | | `reconnectAttempt` | `number` | Current attempt number (resets to `0` after a successful reconnect). | #### Force a reconnect `useRecording` also returns a `reconnect()` function — call it from platform lifecycle handlers like `visibilitychange` or React Native `AppState` to proactively rebuild the session when you suspect a stale connection. Requires `auto_reconnect: true`. ```tsx const { reconnect } = useRecording({ model: "stt-rt-v5", auto_reconnect: true, }); useEffect(() => { const onVisibility = () => { if (document.visibilityState === "visible") reconnect(); }; document.addEventListener("visibilitychange", onVisibility); return () => document.removeEventListener("visibilitychange", onVisibility); }, [reconnect]); ``` ### Handling translation The React SDK supports one-way and two-way real-time translation. Configure translation in the useRecording hook config. The hook automatically groups tokens by translation status or language via the groups snapshot field, so you can render original and translated text separately without manual filtering. #### One-way translation Translates all spoken audio into a single target language. When translation is provided with type: `one_way`, the hook automatically sets `groupBy: 'translation'`, splitting tokens into `original` and `translation` groups. ```tsx const { groups } = useRecording({ model: "stt-rt-v5", translation: { type: "one_way", target_language: "es", // Translate everything to Spanish }, }); // Render grouped text return (

Original: {groups.original?.text}

Translated: {groups.translation?.text}

); ``` #### Two-way translation Translates between two languages — each speaker's speech is translated into the other language. When translation is provided with type: `two_way`, the hook automatically sets `groupBy: 'language'`, splitting tokens by language code (e.g. `en`, `fr`). ```tsx const { groups } = useRecording({ model: "stt-rt-v5", translation: { type: "two_way", language_a: "en", language_b: "fr", }, }); // Render grouped text by language return (

English: {groups.en?.text}

French: {groups.fr?.text}

); ``` Learn more about [Real-time translation](/translation/stt-translation/rt-translation) ### Utterances When `enable_endpoint_detection` is enabled, the `utterances` array accumulates utterances separated by natural pauses: ```tsx function TranscriptWithUtterances() { const { utterances, partialText, start, stop, isActive } = useRecording({ model: "stt-rt-v5", enable_endpoint_detection: true, }); return (
{utterances.map((utterance, i) => (

{utterance.text}

))} {partialText &&

{partialText}

}
); } ``` Learn more about [Endpoint detection](/stt/rt/endpoint-detection) ### Token grouping The `groupBy` option splits tokens into named groups, accessible via `recording.groups`. This is particularly useful for translation and multi-speaker scenarios. #### `groupBy` strategies | Value | Keys | Description | | ------------------- | ------------------------------------ | -------------------------------- | | `'translation'` | `"original"`, `"translation"` | Group by `translation_status`. | | `'language'` | Language codes (e.g. `"en"`, `"fr"`) | Group by token `language` field. | | `'speaker'` | Speaker IDs (e.g. `"1"`) | Group by token `speaker` field. | | `(token) => string` | Custom keys | Custom grouping function. | Learn more about [Speaker diarization](/stt/concepts/speaker-diarization) #### TokenGroup fields Each group in `recording.groups` contains: | Field | Type | Description | | --------------- | ----------------- | ------------------------------------------------------- | | `text` | `string` | Full text: `finalText + partialText`. | | `finalText` | `string` | Accumulated finalized text in this group. | | `partialText` | `string` | Text from current non-final tokens. | | `partialTokens` | `RealtimeToken[]` | Current non-final tokens (from the latest result only). | #### Automatic grouping for translation When a `translation` config is provided, `groupBy` is set automatically: * `one_way` translation → groups by `'translation'` (keys: `"original"`, `"translation"`) * `two_way` translation → groups by `'language'` (keys: language codes like `"en"`, `"es"`) ```tsx function TranslatedTranscript() { const { groups, start, stop, isActive } = useRecording({ model: "stt-rt-v5", translation: { type: "one_way", target_language: "es" }, }); return (

Original

{groups.original?.text}

Translation

{groups.translation?.text}

); } ``` ## `useSoniox` Returns the `SonioxClient` instance from the nearest `SonioxProvider`. Useful for low-level session access. ```tsx import { useSoniox } from "@soniox/react"; function MyComponent() { const client = useSoniox(); // Low-level session access (non-reactive): // const session = client.realtime.stt({ model: 'stt-rt-v5' }, { api_key: '...' }); // // Permission helpers (if a resolver is configured): // const result = await client.permissions?.check('microphone'); return null; } ``` `client.tts` in the browser only exposes `generate()` and `generateStream()`. To enumerate available TTS models and voices, use the [Node SDK's `client.tts.listModels()`](/sdk/node-SDK/tts/rest-speech-generation#list-available-models) on your server. ## `useMicrophonePermission` Hook for checking and requesting microphone permission before recording. Requires a `SonioxProvider` with a permission resolver configured (default in browsers). ```tsx import { useMicrophonePermission } from "@soniox/react"; function PermissionGate({ children }) { const mic = useMicrophonePermission({ autoCheck: true }); if (!mic.isSupported) { return

Microphone permissions are not available.

; } if (mic.status === "unknown") { return

Checking permission...

; } if (mic.isDenied) { return (

Microphone access denied.

{!mic.canRequest && (

Please enable microphone access in your browser settings.

)}
); } if (mic.status === "prompt") { // `mic.check` re-queries the permission state. To actually show the // browser prompt, start a recording or call `getUserMedia({ audio: true })` // from the click handler. return ( ); } return children; } ``` ### Options | Option | Type | Default | Description | | ----------- | --------- | ------- | ---------------------------------------- | | `autoCheck` | `boolean` | `false` | Automatically check permission on mount. | ### Return value | Field | Type | Description | | ------------- | --------------------- | ------------------------------------------------------------------------------------------------------ | | `status` | `MicPermissionStatus` | Current status: `'granted'`, `'denied'`, `'prompt'`, `'unavailable'`, `'unsupported'`, or `'unknown'`. | | `canRequest` | `boolean` | Whether the user can be prompted again. `false` when permanently denied. | | `isGranted` | `boolean` | `status === 'granted'`. | | `isDenied` | `boolean` | `status === 'denied'`. | | `isSupported` | `boolean` | Whether permission checking is available. | | `check` | `() => Promise` | Check (or re-check) the microphone permission. No-op when unsupported. | ### Status values | Status | Description | | --------------- | --------------------------------------------------- | | `'granted'` | Microphone access is granted. | | `'denied'` | Microphone access is denied. | | `'prompt'` | User hasn't been asked yet. | | `'unavailable'` | Permissions API not available in this browser. | | `'unsupported'` | No `PermissionResolver` configured in the provider. | | `'unknown'` | Initial state before the first `check()` call. | ## `useAudioLevel` Hook for real-time audio volume metering. Useful for building recording indicators and animations. ```tsx import { useAudioLevel } from "@soniox/react"; function VolumeIndicator({ isActive }) { const { volume } = useAudioLevel({ active: isActive }); // float value between 0 and 1 return (
); } ``` ## Next.js (App Router) The package declares `'use client'` at the entry point. All hooks must be used inside Client Components. Server Components cannot use `useRecording` or other hooks directly. # Real-time speech generation with React SDK URL: /sdk/react-SDK/tts/realtime-speech-generation Stream text to speech in React with the useTts hook import { LinkCards } from "@/components/link-card"; The Soniox React SDK exposes a single [`useTts`](/sdk/react-SDK/reference/types#usetts) hook that covers both real-time WebSocket TTS and one-shot REST TTS. It manages the stream lifecycle, surfaces reactive state for rendering, and handles cleanup automatically when your component unmounts. ## Transport modes `useTts` has two modes selected via the `mode` option: | Feature | `'websocket'` (default) | `'rest'` | | -------------------------------------------- | --------------------------------------------------- | ----------------------------------------------------- | | `speak(string)` | Yes | Yes | | `speak(asyncIterable)` — LLM token streaming | Yes | No | | `sendText()` / `finish()` — incremental text | Yes | No-op | | Audio delivery | Streaming chunks | Streaming chunks | | Error detection | Full (in-band WebSocket errors) | Pre-stream only (HTTP status) | | Use when... | Narrating LLM output, lowest latency to first audio | You have the full text and want a simple HTTP request | ## Set up your temporary API key endpoint In a browser environment you don't want to expose your primary API key. Create a temporary key endpoint on your server using the Soniox [Node SDK](/sdk/node-SDK). TTS keys use the `tts_rt` usage type. To attribute browser-side TTS traffic to an end user or session, pass `client_reference_id` to `createTemporaryKey` - every request authenticated with the key is recorded under that identifier in [usage logs](/guides/usage-logs). Clients cannot override it. ```ts import express from 'express'; import { SonioxNodeClient } from '@soniox/node'; const app = express(); const client = new SonioxNodeClient(); // reads SONIOX_API_KEY from env app.get('/tts-tmp-key', async (_req, res) => { try { const { api_key, expires_at } = await client.auth.createTemporaryKey({ usage_type: 'tts_rt', expires_in_seconds: 300, }); res.json({ api_key, expires_at }); } catch (err) { res.status(500).json({ error: err instanceof Error ? err.message : 'Failed to create temporary key' }); } }); app.listen(3000); ``` Because TTS and STT temporary keys have different `usage_type` values, `useTts` always creates its own client from the inline `config` prop — even when a `` is present. Pass the `config` prop on `useTts` with a resolver that fetches a `tts_rt` key. ## Quickstart Pass a `config` resolver and a `voice` — that's all that's required. `speak()` starts generation; `state` reflects the lifecycle; audio plays via the `onAudio` callback or any hook-up of your choice. ```tsx import { useTts } from "@soniox/react"; import { useRef } from "react"; async function fetchTtsKey() { const res = await fetch("/tts-tmp-key"); const { api_key } = await res.json(); return { api_key }; } export function TtsButton() { const audioChunksRef = useRef([]); const { speak, state, isSpeaking, error } = useTts({ config: fetchTtsKey, voice: "Adrian", model: "tts-rt-v2", language: "en", audio_format: "wav", onAudio: (chunk) => { audioChunksRef.current.push(chunk); }, onTerminated: () => { const blob = new Blob(audioChunksRef.current, { type: "audio/wav" }); new Audio(URL.createObjectURL(blob)).play(); audioChunksRef.current = []; }, onError: (err) => console.error(err), }); return (

State: {state}

{error &&

{error.message}

}
); } ``` ## Stream from an LLM WebSocket mode accepts an `AsyncIterable` — pipe LLM tokens straight into `speak()` and audio starts playing as the first tokens arrive. ```tsx async function* llmTokens(prompt: string): AsyncIterable { const res = await fetch("/llm/stream", { method: "POST", body: JSON.stringify({ prompt }), }); const reader = res.body!.getReader(); const decoder = new TextDecoder(); while (true) { const { value, done } = await reader.read(); if (done) return; yield decoder.decode(value); } } function Narrator() { const audioChunksRef = useRef([]); const { speak, isSpeaking, stop } = useTts({ config: fetchTtsKey, voice: "Adrian", audio_format: "wav", onAudio: (chunk) => audioChunksRef.current.push(chunk), }); return ( ); } ``` ## Send text incrementally For finer control over when text arrives, call `sendText` for each chunk and `finish` when done. This is useful when the text source isn't already an async iterable. ```tsx function IncrementalTts() { const audioChunksRef = useRef([]); const { sendText, finish, stop, isSpeaking } = useTts({ config: fetchTtsKey, voice: "Adrian", audio_format: "wav", onAudio: (chunk) => audioChunksRef.current.push(chunk), }); const speakParagraphs = (paragraphs: string[]) => { for (const p of paragraphs) sendText(p + " "); finish(); }; return (
{isSpeaking && }
); } ``` `sendText` and `finish` are no-ops in REST mode — the REST endpoint only accepts the full text in a single request. ## REST mode Set `mode: 'rest'` to run TTS over HTTP. `speak(string)` still works, but `speak(asyncIterable)`, `sendText`, and `finish` are not available (the hook emits an error if you try to stream an async iterable). ```tsx const audioChunksRef = useRef([]); const { speak, state, isSpeaking } = useTts({ config: fetchTtsKey, mode: "rest", voice: "Adrian", audio_format: "wav", onAudio: (chunk) => audioChunksRef.current.push(chunk), onTerminated: () => console.log("done"), }); speak("Hello over REST."); ``` Use REST mode for one-off playback (confirmations, notifications) where the lower latency of WebSocket isn't worth the extra connection. REST mode requires `voice` in the hook config — there is no built-in fallback. Omitting it surfaces an error via `onError` and leaves `state: 'error'`. WebSocket mode also needs a `voice`, but it can come from the hook config **or** from server-returned `tts_defaults` (see [Server-driven defaults](#server-driven-defaults)). To discover available voices, call [`client.tts.listModels()`](/sdk/node-SDK/tts/rest-speech-generation#list-available-models) from the Node SDK on your server — it is not available in the browser client. ## Lifecycle `useTts` exposes a single `state` that transitions through the lifecycle below. `isSpeaking` and `isConnecting` are derived booleans you can use directly in UI. | State | Meaning | | ------------ | ----------------------------------------------------------------------------- | | `idle` | No generation in flight. Initial state, or after a completed / cancelled run. | | `connecting` | Opening the WebSocket (or issuing the REST request). | | `speaking` | Receiving audio chunks. | | `stopping` | `stop()` was called — waiting for `terminated` to flush. | | `error` | Last run failed. Inspect `error` and call `speak()` again to retry. | Transitions, in plain terms: * The hook starts in `idle`. Calling `speak()` (or `sendText()` in WebSocket mode) moves it to `connecting`. * Once the first audio chunk is received, it moves to `speaking`. * When the server finishes (either because `speak()` passed a complete string, you called `finish()`, or the LLM async iterable ended), the hook fires `onTerminated` and returns to `idle`. * Calling `stop()` during `speaking` moves it to `stopping` and then back to `idle` once the server flushes. Calling `cancel()` at any point jumps straight back to `idle`. * Any error (connect failure or in-stream error) moves it to `error`. The next `speak()` resets it back to `connecting`. ## Methods | Method | Signature | Description | | ---------- | ------------------------------------------------- | ---------------------------------------------------------------------------------- | | `speak` | `(text: string \| AsyncIterable) => void` | Start a new run. Cancels any in-flight generation first. | | `sendText` | `(text: string) => void` | WebSocket only. Send one chunk without finishing. Use with `finish()`. | | `finish` | `() => void` | WebSocket only. Signal no more text — server finishes and sends `terminated`. | | `stop` | `() => Promise` | Graceful stop. Sends `finish()` and resolves when the server reaches `terminated`. | | `cancel` | `() => void` | Immediate cancel. Audio stops right away. | ## Callbacks | Callback | Signature | Description | | --------------- | ------------------------------------ | -------------------------------------------------------------- | | `onAudio` | `(chunk: Uint8Array) => void` | Audio chunk received. Fired for both REST and WebSocket modes. | | `onAudioEnd` | `() => void` | Server marked the final audio payload. | | `onTerminated` | `() => void` | Generation is fully complete. | | `onError` | `(error: Error) => void` | Stream or connection error. | | `onStateChange` | `({ old_state, new_state }) => void` | Fired on every state transition. | ## Return values Reactive snapshot exposed by the hook — see [`UseTtsReturn`](/sdk/react-SDK/reference/types#usettsreturn): | Field | Type | Description | | ----------------------------------------------- | ----------------------------------------------------- | ------------------------------ | | `state` | [`TtsState`](/sdk/react-SDK/reference/types#ttsstate) | Current lifecycle state. | | `isSpeaking` | `boolean` | `state === 'speaking'`. | | `isConnecting` | `boolean` | `state === 'connecting'`. | | `error` | `Error \| null` | Last error, or `null` if none. | | `speak`, `sendText`, `finish`, `stop`, `cancel` | — | Control methods (see above). | ## Configuration See [`UseTtsConfig`](/sdk/react-SDK/reference/types#usettsconfig) for the full type. Most-used options: | Option | Type | Description | | -------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `config` | `SonioxConnectionConfig \| (() => Promise)` | Connection configuration. Required — `useTts` always uses its own client. | | `mode` | `'websocket' \| 'rest'` | Transport mode. Default `'websocket'`. | | `voice` | `string` | Voice identifier (e.g. `"Adrian"`). **Required** unless provided via server-returned `tts_defaults` (WebSocket mode only). Discover available voices via the Node SDK's `client.tts.listModels()`. | | `model` | `string` | TTS model. Default `"tts-rt-v2"`. | | `language` | `string` | Language code. Default `"en"`. | | `audio_format` | `TtsAudioFormat` | Output audio format. Default `"wav"`. | | `sample_rate` | `number` | Output sample rate in Hz. Required for raw PCM formats. | | `bitrate` | `number` | Codec bitrate in bps (for compressed formats). | | `stream_id` | `string` | Override the auto-generated stream id. WebSocket mode only. | See [Available models](/tts/models) for the full list of TTS models, voices, and supported audio formats. ## Server-driven defaults There's no first-class endpoint for TTS defaults — you own them. Keep them on your server next to the temporary-key endpoint and return them via `SonioxConnectionConfig.tts_defaults`. `useTts` consumes the defaults automatically through its `config` resolver; caller-provided hook options (`voice`, `model`, `audio_format`, ...) still override them. ```ts // server app.get('/tts-tmp-key', async (_req, res) => { const { api_key, expires_at } = await nodeClient.auth.createTemporaryKey({ usage_type: 'tts_rt', expires_in_seconds: 300, }); res.json({ api_key, expires_at, tts_defaults: { model: 'tts-rt-v2', language: 'en', voice: 'Adrian', audio_format: 'wav', }, }); }); ``` ```tsx // client async function fetchTtsKey() { const res = await fetch("/tts-tmp-key"); return await res.json(); // { api_key, tts_defaults, ... } } function TtsButton() { const audioChunksRef = useRef([]); // Inherits model / voice / audio_format from tts_defaults returned by the server. const { speak } = useTts({ config: fetchTtsKey, onAudio: (chunk) => audioChunksRef.current.push(chunk), }); return ; } ``` ## See also * [`useTts` return type](/sdk/react-SDK/reference/types#usettsreturn) and [config](/sdk/react-SDK/reference/types#usettsconfig) * [`TtsState` reference](/sdk/react-SDK/reference/types#ttsstate) * [Web SDK real-time TTS](/sdk/web-SDK/tts/realtime-speech-generation) — the underlying transport used in `'websocket'` mode. * [Web SDK REST TTS](/sdk/web-SDK/tts/rest-speech-generation) — the underlying transport used in `'rest'` mode. # React Native SDK URL: /sdk/react-native-SDK Build speech-to-text workflows in React Native with real-time API. Soniox [React SDK](/sdk/react-SDK) works with React Native and Expo out of the box, providing the same hooks for real-time speech-to-text. It lets you: * Capture audio from the device microphone with a single hook * Stream audio to Soniox in real time * Receive transcription and translation results as reactive state ## Quickstart ### Install Install via your preferred package manager: ```bash tab npm install @soniox/react @soniox/client ``` ```bash tab yarn add @soniox/react @soniox/client ``` ```bash tab pnpm add @soniox/react @soniox/client ``` ```bash tab bun add @soniox/react @soniox/client ``` ### Set up your temporary API key endpoint In client environments (browser, mobile app, React Native, etc.), you don't want to expose your API key. Create a temporary API key endpoint on your server and use it to issue short-lived keys for the client. Read more about using temporary API keys with the [React SDK](/sdk/react-SDK#set-up-your-temporary-api-key-endpoint). ### Create a custom audio source Wrap any RN audio streaming library (e.g. `@siteed/expo-audio-studio`) with the `AudioSource` interface to stream PCM audio chunks to Soniox ```ts import type { AudioSource, AudioSourceHandlers } from "@soniox/client"; class MyAudioSource implements AudioSource { private handlers: AudioSourceHandlers | null = null; async start(handlers: AudioSourceHandlers): Promise { this.handlers = handlers; // Start your audio capture here. // Call handlers.onData(chunk) with each audio chunk as an ArrayBuffer. // Call handlers.onError(error) if something goes wrong. // Call handlers.onMuted?.() / handlers.onUnmuted?.() when the mic is // muted or unmuted externally (e.g. OS-level, hardware switch). } stop(): void { // Stop audio capture and release resources. this.handlers = null; } } ``` ### Create your first real-time session The core hooks (e.g. [`useRecording`](/sdk/react-SDK/stt/realtime-transcription#userecording)) are platform-agnostic. To use them in React Native, provide a custom [`AudioSource`](/sdk/web-SDK/reference/types#audiosource) that streams PCM audio chunks ```tsx import { useRef } from "react"; import { SonioxProvider, useRecording } from "@soniox/react"; import { MyAudioSource } from "./MyAudioSource"; // Fetch a temporary API key from your server endpoint. async function fetchConfig() { const res = await fetch("/api/soniox-temporary-key", { method: "POST" }); const { api_key } = await res.json(); return { api_key }; } function App() { return ( // Wrap your app with a SonioxProvider. `permissions={null}` disables the // default browser permission resolver — not applicable on React Native. ); } function Transcription() { // Instantiate the audio source const sourceRef = useRef(null); if (sourceRef.current === null) { sourceRef.current = new MyAudioSource(); } // Create a recording session const { state, isActive, finalText, partialText, start, stop } = useRecording({ model: "stt-rt-v5", audio_format: "pcm_s16le", sample_rate: 16000, num_channels: 1, source: sourceRef.current, }); return ( {finalText} {partialText} {isActive ? (