Skip to content

Speech to text

RouteAPI exposes the two OpenAI speech-to-text endpoints: transcription, which returns the audio in its original language, and translation, which always returns English. Both accept multipart/form-data, return their result in the same response — there is no asynchronous task or polling step — and are authenticated with the same API key as the rest of the Model API.

EndpointPurposeResponse
POST /v1/audio/transcriptionsAudio to text, in the source languageJSON or text, depending on response_format
POST /v1/audio/translationsAudio to English textJSON or text, depending on response_format

If your client’s base URL is configured without /v1, POST /audio/transcriptions and POST /audio/translations work as well; the gateway rewrites them to the /v1 paths internally.

Transcribes an audio file in its original language. Send it as multipart/form-data.

POST /v1/audio/transcriptions
https://api.routeapi.ai/v1/audio/transcriptions
FieldTypeRequiredDescription
filefileYesThe audio file. Only the first file part is forwarded
modelstringYesTranscription model ID, for example whisper-1, gpt-4o-transcribe, or gpt-4o-mini-transcribe
response_formatstringNoRequested output format such as json, text, srt, vtt, or verbose_json. RouteAPI records json as its default but does not write a default into the forwarded form — when you omit the field the upstream applies its own default, and the upstream body is returned unchanged
languagestringNoISO-639-1 language hint, forwarded to the upstream
promptstringNoContext/terminology hint, forwarded to the upstream
temperaturenumberNoSampling temperature, forwarded to the upstream
timestamp_granularities[]arrayNoTimestamp detail level; forwarded, and only meaningful together with verbose_json upstream

Other form fields are forwarded too. The gateway rebuilds the multipart body from your form: it writes model itself, copies the first file part, and copies every other text field through. RouteAPI validates only model; whether fields such as chunking_strategy are honoured is decided by the upstream model.

Terminal window
curl https://api.routeapi.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-F "file=@./meeting.mp3" \
-F "model=whisper-1" \
-F "response_format=json" \
-F "language=en"
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ROUTEAPI_KEY"],
base_url="https://api.routeapi.ai/v1",
)
with open("meeting.mp3", "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
response_format="json",
)
print(transcript.text)

The upstream response body is returned as-is, with Content-Type and Content-Length normalised. With response_format set to json — the OpenAI-compatible upstream default — you get:

{
"text": "This is the transcribed content of the uploaded audio."
}

With verbose_json you normally also get task, language, duration, and segments; with text, srt, or vtt the body is plain text rather than JSON. Exactly which of these a given model supports is defined by the provider — RouteAPI does not reshape the body.

Same multipart shape as transcriptions, but the output is always English text, regardless of the input language. The same fields apply (file, model, response_format, prompt, temperature). The source language is detected by the model, so there is no language parameter in the translation contract — the gateway passes extra form fields through, but an upstream that does not accept them may reject the request.

POST /v1/audio/translations
https://api.routeapi.ai/v1/audio/translations
Terminal window
curl https://api.routeapi.ai/v1/audio/translations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-F "file=@./interview-de.mp3" \
-F "model=whisper-1"
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ROUTEAPI_KEY"],
base_url="https://api.routeapi.ai/v1",
)
with open("interview-de.mp3", "rb") as audio_file:
result = client.audio.translations.create(
model="whisper-1",
file=audio_file,
)
print(result.text)

Speech-to-text calls use the same wallet and quota mechanism as every other Model API call: an estimate is pre-charged, the call is settled after the upstream responds, and a failed call is refunded. Prices come from the model’s configuration — see Model Pricing for how prices are displayed on a model’s detail page.

  • If the upstream response contains a usage object with a non-zero total_tokens, that usage is what gets billed (input_tokens/output_tokens are used when prompt_tokens/completion_tokens are absent).
  • If the upstream reports no usage, the gateway falls back to the duration estimate: 1000 tokens per minute of uploaded audio and no output tokens. On token-priced models the same estimate drives the pre-charge (floored at the gateway’s minimum pre-charge for any request).
  • If the reported usage carries audio token details, those tokens are priced at the audio rate; otherwise they are priced as ordinary input tokens at the model’s ratio. The duration fallback has no audio details, which is why 1000 tokens per minute lines up with a per-minute rate.
  • When the fallback applies, a transcription’s cost tracks the audio length, not how much text comes back. When the upstream does report usage, that reported breakdown wins.

Audio requests use the standard { "error": { ... } } body, and the message carries a request ID you can search for in the console logs. See Common errors for the full list.

StatusCodeCause
400invalid_requestmodel is missing or empty (Missing required field: model)
403insufficient_user_quota / pre_consume_token_quota_failedThe account balance or the key’s quota cannot cover the estimated cost
403—The model is outside the key’s model allowlist (This token has no access to model ...)
429—The request rate limit was exceeded
503model_not_foundNo usable channel for the model (No valid upstream service)
500count_token_failedThe uploaded audio’s duration cannot be measured (unsupported extension or container)
500convert_request_failedThe request cannot be converted for the channel — for example a transcription with no file part, or a channel whose adaptor does not implement audio
4xx / 5xxupstream codeThe provider rejected the request; status and message are passed through
{
"error": {
"message": "Missing required field: model (request id: 20261023153000123456789AbCdEfGh)",
"type": "error",
"code": "invalid_request"
}
}

Two failure modes are worth preparing for, because they are easy to mistake for provider problems:

  • Missing file on a transcription or translation is not caught by the gateway’s validation layer; it surfaces later as convert_request_failed. Check the field name is exactly file and that the client actually attached a part.
  • Unsupported audio container fails during token estimation, before any upstream call, so it is reported as count_token_failed rather than as an upstream error.

When a request fails, the pre-charged amount is refunded.

  • Text to speech — generate audio from text.
  • Models — confirm the model ID is visible to your Key before calling an audio endpoint.
  • Model Pricing — how audio input and output prices are shown.
  • Common errors — status codes, error bodies, and troubleshooting order.