Skip to main content

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)
Always validate the signature before processing the webhook payload. Never trust an unverified payload.

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
Never expose your webhook_secret and never reuse your API Key as the secret. Store it securely (environment variable, secrets vault, etc.).

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

Where:
  • webhook_secret → the shared secret
  • raw_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
This is the legacy method. It may still appear on any integration, so keep supporting it — but always prefer X-Signature (HMAC-SHA256) and don’t build new implementations around this method.

Formula

Here the secret is simply prepended to the body, and the hash is computed over that concatenation.

Code examples

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.
A webhook signature doesn’t validate JSON — it validates exact bytes. Capture the raw body before any middleware that parses the request (e.g. express.raw() in Express, or the raw await request.body() in FastAPI).

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 for X-Nox-Signature)
  • The Webhook Secret is correct
  • The encoding is UTF-8
  • The correct header is being read
In a secure environment, log the expected vs. received signature side by side. The difference usually points straight to the cause.