Sume job status: stop on terminal, fetch on result_ready

A Sume status reply has two booleans. terminal says stop polling; result_ready says GET /result will work. Failed and canceled jobs stop but have no result.

4 min readSume
All posts

Short answer

Two booleans on the Sume job envelope answer two different questions. terminal tells you to stop polling, and it is true for completed, failed and canceled. result_ready tells you that GET /v1/jobs/:id/result will return the result, which only a completed job has. Poll until terminal, then fetch only when result_ready is true.

The statuses

A job moves through queued and processing to one of three terminal states. The jobs docs list the full set, and the poller should treat the last three as the end of the line.

Do not treat queued as failure. When a workspace is at its concurrency limit, jobs wait in the queue until a slot frees, and polling with backoff is the correct response.

Job statuses and what a client does next (read 2026-10-03)
sume_statusterminalNext step
queuedfalseKeep polling
processingfalseKeep polling
completedtrueGET /v1/jobs/:id/result when result_ready is true
failedtrueRead the error from GET /v1/jobs/:id; there is no result
canceledtrueStop; there is no result

Why not just check for completed

You can; the docs say to fetch the result when a job reports result_ready true or status completed. The booleans are friendlier to code. A loop that tests terminal has no list of status strings to maintain, and a new non-terminal state would not break it. A fetch guarded by result_ready cannot hit the 409 that /result returns for jobs that are not completed.

That 409 is job_not_completed. If you see it, your loop fetched too early or the job ended in failure. Read the job record instead and look at its error, rather than retrying the result call.

id=$1
while true; do
  s=$(curl -fsS "https://api.sume.com/v1/jobs/$id/status" \
    -H "x-api-key: $SUME_API_KEY") || exit 1
  [ "$(echo "$s" | jq -r .terminal)" = true ] && break
  sleep "$(echo "$s" | jq -r '.next_poll_after_seconds // 3')"
done
[ "$(echo "$s" | jq -r .result_ready)" = true ] &&
  curl -fsS "https://api.sume.com/v1/jobs/$id/result" -H "x-api-key: $SUME_API_KEY"

Pacing the loop

The status reply may carry next_poll_after_seconds. Honor it when present and use your own exponential backoff when it is absent. Reads draw on a separate budget from writes, forty times larger, so a well-behaved loop will not exhaust it, but a tight loop with no sleep wastes requests for no benefit.

A 429 on a read names its scope in error.details.scope and carries retry-after; wait that long. A 404 not_found on a job you know exists usually means the job was created by a different member's key, since job reads through an API key are scoped to the member that owns it.

What a timeout does

If your own polling deadline passes, the job keeps running. Resubmitting creates a second paid job. Store the job id, resume polling later, or cancel; cancel works only before generation starts, and afterward the API answers 409 job_generation_already_started.

Webhooks can replace the loop. Submit with a callback and wait for job.completed, job.failed or job.canceled, keeping a slow poll as a backup. The same two booleans apply when you read the job after the callback arrives.

In tests

Cover three fake status replies: one with terminal false, one completed with result_ready true, and one failed. Assert that the result route is called for the second and never for the third. That single assertion protects you from the most common poller bug, a result fetch on a job that never completed, and it needs no network if you use a mock transport or a fake fetch.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume