Sume job vs run: generation jobs and Format, Action, Agent runs
A Sume job is one generation request tracked at /v1/jobs; a run is one agent turn from a Format, schedule, or Agent Completion. Ids, webhooks, and waits differ.

In the Sume API, a job is one generation request from a model endpoint such as POST /v1/videos or an Avatar route, tracked at /v1/jobs/{id}. A run is one agent turn started by a Format, a schedule (the Actions API), or an Agent Completion, tracked under /v1/format-runs, /v1/action-runs, or /v1/agent-runs. Their ids, statuses, webhooks, and wait helpers differ, and a job id and a run id are not interchangeable.
The comparison below draws on Sume's Jobs and results, API reference, Run webhooks, and Waiting for runs and jobs docs, read on 2026-09-26.
What is the difference between a job and a run?
Side by side, for the calls you make most. The Format run lifecycle itself is covered in Sume Format run lifecycle.
| Aspect | Generation job | Format, Action, or Agent run |
|---|---|---|
| Created by | A model endpoint: POST /v1/videos, the Avatar routes, the /v1/models/sume/…/runs aliases | POST /v1/formats/{handle}/{slug}/runs, POST /v1/actions/{action_id}/runs, POST /v1/agent/completions |
| Id | job_… | arun_… for Format runs and API-triggered Action runs (the schedule docs show run_… on a scheduled one), agrun_… for Agent Completions |
| Read at | GET /v1/jobs/{id}, plus /status, /result, and /events | GET /v1/format-runs/{run_id}, /v1/action-runs/{run_id}, or /v1/agent-runs/{run_id}, plus /status and /result |
| Terminal statuses | completed, failed, canceled | The same, plus skipped on Format and Action runs |
| Delivery choice | mode: async, sync, subscribe, or webhook | communication.mode: async or webhook |
| Webhook events | job.completed, job.failed, job.canceled | format.run.terminal, action.run.terminal, agent.run.terminal, on completed or failed only |
| Cancel | Only before generation starts; then 409 job_generation_already_started | Idempotent POST …/cancel; stops a run that is queued or processing |
| TypeScript wait | waitForJob | waitForRun with family, or subscribeFormatRun |
How do I tell which one I created?
Look at the route you called and the response. A job submit envelope carries request_id, which is the job id, and POST /v1/videos answers with an id that is the job id. A run create returns a receipt whose object is format.run, action.run, or agent.run, with a status_url on its own family's route. Read each one where it lives:
# A job, from POST /v1/videos or an Avatar route
curl https://api.sume.com/v1/jobs/$JOB_ID/status \
-H "Authorization: Bearer $SUME_API_KEY"
# A Format run: its own family route, not /v1/jobs
curl https://api.sume.com/v1/format-runs/$RUN_ID \
-H "Authorization: Bearer $SUME_API_KEY"How are runs and jobs related?
A run is one agent turn, so its terminal webhook fires once, however many clips or images the turn produced. Progress inside the turn lives at the generation-job layer, whose webhooks fire per job as each one completes.
For cost, GET /v1/usage takes run_id to sum what one Format, Action, or Agent run cost, the agent's own turns included, or job_id to sum one generation job.
Which webhook will I get?
Jobs and runs send different events and payloads, but the signature scheme is identical, so one verifier covers both: route on event. Dedupe job deliveries on job_id and run deliveries on the envelope's request_id, which equals run_id. Signed webhooks for video runs covers verification.
One difference catches people: a job reaching canceled sends job.canceled, but a canceled or skipped run never delivers a webhook. Trust the cancel response, or the create response for a skip.
Which mistakes does the split cause?
Most bugs here come from treating the two as one resource:
- Polling
/v1/jobswith a run id. Actions have their own run resource and do not appear under/v1/jobs, and an Action or Format run id does not resolve on/v1/agent-runs. - Looking for
GET /v1/format-runs. There is no cross-Format run list: list runs per Format, or keep your own index of the run ids you stored. Jobs do have a list,GET /v1/jobs. - Sending
mode: "subscribe"to a run.communication.modehas nosubscribevalue, and supplyingwebhook_urlis what arms delivery. - Expecting to cancel a job mid-generation. Job cancel succeeds only before generation work starts, while a run stays cancelable through
processing. - Calling
waitForRunwith a job id. UsewaitForJobfor jobs; Wait for jobs and runs in the Sume SDK covers both helpers.
Sources
Related posts
Written by Sume