Reference
REST API
Every HTTP endpoint, from the router's OpenAPI document.
Provider keys#
Set, list and delete your org’s provider keys with an API key, as the dashboard does. Write-only: a stored key is never returned.
get/v1/provider-keysList your provider keys
GET https://api.ttscacherouter.dev/v1/provider-keys
Which providers have a key stored, with each key's last four characters.
Responses
200Successful Response
An array of ProviderKey:
provider"sarvam" | "raya" | "elevenlabs"Requiredlast4stringRequired- The key's last four characters. The key itself is never returned.
updated_atstring (date-time)Required
401Not signed in, or the session expired
422Validation Error
put/v1/provider-keys/{provider}Set or replace a provider key
PUT https://api.ttscacherouter.dev/v1/provider-keys/{provider}
Stored encrypted and never returned. The router uses a new or replaced key within seconds.
Parameters
providerpath, "sarvam" | "raya" | "elevenlabs"Required
Request body
api_keystring, min length 1, max length 512Required- Your key for the provider. Stored encrypted; it can't be read back.
{ "api_key": "sk_…"}Responses
200Successful Response
provider"sarvam" | "raya" | "elevenlabs"Requiredlast4stringRequired- The key's last four characters. The key itself is never returned.
updated_atstring (date-time)Required
Example { "last4": "x9Qa", "provider": "sarvam", "updated_at": "2026-10-10T09:32:00Z"}401Not signed in, or the session expired
422The request failed validation
delete/v1/provider-keys/{provider}Delete a provider key
DELETE https://api.ttscacherouter.dev/v1/provider-keys/{provider}
Requests for this provider fail with provider_key_missing within seconds.
Parameters
providerpath, "sarvam" | "raya" | "elevenlabs"Required
Responses
204Successful Response
401Not signed in, or the session expired
404Not found, or not visible to the signed-in user
422Validation Error
Models#
What the router accepts, per provider. No authentication.
get/v1/modelsList providers and models
GET https://api.ttscacherouter.dev/v1/models
Every provider and model the router accepts, with the voices, languages, speed range, sample rates, formats and options each one takes. No authentication.
Responses
200Successful Response
providersProvider[]Required
Example { "providers": [ { "docs_url": "https://docs.sarvam.ai/api-reference/text-to-speech/stream", "formats": [ "pcm", "wav", "mp3", "aac", "mulaw", "alaw" ], "id": "sarvam", "models": [ { "id": "bulbul:v3", "languages": [ "hi-IN", "en-IN" ], "voices": [ "shubh", "aditya", "ritu" ], "voices_url": "https://docs.sarvam.ai/api/getting-started/models/bulbul" } ], "name": "Sarvam", "options": [ { "default": 0.6, "description": "Sampling temperature.", "max": 1, "min": 0.01, "name": "temperature", "nullable": false, "type": "number", "models": null }, { "default": 0, "description": "Pitch: lower is deeper, higher is sharper.", "max": 0.5, "min": -0.5, "models": [ "bulbul:v4-flash" ], "name": "pitch", "nullable": false, "type": "number", "values": null } ], "sample_rates": [ 8000, 16000, 22050, 24000 ], "speech_sample_rates": [ 8000, 16000, 22050, 24000, 32000, 44100, 48000 ], "speed": { "max": 2, "min": 0.5 } } ]}
Speech#
Shaped like OpenAI’s. The guide is /v1/audio/speech.
post/v1/audio/speechCreate speech
POST https://api.ttscacherouter.dev/v1/audio/speech
Synthesizes input, shaped like OpenAI's audio/speech, so the OpenAI SDK works with base_url="https://api.ttscacherouter.dev/v1" and your tcr_ key. Provider-specific fields go in the body (extra_body in the OpenAI SDK).
The input is split into sentences; each one your org has synthesized before with the same settings is served from the cache, the rest by the provider with your stored provider key. Audio streams back as each sentence resolves. An error after audio has started can only abort the body.
Request body
modelstringRequired<provider>/<model>:sarvam/bulbul:v3,sarvam/bulbul:v4-flash,raya/standard,raya/m1, or an ElevenLabs model such aselevenlabs/eleven_flash_v2_5(seeGET /v1/models).inputstring, min length 1Required- The text to speak.
voicestring, min length 1Required- The provider's voice id: a Sarvam speaker, a Raya voice id or an ElevenLabs voice id.
languagestring | null, min length 1- The provider's language code, e.g.
hi-IN(Sarvam),hi(Raya),en(ElevenLabs). Required for Sarvam and Raya; optional for ElevenLabs, which otherwise detects the language. response_format"pcm" | "wav" | "mp3" | "aac" | "mulaw" | "alaw" | "flac" | "opus"pcm(s16le mono),wav,mp3,aac,mulaworalaw. Raya supportspcm,wavandmulaw; ElevenLabspcm,wav,mp3,mulawandalaw.flacandopusare not supported.speednumber- Sarvam 0.5–2.0, Raya 0.5–1.5. Not for ElevenLabs, whose speed is
voice_settings.speed. sample_rate8000 | 16000 | 22050 | 24000 | 32000 | 44100 | 48000- 32000, 44100 and 48000 are Sarvam's over its REST API (one request per sentence), where
bitrateis fixed at 128k, and ElevenLabs'pcm. ElevenLabs'mp3is 22050, 24000 or 44100 Hz; itsmulawandalaw8000 Hz (their default). stream_format"audio"- Only
audio: the body is the audio itself. temperaturenumber | null- Sarvam only: 0.01–1.0, default 0.6.
dict_idstring | null- Sarvam only: a pronunciation dictionary.
bitrate"32k" | "48k" | "64k" | "96k" | "128k" | "192k" | nullmp3(and Sarvam'saac). Sarvam: 32k–192k, default128k. ElevenLabs: 32k at 22050 Hz, 48k at 24000 Hz, 32k–192k at 44100 Hz (default 128k).pitchnumber | null- Sarvam
bulbul:v4-flashonly: -0.5 (deeper) to 0.5 (higher), default 0. loudnessnumber | null- Sarvam
bulbul:v4-flashonly: 0.1–2.5, default 1.0. enable_preprocessingboolean | null- Sarvam
bulbul:v4-flashonly: normalize numbers and English words in the text before synthesis. Default false. min_buffer_sizeinteger | null, ≥ 30, ≤ 200- Sarvam only: characters Sarvam buffers before it starts synthesizing, 30–200. Default: the router's choice, the least Sarvam allows.
max_chunk_lengthinteger | null, ≥ 50, ≤ 500- Sarvam only: the longest text Sarvam synthesizes in one piece, 50–500; it splits longer sentences. Default: the router's choice, the most Sarvam allows, so each sentence is synthesized whole.
voice_settingsobject | null- ElevenLabs only: the voice's settings; null for its stored settings. Dialogue models (
eleven_v3,eleven_v4) usestabilityonly. apply_text_normalization"auto" | "on" | "off" | null- ElevenLabs only:
auto(default),onoroff. apply_language_text_normalizationboolean | null- ElevenLabs only: language-specific normalization (Japanese).
enable_ssml_parsingboolean | null- ElevenLabs only: parse SSML tags. Default false.
enable_loggingboolean | null- ElevenLabs only: false for ElevenLabs' zero-retention mode (enterprise accounts). Default true.
pronunciation_dictionary_locatorsobject[] | null- ElevenLabs only: up to 3 pronunciation dictionary versions.
{ "input": "नमस्ते, मैं सिटी हॉस्पिटल से प्रिया बोल रही हूँ।", "language": "hi-IN", "model": "sarvam/bulbul:v3", "response_format": "mp3", "voice": "shubh"}Responses
200The audio, streamed.
400Invalid request, or the provider refused it
401Missing or invalid API key
402The org is out of credit (`insufficient_credits`): buy credit in the dashboard
429Your provider quota is exhausted
502The provider failed
504The provider timed out
Provider drop-ins#
Mirrors of each provider's own endpoints. The WebSockets aren't in OpenAPI; each provider's drop-in page lists them.
Sarvam drop-in
post/sarvam/text-to-speech/streamSarvam: text to speech (HTTP stream)
POST https://api.ttscacherouter.dev/sarvam/text-to-speech/stream
Mirrors POST https://api.sarvam.ai/text-to-speech/stream ([Sarvam's reference](https://docs.sarvam.ai/api-reference/text-to-speech/convert-stream)): the same body, response and errors. Send your tcr_ key in api-subscription-key; the request goes to Sarvam verbatim with your stored Sarvam key. Each request is one cache entry; a hit returns the stored audio with the codec's Content-Type. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Request body
Responses
200Successful Response
post/sarvam/text-to-speechSarvam: text to speech (REST)
POST https://api.ttscacherouter.dev/sarvam/text-to-speech
Mirrors POST https://api.sarvam.ai/text-to-speech ([Sarvam's reference](https://docs.sarvam.ai/api-reference/text-to-speech/convert)): the same body, response and errors. Send your tcr_ key in api-subscription-key; the request goes to Sarvam verbatim with your stored Sarvam key. Each request is one cache entry; a hit returns {"request_id": null, "audios": [...]}. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Request body
Responses
200Successful Response
Raya drop-in
post/raya/v1/text-to-speechRaya: text to speech (REST)
POST https://api.ttscacherouter.dev/raya/v1/text-to-speech
Mirrors POST https://hub.getraya.app/v1/text-to-speech ([Raya's reference](https://docs.litwizlabs.com/api-reference/text-to-speech/text-to-speech)): the same body, response and errors. Send your tcr_ key in X-API-Key; the request goes to Raya verbatim with your stored Raya key. Each request is one cache entry; a hit returns the stored bytes with Raya's headers. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Request body
Responses
200Successful Response
post/raya/v1/text-to-speech/streamRaya: text to speech (SSE stream)
POST https://api.ttscacherouter.dev/raya/v1/text-to-speech/stream
Mirrors POST https://hub.getraya.app/v1/text-to-speech/stream ([Raya's reference](https://docs.litwizlabs.com/api-reference/text-to-speech/text-to-speech-stream)): the same body, response and errors. Send your tcr_ key in X-API-Key; the request goes to Raya verbatim with your stored Raya key. Each request is one cache entry; a hit replays the stored samples as chunk events (without step_time), then done. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Request body
Responses
200Successful Response
get/raya/v1/voicesRaya: list voices
GET https://api.ttscacherouter.dev/raya/v1/voices
Mirrors GET https://hub.getraya.app/v1/voices ([Raya's reference](https://docs.litwizlabs.com/api-reference/voices/list-voices)): the same body, response and errors. Send your tcr_ key in X-API-Key; the request goes to Raya verbatim with your stored Raya key. Not cached. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Responses
200Successful Response
ElevenLabs drop-in
post/elevenlabs/v1/text-to-speech/{voice_id}ElevenLabs: text to speech
POST https://api.ttscacherouter.dev/elevenlabs/v1/text-to-speech/{voice_id}
Mirrors POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id} ([ElevenLabs' reference](https://elevenlabs.io/docs/api-reference/text-to-speech/convert)): the same query, body, response and errors. Send your tcr_ key in xi-api-key; the request goes to ElevenLabs verbatim with your stored ElevenLabs key. Each request is one cache entry; a hit replays the stored response. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Parameters
voice_idpath, stringRequired
Request body
Responses
200Successful Response
post/elevenlabs/v1/text-to-speech/{voice_id}/streamElevenLabs: text to speech (stream)
POST https://api.ttscacherouter.dev/elevenlabs/v1/text-to-speech/{voice_id}/stream
Mirrors POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream ([ElevenLabs' reference](https://elevenlabs.io/docs/api-reference/text-to-speech/stream)): the same query, body, response and errors. Send your tcr_ key in xi-api-key; the request goes to ElevenLabs verbatim with your stored ElevenLabs key. Each request is one cache entry; a hit replays the stored response. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Parameters
voice_idpath, stringRequired
Request body
Responses
200Successful Response
post/elevenlabs/v1/text-to-speech/{voice_id}/with-timestampsElevenLabs: text to speech with timestamps
POST https://api.ttscacherouter.dev/elevenlabs/v1/text-to-speech/{voice_id}/with-timestamps
Mirrors POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id}/with-timestamps ([ElevenLabs' reference](https://elevenlabs.io/docs/api-reference/text-to-speech/convert-with-timestamps)): the same query, body, response and errors. Send your tcr_ key in xi-api-key; the request goes to ElevenLabs verbatim with your stored ElevenLabs key. Each request is one cache entry; a hit replays the stored response. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Parameters
voice_idpath, stringRequired
Request body
Responses
200Successful Response
post/elevenlabs/v1/text-to-speech/{voice_id}/stream/with-timestampsElevenLabs: text to speech with timestamps (stream)
POST https://api.ttscacherouter.dev/elevenlabs/v1/text-to-speech/{voice_id}/stream/with-timestamps
Mirrors POST https://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream/with-timestamps ([ElevenLabs' reference](https://elevenlabs.io/docs/api-reference/text-to-speech/stream-with-timestamps)): the same query, body, response and errors. Send your tcr_ key in xi-api-key; the request goes to ElevenLabs verbatim with your stored ElevenLabs key. Each request is one cache entry; a hit replays the stored response. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Parameters
voice_idpath, stringRequired
Request body
Responses
200Successful Response
post/elevenlabs/v1/text-to-dialogue/streamElevenLabs: text to dialogue (stream)
POST https://api.ttscacherouter.dev/elevenlabs/v1/text-to-dialogue/stream
Mirrors POST https://api.elevenlabs.io/v1/text-to-dialogue/stream ([ElevenLabs' reference](https://elevenlabs.io/docs/api-reference/text-to-dialogue/stream)): the same query, body, response and errors. Send your tcr_ key in xi-api-key; the request goes to ElevenLabs verbatim with your stored ElevenLabs key. Each request is one cache entry; a hit replays the stored response. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Request body
Responses
200Successful Response
get/elevenlabs/v1/voicesElevenLabs: list voices
GET https://api.ttscacherouter.dev/elevenlabs/v1/voices
Mirrors GET https://api.elevenlabs.io/v1/voices ([ElevenLabs' reference](https://elevenlabs.io/docs/api-reference/voices/search)): the same query, response and errors. Send your tcr_ key in xi-api-key; the request goes to ElevenLabs verbatim with your stored ElevenLabs key. Not cached. An org out of credit is refused with HTTP 402 in the provider's error shape, code insufficient_credits.
Responses
200Successful Response
OpenAPI document#
The whole HTTP API as OpenAPI 3.1, for code generators and API clients. The WebSocket protocol has its own page.
curl https://api.ttscacherouter.dev/openapi.jsonIt also lists the dashboard’s session endpoints (/api/…), which take the dashboard’s sign-in cookie rather than an API key and aren’t meant for your code.