Jobs & transcripts workflows

End-to-end patterns for submitting transcription work, polling for completion, and consuming or editing transcripts. Use this guide to pick the right endpoint for each integration step.

Async transcription pipeline

Transcription is always asynchronous. Jobs track status and progress; transcripts hold the final text and timings.

  1. POST /v1/jobs with serviceType: transcription — save data.jobId.
  2. Poll GET /v1/jobs/{jobId} until status is terminal (completed, failed, or cancelled). New jobs may show pending before queued; keep polling through cancelling until cancelled.
  3. Optional: POST /v1/jobs/{jobId}/cancel to stop a job before it finishes.
  4. On success, read resultSummary.transcriptionId and fetch via GET /v1/transcriptions/{transcriptionId}.
  5. Use GET /v1/transcriptions/{transcriptionId} for export-ready JSON or SRT.
Poll retrieve, not list. Listing jobs is for dashboards and search — it is not a substitute for polling a single in-flight job. For push notifications, configure job status webhooks instead of polling.

On failed, read error.code (e.g. duration_exceeded, transcript_too_large) and progress[] — see Plans & limits → Job failure codes.

Jobs run extract_audio and denoise_audio by default; separate_vocals only when enabled in platform settings. Progress emits the configured stages — see Jobs for the full stage list.

Which endpoint for which UI

What you are buildingJobs APITranscripts & catalog API
Submit new transcriptionPOST /v1/jobs
Progress bar / stage timelineGET /v1/jobs/{id}progress[] (incl. preprocessing + chunk stages)
Show job submit options (language only)Echo job.input.options from retrieve/list
Jobs history tableGET /v1/jobs
Cancel in-flight jobPOST /v1/jobs/{id}/cancel
Transcripts library (previews only)GET /v1/transcriptions
Export / clips / captionsGET …/transcriptions/{id} or ?format=srt or ?format=vtt
Custom transcript editor (load)GET …?include=layers
Save one segment editPATCH …/segments/{segmentId} + revision
Save many segment editsPATCH …/segments with updates[]
Glossary / revert in editorPOST …/glossary/*, POST …/revert/*
Index for semantic searchPOST /v1/jobs (serviceType: indexer)
Search indexed speechPOST /v1/catalog/search (ai:search)
Index inventory / remove from indexGET/DELETE /v1/catalog/indexed-transcriptions/…

Default transcript vs layers

Default GET returns the working copy your users should see in production: glossary applied, manual edits included, word timings reconciled to segment text. This is what you feed into clips, search, or downstream AI.

Layers expose the editorial history:

  • raw — engine output as stored at job completion
  • glossary — after project glossary rules
  • current — glossary plus any manual segment edits
  • diffs — text changes between layers; wordSyncVsRaw shows word-timing adjustments

Fetch layers with ?include=layers on retrieve (one request) or GET …/layers (separate call). Only integrations that need review, audit, or edit UIs should load layers — export pipelines should use default GET.

Semantic search workflow

Semantic search runs on vectors produced by indexer jobs — not on raw transcripts until they are indexed.

  1. Complete a transcription and note transcriptionId.
  2. POST /v1/jobs with serviceType: indexer and input.transcriptionIds (array, one to 50 IDs). Poll until completed.
  3. Optional: GET /v1/catalog/indexed-transcriptions to confirm chunk counts.
  4. POST /v1/catalog/search with a natural-language query. Responses are camelCase: prefer groups[] (one row per transcript with topScore) or flat results[] for the full hit payload (transcriptionId, startTimestamp, sourceUrl, etc.). Each hit includes start / end and optional startSegmentId / endSegmentId. Pair with latestJobId from the index list or jobId from GET /v1/transcriptions/{id} to open the transcript editor.
  5. To drop vectors without deleting the transcript: DELETE /v1/catalog/indexed-transcriptions/{transcriptionId}.

See Semantic search and Create indexer job.

Custom editor workflow

  1. Load GET /v1/transcriptions/{id}?include=layers — bind segment list to layers.current.segments and store layers.current.revision (or data.revision from GET without layers).
  2. Show diffs from layers.diffs — highlight glossary changes and wordSyncVsRaw where timings were adjusted.
  3. Save edits: one segment → PATCH …/segments/{segmentId} with text + revision, then update local revision from data.revision. Many segments → one PATCH …/segments with updates[] (see Edit multiple segments). Never fire parallel single-segment PATCH calls with the same starting revision.
  4. On 409 conflict, re-GET the transcript, merge UI state, and retry with the new revision.
  5. Before bulk terminology fixes: POST …/glossary/preview, then POST …/glossary/apply if the user confirms.
  6. Undo paths: POST …/revert/glossary (drop manual edits, keep glossary) or POST …/revert/raw (full reset to engine output).

See Transcripts for request/response examples, including batch vs parallel behavior.