API docs
An OpenAI-compatible text-to-speech endpoint, the first product on the gateway. If your code already speaks /v1/audio/speech, changing the base URL and the key is the whole migration. When another model family ships it gets its own section here, documented the same way.
Authentication
Every request carries your key as a bearer token:
Authorization: Bearer $MODELWORKS_KEY
Keys are issued by email - ask for one. The first 250,000 characters are free. Do not put the key in client-side code; if it leaks, tell us and it is revoked.
Create speech
POST https://api.modelworks.dev/v1/audio/speech
| Field | Required | What it is |
|---|---|---|
model | yes | kokoro or tts-1 - the same engine under two names |
input | yes | The text to read. Up to 2,000 characters per request |
voice | yes | A voice name from the list below, or a combination like af_sky+af_bella |
response_format | no | mp3 (default), wav, opus, flac, aac, pcm |
speed | no | Speaking rate, 1.0 by default |
curl https://api.modelworks.dev/v1/audio/speech \
-H "Authorization: Bearer $MODELWORKS_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"kokoro","voice":"af_sarah","input":"Text to read aloud."}' \
--output speech.mp3
The response is the audio file itself, in the format you asked for.
Limits
2,000 characters per request. Longer text is chunked by you, not by the API - split on sentence boundaries and concatenate the audio. This keeps a single request from holding the box for minutes.
When the box is saturated you get 503 with a Retry-After: 1 header. That means overloaded, not rate-limited: back off a second and retry. The OpenAI SDKs honour the header.
Per-key rate limits are set when the key is issued and stated in the email with it.
Call platforms and IVR
If the audio is going into a phone system rather than a file, the format is the only part that differs. The API returns 24 kHz audio in mp3, wav, opus, flac, aac or pcm, and telephony almost always wants 8 kHz mono mu-law. That is one conversion pass, and this is the exact command that produced the file we checked:
curl https://api.modelworks.dev/v1/audio/speech \
-H "Authorization: Bearer $MODELWORKS_KEY" -H "Content-Type: application/json" \
-d '{"model":"kokoro","voice":"af_heart","input":"Press one for sales.","response_format":"wav"}' \
--output prompt.wav
ffmpeg -i prompt.wav -ar 8000 -ac 1 -c:a pcm_mulaw prompt-8k.wav
ffprobe -show_entries stream=codec_name,sample_rate,channels prompt-8k.wav
# codec_name=pcm_mulaw sample_rate=8000 channels=1
Worth knowing before you build around this: the conversion is downstream of us, so the text still never leaves the request - the audio comes back at 24 kHz and you resample it on your side. IVR prompts, voicemail greetings, hold messages and campaign scripts are all short, cacheable text, which is the cheapest shape of this product to run.
Errors
| Status | Meaning | What to do |
|---|---|---|
401 | The key is missing or not valid | Check the Authorization header |
422 | The request is malformed, input is over 2,000 characters, or the key's character allowance is used up - the body carries "type": "budget_exceeded" in that case | Fix the body, split longer text, or top up the key; the error type tells you which |
429 | A per-key limit was exceeded | Back off; the limit is in your key email |
503 | The box is at capacity | Wait for Retry-After and retry |
Voices
54 voices across nine languages. Names follow the engine's own convention: the first letter is the language, the second the gender - af is American English female, hm is Hindi male.
| Language | Female | Male |
|---|---|---|
| American English | af_heart, af_alloy, af_aoede, af_bella, af_jessica, af_kore, af_nicole, af_nova, af_river, af_sarah, af_sky | am_adam, am_echo, am_eric, am_fenrir, am_liam, am_michael, am_onyx, am_puck, am_santa |
| British English | bf_alice, bf_emma, bf_isabella, bf_lily | bm_daniel, bm_fable, bm_george, bm_lewis |
| Hindi | hf_alpha, hf_beta | hm_omega, hm_psi |
| Japanese | jf_alpha, jf_gongitsune, jf_nezumi, jf_tebukuro | jm_kumo |
| Mandarin Chinese | zf_xiaobei, zf_xiaoni, zf_xiaoxiao, zf_xiaoyi | zm_yunjian, zm_yunxi, zm_yunxia, zm_yunyang |
| Spanish | ef_dora | em_alex, em_santa |
| French | ff_siwis | |
| Italian | if_sara | im_nicola |
| Brazilian Portuguese | pf_dora | pm_alex, pm_santa |
Voice quality varies with how much training audio each voice had. af_heart and af_bella are the strongest; some of the smaller voices are noticeably thinner. Five of them are on the front page to listen to, and the free tier is what lets you try your own text on the voice you actually want before committing.