Batch transcription
POST /v1/transcribe with workload=transcription: diarization, formatting, and per-provider batch params.
Recorded audio in, formatted transcript out. Set workload: "transcription" in the X-Speko-Stt-Options header to apply transcript-reading defaults such as smart formatting instead of the conversational defaults live agents use.
curl -X POST https://api.speko.dev/v1/transcribe \
-H "Authorization: Bearer $SPEKO_API_KEY" \
-H "Content-Type: audio/wav" \
-H "x-speko-intent: {\"language\":\"en-US\"}" \
-H "x-speko-stt-options: {\"workload\":\"transcription\"}" \
--data-binary @meeting.wavThe response is the usual SSE stream. When the request uses workload or any provider param, the final done event reports what actually applied:
{
"text": "...",
"provider": "deepgram",
"model": "nova-3",
"confidence": 0.96,
"failoverCount": 0,
"effectiveParams": {
"provider": "deepgram",
"model": "nova-3",
"applied": ["smartFormat"],
"defaultsVersion": "2026-08-06"
}
}warnings appears alongside effectiveParams when params were dropped or candidates excluded. The per-provider defaults each workload applies are listed in Provider params.
Diarization
curl -X POST https://api.speko.dev/v1/transcribe \
-H "Authorization: Bearer $SPEKO_API_KEY" \
-H "Content-Type: audio/wav" \
-H "x-speko-intent: {\"language\":\"en-US\"}" \
-H "x-speko-stt-options: {\"workload\":\"transcription\",\"diarization\":true,\"speakersExpected\":2}" \
--data-binary @interview.wavdiarizationis batch-only and demote-class: providers that cannot diarize are removed from the failover ladder before the first attempt, each reported as acandidate_excludedwarning. If no capable provider remains, the request fails with422{ "error": "no_capable_provider", "param": "diarization" }rather than silently transcribing without speakers.speakersExpectedis a hint, forwarded where supported (AssemblyAIspeakers_expected, ElevenLabsnum_speakers, GooglediarizationConfig.maxSpeakerCount) and dropped elsewhere.- Speaker labels are normalized to
S0,S1, ... across providers on word-level output. Today the/v1/transcriberesponse returns the merged transcript text; exposing the per-word speaker labels on this endpoint is a follow-up.
Batch formatting params
Provider-specific batch knobs go in providerOptions. They are validated up front and apply only when that provider serves the request:
curl -X POST https://api.speko.dev/v1/transcribe \
-H "Authorization: Bearer $SPEKO_API_KEY" \
-H "Content-Type: audio/wav" \
-H "x-speko-intent: {\"language\":\"en-US\"}" \
-H "x-speko-stt-options: {\"workload\":\"transcription\",\"providerOptions\":{\"deepgram\":{\"dictation\":true}}}" \
--data-binary @meeting.wavCommon batch params:
| Provider | Param | Type | Values | Effect |
|---|---|---|---|---|
| Deepgram | detect_language | boolean | Detects the dominant language of each channel. | |
| AssemblyAI | multichannel | boolean | Transcribes each channel of a recording separately. | |
| AssemblyAI | language_detection | boolean | Detects the language of a prerecorded transcript. | |
| ElevenLabs | timestamps_granularity | enum | word, character | Selects word- or character-level transcript timestamps. |
| ElevenLabs | tag_audio_events | boolean | Includes non-speech audio event tags in the transcript. |
Full registry, validation rules, and failover semantics: Provider params.
Picking providers
POST /v1/recommend-stackwith{ "useCase": "<vertical id>" }returns ranked stacks per vertical;POST /v1/recommend-stack/from-descriptionclassifies a freeform description first.- To pin the STT pool directly, use the
x-speko-constraintsheader:{"allowedProviders":{"stt":["deepgram","assemblyai"]}}. Routing still ranks within the allow-list.
Limits
X-Speko-Stt-Optionsis capped at 4 KB./v1/transcribevalidates params against thebatchsurface. Streaming-only params (Deepgramendpointing, AssemblyAI turn thresholds) belong to the streaming WebSocket,/v1/transcribe/stream.