Proposed scheme. The signature format below follows industry conventions (Stripe, GitHub). Concrete header names and the HMAC secret rotation flow will be confirmed with the BlooBank platform team before this scheme exits “Proposed” status.
The scheme
HMAC-SHA256 over a deterministic signed payload, transmitted in theX-Bloobank-Signature header.
The signed payload
The
. is the literal ASCII period separator. The whole string is UTF-8 encoded.
The signature header
X-Bloobank-Signature carries one or more signatures, comma-separated, each prefixed with a version label:
Future scheme versions may add
v2=... for migration; your verifier should accept any version it understands and reject the delivery if none match.
The webhook secret
The webhook signing secret is generated by BlooBank when you configure an endpoint. It is a high-entropy random string (≥ 32 bytes, base64-encoded) shown once in the Dashboard. Copy it into your secret manager and never expose it. Each endpoint configuration has its own secret. Rotating the secret produces a new value while the old one is briefly accepted in parallel — see Rotation below.Verification — the algorithm
1
Read the headers and raw body
Capture
X-Bloobank-Timestamp, X-Bloobank-Signature, and the raw bytes of the request body — do not re-parse and re-serialize.2
Parse the signature header
Split by
,, then by = for each part. Extract the t= timestamp and every vN= signature.3
Verify the timestamp
The header timestamp must be within ±5 minutes of your server’s current time. Reject older deliveries — they are stale (probably replays).
4
Compute the expected HMAC
expected = HMAC_SHA256_hex(secret, "{timestamp}.{rawBody}")5
Constant-time compare
Compare each
vN from the header to your expected using a constant-time comparison function (crypto.timingSafeEqual in Node, hmac.compare_digest in Python, etc.). If any matches, the signature is valid.6
Reject otherwise
Return
401 Unauthorized (without a body). Do not log the body, do not process the event.Code
Rotation
Webhook secrets should be rotated periodically. The flow:1
Request rotation in the Dashboard
Generates a new secret. Both old and new secrets are valid for a configurable overlap window (default 24 hours).
2
During the overlap, BlooBank signs with both
Deliveries during the window carry two
v1=... signatures — one signed with the old secret, one with the new. Your verifier accepts either.3
Update your secret manager
Replace the old secret with the new one before the overlap window ends.
4
After the window expires, the old secret is invalidated
Only the new secret signs subsequent deliveries.
What can go wrong
Next
Retry & delivery
The delivery contract.
Best practices
Idempotency, ordering, deduplication.
Payment events
Event catalog.