Skip to main content
Configure a webhook URL in the Dashboard. When inbound email arrives, OpenMail POSTs to your endpoint.

Implementation flow

  1. Receive POST at your endpoint.
  2. Read raw body, X-Timestamp, X-Signature, X-Event-Id.
  3. Verify the signature before processing.
  4. Parse JSON, check event === "message.received".
  5. Use inbox_id to route to the right agent/container.
  6. Return 200 within 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.
  1. Install ngrok: brew install ngrok (macOS) or download from ngrok.com
  2. Sign up and add your authtoken: ngrok config add-authtoken YOUR_AUTHTOKEN
  3. Start your webhook server (see examples below)
  4. In another terminal: ngrok http 3000
  5. Copy the https:// forwarding URL (e.g. https://abc123.ngrok-free.app)
  6. In the DashboardSettings, set webhook URL to https://abc123.ngrok-free.app/webhooks
  7. Copy your webhook secret into .env as OPENMAIL_WEBHOOK_SECRET
Free ngrok accounts have 2-hour session limits. When the tunnel disconnects, restart ngrok and update the webhook URL in the dashboard.

Full server examples

Use express.raw() for the webhook route, not express.json(). Signature verification requires the exact raw body.

Testing locally

  1. Start your server and ngrok.
  2. Set the webhook URL and secret in the dashboard.
  3. Use Test webhook in Settings to send a test event.
  4. 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_SECRET as 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 200 within 15 seconds. Process asynchronously if needed.
  • Idempotency - Use event_id to deduplicate. We may retry; your handler should be idempotent.
  • Attachment URLs - Fetch promptly; signed URLs expire.
  • Verify signatures - Never process webhooks without verifying.

Troubleshooting

Events

Payload structure and field descriptions.

Verification

HMAC formula and verification steps.

Overview

Delivery semantics, retry policy.