Implementation flow
- Receive POST at your endpoint.
- Read raw body,
X-Timestamp,X-Signature,X-Event-Id. - Verify the signature before processing.
- Parse JSON, check
event === "message.received". - Use
inbox_idto route to the right agent/container. - Return
200within 15 seconds.
Local development with ngrok
For local development, you need a public URL so OpenMail can reach your machine. ngrok creates a secure tunnel from a public URL to your local server.- Install ngrok:
brew install ngrok(macOS) or download from ngrok.com - Sign up and add your authtoken:
ngrok config add-authtoken YOUR_AUTHTOKEN - Start your webhook server (see examples below)
- In another terminal:
ngrok http 3000 - Copy the
https://forwarding URL (e.g.https://abc123.ngrok-free.app) - In the Dashboard → Settings, set webhook URL to
https://abc123.ngrok-free.app/webhooks - Copy your webhook secret into
.envasOPENMAIL_WEBHOOK_SECRET
Full server examples
Testing locally
- Start your server and ngrok.
- Set the webhook URL and secret in the dashboard.
- Use Test webhook in Settings to send a test event.
- Or send an email to one of your inbox addresses and watch the console.
Production deployment
Deploy your webhook server to a hosting provider with a stable public HTTPS URL. Options include Render, Railway, Fly.io, Vercel (serverless), or any cloud provider.- Set
OPENMAIL_WEBHOOK_SECRETas an environment variable. - Update the webhook URL in the dashboard to your production URL.
- Always verify signatures in production - never skip verification.
Best practices
- Respond quickly - Return
200within 15 seconds. Process asynchronously if needed. - Idempotency - Use
event_idto deduplicate. We may retry; your handler should be idempotent. - Attachment URLs - Fetch promptly; signed URLs expire.
- Verify signatures - Never process webhooks without verifying.
Troubleshooting
| Issue | Solution |
|---|---|
| Signature verification fails | Use the raw request body, not parsed JSON. Ensure secret matches the dashboard. Check X-Timestamp is within 5 minutes. |
| Webhook not receiving events | Verify ngrok is running and the forwarding URL matches the dashboard. Ensure your server is listening on the correct port. |
| Port already in use | Change the port in your server and ngrok: ngrok http 4000 |
| ngrok tunnel disconnects | Free accounts have 2-hour limits. Restart ngrok and update the webhook URL in the dashboard. |
Related
Events
Payload structure and field descriptions.
Verification
HMAC formula and verification steps.
Overview
Delivery semantics, retry policy.