Email to Webhook for AI Agents: A Reliable Inbound Pattern
An email-to-webhook flow turns inbound email into a signed HTTP event your application can process immediately. For an AI agent, the reliable pattern is: receive mail in a dedicated inbox, verify the webhook against the raw request body, return a fast 2xx, and move the agent’s heavier work to an asynchronous job.
That gives the agent real-time inbound communication without polling on every loop. It also creates a clean boundary between accepting an event and letting a model read, classify, or answer the message.
Sentvia’s receiving documentation confirms that inbound messages are parsed, threaded, and delivered by webhook or through GET /messages, with webhooks recommended for push delivery.
The reliable receive loop
A production receive path has six parts:
- A dedicated inbox receives the message.
- The email platform parses and threads it into application-readable data.
- A webhook POST reaches your endpoint with an event type and signed body.
- Your endpoint verifies the signature before trusting the payload.
- Your endpoint returns
2xxquickly after durable acceptance. - A worker runs the agent logic and decides whether to classify, store, escalate, or reply.
The important separation is between steps five and six. A webhook endpoint should confirm receipt; it should not wait for an LLM call, a vector search, or a slow downstream API before responding.
1. Register only the events you need
Create a webhook endpoint and subscribe to the inbound and delivery events your application actually handles:
curl -X POST https://api.sentvia.ai/v1/webhooks \
-H "Authorization: Bearer sv_live_…" \
-H "Content-Type: application/json" \
-d '{ "url": "https://your-app.com/sentvia", "events": ["message.received","message.bounced"] }'
The registration response returns a signing secret that is shown once. Store it as a secret, not in source control or client-side code. The supported event set in the current docs includes:
| Event | Meaning |
|---|---|
message.received | An inbound email arrived at one of your inboxes. |
message.delivered | An outbound message was accepted by the recipient’s server. |
message.bounced | A hard or soft bounce occurred. |
message.complained | A spam complaint was recorded. |
message.rejected | The provider rejected the send. |
For a first inbound agent workflow, message.received is the essential event. Add delivery events only when the application has a clear action for them.
2. Verify the raw body before parsing
Sentvia sends the event name in x-sentvia-event and the signature in x-sentvia-signature. The signature is an HMAC-SHA256 computed from the raw request body and your webhook secret.
The official verification pattern is:
import crypto from "node:crypto";
function verify(rawBody: string, signature: string, secret: string) {
const expected =
"sha256=" +
crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature),
);
}
Verify every request and reject mismatches. Do not parse the JSON and serialize it again before hashing; even equivalent JSON can produce different bytes and fail signature verification.
Your framework must therefore preserve access to the raw body. The exact configuration differs by framework, so check its request-body documentation rather than copying an unverified middleware snippet.
3. Acknowledge quickly, process asynchronously
The current receiving docs state that deliveries are retried with backoff after non-2xx responses. They also recommend returning 2xx quickly and doing heavy work asynchronously.
A practical handler should therefore:
- read the raw body;
- verify the signature;
- validate that the event type is expected;
- durably enqueue or store the event;
- return
2xx; and - let a worker run the agent.
Because a failed delivery can be retried, design the worker so repeated processing is safe. Do not let a retry create two tickets, send two replies, or run the same side effect twice. If your payload or application record has a stable identifier, use it to guard side effects; otherwise record enough message context to detect work already completed.
4. Keep the agent behind an application boundary
Do not pass an unverified request straight into a model. Treat inbound email as untrusted input and apply normal application controls first:
- authorize the event through its signature;
- validate the event shape your code expects;
- route by inbox, tenant, or workflow;
- preserve thread context for later turns;
- apply attachment and content policies;
- set timeouts and budgets for downstream work; and
- require explicit application rules before sending a reply.
This boundary matters for multi-tenant agent platforms. An inbox identifies where the message arrived, but your application still owns tenant isolation, permissions, business rules, and the decision to let an agent act.
For the broader architecture, see Email Infrastructure for Autonomous AI Agents.
5. Handle attachments as temporary resources
Sentvia includes attachment metadata and short-lived signed download URLs in webhook delivery data. Treat those URLs as temporary:
- fetch only after the webhook is verified;
- enforce file-size and content-type limits;
- scan or isolate files before model access when appropriate;
- copy required files into your controlled storage before the URL expires; and
- avoid logging signed URLs.
The attachments guide is the source of truth for current attachment behavior.
6. Use polling when push delivery is not possible
Webhooks are the right default for real-time agents, but polling remains useful for local development, recovery tooling, or environments without a public endpoint:
curl "https://api.sentvia.ai/v1/messages?inbox_id=INBOX_ID&limit=25" \
-H "Authorization: Bearer sv_live_…"
Polling trades immediacy for operational simplicity. If the agent only checks mail at scheduled intervals, that can be acceptable. For interactive support, approvals, or workflows that should react as soon as a reply arrives, webhooks avoid repeated empty reads and reduce response latency.
Webhook versus polling
| Requirement | Webhook | Polling |
|---|---|---|
| React as soon as mail arrives | Best fit | Depends on interval |
| No public endpoint available | Poor fit | Best fit |
| Minimize repeated API reads | Best fit | Poorer fit |
| Simple local prototype | Requires a reachable endpoint | Often simpler |
| Recovery or reconciliation job | Useful as the primary signal | Useful as a secondary check |
A robust system can use webhooks for the normal path and the messages API for reconciliation or manual recovery. That is an application architecture choice; it does not require the agent to poll continuously.
A production checklist
Before connecting inbound email to an autonomous workflow, verify that:
- the signing secret is stored securely;
- signature verification uses the raw body;
- invalid signatures are rejected;
- the endpoint acknowledges accepted events quickly;
- model and tool calls happen outside the request path;
- repeated processing cannot duplicate side effects;
- tenant and inbox routing is explicit;
- thread context is preserved;
- attachment handling is bounded and isolated;
- failures are observable; and
- polling or replay procedures exist for recovery.
Email receiving is not just a trigger. It is the input boundary for an agent that may later send messages, call tools, or change external systems. Treating that boundary as infrastructure—not prompt glue—makes the entire loop easier to trust.
Sentvia provides real inboxes for AI agents with two-way email, native threading, and real-time inbound events. You can start free with 5 inboxes and 5,000 emails, or review the current pricing.
Frequently asked questions
What is an email webhook?
An email webhook is an HTTP request sent to your application when an email event occurs. For inbound agent email, the key event is message.received, which lets the application react without repeatedly polling for new messages.
Should an AI agent process the email inside the webhook request?
Usually no. Verify and durably accept the event, return 2xx quickly, then process it asynchronously. This reduces delivery retries and keeps slow model or tool calls out of the webhook request path.
Why must signature verification use the raw request body?
The signature is computed from the original body bytes. Parsing and re-serializing JSON can change whitespace or ordering, producing different bytes and causing a valid request to fail verification.
What happens when the endpoint returns an error?
Sentvia’s public receiving docs state that non-2xx deliveries are retried with backoff. Build the worker so repeated delivery does not repeat external side effects.
Can I receive email without a webhook?
Yes. The current API supports polling recent mail with GET /messages. Polling is useful when no public endpoint is available, while webhooks are the recommended push path for real-time workflows.
Sources
- Sentvia: Receiving email — webhook registration, events, signature verification, retries, attachment metadata, and polling.
- Sentvia: Email for AI agents — two-way email, native threading, and real-time inbound product capabilities.
- Sentvia: Pricing — current plan allowances and signup path.
- Sentvia: 100,000 emails sent — operational context on reliable agent email and deliverability.