Skip to Content
APISpeech to Text

STT API

Transcribe audio files to text using Revolab’s Aisyah speech recognition models.

POST https://api.revolab.ai/v1/stt

The request is multipart/form-data — send the audio as a file field alongside model and language as form fields.

Request parameters (multipart/form-data)

ParameterTypeRequiredDefaultDescription
fileFile (multipart)requiredAudio file to transcribe. Accepted formats: WAV, MP3, M4A, FLAC, OGG, Opus, WebM. Maximum size: 50 MB. Maximum duration: 30 minutes.
modelstring (form)optional"aisyah-1.0-flash"Model to use for transcription. Values: aisyah-1.0-flash, aisyah-1.0-pro
languagestring (form)optionalnull (auto-detect)BCP-47 language code hint (e.g., "en", "ms", "zh"). When omitted, the model auto-detects the language.
denoiseboolean (form)optionalfalseClean up background noise before transcribing. See Denoise.
diarizeboolean (form)optionalfalseSplit the transcript by speaker. Adds a segments[] array with per-segment speaker labels.
language_tagsboolean (form)optionalfalseDetect the language of each transcript segment. Adds a segments[] array with per-segment language tags.

Request examples

curl -X POST https://api.revolab.ai/v1/stt \ -H "Authorization: Bearer $REVOLAB_API_KEY" \ -F "file=@/path/to/audio.wav" \ -F "model=aisyah-1.0-flash" \ -F "language=en"

Response (200 OK)

{ "text": "The quick brown fox jumped over the lazy dog.", "language": "en", "duration_s": 3.12, "confidence": 0.97, "latency_ms": 520 }
FieldTypeDescription
textstringThe transcript of the audio.
languagestringBCP-47 code of the detected or specified language.
duration_sfloatDuration of the audio file in seconds.
confidencefloatTranscript confidence score (0.0–1.0). Higher is more confident.
latency_msintegerEnd-to-end transcription latency in milliseconds.
segmentsarrayOnly when diarize or language_tags was requested (and ran). See segments[] response shape.
warningsarrayOnly when a requested pipeline feature had to be skipped. See Degradation contract.

Pipeline features

Three optional form fields run extra processing around the transcription. They default to false, and with all of them off the response shape is exactly the plain object above.

curl -X POST https://api.revolab.ai/v1/stt \ -H "Authorization: Bearer $REVOLAB_API_KEY" \ -F "file=@/path/to/meeting.mp3" \ -F "model=aisyah-1.0-flash" \ -F "denoise=true" \ -F "diarize=true" \ -F "language_tags=true"

Denoise

denoise=true cleans up background noise before transcribing. It can also soften quiet voices, so some words may be missed — if the transcript looks incomplete, try turning it off. Denoising is single-voice speech enhancement and is applied per chunk (after any speaker/chunk splitting), so within each chunk the dominant voice is enhanced rather than competing speakers being suppressed.

Diarize

diarize=true splits the audio by speaker before transcription. Each entry in segments[] carries a speaker label (e.g. "SPEAKER_00", "SPEAKER_01").

Language tags

language_tags=true detects the language of each transcribed segment and sets the segment’s language field (a per-segment detection failure just leaves that segment’s tag null — the request still succeeds).

Long audio and the 30-minute cap

  • Maximum duration is 30 minutes (1800 seconds). Longer audio is rejected with 400 validation_error ("Audio is 2100s long; the maximum is 1800s (30 minutes).") — or 413 when the over-length WAV is caught by header inspection.
  • Audio longer than 30 seconds is chunked transparently. The gateway splits it on speech boundaries (voice-activity detection, or speaker turns when diarize is on), transcribes the chunks in parallel, and stitches the results back into one transcript. You always receive a single response — no client-side chunking needed.

segments[] response shape

Present only when diarize or language_tags was requested and actually ran. Each segment covers a time span of the input audio:

{ "text": "Good morning everyone. Selamat pagi.", "language": "en", "duration_s": 754.2, "confidence": 0.95, "latency_ms": 41210, "segments": [ { "start": 0.0, "end": 12.4, "text": "Good morning everyone.", "speaker": "SPEAKER_00", "language": "en" }, { "start": 12.4, "end": 15.1, "text": "Selamat pagi.", "speaker": "SPEAKER_01", "language": "ms" } ] }
FieldTypeDescription
startfloatSegment start time in seconds from the beginning of the audio.
endfloatSegment end time in seconds.
textstringTranscript of this segment.
speakerstring | nullSpeaker label — set when diarize was requested, null otherwise.
languagestring | nullBCP-47 tag for this segment — set when language_tags was requested and detection succeeded, null otherwise.

Degradation contract (warnings[])

Pipeline features degrade — they never take your transcription down. If the platform service backing denoise / diarize / language_tags is unavailable, the requested features are skipped with a warning and you still get the plain transcript back with 200 OK — never a 503.

When that happens, the response carries a warnings array naming the skipped features:

{ "text": "The quick brown fox jumped over the lazy dog.", "language": "en", "duration_s": 3.12, "confidence": 0.97, "latency_ms": 520, "warnings": [ { "code": "platform_features_unavailable", "features": ["denoise", "diarize"], "message": "These requested features were skipped because the platform service is temporarily unavailable: denoise, diarize" } ] }
  • code is always platform_features_unavailable.
  • features lists which of denoise, diarize, language_tags were skipped.
  • Only features that actually ran produce segments[] — if every requested feature was skipped, the response is a plain transcript plus the warning.

Status codes

200 OK — Success

{ "text": "The quick brown fox...", "language": "en", "duration_s": 3.12, "confidence": 0.97, "latency_ms": 520 }

400 Bad Request — Unknown model, or audio longer than the 30-minute cap

{ "error": { "code": "validation_error", "message": "Unknown model 'aisyah-2.0'. Valid models: ['aisyah-1.0-flash', 'aisyah-1.0-pro']", "request_id": "req_01HXYZ..." } }

401 Unauthorized — Missing, invalid, or revoked API key

{ "error": { "code": "unauthorized", "message": "Invalid API key format. Keys must start with 'rvl_live_'.", "request_id": "req_01HXYZ..." } }

413 Payload Too Large — File too large (> 50 MB) or audio too long (> 30 minutes)

{ "error": { "code": "validation_error", "message": "File exceeds maximum size of 50 MB.", "request_id": "req_01HXYZ..." } }

415 Unsupported Media Type — File extension not supported, or content does not match the declared format (magic-bytes check)

{ "error": { "code": "validation_error", "message": "File extension '.txt' is not supported. Allowed: flac, m4a, mp3, ogg, opus, wav, webm", "request_id": "req_01HXYZ..." } }

422 Unprocessable Entity — Malware detected by the upload scan

{ "error": { "code": "malware_detected", "message": "The uploaded file failed malware scanning.", "request_id": "req_01HXYZ..." } }

429 Too Many Requests — Rate limit exceeded

{ "error": { "code": "rate_limited", "message": "Rate limit exceeded.", "request_id": "req_01HXYZ..." } }

502 Bad Gateway — STT model endpoint returned an error

{ "error": { "code": "endpoint_unavailable", "message": "The upstream STT service returned an unexpected response.", "request_id": "req_01HXYZ..." } }

503 Service Unavailable — STT service is under maintenance or endpoint config is missing

{ "error": { "code": "service_unavailable", "message": "STT service is temporarily unavailable.", "request_id": "req_01HXYZ..." } }

File constraints

  • Formats: WAV, MP3, M4A, FLAC, OGG, Opus, WebM
  • Maximum size: 50 MB
  • Maximum duration: 30 minutes (1800 seconds)
  • All uploads are scanned for malware by GuardDuty. Files that fail scanning receive a 422 malware_detected response and are not processed.