Transcribe audio
https://api.stav.ai/v1/audio/transcriptionsTranscribes an audio file. Drop-in for the OpenAI SDK
(client.audio.transcriptions.create). Scope inference:audio.
Name a model listed with the transcriptions surface on
GET /v1/models; auto and Routers are refused
(router_not_supported). Any field not listed here, and stream,
is refused by name (unsupported_parameter). The file must be
within the serving Provider Endpoint's cap — stav_max_upload_mb
on the model object, 25 MB unless stated — or the request is
refused with 413 audio_too_large. The audio must also be within
the length an endpoint takes — stav_max_audio_seconds on the
model object, no limit when null. When a model has several
endpoints, a long file goes to one that takes it; when none does,
the request is refused with 400 audio_too_long before the file
leaves Stav.
Billing is per second of audio (the provider's duration when it
reports one, else read from the file; rounded half up, minimum 1)
at the endpoint's per-minute price ÷ 60, or per token on a
token-priced model. The billed seconds are returned in
X-Stav-Audio-Seconds. The audio is never stored.
Forespørselsinnhold
filestring (binary)påkrevdThe audio to transcribe: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav or webm. Up to the serving Provider Endpoint's cap (
stav_max_upload_mb; 25 MB unless stated).modelstringpåkrevdlanguagestringISO-639-1 code of the spoken language (
no,en,de). Omit to let the model detect it.promptstringNames and terms the audio uses, to steer spelling.
response_formatenumjsontextverbose_jsonsrtvtttemperaturenumber
Merknader
POST https://api.stav.ai/v1/audio/transcriptions takes the same multipart/form-data request as OpenAI's transcriptions endpoint. The OpenAI SDK works as-is.
Request
| Field | Type | Notes |
|---|---|---|
file | file | Required. flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav or webm, up to the serving Provider Endpoint's cap (25 MB unless the model page says more). The audio length can also be capped: the model page and stav_max_audio_seconds on GET /v1/models show the longest audio the model takes. |
model | string | Required. A model listed with the transcriptions surface on GET /v1/models. auto and Routers do not apply. |
language | string | ISO-639-1 code (no, en, de). Leave it out to let the model detect it. |
prompt | string | Names and terms the audio uses, to steer spelling. |
response_format | json, text, verbose_json, srt, vtt | Default json. |
temperature | number | 0 to 1. |
Any other field — including stream — is refused by name with 400 unsupported_parameter. Nothing is dropped silently.
A model served by Mistral (Voxtral) takes language and temperature, and answers json or text. It has no free-text prompt and produces no verbose_json, srt or vtt: those are refused by name with 400 unsupported_parameter before the audio is sent, and nothing is charged.
Response
The provider's body is returned as-is in the format asked. For json:
{ "text": "Velkommen til møtet. Vi starter med budsjettet." }
verbose_json adds duration, language and segments where the provider produces them; text, srt and vtt are plain bodies.
Two headers matter beside the usual response headers:
| Header | Meaning |
|---|---|
X-Stav-Audio-Seconds | The seconds of audio the request was billed for |
X-Stav-Compute-Countries | Where the audio may have been processed: one country, or a list such as FI,FR when the provider runs each request in one of them |
X-Stav-Compute-Country | Where the audio was processed, when that is exactly one country |
How it differs from chat
- Name the model.
autoand Routers serve the chat surfaces only. - Which models qualify. A model is callable here when a Provider Endpoint of it has been proven to answer on
/audio/transcriptions— Stav sends each endpoint a one-second test file and records the answer, so a provider that lists a model it does not serve there is never offered. Some chat models qualify too (Mistral's Voxtral Mini answers both). - The same policy wall. Compute country, zero data retention, no-training, the sovereignty floor and blocked providers apply exactly as on chat; a request the policy cannot place is refused with the same codes.
- Your key needs the
inference:audioscope. Without it:403 insufficient_scope. A key with no scopes has full access. - Billing is per second. The audio's duration — the provider's count when it gives one, else read from the file — is rounded half up to whole seconds (never less than one) and charged at the endpoint's per-minute catalogue price ÷ 60, as one line in your usage. A model priced per token (OpenAI's
gpt-4o-transcribefamily) is charged the tokens the provider reports instead. A failed request is not charged, and neither is one whose caller closed the connection before the transcript was ready (see Long audio). See Credits and billing. - The audio is never stored. Not in the request log, not in a capture window, not in the Playground. The request log keeps the duration, the size and the format; a capture window keeps the transcript.
Long audio
The request is synchronous: the answer comes when the provider has transcribed the whole file. That takes time in proportion to the audio — roughly 5 seconds per minute of audio is typical, so a one-hour meeting takes four to five minutes.
- Stav waits.
api.stav.aiholds the connection for up to 60 minutes, and Stav waits up to 10 minutes for the provider's answer before it returns504 backend_timeout. Any file within the upload cap fits inside both. - Your side may not. A proxy or serverless platform between your code and Stav often closes a request that has been silent for 100 seconds or so. Cloudflare answers such a request with
524. That status never comes from Stav. - A request you hang up on is not charged. If the connection is gone when the transcript is ready, Stav discards it and charges nothing. The request log shows the row as
client_disconnected, with the audio's duration, so you can see it happened. - If your platform has a short timeout, split the file. Parts of about 10 minutes finish in under a minute each. With
diarize, each part numbers its speakers on its own.
Errors
| Status | When |
|---|---|
400 unsupported_parameter | An unknown field, or stream |
400 audio_duration_unknown | The duration could not be read from the file and the model is priced per minute. Re-encode as wav, mp3, m4a, ogg or flac |
400 router_not_supported | model was auto or a Router |
403 insufficient_scope | The key lacks inference:audio |
404 audio_not_enabled | Transcriptions are not enabled on this deployment |
404 model_not_found | The model is not a transcription model, or has no priced Provider Endpoint on this surface |
400 audio_too_long | The audio is longer than every Provider Endpoint of the model takes. The message names the limit and the model. Split the file and send the parts. No upload is made to the provider |
413 audio_too_large | The file is over the Provider Endpoint's cap. The message names the limit and the model |
402 | Not enough credits, or a spend limit was reached |
501 transcription_not_supported | The model's Inference Provider has no /audio/transcriptions door |
502 node_offline / 504 node_timeout / 502 node_backend | The model runs on your own Stav Tunnel node, and the node is not connected, did not answer in time, or its local server refused the file. The message names the node |
| Provider status | The provider refused the request; its message is passed through as provider_error |
Full catalogue: Errors.
On your own machine
A Whisper model you run yourself can serve this endpoint through Stav Tunnel, so the audio never leaves your machine. Start it in vLLM (for example vllm serve NbAiLab/nb-whisper-large) on a machine with a node; within a minute Stav proves the transcription door with its one-second test file, and the model is callable with your usual key — @your-workspace/local-id, or the catalogue name when Stav knows the model. Requests to your node cost €0. A node takes files up to 24 MB. A request pinned to your node (…/@node) or to a private @your-workspace/… model is never sent anywhere else.
In the Playground
Connect → Playground has a Transcribe mode beside Chat: pick a transcription model, drop a file, read the transcript, download it as .txt (or .srt / .vtt when you asked for that format), and see the receipt — where it ran, the duration and what it cost. The Get code panel prints this call as curl, Python and TypeScript.
Svarheadere
| Header | Betydning |
|---|---|
X-Stav-Request-Id | Unique request identifier, identical to the completion |
X-Stav-Model | The model that actually served the request — not necessarily the one you asked for, when routing or failover intervened. |
X-Stav-Provider | The provider that served the request. |
X-Stav-Sovereignty-Level | The sovereignty level of the serving Provider Endpoint. |
X-Stav-Compute-Countries | Every country the audio may have been processed in, comma-separated ISO 3166-1 alpha-2, when known. Two or more means the provider runs each request in one of them without saying which. |
X-Stav-Compute-Country | ISO 3166-1 alpha-2 country where the audio was processed, when that is exactly one known country. Absent for a set; read X-Stav-Compute-Countries. |
X-Stav-Audio-Seconds | The seconds of audio the request was billed for. |
X-RateLimit-Limit | Per-minute request cap on this key. |
X-RateLimit-Remaining | Requests remaining in the current window. |
X-RateLimit-Reset | Unix timestamp (seconds) when the current window rolls over. |
Feil
| Status | Når |
|---|---|
| 400 | A bad request. |
| 401 | Missing or invalid API key. |
| 403 | API key lacks the required scope (e.g., |
| 404 |
|
| 413 |
|
| 429 | Per-key or per-IP rate limit exceeded. |
| 501 |
|
| 502 | An upstream provider (Anthropic, OpenAI, etc.) returned an error. |
Alle feilkoder, hva de betyr og hva du gjør: Feil.