Text-to-speech API
Synthesize speech from a string with the OpenAI-compatible speech endpoint, including streaming and audio formats.
POST /v1/audio/speech follows the OpenAI speech shape. If you already call
OpenAI for text to speech, change the base URL and the model.
The speech models are chorus-voices, chorus-clone, and chorus-design,
with chorus covering the first two. Symphony is rejected here with a 400; it
does not speak text you hand it, it speaks its own replies in a
speech to speech session.
Synthesize speech
curl https://api.sprag.ai/v1/audio/speech \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SPRAG_API_KEY" \
-d '{
"model": "chorus",
"input": "The quarterly numbers are in and they look good.",
"voice": "serena",
"response_format": "mp3"
}' \
--output out.mp3The response body is the audio itself, not JSON.
Request fields
| Field | Required | Type | Notes |
|---|---|---|---|
model | Yes | string | chorus, chorus-voices, chorus-clone, or chorus-design. |
input | Yes | string | The text to speak. |
voice | No | string | A preset id. Anything else is rejected. |
instructions | No | string | Style guidance on a preset, or the voice description itself on chorus-design. |
response_format | No | string | mp3, opus, flac, wav, or pcm. |
speed | No | number | Speaking rate multiplier, 0.25 to 4.0. |
language | No | string | Output language. See languages. |
stream_format | No | string | sse or audio. Omit to buffer the whole clip. |
ref_audio | No | string | Inline data: URL of reference audio, on chorus-clone. |
ref_text | No | string | Transcript of that reference audio. |
cache_salt | No | string | Prefix-cache isolation key. Overwritten when ref_audio is present. |
Set response_format when the container matters to whatever plays or stores
the file; omit it and the model's own container comes back. Omit speed to
leave the model at its normal rate; a value outside 0.25 to 4.0 is a
validation error.
Voices
Presets are listed per model, and the listing needs no key.
curl "https://api.sprag.ai/v1/audio/voices?model=chorus"model is required: omitting it is a 400, and a model that does not exist is
a 404. chorus returns all 56 presets, chorus-voices the nine built-in
speakers, and chorus-clone the 47 that ship with the cloning model. Ids come
back lowercase. There are no per-account voices, so any id not on this list is
rejected. To design or clone a voice instead, see Voices.
Streaming
Set stream_format when playback should start before generation finishes.
stream_format | Delivery |
|---|---|
| omitted | One buffered response after generation finishes. |
audio | Raw chunked audio as it is generated. |
sse | speech.audio.delta and speech.audio.done events. |
Streaming narrows the format choice. Only pcm and wav stream; any other
response_format alongside stream_format is a 400, and omitting
response_format on a streamed request gives you wav. Use pcm when the
bytes feed another pipeline: streamed wav carries 0xFFFFFFFF placeholder
sizes in its RIFF header, because the length is not known when the header goes
out, so anything that reads duration or size from the header misreports it.
Audio formats covers the choice in full.
Limits
Nothing caps the length of input. The request as a whole is admitted up to
100 MiB, so inline reference audio for cloning has to fit inside that. Rate
limits are per organization rather than per key, 60 requests per 60 seconds by
default, so every key in the org draws on one budget.
Rate limits has the headers and retry guidance.
Errors
| Status | Meaning |
|---|---|
400 | Validation error, an unknown voice, or a value outside an enum. |
401 | Missing, invalid, or expired credentials. |
402 | No payment method on the account. |
403 | Not a member of the requested organization. |
404 | No model by that name. |
413 | Reference audio too large after transcoding. |
429 | Rate limit exceeded. |
503 | Temporarily unavailable: capacity, a cold model, or a dependency outage. Honor Retry-After when it is set. |
Full schemas are in the speech reference.