1Authentication
Every request to /v1/* must include your secret key in the X-API-Key header (a Authorization: Bearer <key> fallback is also accepted). Keep the key server-side — never expose it in a browser or mobile client.
curl https://tts-api.sikasio.com/v1/voices \
-H "X-API-Key: ttk_live_your_key_here"
401 invalid_key. Each key has its own rate + daily limits — see Limits.2Quickstart
The fastest path: send text with ?wait=true and get the finished audio URL back in one call (blocks up to 120s).
curl -X POST "https://tts-api.sikasio.com/v1/speak?wait=true" \
-H "X-API-Key: ttk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"text":"Your brand, brought to life.","language":"en","gender":"female"}'
Response:
{
"id": "c8db555a-…",
"status": "done",
"audio": {
"url": "https://tts-api.sikasio.com/files/c8db555a-…wav",
"durationSec": 4,
"format": "wav"
}
}
For longer text or batch jobs, omit wait to get a job id immediately (202) and poll it.
3Create speech
Synthesizes speech from text. Returns 202 { id } immediately (async). Add ?wait=true to block until the audio is ready and receive the finished job.
Body parameters
| Field | Type | Default | Description |
|---|---|---|---|
text required | string | — | The text to speak. 1–5000 characters. |
language optional | string | en | Spoken language: en (English) or ar (Arabic). |
gender optional | string | female | Voice gender: male or female. |
format optional | string | wav | Audio format: wav (24kHz PCM) or mp3. |
rate optional | number | 1.0 | Speaking rate, 0.25–2.0. Lower is slower. |
style optional | string | — | A short delivery hint, e.g. "warm and upbeat" (max 500 chars). |
Query
wait | Set true to block for the result (up to 120s) and return the settled job instead of 202. |
Example
curl -X POST https://tts-api.sikasio.com/v1/speak \
-H "X-API-Key: ttk_live_…" -H "Content-Type: application/json" \
-d '{"text":"ابدأ رحلتك اليوم","language":"ar","gender":"male","format":"mp3"}'
→ 202 { "id": "7d09…", "status": "queued" }
4Poll a job
Returns the current state of a job. A key can only read jobs it created; unknown or foreign ids return 404.
Lifecycle
| status | meaning |
|---|---|
queued | Accepted, waiting for a worker. |
running | Synthesizing. |
done | Finished — audio is present. |
failed | Could not synthesize — see error. |
Response (done)
{
"id": "7d09…",
"status": "done",
"audio": { "url": "https://…/files/7d09…mp3", "durationSec": 4.7, "format": "mp3" }
}
Recommended polling: every 1–2s until status is done or failed.
5Voices
Lists the available (language, gender) combinations. Voices are warm and natural, tuned for narration and marketing.
| language | gender | tone | locale |
|---|---|---|---|
English (en) | female | warm | en-US |
English (en) | male | warm | en-US |
Arabic (ar) | female | warm | ar-EG |
Arabic (ar) | male | warm | ar-EG |
6Audio files
On success a job returns audio.url, a public link served from /files/<name> with unguessable filenames. Download it, or use it directly in a video/render pipeline.
| property | value |
|---|---|
| WAV | Linear PCM, mono, 24 kHz, 16-bit — with a click-free fade-in and end padding. |
| MP3 | Compressed, smaller download. |
durationSec | Measured length in seconds (rounded to 0.1). Useful for timing/sync. |
| Caching | Cache-Control: immutable, 7 days. |
| Retention | Files are pruned after 7 days. Persist anything you need to keep. |
7Errors
Errors return a JSON body { "error": { "code", "message" } } with the matching HTTP status.
| HTTP | code | when |
|---|---|---|
| 400 | bad_request | Missing/invalid field (e.g. empty text, bad language). |
| 400 | bad_json | Body is not valid JSON. |
| 401 | invalid_key | Missing or unrecognized API key. |
| 404 | not_found | Job id doesn't exist or isn't yours; unknown endpoint. |
| 413 | too_large | Request body exceeds the size limit. |
| 429 | rate_limited | Per-key rate or daily cap exceeded — retry after the window. |
| 502 | failed / synth error | Synthesis failed (with ?wait=true). |
| 503 | busy | Queue is full — honor Retry-After and retry. |
8Rate limits
Each API key has a requests-per-minute limit and a daily cap. Exceeding either returns 429. Jobs run with bounded concurrency, so a burst may briefly queue rather than fail. If you need higher limits, request a new key with a larger allowance.
| endpoint | counts toward limit? |
|---|---|
POST /v1/speak | Yes — one unit per created job. |
GET /v1/jobs/:id, GET /v1/voices | No quota cost (subject to a basic IP floor). |