Skip to content

SPEV: turn decisions up to 36% sooner. Details →

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. Models lists the models that transcribe; the examples below use rhythm.

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.

Request fields

FieldRequiredTypeNotes
fileYesfileThe audio to transcribe. Common containers such as MP3, WAV, FLAC, M4A, OGG, AAC, AIFF, and WebM are accepted.
modelYesstringA transcription model id, such as rhythm.
response_formatNostringjson (default), verbose_json, text, srt, or vtt.
timestamp_granularities[]Noarrayword, segment, or both. A verbose response carries both without it.
speaker_labelsNobooleanAdds a speaker index to each word. Requires verbose_json.
num_speakersNointegerThe number of speakers, when you know it. Applies with speaker_labels.
streamNobooleanStreams the transcript as server-sent events.
stream_include_usageNobooleanSet to false to leave usage off the transcript.text.done event. Applies with stream.

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.

FieldTypeWhen it appears
textstringEvery JSON response. The transcript.
usageobjectMeasured per-modality usage and cost.
taskstringverbose_json only. Always "transcribe".
durationnumberverbose_json only. Audio duration in seconds.
segmentsarrayverbose_json only. One entry per segment, with start and end times.
wordsarrayverbose_json only. One entry per word, with start and end times. Omitted when a granularity list leaves word out.

Stream a transcript

To receive the transcript while the file is still being transcribed, set stream=true. The response is a stream of server-sent events.

curl -N https://api.sprag.ai/v1/audio/transcriptions \
  -H "Authorization: Bearer $SPRAG_API_KEY" \
  -F [email protected] \
  -F model=rhythm \
  -F stream=true
data: {"type":"transcript.text.delta","delta":"Thanks,"}

data: {"type":"transcript.text.delta","delta":" everyone, for joining."}

data: {"type":"transcript.text.delta","delta":" Let us start with the roadmap."}

data: {"type":"transcript.text.done","text":"Thanks, everyone, for joining. Let us start with the roadmap.","usage":{"input":{"audio":{"duration":"5"}}}}

Each transcript.text.delta event carries the next piece of the transcript in delta. The stream ends with one transcript.text.done event. The transcript.text.done event carries the full transcript in text and the same usage object a non-streamed response returns.

stream applies with response_format set to json or text. If you send stream=true with verbose_json, srt, or vtt, the request returns HTTP 400. If transcription fails after the stream starts, the last event's data is an error object, and no transcript.text.done event follows.

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.

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 when you know it. Speaker labels need verbose_json and, if you send a granularity list, word in it.

Timestamps and diarization cover the payloads.

Errors

StatusMeaning
400Validation error, such as an unsupported response_format, stream with a format other than json or text, or audio that cannot be decoded.
401Missing, invalid, or expired credentials.
402Out of credit. Also sent with the code payment_overdue when a plan invoice is unpaid. Also sent while billing for a new account is being set up; retry the request after a moment.
403Not a member of the requested organization.
404Unknown model id.
413Request too large.
429Rate limit exceeded. Wait Retry-After seconds.
500Unhandled server error.
503Temporarily unavailable. Retry after Retry-After when it is set.

Full schemas are in the transcriptions reference.