Which API key scope does each Sume webhook endpoint need?
The signing secret needs account:read, rotate and test deliveries need account:write, redeliver needs jobs:write or formats:write. Map each call to a key.

Five Sume webhook calls need three different scopes. Reading the signing secret needs account:read. Rotating the secret and sending a test delivery both need account:write. Redelivering a job webhook needs jobs:write, and redelivering a Format run webhook needs formats:write. Your receiver itself needs no API key at all, because it only checks a signature.
The five calls and their scopes
A key that was created for generation work often has none of the account scopes. The call then fails with a permission error even though the key is valid, and the failure looks like an authentication problem in logs. Decide which key does which job before you wire up a deploy pipeline.
| Call | Scope | What it does |
|---|---|---|
| GET /v1/webhooks/signing-secret | account:read | Returns your workspace signing secret |
| POST /v1/webhooks/signing-secret/rotate | account:write | Starts a 24 hour rotation window |
| POST /v1/webhooks/test-deliveries | account:write | Sends a dummy webhook.test payload to your URL |
| POST /v1/jobs/{id}/webhook/redeliver | jobs:write | Sends a job webhook again |
| POST /v1/format-runs/{id}/webhook/redeliver | formats:write | Sends a Format run webhook again |
Split keys by purpose
The cleanest split is one key per purpose. A deploy key holds account:read and account:write and is used only by your release tooling to fetch or rotate the secret. A support key holds jobs:write and formats:write and is used by the person or script that replays a missed delivery. Your production submit path keeps whatever generation scopes it already has.
The signing secret is not an API key. The docs say the secret is derived for your workspace, and the same value is on the Webhooks tab of the dashboard. If you only need to read it once, the dashboard avoids minting a scoped key at all.
One credential header
Authenticate with one header only. The API answers 401 when a request carries both Authorization: Bearer and x-api-key, so pick one.
import os
SCOPES = {
"signing-secret": "account:read",
"rotate": "account:write",
"test-deliveries": "account:write",
"job-redeliver": "jobs:write",
"format-run-redeliver": "formats:write",
}
def missing(call, key_scopes):
need = SCOPES[call]
return None if need in key_scopes else need
have = set(os.environ.get("KEY_SCOPES", "account:read").split(","))
for call in SCOPES:
print(call, "missing:", missing(call, have))
What goes wrong in practice
Four failure patterns come up when teams first wire webhooks. Redelivery is safe to use during an incident. It sends a fresh timestamp and a fresh signature, and it does not count against the 10 delivery attempts. Your receiver still has to dedupe on job_id or request_id, because the same terminal event can arrive twice.
- A CI job that reads the secret with a generation-only key and receives a permission error. Add
account:readto a separate key, not to the production key. - A rotation script that was tested with a read-only key. Rotation is a write, so it needs
account:write, and the 24 hour window starts the moment it succeeds. - A support engineer who replays a missed Format run delivery with a key that only has
jobs:write. The Format run route needsformats:write, and the job route needsjobs:write, so each replay needs its own scope. - A service account key used for a Format run call. The docs reject service-account keys for Format runs, so a replay or run through one will not work whatever its scopes are.
Checking a failing call
Keep the check close to the receiver code. When a rotation script fails with a permission error, compare the scope in the table with the scopes shown for that key in the dashboard. After a rotation, the delivery header x-sume-webhook-secret-fingerprint names the new secret from that moment, so you can confirm the right secret reached your receiver.
Test before you rely on it
Use the dummy webhook.test payload to confirm a new deploy before real jobs depend on it. It carries no job_id, so your handler must accept an event without one. The SDK page on verifying webhooks also says an unknown event should answer 204, not 500, so a new event type never causes a retry storm.
Sources
Related posts
More in Developers
- Which Sume API requests count against the read rate limit?
Every GET and HEAD is a read, and so are POST /v1/generation/admission-preview and the MCP endpoint. Reads have their own per-key bucket, 40x the write one.
- Which Sume API routes are missing from the public OpenAPI document?
Asset upload routes, admission-preview, POST /v1/avatars, POST /v1/avatar-videos and the generic model runs path are implemented but hidden from OpenAPI.
- Which Sume API routes work without an API key?
Only health, catalog, openapi.json and the three bgm routes work without a key. Every other /v1 route needs a Bearer or x-api-key credential, never both.
- Which Sume media routes have GET /:id, and which poll /v1/jobs
Video inspect, video frames, captions and reference ingest have GET /:id. Trim, detach, filter, timeline, audio and compose have none; poll /v1/jobs/:id/status.
Written by Sume