Replicate webhook URL custom id vs Sume job_id as the key
Replicate suggests a query param like customId on the webhook URL. Sume bodies carry request_id and job_id, and job_id is the receiver's idempotency key.

Replicate's tip is to add query params to the webhook URL, such as https://example.com/replicate-webhook?customId=123, to carry an internal id. With Sume, the body of each delivery already has request_id and job_id, and the docs say receivers must treat job_id as the idempotency key.
Replicate's example is from its webhook setup page; Sume's behavior is from Webhooks, read 2026-10-01.
How do I tie a Sume callback to my own record?
Store your record id next to the job_id when you submit, then look the record up from the job_id in the delivery body. The payload shown in the docs includes event (job.completed, job.failed or job.canceled), request_id, job_id and status.
| Approach | Replicate | Sume |
|---|---|---|
| Id in the URL | Query param such as customId, per Replicate's tip | Possible, but the docs do not describe it as the key |
| Id in the body | Prediction object | job_id and request_id in the payload |
| Dedupe key | Your choice | job_id, per the docs |
Why not rely on the URL alone?
Redeliver re-POSTs the job's real terminal event with a fresh timestamp and signature, on the same URL. The docs say it does not change the destination URL: a new URL is a new job. So a per-job URL is fixed at submit time, and the same job can arrive more than once. Keying on job_id makes the second delivery a no-op.
What does a deduplicating receiver look like?
Verify the signature first (see debug Sume webhook delivery), then insert the job_id once.
const seen = new Set<string>(); // use a database unique key in production
export function handle(body: { event: string; job_id: string }) {
if (seen.has(body.job_id)) return { duplicate: true };
seen.add(body.job_id);
// load your record by job_id, then act on body.event
return { duplicate: false };
}Should the receiver also poll?
It can. Reading GET /v1/jobs/{job_id}/status is a read, so it is safe to repeat, and it reports the job's current status.
Sources
Related posts
More in Developers
- gen3a_turbo no longer available on Runway: re-read Sume's model list
Runway now fails requests for gen3a_turbo and gen4_aleph. Avoid the same break on Sume: read /v1/videos/models instead of hard-coding ids.
- Runway Model Router allow and deny lists vs Sume auto
Runway's Model Router has allow and deny lists plus per-modality credit ceilings. Sume has no lists: pin a catalog id, or send sume/auto and accept its pick.
- Runway per-generation usage export vs the Sume GET /v1/usage ledger
Runway's enterprise usage export lists credits per generation. On Sume, GET /v1/usage returns USD ledger rows per workspace, filterable by job_id.
- Seedance 2.5 1080p ratio 1920:1080 on Sume: resolution + aspect_ratio
Runway takes a 1080p ratio like 1920:1080. Sume takes two fields instead: resolution 1080p plus aspect_ratio 16:9, and rejects size on v1.
Written by Sume