Text to speech
POST /v1/audio/speech is OpenAI-compatible speech synthesis. The response
is binary audio with a content type derived from response_format.
curl "$SONIX_URL/v1/audio/speech" \
-H "Authorization: Bearer $SONIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kokoro-82m",
"input": "Hello from sonix.",
"voice": "af_heart",
"response_format": "wav",
"speed": 1.0
}' --output hello.wav
Request fields
| Field | Required | Notes |
|---|---|---|
model | yes | A speech-capable model ID. See Models. |
input | yes | The text to synthesize. |
voice | yes | A voice ID or OpenAI-style name (alloy, …), or an object like { "id": "af_heart" }. See Voices. |
response_format | no | mp3 (default), opus, aac, flac, wav, or pcm. |
speed | no | 0.25 to 4.0. Defaults to 1.0. |
instructions | no | Forwarded to the model as synthesis metadata. Not delivered to qwen3-tts-0.6b; see below. |
stream_format | no | audio (default). sse is rejected until event streaming ships. |
wav responses are wrapped in a WAV container server-side; other formats
are returned as produced by the model. Unsupported parameters are rejected
with a validation error rather than silently ignored.
Format support varies by model. qwen3-tts-0.6b produces pcm and wav
only: an omitted response_format returns wav there, an explicit mp3,
opus, aac or flac returns a validation error. On that model speed
is accepted but currently unapplied; the x-zzz-speed-applied response
header reports the speed actually used. instructions is not delivered
to that model either; only input, voice, response_format and speed
reach it.
Using the OpenAI SDK
Any OpenAI SDK works by overriding the base URL:
from openai import OpenAI
client = OpenAI(base_url=f"{SONIX_URL}/v1", api_key=SONIX_API_KEY)
speech = client.audio.speech.create(
model="kokoro-82m",
voice="af_heart",
input="Hello from sonix.",
response_format="wav",
)
speech.write_to_file("hello.wav")
