v0.4.1 — Per-request length & body-size limits
- Maximum input length — a request is rejected if its transcript predicts more than ~46.5 s of generated audio (the generator’s hard ceiling), checked before synthesis so nothing is billed on a rejection. The limit is on predicted duration, not characters: it’s digit-aware and per-language, so a rough en-US guide is ~900 characters of prose but only ~130 digits (number-heavy text hits it with far less text). Over the limit returns
input_too_long—400on/tts/bytesand/tts/sse, or a per-context error frame (the socket stays open) on/tts/websocket. Split longer content across requests/turns. - Request body cap —
/tts/bytesand/tts/ssereject a body larger than 64 KB (65536 bytes) with413 payload_too_large. Normal requests are nowhere near this. - Unknown voice ids return
404— a misspelled or unknownvoice.idreturnsvoice_not_found(404) instead of falling back to a default;voice.idmust reference an existing voice.
v0.4.0 — Required voice & strict clone language
voiceis now required on/tts/bytes,/tts/sse, and/tts/websocket(per message) — there is no default voice anymore. A request that doesn’t resolve to a voice returns an error instead of silently synthesizing a default. The only accepted form is the nested object{ "mode": "id", "id": "<voice-id>" }; a top-levelvoice_idis not supported andmodemust be"id".- New voice/transcript error codes —
missing_voice,missing_voice_id,unknown_voice_mode(400),voice_not_found(404), andmissing_transcript(400). HTTP errors now use a{ error, error_code, message, detail }envelope (error_codeis canonical). - WebSocket is stricter — a message that omits
transcriptreturns amissing_transcripterror frame instead of a silentdone. The end-of-turn terminator (transcript: ""withcontinue: false) remains valid. - Voice-clone
languagemust be a valid BCP-47 tag —POST /voices/clonerejects malformed tags (en_US,en-USA,123) withinvalid_language(400). Send the full dialect (en-US); values are canonicalized on save (en-us→en-US).
v0.3.0 — Strict output formats, telephony & clearer limits
output_formatis now strictly validated — unsupported values return400instead of silently falling back. Supported:containerraw/wav,encodingpcm_s16le/pcm_mulaw/pcm_alaw,sample_rate8000/16000/22050.- Telephony encodings added — 8 kHz μ-law (
pcm_mulaw) and A-law (pcm_alaw) for Twilio/SIP media streams. - Removed formats —
mp3,pcm_f32le, and sample rates24000/44100/48000are no longer accepted. - Streaming is
raw-only —wavis available on/tts/bytesonly;/tts/sseand/tts/websocketrequireraw. - Limits clarified as per-org — rate and concurrency limits are shared across all of an org’s API keys; extra keys don’t add capacity. Concurrency is measured per active-speech turn, not per call.
- Dutch voices are now tagged
nl-NL(BCP-47 dialect) instead of barenl.
v0.2.0 — Cartesia-compatible API
- Cartesia-compatible surface:
POST /tts/bytes,POST /tts/sse,GET /tts/websocket,/voicesCRUD,POST /voices/clone - Model:
gepard-1.0 - Real-time WebSocket streaming with per-transcript billing
- Voice cloning and the full Cartesia voice library
- API keys now use the
sk_996_<prefix>_<secret>format, scoped to a project - Prepaid credits: 1 credit per character, $5 per 1M characters, credits never expire
- Per-project tiers (rate + concurrency): tier1 / tier2 / tier3, with auto-upgrade to tier2 at $50 lifetime spend
v0.1.0 — Initial Release
- OpenAI-compatible TTS API (deprecated; replaced by the Cartesia-compatible surface above)