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

# Verify signatures

# Verifying Webhook Signatures

To ensure incoming webhook requests originated from Mailofly and were not tampered with in transit, verify the cryptographic signature sent in the request headers.

***

## Webhook Headers

Each request sent by Mailofly includes:

* `mailofly-signature`: An HMAC-SHA256 signature calculated over timestamp + raw payload body.
* `mailofly-timestamp`: Unix timestamp (in seconds) when the webhook was signed.

***

## Verification Example (Node.js)

```typescript theme={null}
import * as crypto from "crypto";

export function verifyMailoflyWebhook({
  payload,
  signature,
  timestamp,
  secret,
}: {
  payload: string; // RAW request body (not parsed JSON)
  signature: string;
  timestamp: string;
  secret: string;
}): boolean {
  // Prevent replay attacks: reject timestamps older than 5 minutes
  const currentTime = Math.floor(Date.now() / 1000);
  if (Math.abs(currentTime - parseInt(timestamp, 10)) > 300) {
    return false;
  }

  const signedContent = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(signedContent)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}
```

> **Important**: Always use the **raw, unparsed body** when verifying the signature. Parsing the JSON before verification may change whitespace and cause signature mismatches.


## Related topics

- [Configure webhook](/receiving/configure-webhook.md)
- [Create Webhook](/api/webhooks/create-webhook.md)
- [Introduction](/webhooks/introduction.md)
- [Custom Domains](/receiving/custom-domains.md)
- [Verify Domain](/api/domains/verify-domain.md)
