Submit a batch transcription job from a public audio URL.
For client-VAD speech clips use [Segment Transcription](/docs/api-reference/segment-transcription) instead.
Submit a job
Request
curl -X POST https://audio.lansonai.com/v1/audio/transcriptions/jobs \
-H "Authorization: Bearer sk-..." \
-H "Content-Type: application/json" \
-d '{
"audio_url": "https://cdn.example.com/meeting.wav",
"language": "zh",
"prompt": "Medical cardiology conference",
"webhook_url": "https://your-server.com/webhook"
}'
Request body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| audio_url | string | yes | — | Public audio URL, must be http(s):// |
| request_id | string | no | random UUID | Idempotency key; same ID resumes from R2 checkpoint |
| language | string | no | — | Language hint (e.g. zh, en) |
| model | string | no | env default | STT model override |
| prompt | string | no | — | Transcription context hint |
| segment_seconds | number | no | 300 | Slice length in seconds, must be > 0 |
| response_format | string | no | verbose_json | Response format |
| concurrency | number | no | 6 | Concurrent chunk transcription, must be > 0 |
| webhook_url | string | no | — | POST final result to this URL on completion |
| review | boolean | no | false | Enable two-stage LLM review |
| metadata | object | no | — | Context forwarded to review stages |
::callout{icon="i-lucide-info"}
response_format defaults to verbose_json in the OpenAPI schema, but the workflow currently hardcodes verbose_json for every chunk transcription. Setting this field has no effect today.
::
Response — 202 Accepted
{
"request_id": "...",
"workflow_id": "cf_55190d1a608984daf77cbfca6b7b5438891436f8522f2be7be12fc93fa239ad4",
"status": "queued",
"endpoint": "GET /cf_...",
"poll_endpoint": "GET /v1/audio/transcriptions/jobs/cf_..."
}
workflow_id is a Cloudflare Workflow id (cf_ + 64 hex), not a UUID.
Poll for results
curl https://audio.lansonai.com/v1/audio/transcriptions/jobs/<workflow_id> \
-H "Authorization: Bearer sk-..."
Legacy aliases: GET /<workflow_id>, GET /v1/audio/transcriptions/<workflow_id>
Status values
| Status | Meaning |
|---|---|
| queued | Waiting to start |
| running | Processing |
| complete | Done (result in output) |
| errored | Failed (error in error) |
| terminated | Terminated |
Complete output
{
"status": "complete",
"output": {
"result": {
"segments": [
{ "id": 0, "start_time": 0.0, "end_time": 3.2, "duration": 3.2, "text": "The weather is nice today", "confidence": 0.95 }
],
"summary": {
"total_duration": 120.5,
"total_speech_duration": 95.3,
"overall_speech_ratio": 0.79,
"num_segments": 45
},
"metadata": {
"language": "zh",
"chunk_count": 3,
"audio_duration_seconds": 120.5
}
}
}
}
Webhook
Set webhook_url to receive the final result via HTTP POST when the job completes.
LLM review
Set review: true to enable two-stage LLM correction.
R2 artifacts
Results are stored in R2 under transcription/{request_id}/:
| Artifact | Key |
|---|---|
| Per-chunk transcription | chunk_{i}.json |
| Raw aggregated transcript | result.json |
| Per-chunk review annotations | review_chunk_{i}.json (when review: true) |
| Final corrected transcript | reviewed_result.json (when review: true) |
Idempotency
Provide request_id for idempotency — already-transcribed chunks are skipped on retry.