Which ID to store from a Sume call: id, generation_id or request_id

Sume returns an id, a generation_id, a request_id and an error request_id. Store the job id and keep the req_ error id in logs only. Here is where each appears.

5 min readSume
All posts

Store the job id, one string for every job. On the job routes it is returned as request_id, on the OpenRouter-compatible /v1/videos routes it is returned as id and repeated as generation_id, and on a webhook it is job_id. They are the same value, so one column named job_id covers every path. The only id you should not store as the job key is the req_... value inside an error envelope: it names a failed request, not a job.

The shapes come from Jobs and results, the video models reference and Errors and credits.

Where each id appears

Identifiers in Sume responses (Sume docs, read 2026-10-04)
FieldWhereWhat it identifiesStore it as
request_idJob submit response (async)The job idjob_id
idPOST and GET on /v1/videosThe job idjob_id
generation_idGET /v1/videos/{id} poll bodyThe job id againNothing extra
job_idWebhook payloadThe job idjob_id, also the dedupe key
error.request_idError envelope, shaped req_...One failed requestLog field only

One function that picks the right id

The Python below normalizes all three success shapes into one id and keeps the error id apart. Run it as is: it uses canned payloads, so no key is needed.

import asyncio

def job_id_of(payload: dict) -> str | None:
    """Return the job id from a submit, poll or webhook body."""
    body = payload.get("data", payload)
    for key in ("job_id", "id", "generation_id", "request_id"):
        value = body.get(key)
        if isinstance(value, str) and value and not value.startswith("req_"):
            return value
    return None

def error_id_of(payload: dict) -> str | None:
    return (payload.get("error") or {}).get("request_id")

async def main() -> None:
    samples = [
        {"request_id": "job_123", "status_url": "/v1/jobs/job_123/status"},
        {"id": "job_01HXYZ", "generation_id": "job_01HXYZ"},
        {"event": "job.completed", "job_id": "job_456"},
        {"error": {"code": "rate_limited", "request_id": "req_abc"}},
    ]
    for s in samples:
        print(job_id_of(s), error_id_of(s))

asyncio.run(main())

Why the job id is the one that matters

The job id is the key for everything that follows submit: the status route, the result route, a cancel, the event log and the webhook redeliver call all take it. If your process dies between a paid submit and a database write, that id is the only handle you have, so write it in the same step as the submit. If it is lost, you cannot recover the job and a resubmit will bill again.

On /v1/videos, a replay with the same Idempotency-Key returns the original job, so the key you generate is a second route back to the same id. Persist the key before you send the request.

Caveats

  • An error envelope has error.code, error.message and error.request_id. Quote the req_... id in a support ticket, but do not use it to poll anything.
  • A 409 idempotency_conflict means the key was reused with a different body. Generate a new key for new work.
  • Submit-time failures such as 402 insufficient_credits return no job, so there is nothing to store and nothing to poll.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume