API reference
Sautna API
One endpoint. Send text with your API key, receive a WAV file (24 kHz, mono, 16-bit). Create keys in Studio → API keys (paid plans).
Synthesize speech
POST /api/v1/tts
| Field | Type | Description |
|---|---|---|
| text | string | The Arabic text to speak. Per-request length depends on your plan. |
| voice | string | Voice id. zol (male, default) or zola (female). |
Success responses include X-Characters-Billed and X-Quota-Remaining headers. Errors are JSON: {"error": {"code", "message"}}.
curl
curl -X POST https://sautna.com/api/v1/tts \
-H "Authorization: Bearer sautna_sk_..." \
-H "Content-Type: application/json" \
-d '{"voice": "zol", "text": "أهلين! كيفنك؟"}' \
--output speech.wavPython
import requests
resp = requests.post(
"https://sautna.com/api/v1/tts",
headers={"Authorization": "Bearer sautna_sk_..."},
json={"voice": "zol", "text": "أهلين! كيفنك؟"},
)
resp.raise_for_status()
open("speech.wav", "wb").write(resp.content)JavaScript
const res = await fetch("https://sautna.com/api/v1/tts", {
method: "POST",
headers: {
Authorization: "Bearer sautna_sk_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ voice: "zol", text: "أهلين! كيفنك؟" }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
await Bun.write("speech.wav", await res.arrayBuffer()); // or fs.writeFileLimits by plan
| Plan | Chars / month | Chars / request | Requests / min |
|---|---|---|---|
| Free | 5,000 | 300 | 6 |
| Starter | 100,000 | 1,000 | 20 |
| Pro | 500,000 | 2,000 | 60 |
| Scale | 2,500,000 | 3,000 | 180 |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | missing_api_key / invalid_api_key | No key sent, or the key was revoked. |
| 402 | quota_exceeded | Monthly character quota used up — upgrade or wait for reset. |
| 403 | api_not_included | API access needs a paid plan. |
| 404 | unknown_voice | The voice id doesn't exist. |
| 413 | text_too_long | Text exceeds your plan's per-request limit. |
| 429 | rate_limited | Too many requests per minute — back off and retry. |
| 502/504 | synthesis_failed | Upstream synthesis error or timeout — safe to retry. |
Cold starts
Synthesis runs on GPUs that scale to zero when idle. After a quiet period the first request can take up to ~90 seconds while a GPU boots; subsequent requests take a few seconds. Set client timeouts to at least 120 seconds, or send a short warm-up request before a batch.