Verify a Sume avatar video webhook signature in Python
A Python verifier for Sume job webhooks: HMAC SHA-256 over timestamp.raw_body, sume-v1 entries, a 5-minute window, and a refusal when the secret is empty.
Sume signs the raw JSON body of each job webhook with HMAC SHA-256 over the string timestamp, a dot, then the raw body. Read x-sume-webhook-timestamp and x-sume-webhook-signature, rebuild the digest with your signing secret, and compare it with each sume-v1 entry in the header. The Python function below also refuses to verify when the secret is empty.
What Sume sends
For an avatar video you submit with mode webhook and a public HTTPS webhook_url, Sume sends terminal events only: job.completed, job.failed or job.canceled. There are no progress deliveries. From the Webhooks page, read 2026-10-08:
| Header | Meaning |
|---|---|
| x-sume-webhook-timestamp | Unix seconds used in the signed string |
| x-sume-webhook-signature | One or more sume-v1=<hex> entries, comma separated |
| x-sume-webhook-secret-fingerprint | Fingerprint of the secret, for debugging a mismatch |
Rules your verifier must follow
- Sign the raw body bytes as received, not re-serialized JSON.
- Reject timestamps outside a replay window; five minutes is a reasonable default.
- During secret rotation the header carries one entry per live secret, newest first; accept the delivery if any entry matches.
- Compare every entry with a constant-time function.
- Return any 2xx only after storing the event durably; use job_id as your idempotency key.
Python verifier
Pass the raw request body as a string. In a web framework, read the body before parsing it as JSON.
import hashlib
import hmac
import time
def verify_sume_webhook(raw_body, timestamp, header, secret, tolerance=300):
if not secret:
return False
try:
ts = int(timestamp)
except (TypeError, ValueError):
return False
if abs(int(time.time()) - ts) > tolerance:
return False
digest = hmac.new(
secret.encode(), f"{ts}.{raw_body}".encode(), hashlib.sha256
).hexdigest()
expected = f"sume-v1={digest}"
matched = False
for entry in header.split(","):
if hmac.compare_digest(entry.strip(), expected):
matched = True
return matched
Operating notes
Sume retries up to 10 attempts in total, with a fixed delay (30 seconds by default) and a 10-second timeout for each attempt. After that you have a failed delivery for a job that still finished, so keep polling status_url as a fallback. Your signing secret is on the dashboard Webhooks tab, and the docs name the environment variable SUME_COM_WEBHOOK_SIGNING_SECRET. If verification fails, compare the fingerprint header with the fingerprint shown next to the secret.
Testing the verifier
Test with three cases. First, a valid delivery built with your secret and a current timestamp should return true. Second, an old timestamp, such as one ten minutes ago, should return false. Third, an empty secret should always return false, even if the other inputs look valid, because an empty key would let anyone forge a signature.
During rotation, build a header with two entries joined by a comma and confirm the function accepts it when either entry is right. Keep the check constant time: the loop above compares every entry instead of returning on the first match.
Finally, do the work after verification. Store the event by job_id, return a 2xx, and process asynchronously. Sume allows 10 seconds per attempt, so a slow handler wastes the retry budget.
Sources
Related posts
More in Developers
- Verify a Sume agent.run.terminal webhook in Python
Python HMAC-SHA256 check for a Sume run webhook: sume-v1 signature over timestamp.raw_body, a five-minute window, and a verifier that refuses an empty secret.
- Verify a Sume image webhook in Python, then read artifacts[]
A 23-line Python verifier for Sume's x-sume-webhook-signature header on an image job: refuses an empty secret, checks a 5-minute window, reads the image URL.
- Verify the Sume signature in the HTTP handler, not in the queue worker
A queue delay over 300 seconds makes a valid Sume signature look stale. Verify at receipt, enqueue the verified event, and use redeliver if a late check failed.
- Verify x-sume-webhook-signature in Node: sume-v1 HMAC, raw body
A node:crypto verifier for Sume's sume-v1 signature that refuses an empty secret, checks the 5-minute window, and accepts either entry during a rotation.
Written by Sume