Router9
Documentation
API Reference

Audio Tool

Speech-to-text and text-to-speech capabilities

Speech-to-Text (Transcription)

Transcribe audio to text. The endpoint is OpenAI-compatible, so openai.audio.transcriptions.create(...) works against a Router9 base URL unchanged.

Endpoint

POST /v1/audio/transcriptions

POST /v1/audio/transcribe was removed. Use /v1/audio/transcriptions.

Request (multipart/form-data)

Upload an audio file directly — this is what the OpenAI SDKs send:

curl https://api.router9.com/v1/audio/transcriptions \
  -H "Authorization: Bearer sk-r9k-your-key" \
  -F [email protected] \
  -F language=en

Request (JSON)

Provide audio by URL or base64, which is usually easier from a workflow or an agent that already holds a link rather than a file handle:

curl https://api.router9.com/v1/audio/transcriptions \
  -H "Authorization: Bearer sk-r9k-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "mediaUrl": "https://example.com/audio.mp3",
    "language": "en"
  }'
ParameterTypeRequiredDescription
filebinaryOne of file/mediaUrl/mediaBase64Audio file (multipart upload)
mediaUrlstringOne of file/mediaUrl/mediaBase64URL to audio file
mediaBase64stringOne of file/mediaUrl/mediaBase64Base64-encoded audio
languagestringNoLanguage hint, e.g. en, zh
modelstringNoOverride the default transcription model (must be allowlisted)
response_formatstringNojson (default), text, verbose_json, srt, vtt

Response

response_format: "json" (the default):

{
  "model": "google/gemini-3.5-flash",
  "text": "Hello everyone, today we'll discuss the new API design."
}

response_format: "text" returns the transcript as a plain text/plain body, with no JSON wrapper. srt and vtt likewise return the subtitle file itself, as application/x-subrip and text/vtt — not JSON with the file inside a string.

response_format: "verbose_json" adds the timings:

{
  "model": "nova-3",
  "text": "Hello everyone, today we'll discuss the new API design.",
  "language": "en",
  "task": "transcribe",
  "duration": 6.5,
  "segments": [
    { "id": 0, "start": 0.1, "end": 2.0, "text": "Hello everyone,", "speaker": 0 },
    { "id": 1, "start": 2.0, "end": 6.5, "text": "today we'll discuss the new API design." }
  ]
}

speaker is present only when the provider labelled one, and is omitted rather than defaulted — speaker 0 is a real person in a diarized transcript.

verbose_json, srt and vtt are rendered from time-bounded segments, and not every transcription provider produces them. Asking one that does not returns 400 naming the provider — before the call is made and billed, rather than after. Call GET /v1/public/audio-models to see which formats the model you are using can actually serve.

Text-to-Speech (Synthesis)

Convert text to spoken audio. POST /v1/audio/speech is the OpenAI-compatible spelling of the same capability, so openai.audio.speech.create(...) works unchanged.

Endpoint

POST /v1/audio/synthesize
POST /v1/audio/speech

Request

curl https://api.router9.com/v1/audio/synthesize \
  -H "Authorization: Bearer sk-r9k-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "input": "Hello, welcome to Router9!",
    "voice": "English_Trustworthy_Man"
  }' \
  --output speech.mp3
ParameterTypeRequiredDescription
inputstringYesText to synthesize
voicestringNoA voice id from GET /v1/audio/voices
formatstringNomp3 (default), wav, opus, flac, pcm
speednumberNoPlayback rate
modelstringNoOverride the default TTS model (must be allowlisted)

Voice ids are provider-specific. OpenAI names such as alloy or nova are not valid — call GET /v1/audio/voices for the list, or omit voice to use the deployment's default.

Response

The audio bytes, with Content-Type matching the requested format. Because a binary body has nowhere to carry metadata, the numbers a caller needs travel in headers: X-Router9-Audio-Characters, X-Router9-Audio-Format, X-Router9-Audio-Duration-Ms, and X-Router9-Upstream-Trace-Id.

Catalogs

GET /v1/audio/voices          → { "voices": [...] }
GET /v1/public/audio-models   → { "speech": [...], "transcription": [...], "planLimits": {...} }

Both are public. Each model in /v1/public/audio-models carries a constraints block — the character cap, the formats, the response formats it can produce — so a client can discover a limit without having to be refused by it. planLimits is separate and stated per tier, because those are the caps your plan adds on top of what the vendor accepts.

Errors

Every audio endpoint answers failures in the shared media error envelope. See Errors.

Credits

Audio Skill calls consume credits from your plan's monthly credit allowance — the same allowance used for chat completions. There are no separate per-Skill quotas. See Credits & Usage and Tool Usage & Credits.

On this page