POST you a fake event pretending to be Boble. To protect against this, every Boble delivery is signed with a secret only you and Boble know.
Before you act on any event — granting access, sending a welcome email, removing a Discord role — make sure the signature is valid.
Your signing secret
When you turn on webhooks for the first time, Boble generates a signing secret for your tenant. The same secret is used to sign deliveries for every promotion you connect a webhook to. You retrieve it from your dashboard, and you can rotate it at any time.The Boble-Signature header
Every delivery carries a header that looks like this:
t— the Unix timestamp in seconds when Boble emitted the event. Same value as thecreatedfield in the body.v1— the signature: an HMAC-SHA256 in lowercase hex over the string<t>.<rawBody>, using your signing secret.
How to verify
The verification is a three-step recipe:Recompute the signature on your side
Compute
HMAC-SHA256(secret, "<t>.<rawBody>") and hex-encode it.- The signature is calculated over the raw bytes of the body, exactly as Boble sent them. If your framework parses the JSON and re-serializes it before you check the signature, you’ll get a different string and verification will fail. Capture the raw body before any JSON middleware runs.
- The comparison must be constant-time. Don’t use a regular string equality — most languages ship a dedicated function for this (
crypto.timingSafeEqual,hmac.compare_digest,hash_equals, etc.). - It’s a good idea to also reject events whose
tis more than a few minutes old (5 minutes is a reasonable default). This blocks replay attacks where someone captures a real signed body and replays it later.
Rotating the signing secret
You can regenerate the signing secret from your dashboard at any time. The moment you do:- The old secret stops working immediately for new events.
- Any event Boble was about to send is signed with the new secret.
- Deploy the new secret to your receiver first.
- Then trigger the rotation from your dashboard.