Skip to main content
The gateway covers both directions of audio with two synchronous endpoints:
  • Text to speechPOST /v3/audio/speech turns text into spoken audio.
  • Speech to textPOST /v3/audio/transcriptions turns audio into a transcript.
Both are provider-agnostic: model selects the provider, a small set of fields is normalized for you, and anything model-specific goes in parameters. You can also clone a custom voice from a short sample and reuse it. For live, two-way voice conversations, use Realtime instead.

Text to speech

Pass a model and the input text. The response carries the audio inline as base64 and, by default, a stored file_id + presigned url.
Response
Speech is billed per input character.

Expressiveness

A voice can sound flat by default. How you add expression depends on the provider:
  • ElevenLabs exposes voice controls through parameters.voice_settings: lower stability for a more dynamic, emotional read, higher style to exaggerate delivery, and use_speaker_boost. The elevenlabs/eleven_v3 model also understands inline audio tags in the input text — [excited], [whispers], [sarcastic], [laughs] — for fine-grained emotion.
  • Mistral Voxtral has no style knobs; it mirrors the delivery of the voice it speaks as. For a lively result, use — or clone — a lively-sounding voice.
Audio tags count toward billed input characters, and eleven_v3 bills at a higher rate — great for a hero voice, more than you need for bulk narration. Use GET /v3/audio/models to discover the exact parameters a model accepts (its params.tts.parameters list).

Custom voices (cloning)

Clone a voice from a short reference sample and reuse it by an opaque id. POST /v3/audio/voices takes a model (which selects the provider to clone on), an audio reference — a file_id, https URL, or base64 data-URI of a few seconds of speech — and an optional name, languages, and gender. It returns a voice_... id you pass as voice on /v3/audio/speech, exactly like a built-in voice.
Response (create)
Manage your voices — all scoped to your project:
A clone carries the voice, not a language. Cloning captures timbre and accent; the output language comes from the text you synthesize with a multilingual model — so one clone can speak any supported language. Recording in the target language gives the most native accent.
A few things to know:
  • Provider binding. A voice is bound to the provider you cloned it on and only works with that provider’s TTS models. Using it with another provider’s model returns a 400.
  • Isolation & privacy. Voices are scoped to your project — never visible to or usable by another project — and the reference sample is not stored.
  • Expiry. Some providers auto-delete clones after a while (Mistral keeps one ~30 days); when they do, expires_at is returned, and once it lapses a speak returns a clear “no longer available” error — just create a new one. Providers that don’t expire voices omit expires_at.
  • Sample length. A few seconds is enough for Mistral Voxtral (zero-shot). ElevenLabs works best with ~1–2 minutes of clean audio (avoid more than ~3 minutes); recording quality matters more than length.

Speech to text

Pass a model and an audio source: a file_id from a previous generation or upload, an https URL, or a data-URI (max 25 MB decoded synchronously; up to 100 MB in async mode).
A file_id lets you transcribe audio you already have on Opper — a clip you uploaded, or speech you just generated with /v3/audio/speech — without re-sending the bytes. See Files for how files work, lifecycle, and storage quotas.
Transcribe a file_id
Response
Transcription is billed per provider-reported audio duration. Segment and word timestamps are returned when the model provides them.

Live transcript (streaming)

Set stream: true to receive the transcript as it’s produced — as Server-Sent Events instead of one JSON body — for a live transcript while the audio is processed. The stream emits transcript.text.delta chunks, then a terminal transcript.text.done with the full transcript and usage, then data: [DONE]. Streaming is supported on models whose params.stt.stream is true (discover them via GET /v3/audio/models) — e.g. mistral/voxtral-mini-2602; other models return a 400. stream and async are mutually exclusive.
Event stream
Billing is identical to the synchronous call (per provider-reported audio duration). For long recordings that don’t need a live transcript, use async instead; for two-way live voice, use Realtime.

Long recordings (async)

A synchronous request is a good fit up to roughly an hour of audio. For longer recordings, set async: true: the request returns immediately with a 202 and a status_url. Poll it until the job is completed, then fetch the transcript from the returned url. Async accepts the same audio sources as the synchronous call (file_id, https URL, or data-URI). Async also raises the decoded-audio limit from 25 MB to 100 MB (the synchronous cap stays 25 MB). To reach the full 100 MB, pass a file_id or https URL — a data-URI that large would need a ~133 MB request body. This lines up with the Files per-file limit, so a stored file_id transcribes in full.
Submit + poll
mistral/voxtral-mini-2602 is an EU-hosted batch transcription model (speaker diarization, word timestamps, up to 3 h per request) — a good fit for the async flow.

Discover models

GET /v3/audio/models lists the audio models available, tagged tts or stt, with their voices and formats. Each model’s params.tts / params.stt block also carries a parameters list of the native passthrough keys it accepts (e.g. ElevenLabs’ exact output_format preset, or a language_code), so you can discover the model-specific knobs for parameters rather than guessing:

What’s next

Realtime voice

Live, two-way voice over WebSocket.

Models

Which models do speech and transcription.

Control Plane

Govern providers, regions, and spend on every call.

Video

Generate video from a prompt or image.