Sume webhook rotation: upgrade the verifier before you click Rotate
During a rotation window Sume sends two signatures in one header. A receiver that compares the whole header for equality fails every delivery. Fix it first.

The Sume SDK docs carry a caution before the rotation steps: upgrade the receiver before you rotate. For 24 hours after a rotation, x-sume-webhook-signature holds two entries, sume-v1=<new>,sume-v1=<old>, newest first. A hand-rolled verifier that compares the header with == fails every delivery during that window.
Outside a window the header has a single entry, so the bug stays invisible until the day you rotate.
Naive versus safe
Run the sample: both verifiers agree outside a window, and only the safe one survives inside it.
import hashlib, hmac, time
def sign(secret, ts, body):
return hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
def naive_ok(header, secret, ts, body): # breaks while a rotation window is open
return header == f"sume-v1={sign(secret, ts, body)}"
def rotation_safe_ok(header, secret, ts, body):
want = sign(secret, ts, body)
return any(hmac.compare_digest(p.removeprefix("sume-v1="), want) for p in header.split(","))
ts, body = str(int(time.time())), b'{"event":"job.completed"}'
single = f"sume-v1={sign('new', ts, body)}"
double = f"sume-v1={sign('new', ts, body)},sume-v1={sign('old', ts, body)}"
for label, header in (("outside a window", single), ("inside the 24 h window", double)):
print(label, "naive:", naive_ok(header, "new", ts, body),
"safe:", rotation_safe_ok(header, "new", ts, body))Checklist before rotating
| Check | Why |
|---|---|
| Verifier accepts any sume-v1 entry | Header has two entries during the window |
| Secret read from SUME_COM_WEBHOOK_SIGNING_SECRET | One place to change |
| Empty secret refused | Fail closed rather than accept everything |
| Raw body is verified | A re-serialized body changes the signature |
Notes
verifyWebhookin@sume-com/sdk0.2.0 already handles the multi-signature header and returns false rather than throwing.- Rotation needs
account:write;rotation.previous_valid_untilshows the end of the window. - Deploy the new secret to receivers during the window, not at the same instant you press the button.
Sources
Related posts
More in Developers
- Sume webhook signature will not verify: compare the fingerprint
Each Sume delivery has x-sume-webhook-secret-fingerprint. Compare it with the dashboard fingerprint to find a wrong secret without ever sending the secret.
- Sume webhook secret fingerprint header: check your secret safely
Every Sume run webhook carries x-sume-webhook-secret-fingerprint. Compare it to the receipt and dashboard fingerprint to catch a wrong secret before verifying.
- Sume webhook secret rotation: why the header has two sume-v1 entries
During a signing-secret rotation Sume sends one sume-v1 entry per live secret, newest first, comma separated. Accept the delivery if any entry matches.
- Sume webhook Send test vs Redeliver: they are not the same
Send test posts a dummy signed webhook.test payload to a URL you type. Redeliver re-sends a real job's terminal event. Pick the right one for the job.
Written by Sume