Developers
Trigger an AI agent from an email.
Point any alias at your HTTPS endpoint and ForwardMailTo POSTs each inbound message as signed JSON. An incoming email becomes a trigger for your agent, automation, or app. Webhook forwarding is a Pro feature.
How it works
- Create an alias on a verified domain and set delivery to
A webhook (HTTPS endpoint). - Enter your endpoint, for example
https://api.yourapp.com/inbound. - Send an email to that alias. We POST the JSON payload below to your endpoint.
- Verify the signature, then hand the message to your agent.
Payload
Every inbound message is delivered as a JSON body:
{
"domain": "yourdomain.com",
"alias": "[email protected]",
"from": "[email protected]",
"to": "[email protected]",
"subject": "Summarize this thread",
"message_id": "0000abcd1234...",
"received_at": "2026-01-01T12:00:00Z",
"spam": false,
"text": "Plain-text body of the email.",
"html": "HTML body if the message had one, otherwise null.",
"date": "2026-01-01T12:00:00Z",
"cc": ["[email protected]"],
"reply_to": ["[email protected]"],
"in_reply_to": "parent-message-id",
"references": ["parent-message-id"],
"attachments": [
{ "filename": "report.pdf", "content_type": "application/pdf", "size": 20481 }
],
"raw_mime": "From: ...full raw MIME message..."
}
Fields
| Field | Type | Description |
|---|---|---|
from |
string | The sender address of the inbound email. |
to |
string | The alias the email was delivered to. |
alias |
string | The full alias address, local part plus domain. |
subject |
string | The email subject line. |
text |
string / null | Parsed plain-text body. Null when the message has no text part. |
html |
string / null | Parsed HTML body. Null when the message has no HTML part. |
cc |
array | CC recipient addresses. |
reply_to |
array | Reply-To addresses from the original message. |
in_reply_to |
string / null | The parent Message-ID for threaded replies. |
references |
array / null | The thread reference chain. |
attachments |
array | Metadata for each attachment: filename, content_type, and size in bytes. |
message_id |
string | The provider Message-ID. Use it to de-duplicate retries. |
received_at |
string | ISO 8601 timestamp of when we processed the message. |
date |
string / null | The Date header from the original message. |
spam |
boolean | True when the message failed the spam check. |
raw_mime |
string | The complete raw MIME message, if you need to parse it yourself. |
Request headers
| Header | Value |
|---|---|
Content-Type |
application/json |
User-Agent |
ForwardMailTo-Webhook/1 |
X-ForwardMailTo-Timestamp |
Unix timestamp (seconds) when the request was signed |
X-ForwardMailTo-Signature |
sha256=<hex> HMAC of the signed payload |
Verify the signature
We sign every request with the account signing secret shown on the alias form. Compute an HMAC-SHA256 over the string timestamp + "." + rawBody and compare it to the X-ForwardMailTo-Signature header. Always verify against the raw request body, before any JSON re-serialization, and reject stale timestamps to prevent replay.
Node
const crypto = require("crypto")
function verifySignature(secret, timestamp, rawBody, signature) {
const expected = "sha256=" + crypto
.createHmac("sha256", secret)
.update(timestamp + "." + rawBody)
.digest("hex")
const a = Buffer.from(expected)
const b = Buffer.from(signature)
return a.length === b.length && crypto.timingSafeEqual(a, b)
}
Python
import hmac, hashlib
def verify_signature(secret, timestamp, raw_body, signature):
signed = f"{timestamp}.{raw_body}".encode()
expected = "sha256=" + hmac.new(
secret.encode(), signed, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
No code: connect it to n8n, Zapier, or Make
Point the alias at your automation tool and hand each email to an AI step. No server to run.
n8n
- Add a Webhook node set to POST and copy its production URL.
- Paste that URL as the alias webhook endpoint in ForwardMailTo.
- Read the text and subject fields into an AI Agent or OpenAI node.
- Route the AI result into any downstream node — store it, post to Slack, or open a ticket.
Zapier
- Create a Zap with the Webhooks by Zapier — Catch Hook trigger and copy the URL.
- Paste that URL as the alias webhook endpoint in ForwardMailTo.
- Add an AI step such as ChatGPT or Claude, using the text field as input.
- Send the AI result to any downstream app — a sheet, a ticket, or a Slack message.
Make
- Add a Custom webhook module and copy its address.
- Paste that address as the alias webhook endpoint in ForwardMailTo.
- Feed the parsed JSON into an OpenAI or Anthropic module.
- Route the AI result into any downstream module — a datastore, CRM, or notification.
Good to know
- Endpoints must be public HTTPS. We block requests to private and loopback addresses.
- A non-2xx response is retried up to three times with backoff. De-duplicate on
message_id. - Attachments are delivered as metadata only. Parse
raw_mimeif you need the file contents. - The signing secret is shared across all webhook aliases on your account.