Long recordings
Upload audio straight to storage, start a transcription, then poll or wait for a webhook. Works for anything up to two hours.
The asynchronous flow has four steps. The SDKs wrap them in one call (transcribe_file / transcribeFile).
1. Create an upload
Tell the API how large the file is. Including its SHA-256 lets the API prove the stored bytes are exactly yours.
curl "$TWENTYSIX_BASE_URL/v1/uploads" \
-H "Authorization: Bearer $TWENTYSIX_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"bytes\": $(stat -f%z meeting.m4a), \"sha256\": \"$(shasum -a 256 meeting.m4a | cut -d' ' -f1)\"}"The response holds a short-lived, signed upload instruction:
{
"id": "upl_…",
"object": "upload",
"state": "allocated",
"bytes": 48213904,
"upload": { "method": "PUT", "url": "https://…", "headers": { "x-upsert": "false" } },
"expires_in": 3600
}2. Send the bytes
Send the file with the given method, URL and headers. The audio goes directly to storage in your project's region, without passing through the API servers.
curl -X PUT "$UPLOAD_URL" -H "x-upsert: false" --data-binary @meeting.m4aFiles above 50 MB can use the resumable_upload instructions in the same response instead (the tus protocol, 6 MB chunks). An interrupted resumable upload continues from where it stopped. The SDKs switch to it automatically.
3. Complete the upload
curl -X POST "$TWENTYSIX_BASE_URL/v1/uploads/$UPLOAD_ID/complete" \
-H "Authorization: Bearer $TWENTYSIX_API_KEY"The API checks the size and checksum and measures the audio. The upload moves to verifying, then to complete with duration_seconds and channels, or to rejected with an error code such as audio_decode_failed. Poll GET /v1/uploads/{id} until it leaves verifying.
4. Start the transcription
curl "$TWENTYSIX_BASE_URL/v1/transcriptions" \
-H "Authorization: Bearer $TWENTYSIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: meeting-2026-10-20" \
-d '{
"audio": { "upload_id": "upl_…" },
"language": "hi-IN",
"mode": "codemix",
"diarization": true,
"webhook_endpoint_id": "wh_…"
}'The response is 202 Accepted with the transcription. Credit for the measured duration is reserved now and settled when it finishes.
{ "id": "tr_…", "object": "transcription", "state": "queued", "request": { "language": "hi-IN", "mode": "codemix", … }, "created_at": "…", "finished_at": null }Request fields
| Field | Values | Default |
|---|---|---|
audio.upload_id | A complete upload in this project | required |
language | A code from Languages | required |
mode | native, codemix, verbatim — see Output modes | native |
diarization | true / false — speaker labels | false |
timestamps | segment, none | segment |
channel_mode | mix, separate — see Speakers and channels | mix |
webhook_endpoint_id | An endpoint from Webhooks | none |
Unknown fields are rejected with unknown_parameter; nothing is silently ignored.
5. Wait for the result
A transcription moves through queued → preparing → transcribing → finalizing and ends in one of:
| State | Meaning |
|---|---|
completed | The full transcript is ready. |
partial | Most of the audio was transcribed; the stretches that could not be are listed in gaps. Not charged. |
failed | Nothing could be produced; error.code says why. Not charged. |
cancelled | You cancelled it. Not charged. |
Either register a webhook or poll GET /v1/transcriptions/{id} every few seconds. When the state is completed or partial, fetch the transcript:
curl "$TWENTYSIX_BASE_URL/v1/transcriptions/$ID/result" -H "Authorization: Bearer $TWENTYSIX_API_KEY"Cancel, delete, list
POST /v1/transcriptions/{id}/cancelstops a transcription at the next safe point. Cancelled work is never charged.DELETE /v1/transcriptions/{id}deletes the audio and transcript of a finished transcription now, instead of waiting for retention. The transcription record remains withcontent_deleted_at.GET /v1/transcriptions?limit=20&state=completed,partiallists the project's transcriptions, newest first. Pass the response'snextasafterfor the next page.
Supported files
WAV, FLAC, MP3, M4A/AAC, OGG/Opus and WebM audio, up to two hours and 2 GB. Video files are coming soon.