STT API
Transcribe audio files to text using Revolab’s Aisyah speech recognition models.
POST https://api.revolab.ai/v1/sttThe request is multipart/form-data — send the audio as a file field
alongside model and language as form fields.
Request parameters (multipart/form-data)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
file | File (multipart) | required | — | Audio file to transcribe. Accepted formats: WAV, MP3, M4A, FLAC, OGG, Opus, WebM. Maximum size: 50 MB. Maximum duration: 30 minutes. |
model | string (form) | optional | "aisyah-1.0-flash" | Model to use for transcription. Values: aisyah-1.0-flash, aisyah-1.0-pro |
language | string (form) | optional | null (auto-detect) | BCP-47 language code hint (e.g., "en", "ms", "zh"). When omitted, the model auto-detects the language. |
denoise | boolean (form) | optional | false | Clean up background noise before transcribing. See Denoise. |
diarize | boolean (form) | optional | false | Split the transcript by speaker. Adds a segments[] array with per-segment speaker labels. |
language_tags | boolean (form) | optional | false | Detect the language of each transcript segment. Adds a segments[] array with per-segment language tags. |
Request examples
cURL
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
}| Field | Type | Description |
|---|---|---|
text | string | The transcript of the audio. |
language | string | BCP-47 code of the detected or specified language. |
duration_s | float | Duration of the audio file in seconds. |
confidence | float | Transcript confidence score (0.0–1.0). Higher is more confident. |
latency_ms | integer | End-to-end transcription latency in milliseconds. |
segments | array | Only when diarize or language_tags was requested (and ran). See segments[] response shape. |
warnings | array | Only 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).") — or413when 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
diarizeis 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"
}
]
}| Field | Type | Description |
|---|---|---|
start | float | Segment start time in seconds from the beginning of the audio. |
end | float | Segment end time in seconds. |
text | string | Transcript of this segment. |
speaker | string | null | Speaker label — set when diarize was requested, null otherwise. |
language | string | null | BCP-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"
}
]
}codeis alwaysplatform_features_unavailable.featureslists which ofdenoise,diarize,language_tagswere 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_detectedresponse and are not processed.
Related
- Models — compare Aisyah models
- Error catalog — full list of error codes
- Authentication — how to send your API key