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"Required
    last4stringRequired
    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.
Example
{  "api_key": "sk_…"}

Responses

  • 200Successful Response

    provider"sarvam" | "raya" | "elevenlabs"Required
    last4stringRequired
    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 as elevenlabs/eleven_flash_v2_5 (see GET /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, mulaw or alaw. Raya supports pcm, wav and mulaw; ElevenLabs pcm, wav, mp3, mulaw and alaw. flac and opus are 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 bitrate is fixed at 128k, and ElevenLabs' pcm. ElevenLabs' mp3 is 22050, 24000 or 44100 Hz; its mulaw and alaw 8000 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" | null
mp3 (and Sarvam's aac). Sarvam: 32k–192k, default 128k. ElevenLabs: 32k at 22050 Hz, 48k at 24000 Hz, 32k–192k at 44100 Hz (default 128k).
pitchnumber | null
Sarvam bulbul:v4-flash only: -0.5 (deeper) to 0.5 (higher), default 0.
loudnessnumber | null
Sarvam bulbul:v4-flash only: 0.1–2.5, default 1.0.
enable_preprocessingboolean | null
Sarvam bulbul:v4-flash only: 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) use stability only.
apply_text_normalization"auto" | "on" | "off" | null
ElevenLabs only: auto (default), on or off.
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.
Example
{  "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.json

It 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.