Skip to main content
Every webhook Baanx sends is signed with HMAC-SHA256. Verifying this signature ensures the request is genuine and hasn’t been tampered with.

Your API Key

Each webhook endpoint is assigned a unique API key by Baanx. This key is the shared secret used to generate and verify signatures.
Store your API key securely in a secrets manager or environment variable. Never log it, commit it to source control, or expose it in client-side code.
Key properties:
  • Generated and managed by Baanx — not client-generated
  • Unique per webhook endpoint
  • Can be rotated on request (or via the Rotate Key API)
  • Custom keys can be configured in special cases
Example key format:

Request Headers

Every webhook request includes these headers:

How the Signature is Calculated

Baanx constructs the signature as follows:
To verify a request, you reproduce this calculation using the same inputs and compare the result to the X-Signature header.
Use your raw request body (as a string, before JSON parsing) when computing the signature. Parsing and re-serialising the body can change whitespace and key ordering, causing verification to fail.

Verification Steps

1

Extract headers

Read X-Timestamp and X-Signature from the incoming request headers.
2

Check the timestamp

Reject the request if the timestamp is more than 300 seconds (5 minutes) away from the current server time. This prevents replay attacks.
3

Build the signature payload

Concatenate the timestamp, a literal ., and the raw JSON body string:
4

Compute the expected signature

Calculate HMAC-SHA256 over the payload using your API key, then hex-encode the result (lowercase).
5

Compare signatures

Use a timing-safe comparison to compare the computed signature against X-Signature. Never use === — it is vulnerable to timing attacks.

Code Examples

Replay Protection

The X-Timestamp header protects against replay attacks — where an attacker captures a legitimate webhook request and re-sends it later. Your endpoint should reject any request where the timestamp differs from the current server time by more than 5 minutes (300 seconds):
Ensure your server clock is synchronised (e.g., via NTP) so legitimate requests are not incorrectly rejected due to clock skew.

Common Verification Mistakes

If you parse the raw JSON into an object and then re-serialise it to compute the signature, the result may differ from the original raw string (different whitespace, key ordering). Always use the raw request body string from the HTTP request.
Using === to compare signatures leaks information through response time differences. Always use crypto.timingSafeEqual (Node.js) or hmac.compare_digest (Python).
Without timestamp validation, a captured webhook request could be replayed indefinitely. Always reject requests where | now - timestamp | > 300.

Next Steps

Delivery & Retries

How to respond correctly and what happens when delivery fails

Rotate Signing Key

API reference for rotating your webhook API key