API reference
Batch STT API
POST /stt/transcribe transcribes an uploaded audio file — a whole recording at once, not a live stream. Same API key, same balance as your voice agents. No agent required — you pick the STT provider and model directly.
Request
POST /stt/transcribe
Content-Type: multipart/form-data
| field | type | notes |
|---|---|---|
file | file | required — mp3, wav, m4a, or webm. Anything else → 415 |
provider | form field | groq (default), voxtral, elevenlabs, deepgram. Unknown → 422 |
model | form field | optional — defaults to the provider's primary model |
language | form field | en or fr. Omit for auto-detect. Other values → 422 |
diarize | form field | true to label each segment with a speaker — see below |
timestamp_granularities | form field | segment (default) or word |
Size and length limits: uploads over the configured maximum return 413 file_too_large; audio longer than the configured maximum decoded duration returns 413 audio_too_long.
curl -X POST https://api.wakili.dev/stt/transcribe \
-H "Authorization: Bearer wak_your_api_key" \
-F provider=deepgram \
-F language=en \
-F diarize=true \
-F file=@call.m4a
Response
{
"text": "Hi, I'd like to move my appointment. Sure, what day works?",
"language": "en",
"duration_seconds": 74.2,
"provider": "deepgram",
"model": "nova-3",
"segments": [
{ "start": 0.0, "end": 3.1, "text": "Hi, I'd like to move my appointment.", "speaker_id": "speaker_0" },
{ "start": 3.4, "end": 5.9, "text": "Sure, what day works?", "speaker_id": "speaker_1" }
],
"upstream_cost_usd": 0.0053,
"cost_usd": 0.0058
}
speaker_id is null unless diarize=true.
Diarization
diarize=true is only honoured for providers that support speaker labelling: deepgram, elevenlabs, or voxtral. With any other provider (e.g. groq) the request returns 422 with code: "diarization_unsupported" rather than silently ignoring the flag.
Billing
You pay the provider's list price for the audio duration, plus a flat 10% routing fee:
cost_usd = upstream_cost_usd × 1.10
upstream_cost_usd is the per-audio-minute list price for the chosen provider. Debited from the same balance as calls. 402 with code: "insufficient_balance" if the balance can't cover it (checked before the provider is called).
Errors
| status | when |
|---|---|
401 | missing/invalid API key |
402 | insufficient balance |
413 | file too large / audio too long |
415 | unsupported audio format |
422 | unknown provider, bad language/timestamp_granularities, or diarization_unsupported |
502 | upstream STT provider error (code: "provider_error") |