Speech to text over REST
Transcribe a finished audio file with the OpenAI-compatible transcriptions endpoint.
POST /v1/audio/transcriptions transcribes a finished audio file in one
request. It follows the OpenAI transcriptions shape, so point an existing OpenAI
client at it by changing the base URL and the model.
Rhythm and Symphony both transcribe. The examples below use Rhythm; pass
symphony in the same model field to use Symphony instead.
Transcribe a file
Upload the audio as multipart/form-data.
curl https://api.sprag.ai/v1/audio/transcriptions \
-H "Authorization: Bearer $SPRAG_API_KEY" \
-F [email protected] \
-F model=rhythm{
"text": "Thanks, everyone, for joining. Let us start with the roadmap.",
"usage": { "input": { "audio": { "duration": "5" } } }
}usage is abbreviated in the examples on this page. The real object carries a
per-modality vector for both the input and output sides, and transcription fills
only the input audio duration.
Request fields
| Field | Required | Type | Notes |
|---|---|---|---|
file | Yes | file | The audio to transcribe. |
model | Yes | string | rhythm. |
language | No | string | ISO-639-1 code such as en, not a language name. |
response_format | No | string | json (default), verbose_json, text, srt, or vtt. Anything else returns 400. |
timestamp_granularities[] | No | array | word, segment, or both. Optional: verbose responses carry both timings without it. |
speaker_labels | No | boolean | Adds a speaker index to each word. Requires verbose_json, and word in any granularity list you send. |
num_speakers | No | integer | Sets the number of speakers for the diarizer. Ignored without speaker_labels. |
Rhythm reads aac, aiff, flac, m4a, mp3, ogg, wav, and webm
containers. The request body is capped at 100 MiB.
Response fields
json and verbose_json return a JSON object with the fields below. text
returns the transcript as a plain text body, and srt and vtt return a
rendered caption file, cue times included; all three arrive as text/plain
with no JSON fields and no usage record.
| Field | Type | When it appears |
|---|---|---|
text | string | Every JSON response. The transcript. |
usage | object | Measured per-modality usage and cost. Absent when nothing was measured. |
task | string | verbose_json only. Always "transcribe". |
duration | number | verbose_json only. Audio duration in seconds. |
segments | array | verbose_json only. One entry per segment, with start and end times. Present on every verbose response. |
words | array | verbose_json only. One entry per word, with start and end times. Absent when a granularity list omits word. |
language | string | Only when you sent language. It is an echo of your hint, not a detection result. |
The plain json response carries the transcript and the usage record only, with
no language and no duration.
Timestamps and speaker labels
Set response_format=verbose_json when you need more than the transcript
string. That response adds task, duration, a segments array, and a
words array, with start and end times in seconds on every entry.
timestamp_granularities[] takes word and segment, together or alone, and
is optional: the verbose response carries both arrays without it. The one list
that changes the payload is one that leaves word out, which drops the words
array; segments is present on every verbose response.
When captions are the end product, request srt or vtt instead and skip the
client-side assembly; the response body is the rendered cue file.
Speaker labels attach to the word objects. Add speaker_labels=true and each
attributed word gains a speaker index; num_speakers sets the count the
diarizer works to. Diarization needs verbose_json and, if you send a
granularity list, word in it; violating either returns 400.
Timestamps and diarization cover the payloads.
Errors
| Status | Meaning |
|---|---|
400 | Invalid field, an unsupported response_format, an unknown language code, or audio the decoder cannot read. |
401 | Missing, invalid, or expired credentials. |
402 | No payment method on the account. |
403 | Not a member of the requested organization, or a malformed X-Organization-Id. |
404 | Unknown model id. |
413 | Request body over the 100 MiB cap. |
429 | Rate limit exceeded. Wait Retry-After seconds. |
500 | Unhandled server error. |
502 | Timing or speaker enrichment failed. |
503 | Temporarily unavailable: model cold start, capacity shedding, or an authentication dependency outage. Retry-After is set on the cold-start case. |
Full schemas are in the transcriptions reference.