Webhook and poll race on a Sume video: one SQLite insert decides

Keep polling as a backup to the job webhook. Dedupe on job_id with INSERT OR IGNORE so only one path downloads. 10 deliveries 30 s apart cover 270 s.

4 min readSume
All posts

Sume retries a job webhook up to 10 times, 30 s apart, so the last attempt can land 270 s after the first, and your poller may have finished the same job minutes earlier. Insert the job_id into a table with INSERT OR IGNORE, and download only when the insert actually added a row.

The delivery window

Deliveries have a 10 s timeout each, and the docs say to dedupe on job_id and keep polling as a backup. Webhook events are terminal only: job.completed, job.failed and job.canceled.

Attempt n lands about (n - 1) x 30 s after the first, if every earlier attempt failed.

Webhook retry timeline for one job (read 2026-10-09)
AttemptEarliest time after firstCumulative wait
10 s0 s
230 s30 s
5120 s2 min
10270 s4.5 min

The guard and the signature check

Both paths call first_time(job_id) before touching storage. The verifier refuses an empty secret, rejects stale timestamps beyond 300 s and accepts any of the comma-separated signatures sent during a secret rotation.

import hashlib, hmac, os, sqlite3, time

SECRET = os.environ.get("SUME_COM_WEBHOOK_SIGNING_SECRET", "")
if not SECRET:
    raise SystemExit("signing secret missing")

def verify(raw: bytes, ts: str, header: str) -> bool:
    if abs(time.time() - int(ts)) > 300:
        return False
    mac = hmac.new(SECRET.encode(), ts.encode() + b"." + raw, hashlib.sha256)
    want = "sume-v1=" + mac.hexdigest()
    return any(hmac.compare_digest(p.strip(), want) for p in header.split(","))

db = sqlite3.connect("seen.db")
db.execute("create table if not exists seen(job_id text primary key)")

def first_time(job_id: str) -> bool:
    cur = db.execute("insert or ignore into seen values (?)", (job_id,))
    db.commit()
    return cur.rowcount == 1

Gotchas

Verify the raw body bytes, before any JSON parsing; the signed string is the timestamp, a dot and the exact body. Return 2xx quickly and do the download after, because the delivery times out at 10 s.

The header is x-sume-webhook-signature with the prefix sume-v1=, next to x-sume-webhook-timestamp (Unix seconds). For a 30 s Wan clip at 720p ($3.75), a duplicate download wastes bandwidth, not money; for a duplicate downstream post it can cost more, so dedupe anyway.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume