Speech-to-text API
Two ways to transcribe: a REST endpoint for finished audio, and a realtime WebSocket for live speech.
Two transports, one model
Sprag transcribes speech two ways. Both run Rhythm and take the same API key. They differ in whether the audio has already finished.
| REST | Realtime | |
|---|---|---|
| Input | A finished audio file | A live audio stream |
| Transport | POST /v1/audio/transcriptions | WebSocket |
| Result arrives | Once, when the whole file is done | In fragments, as each turn ends |
| Word timings | Yes, via timestamps | Not on this path |
| Speaker labels | Yes, via diarization | Not on this path |
| Use it for | Recordings, voicemail, uploaded media | Live conversation, captions, meeting notes |
Which to use
Use REST when the audio already exists as a file. It is one request, there is no session to manage, and it is the only path that returns word timings and speaker labels.
Use realtime for a live stream, where one session covers a whole conversation and Sprag finds the turn boundaries for you. Neither path returns words mid-utterance: Rhythm decodes a turn once the turn closes. What realtime saves is the round trip per turn, since the socket stays open and the audio has already arrived by the time the speaker stops.
Authentication
Both paths take the same API key. REST sends it as a bearer token.
Authorization: Bearer $SPRAG_API_KEYBrowsers cannot set that header on a WebSocket upgrade, so realtime sessions
opened from a browser pass the credential as a subprotocol pair instead:
sprag-jwt with a short-lived Sprag JWT, or sprag-api-key with an API key.
Realtime covers that handshake.
Errors
Handle failures separately on each path; one handler will not cover both.
REST answers with an HTTP status: 400 for a bad request, 401, 402, and
403 for credentials, payment, and organization membership, 404 for an
unknown model, 413 for an oversized body, 429 for rate limits, and 500,
502, and 503 for server-side faults. REST has the
table with meanings.
Realtime fails in three places. The upgrade is rejected with HTTP 403 before a
socket exists; an open session reports a rejected event in band as an error
event; and the server closes the socket with a code (1003, 1008, 1011, or
1013). Realtime lists what each one means.
The errors reference has the full error shape and retry guidance.