Skip to content

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.mp3

The response body is the audio itself, not JSON.

Request fields

FieldRequiredTypeNotes
modelYesstringchorus, chorus-voices, chorus-clone, or chorus-design.
inputYesstringThe text to speak.
voiceNostringA preset id. Anything else is rejected.
instructionsNostringStyle guidance on a preset, or the voice description itself on chorus-design.
response_formatNostringmp3, opus, flac, wav, or pcm.
speedNonumberSpeaking rate multiplier, 0.25 to 4.0.
languageNostringOutput language. See languages.
stream_formatNostringsse or audio. Omit to buffer the whole clip.
ref_audioNostringInline data: URL of reference audio, on chorus-clone.
ref_textNostringTranscript of that reference audio.
cache_saltNostringPrefix-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_formatDelivery
omittedOne buffered response after generation finishes.
audioRaw chunked audio as it is generated.
ssespeech.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

StatusMeaning
400Validation error, an unknown voice, or a value outside an enum.
401Missing, invalid, or expired credentials.
402No payment method on the account.
403Not a member of the requested organization.
404No model by that name.
413Reference audio too large after transcoding.
429Rate limit exceeded.
503Temporarily unavailable: capacity, a cold model, or a dependency outage. Honor Retry-After when it is set.

Full schemas are in the speech reference.