Skip to main content
When your organization has a webhook secret configured, every webhook delivery includes four signed headers so your receiver can verify the payload came from Tumban, hasn’t been tampered with, and is meant for your organization.

Headers

Both signatures use the same secret. The signed payload is built from raw bytes, not a decoded string — the V2 string-to-sign is the UTF-8 encoding of "{timestamp}.{org_id}." concatenated with the request body bytes. Verify before parsing JSON, since any whitespace or key reordering you apply will change the bytes.
Under rare error paths Tumban sends X-Tumban-Org-Id: "" (empty string) — this happens when the worker that fired the webhook lost its organization context. The V2 verifier above already rejects these payloads because the empty header value will not match EXPECTED_ORG_ID. Treat any webhook with an empty X-Tumban-Org-Id as suspicious.

Setting up

1

Generate a webhook secret

Call Rotate webhook secret (or use the dashboard — see that page). The value is shown exactly once.
2

Store the secret

Put it in your secret manager. Capture the org_id your receiver expects to receive webhooks for at the same time — you’ll bind the receiver to it.
3

Verify every incoming webhook

Use the V2 verifier below. It performs all three required checks: constant-time signature compare, replay window, and tenant binding.

What your verifier must do

A correct verifier performs three checks in addition to recomputing the signature:
  1. Constant-time signature compare. Do not use == on the hex digest. Use hmac.compare_digest (Python), crypto.timingSafeEqual (Node), or your language’s equivalent. A naive == leaks timing information that lets an attacker brute-force a valid signature byte by byte.
  2. Replay protection. Reject anything whose X-Tumban-Timestamp is more than ~5 minutes from now. Captured signed payloads should not be replayable indefinitely.
  3. Tenant binding. Verify X-Tumban-Org-Id matches the org_id your receiver expects. Without this, a webhook signed with org A’s secret can be delivered to a receiver that hardcodes one secret and accepts any “from us” payload — a cross-tenant abuse vector.

Choosing between V1 and V2

  • V2 (X-Tumban-Signature-V2) is recommended for all new receivers. It binds the signature to a specific tenant and timestamp, defending against replay and cross-tenant abuse.
  • V1 (X-Tumban-Signature) is shipped on every delivery for receivers that need the simplest possible HMAC-over-body implementation. It does not bind tenant or timestamp — if you use it, rotate secrets aggressively and never share a secret across orgs.

Rotation

When you rotate the secret, Tumban switches over immediately — incoming webhooks are signed with the new secret only. Update your verification code first, then call Rotate webhook secret.

When the headers are absent

If your organization has no webhook secret configured, Tumban does not send any of the four signature headers. Generate one with Rotate webhook secret before trusting webhook bodies in production.