callback_url on /v1/videos: the Sume job envelope that arrives
A /v1/videos callback_url delivers Sume's job.completed, job.failed or job.canceled envelope, not video.generation.* events. Payload, signature, checks.

Add callback_url (HTTPS only) to a POST /v1/videos body and Sume posts to it when the job reaches a terminal state. The payload is Sume's standard job envelope with event set to job.completed, job.failed or job.canceled, not OpenRouter's video.generation.* events, and the signature header is x-sume-webhook-signature, not X-OpenRouter-Signature.
If you ported a receiver from OpenRouter, the route and the verification both need a change. Events are terminal-only: there are no progress or partial deliveries. Sume retries non-2xx responses and network errors up to 10 attempts in total, with a fixed delay (30 s by default) and a 10-second timeout for each attempt, so return a 2xx quickly after you store the event and use job_id to drop duplicates.
Submit
The callback must be a public HTTPS URL. Localhost, private-network and non-HTTPS URLs are rejected.
curl -X POST https://api.sume.com/v1/videos \
-H "Authorization: Bearer $SUME_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: promo-0042" \
-d '{
"model": "wan-3.0",
"prompt": "Fireworks over a harbor, slow pan",
"duration": 8,
"resolution": "720p",
"callback_url": "https://hooks.example.com/sume"
}'What arrives
A completed job looks like this; failed and canceled ones use status: "ERROR" and add an error object.
| Field | Value |
|---|---|
event | job.completed, job.failed or job.canceled |
request_id, job_id | The job id; use job_id as your idempotency key |
status | OK on success, ERROR otherwise |
payload.artifacts[] | id, url on media.sume.com, type, content_type |
Receiver checklist
- Verify
sume-v1(HMAC SHA-256) over<timestamp>.<raw_body>usingx-sume-webhook-timestampand reject a timestamp outside your tolerance (the docs suggest five minutes), then parse. Refuse to run if your signing secret is empty. - Store the
media.sume.comartifact URL frompayload.artifacts[]. - Keep the poll on
GET /v1/videos/{id}or/v1/jobs/{id}/statusas a backup for deliveries that never land. - A 10-second 720p Wan 3.0 clip reserves $1.25 at submit, whichever way you learn the result.
Test the path before launch
The dashboard Webhooks tab and POST /v1/webhooks/test-deliveries (scope account:write) send a signed dummy webhook.test event to a URL you type. It never replays a real job, so it is the safe way to prove that your endpoint, signature check and 2xx response all work. Once that passes, run one real job and compare the stored job_id with the one the submit returned.
If a delivery is missing, redeliver it with POST /v1/jobs/{job_id}/webhook/redeliver, or read the job from its status URL. Neither changes the destination: a new callback URL means a new job.
Sources
Related posts
More in Developers
- Cancel queued Sume jobs after queue_full; handle 409 already started
How to free capacity after a 429 queue_full: cancel queued jobs, read job_generation_already_started on running ones, and why a cancel releases the reserve.
- Can't choose a video model? Send sume/auto and let Sume pick
model: sume/auto lets Sume select the video family for you: 3 to 10 seconds, 16:9 or 9:16, default 720p and 8 seconds. What it does and does not tell you.
- Cheapest Sume image model for a 21:9 banner from a reference photo
Qwen Image at $0.025 is the cheapest row listing 21:9 with reference input. Flux 2 Pro is next at $0.0375. A short script finds it live.
- Check ad video length for Pinterest, LinkedIn and Google in Python
A short Python check of a video-inspect probe against Pinterest, LinkedIn and Google Video action length limits read on 2026-10-08, before you upload an ad.
Written by Sume