Audio
/v1/audio/speechbinary audio stream/v1/audio/transcriptionsmultipart/form-data/v1/audio/voicesJSON listSpeech (text-to-speech)
Returns audio bytes. The gateway streams the provider's response through without buffering (chunked transfer), so playback can start before synthesis finishes.
curl "https://api.osmexo.com/v1/audio/speech" \
-H "Authorization: Bearer $OSMEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/tts-1",
"input": "The gateway routes each request to the best available provider.",
"voice": "alloy",
"response_format": "mp3",
"speed": 1.0
}' --output speech.mp3| Field | Type | Notes |
|---|---|---|
model | string, required | Speech model id. |
input | string ≤ 40,000 chars, required | Text to speak. |
voice | string | A voice id from GET /v1/audio/voices for a model that publishes one, or the provider's own voice name otherwise. Omit voice to use the model's default. |
response_format | mp3 | opus | aac | flac | wav | pcm | Default mp3. Sets the response Content-Type (audio/mpeg, audio/ogg, audio/aac, audio/flac, audio/wav, audio/pcm). Formats are per model — an ElevenLabs speech model answers mp3, opus or pcm only. |
speed | number 0.25–4 | |
routing | object | Routing override. |
Response headers include X-Request-Id, X-LLM-Model and X-LLM-Cost-Micro. Speech is priced per character or per audio second depending on the model (see the model's pricing keys).
Streaming behaviour
- Headers are sent as soon as the provider starts responding; bytes are forwarded as they arrive.
- Retries and fallback apply only before the first byte is forwarded. A provider failure after that closes the connection early; check that the received byte count matches
Content-Lengthwhen the provider supplies one, or that the container decodes cleanly. Idempotency-Keyis accepted (optional).
const res = await client.audio.speech.create({
model: 'openai/tts-1',
voice: 'alloy',
input: 'Hello from the gateway.',
response_format: 'mp3',
});
await fs.promises.writeFile('speech.mp3', Buffer.from(await res.arrayBuffer()));with client.audio.speech.with_streaming_response.create(
model="openai/tts-1", voice="alloy", input="Hello from the gateway."
) as response:
response.stream_to_file("speech.mp3")Voices
GET /v1/audio/voices?model=elevenlabs/eleven-v3 lists the voices a speech model offers, as stable public ids:
{ "object": "list", "data": [ { "id": "en-female-ava", "name": "Ava", "language": "en", "gender": "female", "style": ["narration"], "preview_url": null, "default": true } ] }Pass the id as voice on /v1/audio/speech; omit voice for the model's default. Ids are OSMEXO's own and do not change when the provider behind a model changes. An unknown id is a 400 validation_failed naming voice. preview_url is reserved and is currently always null. A model that does not publish voices (most non-ElevenLabs speech models) returns an empty list — pass the provider's own voice name to voice instead. This endpoint is free: it is not billed.
curl "https://api.osmexo.com/v1/audio/voices?model=elevenlabs/eleven-v3" \
-H "Authorization: Bearer $OSMEXO_API_KEY"Transcriptions (speech-to-text)
Upload an audio file as multipart/form-data.
curl "https://api.osmexo.com/v1/audio/transcriptions" \
-H "Authorization: Bearer $OSMEXO_API_KEY" \
-F model="openai/whisper-1" \
-F file=@meeting.mp3 \
-F language=en \
-F response_format=json| Form field | Notes |
|---|---|
file | required. Audio file; total request ≤ 25 MiB. |
model | required. Transcription model id. |
language | ISO-639-1 hint (e.g. en). |
response_format | json (default), text, verbose_json, srt, vtt — subject to model support. |
Response for json:
{ "text": "Welcome everyone, let's get started with the roadmap review." }verbose_json additionally returns language, duration and segments[] where the provider supplies them. Transcription is priced per audio second.
const transcription = await client.audio.transcriptions.create({
model: 'openai/whisper-1',
file: fs.createReadStream('meeting.mp3'),
});
console.log(transcription.text);with open("meeting.mp3", "rb") as f:
transcription = client.audio.transcriptions.create(model="openai/whisper-1", file=f)
print(transcription.text)Errors
| HTTP | code | Cause |
|---|---|---|
| 400 | validation_failed | Missing input/file/model, out-of-range speed, or an unrecognized voice id. |
| 404 | model_not_found | Unknown model on /v1/audio/voices. |
| 413 | request_too_large | Multipart body over 25 MiB. |
| 415 | unsupported_media_type | Transcriptions called without multipart. |
| 403 | modality_not_allowed | Key scope excludes audio. |