> ## Documentation Index
> Fetch the complete documentation index at: https://docs.meum.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Verify signatures

> HMAC v1 webhook signature verification.

## Signature format

```
signedPayload = timestamp + "." + rawBody
signature     = HMAC_SHA256(webhook_secret, signedPayload)
header value  = "v1=" + hex(signature)
```

## Verification steps

1. Read raw request body (before JSON parsing)
2. Require `X-Meum-Signature` and `X-Meum-Timestamp`
3. Reject timestamps older than **300 seconds**
4. When `X-Meum-Integration-Id` is present, match your stored `int_...`
5. Compare signatures with constant-time equality
6. Deduplicate on `X-Meum-Event-Id` before processing

## Example (Node.js)

```javascript theme={null}
const crypto = require("crypto");

function verifyWebhook(rawBody, headers, secret) {
  const timestamp = headers["x-meum-timestamp"];
  const signature = headers["x-meum-signature"];
  if (!timestamp || !signature) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - Number(timestamp)) > 300) return false;
  const signed = `${timestamp}.${rawBody}`;
  const expected = "v1=" + crypto.createHmac("sha256", secret).update(signed).digest("hex");
  try {
    return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  } catch {
    return false;
  }
}
```

## Security checklist

* Return HTTP 200 only after verification succeeds
* Never log webhook secrets
* Rotate secrets immediately if compromised ([Incident reporting](/security/incident-reporting))

## Related pages

* [WooCommerce webhook verification](/woocommerce/webhook-verification)
* [Webhooks overview](/webhooks/overview)
