Signed, retried, deduplicated
Webhooks carry X-Innmail-Signature (a timestamp and an HMAC-SHA256 over it and the body) and X-Innmail-Event-Id for dedupe. Failed deliveries retry for 12 hours; an endpoint that fails 25 times in a row is paused and you are told. Add custom headers for your own routing, and subscribe a webhook to one inbox or one pod instead of the whole workspace.
More than received
Event types cover the whole life of a message: received (plus spam, blocked and unauthenticated variants), security verdicts, sent, delivered, simulated, held, approved, rejected, bounced, complained, failed and opened, along with draft, agent, domain and calendar events. Every event is kept for 30 days and can be re-read with GET /events?cursor=.
Streams and polling too
GET /events/stream is an SSE endpoint that resumes with Last-Event-ID, handy for local development and for agents that run as long-lived processes. The SDKs include an event stream helper and a webhook verifier so you never hand-roll either.
Safe by default
Inbound security can run in monitor or hold mode. In hold mode, high-risk mail waits in Approvals and emits message.security.review instead of message.received; a person releases it and the normal event follows. Blocked senders are stored hidden with their own event, so your agent never sees them.
Frequently asked questions
How do I verify a webhook?
Compute HMAC-SHA256 over "timestamp.body" with your webhook secret and compare it with the v1 value in X-Innmail-Signature. Every SDK ships a verifier that does this and rejects stale timestamps.
What if my endpoint is down?
Deliveries retry with backoff for 12 hours. The event stays in the 30-day log, so you can also replay from a cursor once you are back.
Can I get the full raw email?
Yes. The webhook carries ids and a summary; fetch the message, its extracted reply text, attachments or the raw RFC 822 over the API.
What does it cost?
Nothing during the private beta: 3 @innmail.app inboxes and 100 outside recipients a day per workspace, unlimited inboxes on a domain you verify. Mail between your own agents is not counted.
Give every AI agent its own inbox.
A real @innmail.app address in one API call, or one on your own domain. Free in the private beta, no Gmail to connect.
Request beta access