Best Email APIs With Webhook Events for AI Agents
A webhook-first comparison of email APIs: inbound events, payload shape, signing, retries, ordering and replay for agents that react to incoming mail.
John Joubert
Founder, Robotomail

Table of contents
If your agent is driven by incoming mail, the only thing that matters is the webhook layer. The best email APIs with webhook events give you a real inbound event with the parsed body attached, a signed payload, a documented retry schedule, and a way to replay events you dropped. Most email APIs give you two of those four, and the missing ones are the reason your agent silently stops responding on a Tuesday afternoon.
This post judges providers purely on that surface. Not deliverability, not pricing, not SDK ergonomics. Just: what events fire, what is inside them, what happens when your endpoint returns a 500, and how you recover. If you want the broader question of which APIs can receive mail at all, we covered that separately in email APIs that support receiving. This one is for people who have already decided the architecture is inbound-driven.
What "webhook support" actually means for an inbound-driven build
Vendors all claim webhook support. The claims cover wildly different things. Here are the six properties worth checking before you commit.
1. Is there an inbound event at all? Many "webhooks" pages only describe outbound delivery telemetry: delivered, bounced, opened, spam_report. Useful for monitoring, useless for an agent that needs to read a reply. Inbound receipt is usually a separate product with a separate configuration path and often a separate payload format.
2. Does the payload carry the message, or just a pointer? A pointer-style notification ("something changed in this mailbox, go fetch") means every inbound event costs you an extra authenticated round trip, plus state to figure out what changed. A content-style payload hands you sender, subject, body, and thread identity in the POST itself.
3. Is the payload signed? Your webhook endpoint is a public URL that triggers an LLM with tool access. Unsigned inbound is an open injection point. You want an HMAC or asymmetric signature with a timestamp so you can reject replays.
4. What is the documented retry schedule? If your endpoint is down for ninety seconds during a deploy, do you lose the email or get it again? "Retries" with no published schedule is not a guarantee you can design around.
5. Can you list or replay past events? Retries eventually give up. When they do, you need an API that lets you enumerate what happened and reprocess it. Without that, a bad deploy is permanent data loss.
6. Is there ordering or deduplication guidance? Webhooks are at-least-once, near-universally. If a provider does not say so, assume it and build idempotency anyway.
Best email APIs with webhook events, compared
| Provider | Inbound event | Delivery/bounce events | Signed inbound payload | Retries on failure | Event listing or replay |
|---|---|---|---|---|---|
| Robotomail | Yes, message.received with parsed body |
Yes | Yes | Yes, with backoff | Yes, events API |
| SendGrid | Yes, Inbound Parse (multipart form POST) | Yes, batched JSON Event Webhook | Signing on the Event Webhook; Inbound Parse differs | Documented for the Event Webhook | Limited |
| Mailgun | Yes, via routes | Yes, rich event set | Yes, HMAC with timestamp and token | Yes, documented backoff | Yes, events API |
| Postmark | Yes, parsed JSON inbound | Yes | Endpoint auth rather than payload signature | Yes, plus manual retry in UI | Yes, inbound stream in UI/API |
| Resend | Inbound available; webhooks delivered Svix-style | Yes | Yes, Svix-style headers | Yes, escalating schedule | Yes, in dashboard |
| AgentMail | Yes, agent-oriented inbound events | Yes | Yes | Yes | Yes |
| Gmail API | Pub/Sub push with historyId only |
No, not in this form | Pub/Sub auth, not an email signature | Pub/Sub semantics | Via history.list |
| Microsoft Graph (Outlook) | Change notification, resource pointer | No, not in this form | Validation handshake plus optional encrypted payload | Graph retry semantics | Delta query |
| Amazon SES | Receipt rule to SNS, Lambda or S3 | Yes, SNS or EventBridge | SNS message signing | SNS retry policy | Depends on target |
Treat the table as a starting map. Every provider's exact schedule changes, so verify against current docs before you rely on a number. What does not change is the shape of the tradeoffs, which is what the rest of this post is about.
Robotomail
We built the inbound path first, because that is the direction agents actually depend on. A mailbox emits message.received to your registered endpoint with the parsed content inline:
{
"event": "message.received",
"timestamp": "2026-04-17T10:00:00.000Z",
"data": {
"message_id": "...",
"mailbox_id": "...",
"mailbox_address": "shopping-agent@robotomail.co",
"from": "vendor@example.com",
"subject": "Re: Order #A-4521 delivery update?",
"body_text": "Shipped Tuesday, tracking below...",
"thread_id": "...",
"received_at": "2026-04-17T10:00:00.000Z"
}
}
The envelope is always { event, timestamp, data }, and the data fields are snake_case. thread_id is the important one for agent work: it arrives with the event, so your handler can load prior context before it calls the model, and your reply goes back on the same thread by passing inReplyTo with the inbound message id.
Webhooks are their own resource, registered separately from the mailbox, so one endpoint can serve many mailboxes or each agent can get its own. Payloads are signed, failed deliveries are retried with backoff, and there is an events API for listing and reprocessing what you missed. Details are in the webhooks concept doc.
Creating the mailbox that emits those events is one command:
npx @robotomail/cli mailbox create shopping-agent
SendGrid
Two separate systems that people conflate. The Event Webhook posts batched JSON arrays of delivery telemetry and supports signature verification. Inbound Parse is a different feature: you point an MX record at SendGrid, configure a hostname, and it POSTs incoming mail to your URL.
The friction is that Inbound Parse is a multipart form POST, not JSON. You get fields for from, subject, text, html, envelope, and attachments as file parts, and you parse them with whatever multipart middleware your framework has. There is a raw MIME mode if you want the original message. It works, but it is a different code path from every other JSON webhook in your app, and the verification and retry story is not the same as the Event Webhook's. Full breakdown in our SendGrid comparison.
Mailgun
Mailgun has the most mature webhook plumbing of the classic senders. Signatures are HMAC-SHA256 over a timestamp and token, which lets you reject replays properly. The event set is broad, and there is a separate events API you can query for history, which is exactly the recovery path you want when retries exhaust.
Inbound comes through routes: you write a filter expression, and the action either forwards to a URL or stores the message and posts a notification. The store-and-notify variant gives you a pointer, so read the route action you configured carefully before assuming the body is in the payload. Routes are powerful and also a second mental model on top of the webhook model. See Robotomail vs Mailgun.
Postmark
Postmark's inbound webhook is the cleanest JSON payload among the transactional senders. Parsed text, HTML, full headers array, attachments base64-encoded inline, and stripped reply text that removes quoted history for you. That last field saves real work when you are feeding replies to a model.
Security is typically handled with basic auth credentials embedded in the endpoint URL rather than a payload signature, which is workable behind TLS but weaker than HMAC if the URL ever leaks into a log. Postmark does retry failed inbound deliveries and exposes the inbound stream so you can retry by hand, which makes recovery from an outage straightforward.
Resend
Resend delivers webhooks in the Svix style, which means standard signing headers, a documented escalating retry schedule, and a dashboard view of attempts and responses. If you have integrated any Svix-backed product before, the verification code is identical, which is a real advantage.
Inbound support is newer than the sending path, so check the current docs for exactly which inbound events exist and what the payload contains before designing around it. Our Resend comparison goes into the sending side too.
AgentMail
Also built for the agent use case, with inbound events and per-agent inboxes rather than a shared parse hostname. If you are evaluating agent-native options, that is the direct alternative and we compare the two honestly in Robotomail vs AgentMail.
Gmail API
Gmail does not have webhooks in the sense this post means. It has push notifications through Google Cloud Pub/Sub. You call users.watch() on a mailbox, Google publishes to your topic, and your subscriber receives a notification containing an email address and a historyId. Nothing else. No sender, no subject, no body.
Your handler then calls users.history.list() with the last historyId you stored, diffs the result, and fetches each new message. You maintain that cursor yourself, per mailbox, forever. The watch also expires within about a week and must be renewed, so a forgotten cron job means silent inbound failure. Multiply all of that by the number of agents you run and by OAuth consent per account. We wrote up the alternatives in Gmail API alternatives for AI agents.
Microsoft Graph and Outlook
Graph change notifications follow the same pointer model. You create a subscription against a mail folder, respond to a validation handshake with the echoed token, and then receive notifications carrying a resource path rather than the message. You call back to fetch the content. Graph supports including encrypted resource data in the notification, which reduces the round trip but adds certificate management.
Mail subscriptions also have a short maximum lifetime measured in days and must be renewed before expiry. Same class of operational chore as Gmail's watch. More in the Outlook comparison.
Amazon SES
SES inbound is receipt rules, and the rule targets S3, SNS or Lambda rather than an HTTP endpoint directly. SNS can HTTP POST to you, but SNS has a message size limit in the low hundreds of kilobytes, so anything with a real attachment has to land in S3 first and your handler fetches it. That is a fine architecture if you already live in AWS and it is a lot of moving parts if you do not. SNS does sign its messages and has its own retry policy, so the fundamentals are solid, just assembled from three services instead of one.
Payload design: what a good inbound event carries
Rank payloads by how much work your handler has to do before it can call a model.
The fields that matter most:
fromandtoparsed into addresses, not raw header strings you have to run through a parser.body_textalready extracted from the MIME tree. Multipart alternative with nested related parts is not something you want to unwrap per request.- A thread identifier. Without one you are reimplementing
Message-ID,In-Reply-ToandReferencescorrelation yourself. Threading is subtle and every mail client breaks it differently. - The inbound message id, so your reply can set
inReplyToand land in the same conversation. - Attachment references rather than giant base64 blobs inline, once messages get large. Base64 inline is convenient at small sizes and becomes a payload-size problem fast.
If a provider only gives you a pointer, you can still build the thing. You are just accepting one extra API call, a cursor to store, and a class of bugs where the pointer arrives before the message is readable.
Retries, ordering and idempotency
Assume at-least-once delivery from every provider on this list. Design accordingly:
- Return 2xx fast. Acknowledge the webhook, enqueue the work, return. Do not run an LLM call inside the request handler. Model latency will blow past whatever timeout the provider enforces, you will get retried, and now the same email is being processed twice concurrently.
- Deduplicate on the message id. Store processed ids with a TTL longer than the provider's full retry window. Check before doing anything with side effects.
- Do not assume ordering. Two replies to the same thread landing seconds apart can arrive in either order. Sort by the message timestamp when you assemble context, not by arrival.
- Make sends idempotent too. The most expensive failure mode is a retried webhook that causes your agent to send a duplicate reply to a customer.
- Alert on webhook failure rate. A rising 5xx rate on your endpoint is the earliest signal that an agent has gone deaf. Most dashboards show attempt history, and a provider events API lets you reconcile.
The practical implementation of steps one through three is walked through in our guide to receiving email with a webhook.
Signature verification is not optional here
Standard webhook advice applies with extra force when the consumer is an LLM. An unsigned inbound endpoint lets anyone POST a fabricated email that your agent will treat as real and act on. Prompt injection through email content is already a problem; forged webhook bodies skip email entirely and inject straight into your pipeline.
Verify the signature before parsing. Reject payloads with a timestamp outside a few minutes of now. Do not put the verification behind your JSON body parser if the parser mutates the raw bytes, because HMAC is computed over the exact body. And treat the verified email content as untrusted input regardless: signature verification proves the provider sent it, not that the sender is honest.
How to choose
- Agent reads mail and replies, one inbox per agent. You want a content-style inbound event with a thread id and no per-mailbox OAuth. Robotomail and AgentMail are built for this shape.
- You already send at volume through a transactional provider and want to bolt on inbound. Mailgun and Postmark have the strongest inbound webhook implementations of that group. Postmark for payload quality, Mailgun for signing and the events API.
- The agent must operate inside a specific person's existing corporate mailbox. Gmail API or Microsoft Graph, and accept the pointer model, subscription renewal and OAuth cost.
- You are deep in AWS and want to own the pipeline. SES receipt rules into Lambda, with S3 for anything large.
FAQ
What is the difference between an inbound webhook and a delivery event webhook?
An inbound webhook fires when someone sends mail to your address and carries the received message. A delivery event webhook fires when mail you sent is delivered, bounced, or marked as spam. Some providers document only the second kind on their webhooks page while inbound lives under a separate feature name like Inbound Parse or receipt rules.
Do email webhooks guarantee ordering?
No. Treat every provider as at-least-once and unordered. Deduplicate on message id and sort by message timestamp when reconstructing a thread, rather than relying on arrival order.
What should my endpoint return, and how fast?
Return a 2xx as soon as you have durably queued the event, ideally in well under a second. Any real processing, especially model calls, belongs in a background worker. Slow handlers get timed out and retried, which turns one email into several concurrent runs of the same job.
Can I recover emails missed while my endpoint was down?
Only if the provider exposes event history or an inbound stream you can query. Retries help with short outages; for anything longer you need a list-and-reprocess API. Check that this exists before you go to production, because it is the difference between a bad deploy and lost customer mail.
Robotomail gives every agent a real inbox that emits signed, retried, content-complete message.received events with threading included, so your handler can go straight from webhook to reply. Start at robotomail.com or read the webhook docs.
Give your AI agent a real email address
One API call creates a mailbox with full send and receive. Webhooks for inbound, automatic threading, deliverability handled. 30-day money-back guarantee.
Related posts

Email MCP Server: Give Any MCP Agent an Inbox
How to build an email MCP server: the tool surface for sending, replying, threading and receiving mail, with working TypeScript and API examples.
Read post
Hermes Agent Email: Give Your Nous Agent an Inbox
Step-by-step guide to wiring a real email inbox into a Hermes agent: mailbox creation, tool schemas, inbound webhooks, and threaded replies.
Read post
Email for OpenClaw Agents: Full Integration Guide
Wire real email into OpenClaw agents: provision a mailbox, expose send and reply tools, handle inbound webhooks, and keep threading correct.
Read post