Give a support agent an address on your domain, deliver incoming messages to your application, and reply in the same conversation. inbound supplies the email infrastructure; your application decides what the agent can do.
Connect a domain or receiving subdomain, then route an address such as support@agents.example.com to a webhook. inbound delivers an email.received JSON event with parsed content, attachment download URLs, and thread information.
This gives your agent an identity on a domain you control. Connecting an existing human Gmail or Outlook mailbox is a separate integration; creating an inbound address does not grant access to that mailbox.
After verifying and durably storing a webhook, use email.id to identify the message and email.threadId to retrieve its conversation. Load your own customer context, prepare a draft, and apply your application's approval policy before sending.
This worker function takes the webhook's email object. You supply draftAndApprove: an application function that receives the message and thread, then returns approved reply text or null. Set INBOUND_API_KEY and AGENT_FROM to your server-side API key and authorized sending address.
The reply endpoint sets In-Reply-To and References for you. The example reuses one idempotency key for the same support reply; a separate intended reply needs its own key.
async function replyToSupportEmail(email, draftAndApprove) {
const base = "https://inbound.new/api/e2";
const headers = {
Authorization: `Bearer ${process.env.INBOUND_API_KEY}`,
};
let thread = null;
if (email.threadId) {
const res = await fetch(
`${base}/mail/threads/${encodeURIComponent(email.threadId)}`,
{ headers },
);
if (!res.ok) throw new Error(`Thread lookup: ${res.status}`);
thread = await res.json();
}
const text = await draftAndApprove({ email, thread });
if (!text) return;
const res = await fetch(`${base}/emails/${encodeURIComponent(email.id)}/reply`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json",
"Idempotency-Key": `support-reply-${email.id}` },
body: JSON.stringify({ from: process.env.AGENT_FROM, text }),
});
if (!res.ok) throw new Error(`Reply failed: ${res.status}`);
}Create dedicated address routes or use a domain catch-all with an application-owned address map. For example, customer-42@agents.example.com can resolve to a particular customer's support agent without creating a separate endpoint for every customer.
Your application must enforce tenant access before loading customer records, thread history, or attachments. A catch-all alias is a routing identity, not an isolated security boundary. Validate the recipient against your own tenant map rather than trusting the visible To header.
inbound stores mail and exposes thread list and detail endpoints. Persist the workflow state you need separately: tenant ownership, draft revisions, approvals, tool results, and completed actions. An email thread ID does not replace your application's conversation state or authorization checks.
Use REST or the inboundemail TypeScript SDK in your application. For agent-driven operation, inbound also provides the inboundctl CLI, an installable agent skill, and a hosted MCP server. The docs cover API setup; plans start at $4/month, with current details on the pricing page.
inbound transports messages, exposes conversation context, and supports Idempotency-Key on sends and replies. Your builder code must implement tool permissions, human approval where appropriate, and idempotent business actions such as creating tickets or issuing refunds.
Failed webhook deliveries are not retried automatically. After fixing the cause, retry through POST /api/e2/emails/:id/retry. Make reprocessing safe before requesting a retry.
Create specific addresses on your connected domain, or enable catch-all routing and assign aliases in your application. Keep an explicit address-to-tenant mapping and check it before exposing messages or customer data to an agent.
Yes. POST /api/e2/emails/:id/reply accepts an email ID or a thread ID. A thread ID targets the latest message, and inbound sets the threading headers. Your application provides the authorized from address and reply content.
Implement tenant-scoped access, untrusted-content handling, attachment validation, limited tool permissions, and approval for consequential actions. Record actions durably so replaying an email cannot repeat them. These are application responsibilities, separate from inbound's email routing and filtering.
No. inbound also exposes email and thread APIs, the inboundctl CLI, a hosted MCP server, and IMAP access. Webhooks let your application react to incoming messages; choose the access method that fits how your agent runs.
Add a domain, point an address at your webhook, and get structured JSON for every message.
Get started