Introducing Receiving: inbound email API for developers
Nuntly now supports inbound email. Receive, store, and respond to emails through a structured API with inboxes, threads, namespaces, and AI Agent support.
Sending email is only half the picture. Support tickets, billing queries, automated replies, AI agents acting on incoming messages. All of these need an inbound email API, not just an outbound one.
Today, Nuntly supports inbound email natively. Same platform, same API, same domain. Whether you need to monitor incoming messages from a dashboard, give your AI agent its own inbox, or route emails across tenants and teams, Receiving covers it.
Receive and monitor
The simplest pattern: an email arrives, Nuntly fires a message.received webhook event, and you decide what to do with it.
Every inbound message is stored in full: headers, plain text body, HTML body, and attachments. You can inspect messages from the Nuntly dashboard or retrieve them through the API.
1{2 "id": "evt_01ka8k8s80gvx9604cn9am5st4",3 "type": "message.received",4 "createdAt": "2026-03-18T10:30:00.000Z",5 "data": {6 "orgId": "org_01jk8a3f7v0x9qr2mn4p6b5t8w",7 "domainId": "dns_01jk8a3f7v0x9qr2mn4p6b5t8w",8 "domainName": "example.com",9 "inboxId": "ibx_01jk8a3f7v0x9qr2mn4p6b5t8w",10 "threadId": "thr_01jk8a3f7v0x9qr2mn4p6b5t8w",11 "messageId": "imsg_01jk8a3f7v0x9qr2mn4p6b5t8w",12 "from": "Alice <alice@external.com>",13 "subject": "Question about my order"14 }15}16
Use this to trigger internal workflows, send Slack notifications, log inbound emails to your own system, or alert your team when a specific sender writes in. Every domain also gets a default catch-all inbox (*) that captures anything not matched by a specific address.
Give your AI agent an inbox
Webhook events are useful for reacting to incoming messages, but they are ephemeral. Once consumed, the payload is gone. An inbox is different: every message is stored long-term with its full content, attachments, and thread history. You can query past conversations and build on top of a persistent record.
You can assign an AI agent to any inbox and get a complete conversational loop: structured message in, agent processes, reply out.
Inbox: a dedicated email address (e.g., support@yourdomain.com) that your agent owns. Webhook events are lightweight: metadata only (sender, subject, thread ID). Your agent calls the API to fetch the full content when it needs it. No MIME parsing.
Thread: Nuntly reads the In-Reply-To and References headers defined in RFC 5322 and links replies to their original conversation automatically. Your agent gets the full conversation history without managing state.
"The 'In-Reply-To' and 'References' fields are used when creating a reply to a message. They hold the message identifier of the original message and the message identifiers of other messages." RFC 5322, Section 3.6.4
Agent memory: persist context across conversations at three scopes (global, per-inbox, or per-thread). Store summaries, extracted data, or intermediate results so your agent remembers previous interactions.
Reply API: send replies programmatically from the inbox address, linked to the original thread. The full conversation stays in one place through both the API and the Nuntly dashboard.
When a message arrives in an agent-assigned inbox, Nuntly fires a message.agent_triggered webhook event. Your agent handler is invoked automatically.
1import Anthropic from '@anthropic-ai/sdk';2import { Nuntly } from '@nuntly/sdk';34const anthropic = new Anthropic();5const nuntly = new Nuntly({ apiKey: process.env.NUNTLY_API_KEY });67// Called when Nuntly fires message.agent_triggered8export async function handleInbound(event: { messageId: string; from: string; subject: string }) {9 // Fetch full message content10 const content = await nuntly.inbound.messages.content(event.messageId);1112 // Load conversation history from agent memory13 const state = await nuntly.inbound.agents.memory.get({14 scope: 'thread',15 threadId: content.threadId,16 });1718 // Process with your AI model19 const response = await anthropic.messages.create({20 model: 'claude-sonnet-4-6',21 max_tokens: 1024,22 system: 'You are a helpful customer support agent.',23 messages: [24 ...(state?.history ?? []),25 {26 role: 'user',27 content: `From: ${event.from}\nSubject: ${event.subject}\n\n${content.text}`,28 },29 ],30 });3132 const reply = response.content[0].text;3334 // Send the reply35 await nuntly.inbound.messages.reply(event.messageId, {36 subject: `Re: ${event.subject}`,37 html: `<p>${reply}</p>`,38 });3940 // Persist conversation history41 await nuntly.inbound.agents.memory.upsert({42 scope: 'thread',43 threadId: content.threadId,44 data: {45 history: [...(state?.history ?? []), { role: 'assistant', content: reply }],46 },47 });48}49
Email in, agent triggered, reply sent, memory updated.
This pattern applies to customer support automation, lead classification and routing, invoice and document processing, automated follow-ups, onboarding, and email-to-ticket conversion. Few email platforms provide structured JSON payloads, thread context, agent memory, and a Reply API natively. Most require you to stitch together three or four services to get the same result.
Nuntly emits webhook events at every step (message.received, message.agent_triggered, message.sent), so you can monitor and debug the full flow from your existing observability setup.
Multi-tenant routing with namespaces
Namespace: a logical group of inboxes with an optional externalId. Namespaces let you isolate and route emails by tenant, team, or system.
Three common patterns:
SaaS platforms: provision one namespace per customer. Each customer gets isolated inboxes (support@, billing@) with their own agent assignments and state. Query all messages for a specific tenant with a single API call.
Agencies: one namespace per client. Manage contact@client-a.com and contact@client-b.com from the same Nuntly account, with separate webhook routing and dashboards per namespace.
AI agent platforms: one namespace per agent cluster. If you run multiple specialized agents (support agent, sales agent, billing agent), each group gets its own namespace with dedicated inboxes and memory scope. Scale agent deployments without inbox collisions.
1// Create a namespace for a customer2const namespace = await nuntly.namespaces.create({3 name: 'Acme Corp',4 externalId: 'customer_123',5});67// Create inboxes within that namespace8await nuntly.inboxes.create({9 address: 'support',10 domainId: 'dns_01...',11 name: 'Acme Support',12 namespaceId: namespace.id,13});14
Webhook events for email receiving
Receiving adds four webhook event types to the existing Nuntly webhook system:
| Event | Trigger |
|---|---|
message.received | New message arrives in an inbox |
message.security_flagged | Message rejected for security reasons |
message.agent_triggered | Agent invoked for a message |
message.sent | Reply dispatched from an inbox |
Configure these events on any webhook endpoint, the same way you already handle sending events like email.delivered or email.bounced. All webhook events support event replay, so you never lose a notification.
Getting started
Receiving is available on all plans, including the free tier (3,000 emails/month). Setup takes under 5 minutes:
- Make sure your domain is configured in Nuntly
- Create an inbox via the API or dashboard
- Point your domain's MX records to Nuntly (instructions in the setup guide)
- Subscribe to
message.receivedwebhooks or attach an agent
The full Receiving guide covers MX setup, namespace management, thread retrieval, agent configuration, and security filtering in detail.
Ship emails, not infrastructure
Free plan available. No credit card required.
Start sending freeFrequently asked questions
Do I need a separate domain for receiving?
No. You can use the same domain you already use for sending. Nuntly handles both directions from the same domain configuration.
What happens to messages that do not match any inbox?
Every domain has a catch-all inbox (*) that receives anything not matched by a specific address. You can retrieve these messages through the API or ignore them entirely.
Can I use Receiving without an agent?
Yes. Agents are optional. You can receive and retrieve messages through the API without any agent configuration. Many teams use Receiving purely to store inbound messages and query them programmatically.
How does threading work across sending and receiving?
When a customer replies to an email you sent, Nuntly uses the standard In-Reply-To header (RFC 5322) to link their reply to the original thread. The thread contains both directions of the conversation.
Can I run different agents for different inboxes?
Yes. Each inbox has its own agent assignment. You can run a support agent on support@, a sales classifier on sales@, and leave billing@ without an agent, all within the same domain.
Ship emails, not infrastructure
Free plan available. No credit card required.
Start sending free