---
title: "How do I verify Fynex webhook signatures?"
description: "Every webhook is signed. Recompute an HMAC-SHA256 of the timestamp and raw body with your signing secret, compare it to the X-Fynex-Signature header, and reject anything older than 5 minutes."
url: "/docs/developers/how-do-i-verify-fynex-webhook-signatures/"
category: "Developers"
---

Every webhook Fynex sends is **signed**, so you can confirm it really came from us and wasn't tampered with. Each request carries two headers — `X-Fynex-Signature` and `X-Fynex-Timestamp`. To verify, recompute the signature from the timestamp and the **raw request body** using your signing secret, and check it matches.

## The headers

- `X-Fynex-Signature: sha256=<hex>` — an HMAC-SHA256, hex-encoded.
- `X-Fynex-Timestamp: <unix seconds>` — when we sent it.

## How to verify

1. Read `X-Fynex-Timestamp` and the **raw** request body (verify before any JSON parsing — parsing and re-serialising changes the bytes).
2. Build the signed string as `timestamp + "." + rawBody`.
3. Compute `HMAC-SHA256(signingSecret, signedString)` and hex-encode it.
4. Compare it to the hex in `X-Fynex-Signature`, using a **constant-time** comparison.
5. Reject the request if the timestamp is more than **5 minutes** from now — this stops replays.

```js
import crypto from 'node:crypto'

function verify(rawBody, headers, secret) {
  const ts = headers['x-fynex-timestamp']
  const sig = headers['x-fynex-signature'].replace('sha256=', '')

  // reject stale requests (5-minute tolerance)
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${ts}.${rawBody}`)
    .digest('hex')

  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
}
```

## Notes

- Your **signing secret** is set per seller account with your webhook configuration; you can regenerate it if it leaks.
- If no secret is configured, requests aren't signed — set one to enable verification.
- Always return quickly (a 2xx) once verified; do heavy work afterwards, because delivery times out at 10 seconds and retries.

## Related

- [Which webhook events does Fynex send?](/docs/developers/which-webhook-events-does-fynex-send/)
