Jobs API

Retrieve a job by ID, list recent jobs, follow a job to completion, or cancel it. The SDKs wrap every endpoint on this page.

Retrieve a job

GET /api/v1/jobs/{job_id}

Returns the job's current status. Once the job has completed, the response also includes a newly generated download_url, so you can fetch the result long after the job was created.

status = client.get_job_status(job_id)
if status.is_completed:
    result = client.get_transcript(job_id)
    print(result.text)
elif status.is_failed:
    print(status.failed_stage, status.reason)

Response (JobStatusResponse):

json
{
  "job_id": "…",
  "status": "completed",          // processing | completed | failed
  "download_url": "https://…",    // present when status is "completed"
  "llm_download_url": null,       // refined transcript, only for jobs with LLM post-processing
  "failed_stage": null,           // present when status is "failed"
  "reason": null                  // present when status is "failed"
}

List jobs

GET /api/v1/jobs

Returns your most recent jobs, newest first, with cursor pagination. Query parameters: limit (default 50, 1–100) and before (an ISO-8601 created_at cursor; pass the previous page's next_before).

page = client.list_jobs(limit=50)
for job in page["jobs"]:
    print(job["job_id"], job["created_at"])
older = client.list_jobs(limit=50, before=page["next_before"])  # next page

Response (JobListResponse):

json
{
  "jobs": [
    { "job_id": "…", "created_at": "2026-07-22T18:01:00Z" }
  ],
  "next_before": "2026-07-22T18:01:00Z"   // null on the last page
}

SSE stream

GET /api/v1/jobs/{job_id}/stream

A Server-Sent Events stream of a job's progress, ending with its result. You rarely open it yourself: the SDKs follow it inside transcribe(), reconnect with Last-Event-ID if the connection drops, and report progress through the progress callbacks.

Events

The stream emits progress events (zero or more), then one terminal completed or failed event, after which the server closes it. Each event carries an id:. Send the last one back as Last-Event-ID when you reconnect. Lines starting with : are keep-alive comments; ignore them.

A progress event is sent as each step finishes, so the first one you see already has completed of at least 1. The step names depend on the file size:

  • Files under about 3 MiB are processed as one chunk. They usually finish in seconds and may send no progress event before completed.
  • Larger files start with preprocess. Short audio is then one chunk:0. Long audio is split into several chunk:N steps, which can finish in any order, followed by aggregation.

total depends on how many chunks the audio was split into, so read it from each event rather than hard-coding it. A 44-minute file, as streamed:

stream
id: 1791179526032-0
event: progress
data: {"completed": 1, "total": 7, "step": "preprocess"}

id: 1791179533242-0
event: progress
data: {"completed": 2, "total": 7, "step": "chunk:0"}

id: 1791179542519-0
event: progress
data: {"completed": 3, "total": 7, "step": "chunk:4"}

…

id: 1791179547620-0
event: progress
data: {"completed": 7, "total": 7, "step": "aggregation"}

id: 1791179547725-0
event: completed
data: {"download_url": "https://…"}
EventData
progress{"completed": <int>, "total": <int>, "step": "<name>"}
completedTerminal success: {"download_url": "<url>"}, a presigned link to the result. The job_id is in the request path.
failedTerminal failure: {"step": "<name>", "reason": "<msg>"}, for example {"step": "user", "reason": "cancelled_by_user"} after a cancel.

If you open the stream for a job that has already finished, it replays from the start: the job's progress events, then the terminal event.

completed / total → percent

The progress payload carries raw completed and total step counts, not a percentage. The official SDKs compute percent = completed / total × 100 and expose it as ProgressEvent.percent, which is undefined while total is unknown. See any SDK page for the live-progress callbacks.

Cancel a job

POST /api/v1/jobs/cancel
client.cancel_job(job_id)

You can cancel only a job that has not finished processing, and only the portion that has not been processed yet. If most of the audio has already been transcribed when the cancellation arrives, you may be billed for the work already done.

Check failed jobs

POST /api/v1/jobs/check-failed

Checks several jobs at once. The response lists, in request order, whether each job has failed.

json
{"job_ids": ["…", "…"]}

Response: {"failed_jobs": [true, false]}