Sume /v1/videos has id and generation_id: which one do you store?

Both fields hold the same job id on Sume, so store id. Why generation_id exists and where that id also works: /v1/jobs status and result, webhooks, redeliver.

5 min readSume
All posts

Store id. On Sume's /v1/videos, generation_id carries the same value as id; the docs example for a completed poll shows job_01HXYZ in both. The field exists because the OpenRouter response shape has both, and a client written from those docs may read either one.

Why two fields

The route is OpenRouter-faithful, so the poll response keeps the OpenRouter field names. OpenRouter separates a job id from a generation id. Sume has a single id per job, so it returns the same string twice. The API source says so in a comment next to the line that sets generation_id.

That means you do not need a lookup table between the two, and you should not build one. Pick id, save it, and treat generation_id as an alias.

Where the same Sume job id works, from the docs (read 2026-10-08)
SurfaceHow the id is used
GET /v1/videos/{id}poll (this is polling_url)
GET /v1/videos/{id}/contentdownload, with optional ?index=N
GET /v1/jobs/{id}/statussame job in Sume's own shape (queued, processing, canceled)
GET /v1/jobs/{id}/resultsame job's result
POST /v1/jobs/{id}/webhook/redeliverre-send the terminal webhook (jobs:write)
webhook body job_idthe same id; use it as your idempotency key

What to put in your own table

A table for video jobs needs very few columns. Keep the Sume id, the Idempotency-Key you sent, the model string you asked for, and the status you last saw. The model you read back can differ from the one you sent: a request for sume/auto is answered with sume/auto, and Sume does not disclose the family that ran.

create table video_jobs (
  sume_id         text primary key,   -- id (== generation_id)
  idempotency_key text not null unique,
  model_requested text not null,
  status          text not null,      -- pending | in_progress | completed | failed | cancelled
  usage_cost      numeric(10,2),
  error           text,
  updated_at      timestamptz not null default now()
);

A client written from the OpenRouter docs

If your client was written against the OpenRouter video docs, it probably reads generation_id somewhere, for example to look up usage after the job. On Sume that read works and returns the job id, so you can leave the line alone. The two things that do change are the base path (https://api.sume.com/v1/videos, with no /api segment) and the model ids, which are bare catalog ids such as seedance-2 and never carry a provider-org prefix.

If you start fresh, drop generation_id from your types or mark it optional: it is present on the poll response, but the 202 submit response carries only id, polling_url, status and model.

Webhook side

When you use callback_url, the delivery is Sume's job envelope with job_id and request_id. Both identify the job; job_id is the key your handler should dedupe on, because Sume can send the same terminal event up to 10 times if your endpoint answers badly. See the callback_url envelope.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume