canceled vs cancelled: one letter that breaks video status checks

Sume native jobs say canceled and send job.canceled. The OpenRouter-shaped /v1/videos response says cancelled. Normalize the spelling before you branch.

5 min readSume
All posts

Sume spells the status canceled in its own job envelope and its webhook event job.canceled. The OpenRouter-shaped GET /v1/videos/{job_id} response spells the same state cancelled, because that is OpenRouter's wire value. If your poller compares a string against only one spelling, a canceled job looks like an unknown state and your loop either spins forever or marks the item failed. Normalize once, at the edge.

The two vocabularies

OpenRouter's video guide, read 2026-10-05, lists six statuses: pending, in_progress, completed, failed, cancelled and expired. Sume maps its own five job statuses onto that set for the /v1/videos routes and states that expired is in the enum for wire compatibility but never emitted, because Sume does not expire jobs. The native routes GET /v1/jobs/{id}/status and /result use Sume's names.

Status mapping between Sume jobs and the OpenRouter-shaped video response (read 2026-10-05)
Sume `job.status``/v1/videos` statusTerminal
queuedpendingNo
processingin_progressNo
completedcompletedYes
failedfailedYes
canceledcancelledYes

A one-function fix

The function below accepts either vocabulary and returns the Sume names. It runs as written and has no dependencies.

ALIASES = {
    "pending": "queued",
    "in_progress": "processing",
    "cancelled": "canceled",
}
TERMINAL = {"completed", "failed", "canceled"}


def normalize(status: str) -> str:
    return ALIASES.get(status, status)


for s in ("pending", "in_progress", "cancelled", "canceled", "completed"):
    n = normalize(s)
    print(s, "->", n, "terminal" if n in TERMINAL else "keep polling")

Where the spelling bites

Three places show up in practice. A poller written for OpenRouter's docs checks for cancelled and never matches a Sume native result. A webhook handler written for Sume switches on job.canceled and a dashboard that reads the polled job sees cancelled. And a metrics query that counts canceled rows silently misses the other spelling. Cancellation is also idempotent in Sume: canceling a job that is already canceled returns the same canceled job, so a retry of a cancel call is safe.

Do not resubmit the original paid request because your local code does not recognize a status. An unrecognized terminal state is a bug in your parser, and a second submit without the same idempotency key is a second charge.

  • Normalize at the boundary where you read the response, not in every branch.
  • Treat unknown statuses as non-terminal for a bounded time, then alert.
  • Use the same constants in the poller, the webhook handler and the dashboard query.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume