Always verify the webhook signature before processing. Never trust unverified payloads.Documentation Index
Fetch the complete documentation index at: https://docs.openmail.sh/llms.txt
Use this file to discover all available pages before exploring further.
Why verify?
Without verification, anyone who discovers your webhook URL could send fake requests, potentially triggering actions on spoofed events or exhausting your resources. Always verify in production.Signature format
timestamp= value ofX-Timestampheaderraw_json_payload= raw request body as string (do not parse JSON first)
Verification steps
- Read the raw request body as a string.
- Get
X-TimestampandX-Signaturefrom headers. - Compute
HMAC-SHA256(secret, timestamp + "." + body). - Compare with
X-Signatureusing constant-time comparison (e.g.crypto.timingSafeEqualin Node.js,hmac.compare_digestin Python). - Verify
X-Timestampis within 5 minutes of current time (replay protection).
Example (Node.js)
Example (Python)
Getting your secret
Your webhook secret is shown in the Dashboard when you configure your webhook URL. Store it in an environment variable (e.g.OPENMAIL_WEBHOOK_SECRET) and never commit it to version control.
Troubleshooting
| Issue | Solution |
|---|---|
| Signature verification fails | Use the raw request body - do not parse JSON first. Ensure your secret matches the dashboard. |
| Wrong secret | Rotate the secret in Settings → Webhook secret → Rotate and update your env. |
| Timestamp expired | Verify X-Timestamp is within 5 minutes of current time. Check server clock sync. |
| Body parsing strips data | In Express, use express.raw() for the webhook route, not express.json(). |