Purpose
Every webhook request sent by NoxPay is signed. Validating that signature guarantees the webhook:- Has not been tampered with in transit (integrity)
- Was actually sent by NoxPay (authenticity)
How it works
NoxPay signs each webhook using a shared secret (the Webhook Secret). On your side, you reproduce that same signature locally and compare it against the value received in the request header. If they match, the webhook is legitimate.Webhook Secret
- A secret key unique to your integration, generated by NoxPay
- Shared with you securely
- Never sent inside the webhook itself — only you and NoxPay know it
Signature headers
Two signature methods are in use. Each arrives in a different header:Both headers may show up on integrations — including new ones. Your implementation should be prepared to validate both. Prioritize
X-Signature (HMAC) and treat X-Nox-Signature as compatibility with the older method.Current method — HMAC-SHA256
Header to compare:X-Signature
Formula
webhook_secret→ the shared secretraw_body→ the request body exactly as received (raw bytes)- encoding → UTF-8
Step by step
1
Capture the raw body
Take the request body exactly as it arrived, without parsing or re-serializing the JSON.
2
Generate the HMAC-SHA256
Compute the HMAC using
webhook_secret as the key and raw_body as the message.3
Encode as Base64
Convert the binary HMAC output to a Base64 string.
4
Compare securely
Compare against the
X-Signature header using a constant-time comparison function (to avoid timing attacks).Code examples
Legacy method — plain SHA256
Header to compare:X-Nox-Signature
Formula
Code examples
Why is HMAC-SHA256 preferable to plain SHA256?
Why is HMAC-SHA256 preferable to plain SHA256?
Plain SHA256 is just a generic hash function. In the legacy method, security comes from prepending the secret to the body (
SHA256(webhook_secret + raw_body)). The problem is that SHA256 was not designed to be used as a message authentication code: in certain scenarios it is vulnerable to a length extension attack, where it’s possible to compute a new valid hash without knowing the full secret.HMAC-SHA256 was built specifically for this purpose. It applies the hash in two layers, mixing the key in different ways in each one. This structure closes the length extension attack gap and is mathematically proven secure for message authentication — which is why it’s the industry standard for signing webhooks.In short: plain SHA256 is like taping a password to the front of a document and scrambling everything together. HMAC uses the key as a structured, well-tested way to scramble the content — much harder to defeat.Critical points
Apply to both methods.1. Use the actual raw body (the most important one)
The signature depends on the exact bytes of the body. Any alteration breaks validation — including whitespace, line breaks, key order, or re-serializing the JSON.2. Encoding
Always use UTF-8, at every step.Debug / Troubleshooting
If the signature doesn’t match, check in this order:- The raw body wasn’t altered (cause #1)
- The correct method is being used (HMAC for
X-Signature, legacy SHA256 forX-Nox-Signature) - The Webhook Secret is correct
- The encoding is UTF-8
- The correct header is being read

