API reference
Batch TTS API
POST /tts/speak synthesises speech from text and streams the audio back — standalone, no call required. Same API key, same balance as your agents. No agent required — you pick the provider and voice directly.
Synthesise speech
POST /tts/speak
{
"text": "Your appointment is confirmed for Friday at 2pm.",
"voice_id": "autumn",
"provider": "groq",
"model": null,
"language": "en",
"rate": 1.0,
"volume": 1.0,
"format": "mp3"
}
| field | type | notes |
|---|---|---|
text | string | required — 1–8000 characters |
voice_id | string | required — a voice id from GET /tts/voices |
provider | string | groq (default), edge, elevenlabs, deepgram, inworld, voxtral. Unknown → 422 |
model | string | optional — defaults to the provider's primary model |
language | string | en or fr |
rate | number | 0.5–2.0, applied by providers that support it |
volume | number | 0.0–2.0, applied by providers that support it |
format | string | mp3 (default), wav, or flac |
The response is a chunked audio stream with the matching Content-Type (audio/mpeg for mp3, etc.). Two response headers:
| header | meaning |
|---|---|
X-Wakili-Cache | hit or miss — was this served from the cache? |
X-Wakili-Cost-Usd | amount charged for this request (0 on a cache hit) |
Caching (not determinism)
TTS providers do not guarantee byte-identical audio for the same input across calls, so Wakili does not promise deterministic output. Instead it caches: the first synthesis for a given (provider, model, voice_id, rate, volume, format, text) tuple is stored, and every later request with the exact same tuple replays the stored audio. A cache hit is not billed (X-Wakili-Cache: hit, X-Wakili-Cost-Usd: 0). If you need the same audio twice, request it with identical parameters and the second call is free.
List voices
GET /tts/voices?language=en
{
"language": "en",
"voices": {
"groq": ["autumn", "diana", "hannah", "austin", "daniel", "troy"],
"elevenlabs": ["21m00Tcm4TlvDq8ikWAM", "..."]
}
}
Omit language for the full list. Providers whose model is multilingual are always included; single-language voices are filtered to the requested language.
Billing
You pay the provider's list price for the character count, plus a flat 10% routing fee:
cost_usd = upstream_cost_usd × 1.10
upstream_cost_usd is the per-1000-character list price for the chosen provider. Debited from the same balance as calls. 402 with code: "insufficient_balance" if the balance can't cover it (checked before synthesis). A cache hit skips billing entirely.
Errors
| status | when |
|---|---|
401 | missing/invalid API key |
402 | insufficient balance |
422 | invalid body (text length, missing voice_id, unknown provider, bad format) |
502 | upstream TTS provider error |