- Text to speech —
POST /v3/audio/speechturns text into spoken audio. - Speech to text —
POST /v3/audio/transcriptionsturns audio into a transcript.
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 amodel 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: lowerstabilityfor a more dynamic, emotional read, higherstyleto exaggerate delivery, anduse_speaker_boost. Theelevenlabs/eleven_v3model also understands inline audio tags in theinputtext —[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)
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.
- 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_atis 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 omitexpires_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 amodel 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)
Setstream: 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
Long recordings (async)
A synchronous request is a good fit up to roughly an hour of audio. For longer recordings, setasync: 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.