Skip to main content

Speech-to-Text

Transcribe audio files to text. A single endpoint serves three modes — default async, opt-in streaming, opt-in sync — controlled by query parameters.
Edge endpoints accept your pg_* API key as a bearer token. See Authentication for details. The cURL examples below pin Toronto (yto-01) for concreteness — substitute another region or discover the fastest one via GET https://autorouter.polargrid.ai/v1/route.

Transcribe Audio

The multipart body carries only the file. Everything else is a query parameter.

Query Parameters

Three Modes

stream=true and sync=true are mutually exclusive.

OpenAI SDK Drop-In

OpenAI’s transcription endpoint is strictly synchronous, and stock OpenAI SDKs send model, language, response_format, and temperature as multipart form fields — they have no way to add query parameters. The endpoint accepts both shapes:
  • Form fields are honored as fallbacks for any query parameter you don’t set (query always wins when both are present).
  • A request whose model arrives as a form field with no mode flags is served synchronously — a stock OpenAI SDK gets the transcript inline, exactly as it does against OpenAI.
The async-job default (202 + poll_url) applies only to PolarGrid-style requests that pass model as a query parameter. If you build raw requests and want inline results, pass ?sync=true.

Available Models

Examples

Default — async job

Streaming — SSE

Sync — blocking request

Cohere model — same surface, different model id

cohere-transcribe-03-2026 supports the same sync, stream, and async modes. Swap the model query parameter — everything else is identical:
Cohere covers 14 languages but does not auto-detect: it requires a language to decode and falls back to en when language is omitted. The audio is still transcribed correctly (the model is multilingual), but the language field in the response will report en rather than the spoken language. Pass language explicitly (e.g. &language=fr) whenever you need the response metadata to reflect the actual language.

Live Streaming — WebSocket

The upload modes above need the complete file before transcription starts. The WebSocket surface transcribes while you capture: stream PCM frames from the microphone and partial transcripts arrive during the utterance.
  • Connect with ?token=<pg_* key or session JWT>; optional model, language, prompt, window_s query params
  • Send binary frames: 16 kHz mono little-endian 16-bit PCM
  • Send {"type":"stop"} (text frame) to end the utterance
  • Receive the same event vocabulary as SSE: transcript.text.delta per ~1 s window of new audio, then one authoritative transcript.text.done after stop (see Delta semantics — deltas are provisional display hints, not concatenable fragments)
Sessions are capped at 120 seconds of audio — this surface targets conversational turns. For long recordings use the upload endpoint. Measured on a production edge (100 runs, 5-clip 4.2–7.7 s corpus streamed at real-time mic pace): first partial arrives ~1 s into the utterance (the first window boundary), subsequent partials each window while audio is still flowing, and the authoritative done lands 159 ms p50 / 205 ms p95 after the stop marker — the effective end-of-speech-to-transcript latency for a voice agent on this surface. See the whisper-large-v3-turbo model card for the full table.

SSE Event Types

Terminated by data: [DONE]\n\n (SSE surface only).

Delta semantics

Applies to both the SSE and WebSocket surfaces, which share the same engine. Each window re-transcribes the full audio buffered so far, producing a new hypothesis. The delta field then carries one of two things:
  • the new suffix, when the new hypothesis extends the previous one unchanged (e.g. " This is a short."), or
  • the full revised hypothesis, when re-decoding changed earlier text (e.g. "Hello. This is a short test phrase for").
The two cases are not distinguishable from the event alone, so do not concatenate deltas (you will render duplicated text) and do not replace your display with a bare delta (you will drop earlier text when the delta is a suffix). Treat deltas as low-latency provisional output for live display, and always take the final transcript from done.text — it is the only authoritative value, produced by a fresh pass over the complete audio.

Polling Responses

GET /v1/audio/transcriptions?job_id=... returns:
  • 202 while the job is accepted / processing{ job_id, status, poll_interval_ms }
  • 200 when completed — formatted body, with job_id and status: "completed"
  • 400 on failed / cancelled

Supported Audio Formats

MP3, WAV, M4A, OGG, FLAC, WebM

Limits

There is no separate duration limit — only size. As a rule of thumb, 100 MB holds roughly 1.5 hours of 16 kHz mono WAV or many hours of MP3. For recordings over the limit, split the audio into segments (for example with ffmpeg -f segment), submit each segment as its own request — the default async mode is built for this — and concatenate the transcripts. Splitting on silence rather than fixed intervals avoids cutting words in half.