Rotate the Sume webhook secret without dropping deliveries

Sume signs with both secrets for 24 hours after a rotation, comma-separated in x-sume-webhook-signature. Upgrade the verifier first, then rotate. Steps inside.

5 min readSume
All posts

You can rotate a Sume webhook signing secret with no downtime. For 24 hours after the rotation, Sume signs each delivery with the new and the previous secret and sends both signatures in one header, newest first. A verifier that accepts any matching sume-v1= entry keeps working. One that compares the header for equality fails.

What the header looks like

During the window the header carries one entry per live secret, separated by commas:

x-sume-webhook-signature: sume-v1=<new>,sume-v1=<old>

Order of operations

Upgrade the receiver before you press the button. Then rotate from the dashboard Webhooks tab, or call POST /v1/webhooks/signing-secret/rotate with a key that has account:write. Deploy the new secret on your schedule inside the 24 hours.

  • Step 1: make the verifier split the header on commas and accept any match.
  • Step 2: rotate, and read the new secret from the dashboard or GET /v1/webhooks/signing-secret (needs account:read).
  • Step 3: deploy the new value to SUME_COM_WEBHOOK_SIGNING_SECRET.
  • Step 4: after the window, only the new secret verifies.

Details that catch people

x-sume-webhook-secret-fingerprint names the new secret from the moment you rotate. It tells you which secret to move to, not which ones Sume still accepts. If you rotate twice inside one window, the secret from two rotations ago is retired at once, which is how a real leak gets cut off.

The API responses expose rotation.previous_valid_until, so you can read the deadline instead of counting hours.

Use the SDK verifier

verifyWebhook in @sume-com/sdk already handles the multi-signature header, so on TypeScript you can skip the custom comparison. If you never rotate, Sume sends a single signature and nothing changes.

Check it worked

After you deploy, open the Webhooks tab and compare the fingerprint of the new secret with the x-sume-webhook-secret-fingerprint header on a fresh delivery. Use Send test to trigger one without waiting for a job. The fingerprint is the only part you should paste into a ticket.

Keep a poll on status_url for any job that should have produced an event during the cutover. A missed delivery can be replayed with the redeliver route, which signs with the current secret.

Related posts

More in Developers

All Developers posts

Written by Sume