X-Webhook-Signature header containing an HMAC-SHA256 signature. You must verify this signature before processing the payload — otherwise anyone who discovers your endpoint URL could send fake events.
How it works
Mage Loyalty signs every webhook using your subscription’s signing secret:- A signing string is created by concatenating the timestamp, a dot, and the raw request body:
{timestamp}.{rawBody} - The signing string is hashed with HMAC-SHA256 using your signing secret as the key
- The result is hex-encoded and prefixed with
sha256=
Step-by-step
Get the raw request body
You need the raw body string exactly as it was received — not a parsed-and-re-serialized version. Most frameworks provide a way to access this.
Compute the expected signature
Create an HMAC-SHA256 hash of the signing string using your signing secret, then hex-encode it and prepend
sha256=.Complete examples
- Node.js
- Python
- Ruby
- PHP
Replay attack protection (optional)
TheX-Webhook-Timestamp header is included in the signed data, so it cannot be forged. You can optionally reject requests where the timestamp is too old:
Troubleshooting
Signature mismatch — common causes
Signature mismatch — common causes
- Re-serialized body: You parsed the JSON and re-stringified it. Use the raw body exactly as received.
- Wrong secret: Each webhook subscription has its own unique signing secret. Make sure you’re using the correct one.
- Middleware modified the body: Some frameworks (e.g. Express without the
verifyoption) consume the raw body during JSON parsing. Use theverifycallback shown above to preserve it. - Encoding issues: The raw body must be read as UTF-8. Binary or other encodings will produce a different hash.
I lost my signing secret
I lost my signing secret
Signing secrets are shown only once at creation time. If you’ve lost yours, go to Settings > Webhooks, edit the subscription, and click Rotate signing secret. A new secret will be generated and shown once. Update your server with the new secret — the old one is immediately invalidated.
How do I test locally?
How do I test locally?
Use a tunneling tool like ngrok to expose your local server, then register the tunnel URL as your webhook endpoint. You can also use the Test button in the dashboard to send a test event.