Sume job webhooks vs run webhooks: one verifier, two event sets
Job webhooks send job.completed, failed, canceled. Run webhooks send action, format or agent run.terminal. Both share the sume-v1 signature and secret.

Sume has two webhook surfaces with separate events and the same signature scheme. Generation jobs send job.completed, job.failed or job.canceled. Action, Format and Agent Completion runs send action.run.terminal, format.run.terminal or agent.run.terminal. One verifier and one signing secret cover both. Only the body handling differs.
Which events you get
The event sets do not overlap, and the payloads differ. A run webhook carries the full run receipt, not a job result.
| You called | You receive |
|---|---|
| POST /v1/videos, /v1/images, a model endpoint | job.completed / job.failed / job.canceled |
| An Action run endpoint | action.run.terminal |
| A Format run endpoint | format.run.terminal |
| An Agent Completion run endpoint | agent.run.terminal |
Shared signing
Both sign the raw body with HMAC-SHA256 over <timestamp>.<raw_body>, send x-sume-webhook-timestamp and x-sume-webhook-signature: sume-v1=..., and use the workspace secret you store as SUME_COM_WEBHOOK_SIGNING_SECRET. The same rotation window applies to both.
One endpoint, two shapes
If a single endpoint receives both, verify first and then branch on event. Job payloads put artifacts under payload.artifacts and carry a job_id. Dedupe on job_id for job events, and on the run's request_id for run events.
const event = JSON.parse(rawBody); // after verifying
if (event.event.startsWith('job.')) {
await saveJob(event.job_id, event);
} else if (event.event.endsWith('.run.terminal')) {
await saveRun(event.request_id, event);
}Same fallback for both
For jobs, keep status_url polls as a backup. For runs, the SDK offers waitForRun, and subscribeFormatRun polls a Format run client-side. Either way, a delivery is a notification and not the only source of truth.
Related posts
More in Developers
- Sume jobs_wait outcome: wait_slice_expired is not a failed job
jobs_wait returns outcome terminal, wait_slice_expired or operator_stopped. Only terminal means the jobs ended; an expired slice says nothing about the jobs.
- jq one-liners for the video model catalog: ids, durations, 1080p
Two jq filters over GET /v1/videos/models: a table of ids with min and max seconds, and a filter for models that take 20 s at 1080p. Tested on a local copy.
- Kling 3 image-to-video on Sume: the first frame sets the shape
With a first frame, Sume's kling-3 builder does not send aspect_ratio. Crop the image to the shape you want before you submit. Here is the request.
- Kling 3 negative prompt and cfg_scale on Sume: fixed, no field
Sume's kling-3 sends its own negative prompt and a cfg_scale of 0.5 to the provider. There is no public field to change either, so steer with the prompt itself.
Written by Sume