Languages and accents
Which tags the router accepts, what a region subtag changes, and which accents have a validated voice.
One BCP 47 tag carries two decisions.
- Language — the base subtag,
es. Picks which benchmark board ranks the models. Applies to STT, LLM and TTS. - Accent — the region subtag,
PR. Narrows TTS to the voices that produce that accent. Most vendors that speak a language do not speak every regional accent of it.
So es-PR means: rank on the Spanish board, and only consider Puerto Rican voices.
Set it on the key (language) or per request with X-Speko-Language.
Which tags a key routes today, and which accents have a validated voice, are in supported languages. This page is how the tag is interpreted.
An accent is an ordered candidate list: a measured voice first, then a steering fallback on a model that can be directed to produce the accent. The mapping changes as voices are measured and replaced, so x-route on the response, not a table, is what served a given request.
Accent only affects TTS
STT and LLM read the base subtag and ignore the region: transcription and completion are accent-independent, so es, es-CO and es-419 resolve identically for both.
A language can still carry an ordered STT provider preference, tried ahead of the board for that language. Spanish prefers ElevenLabs Scribe, then Soniox. It is a preference and not a restriction — a provider that cannot serve the request is skipped and the rest of the board keeps its order behind it. GET /v1/routing/preview?stage=stt&language=es returns the result.
What wins
Highest first:
voicein the request body — an explicit voice wins outright.- A candidate set that holds none of the accent's vendors —
X-Speko-Allow,X-Speko-Denyor a keyttschain naming other vendors leaves the accent nothing to attach to. - The accent — the voices measured for that accent.
- The ranked board — the language's benchmark ranking.
Rule 2 is narrower than it reads. The accent voice is resolved from the tag and the winning vendor's protocol, so a chain that includes the accent's vendors still produces the accent voice: X-Speko-Allow: cartesia:sonic-3.5 with es-PR gets the Puerto Rican voice, not Cartesia's default Spanish one. A chain naming only vendors that hold no voice for that accent is what drops it.
So for accent routing on a pinned key, either leave the tts chain empty or pin the accent's own vendors.
Accents on the streaming routes
Accent tags work on POST /v1/audio/speech/stream, which reaches every provider able to deliver progressive audio.
They do not work on GET /v1/synthesize/stream. That route is served only by vendors speaking a WebSocket TTS protocol, and no accent voice sits behind one — the two sets do not intersect. Allow only accent vendors there and the socket returns zero bytes, then closes without an error frame. Use chunked HTTP when the accent matters.
A steered accent has a text budget, and crossing it drops the accent silently.
Steering runs on a model whose stream truncates past roughly a minute of audio, so above 700 bytes of UTF-8 the router stops offering it on a streaming route. Bytes, not characters: an accented character costs two, so ordinary Spanish crosses at about 674.
Past the budget the request still returns 200, served by the next allowed vendor, which
holds no voice for that accent, and nothing in the response says so. To make that case loud,
allow only the steering vendor for the tag — the request then returns
503 no_streaming_tts_provider rather than the wrong accent. For longer text use
batch, which has no budget.
Accent direction is never spoken
A steered accent puts the direction in the provider's system-instruction field, not in the text, so the listener hears your input and nothing else.
Send your own instructions and yours replaces it — which also drops the accent direction, so state the accent yourself if you still want it.
Checking the ranking evidence
Not every language has its own measured board. When one does not, ranking falls back to English, and the router says so:
x-route-reason: lang=es(measured)| Value | Meaning |
|---|---|
lang=xx(measured) | The language has its own board. |
lang=xx(english-proxy) | No board for this language; ranked on English. |
lang=xx(none) | No ranking evidence. |
english-proxy means the order is a guess about your language, and pinning may beat it.