---
title: "Announcing Inboxes"
slug: announcing-inboxes
description: "The inbox for agents. Create shared inboxes, connect your own agents, and build workflows around email."
created_at: "2026-10-22"
updated_at: "2026-10-22"
image: https://cdn.resend.com/posts/announcing-inboxes.jpg
humans: ["bu-kinoshita", "giovana-yahiro", "joao-melo", "carolina-josephik", "isabella-aquino", "alexandre-cisneiros", "laura-beatris"]
category: "product"
featured: true
---

Resend started with sending. In 2025, we added [receiving](/blog/inbound-emails), so your app could get mail, too. Webhooks fire, but the rest is up to you.

"The rest" turned out to be a lot of work. Once email comes in, someone has to read it, sort it, reply to it, and remember where the conversation left off. Increasingly, that someone is an agent.

## The inbox for agents

Today we're announcing [**Inboxes**](/products/inboxes).

Built for agents, but ready for your whole team.

<YouTube videoId="BU9wG4p_IBE"/>

An inbox sends and receives email at an address on one of your domains, like `support@example.com`. Every message is grouped into a thread, and every thread is available to your app, your team, and your agents.

<video
  src="https://cdn.resend.com/posts/announcing-inboxes-list.mp4"
  autoPlay
  muted
  playsInline
  className="extraWidth border border-slate-6"
/>

Share an inbox with your team, assign conversations, leave notes, and pick up where someone else left off. The **same inbox can be worked by people and agents** side by side.

## Ready for every use case

You can build and use Inboxes to fit any use case.

- **Agents**: give each AI agent its own address to receive tasks, approvals, and updates.
- **Support**: route support email into your product and fetch threads through the API.
- **Assistant**: let an agent sort incoming requests, draft replies, and keep threads moving.
- **Recruiting**: create an inbox for teams and agents to track candidate conversations.
- **On-call**: collect alerts in one inbox and assign each one, so nothing sits unassigned.
- **Notifications**: send receipts, alerts, and updates for your app to process.

## Build inboxes your way

Inboxes are API-first. Create an inbox, list conversations as they arrive, and reply from your app, an agent, or an automated workflow.

<CodeTabs codeHeight={180}>
```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.inboxes.threads.list({
  inboxId: 'b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1',
});
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->inboxes->threads->list('b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1');
```

```python
import resend

resend.api_key = "re_xxxxxxxxx"

resend.Inboxes.Threads.list("b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1")
```

```ruby
require "resend"

Resend.api_key = "re_xxxxxxxxx"

Resend::Inboxes::Threads.list({ inbox_id: "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" })
```

```go
package main

import "github.com/resend/resend-go/v4"

func main() {
	client := resend.NewClient("re_xxxxxxxxx")

	client.Inboxes.Threads.List("b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1", nil)
}
```

```rust
use resend_rs::{
  list_opts::ListOptions,
  types::ListInboxThreadsOptions,
  Resend, Result,
};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let _threads = resend
    .inboxes
    .list_threads(
      "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
      ListInboxThreadsOptions::new(),
      ListOptions::default(),
    )
    .await?;

  Ok(())
}
```

```java
import com.resend.Resend;
import com.resend.core.exception.ResendException;
import com.resend.services.inboxes.model.ListInboxThreadsResponseSuccess;

public class Main {
    public static void main(String[] args) throws ResendException {
        Resend resend = new Resend("re_xxxxxxxxx");

        ListInboxThreadsResponseSuccess data = resend.inboxes().threads()
                .list("b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1");
    }
}
```

```dotnet
using Resend;

IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

var resp = await resend.InboxThreadListAsync( new Guid( "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" ) );
Console.WriteLine( "Nr Threads={0}", resp.Content.Data.Count );
```

```curl
curl -X GET 'https://api.resend.com/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads' \
     -H 'Authorization: Bearer re_xxxxxxxxx'
```

```cli
resend inboxes threads list --inbox_id b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1
```
</CodeTabs>

Replies stay in the same thread, and reuse the thread's subject when you don't set one:

<CodeTabs codeHeight={300}>
```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.inboxes.threads.emails.reply({
  inboxId: 'b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1',
  threadId: '4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12',
  emailId: '5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60',
  cc: ['billing@example.com'],
  bcc: ['records@example.com'],
  html: '<p>Refund issued for order 1041.</p>',
  text: 'Refund issued for order 1041.',
});
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->inboxes->threads->emails->reply(
  'b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1',
  '4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12',
  '5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60',
  [
    'cc' => ['billing@example.com'],
    'bcc' => ['records@example.com'],
    'html' => '<p>Refund issued for order 1041.</p>',
    'text' => 'Refund issued for order 1041.',
  ]
);
```

```python
import resend

resend.api_key = "re_xxxxxxxxx"

params: resend.Inboxes.Threads.Emails.ReplyParams = {
    "inbox_id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
    "thread_id": "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
    "email_id": "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
    "cc": ["billing@example.com"],
    "bcc": ["records@example.com"],
    "html": "<p>Refund issued for order 1041.</p>",
    "text": "Refund issued for order 1041.",
}

resend.Inboxes.Threads.Emails.reply(params)
```

```ruby
require "resend"

Resend.api_key = "re_xxxxxxxxx"

params = {
  inbox_id: "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
  thread_id: "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
  email_id: "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
  cc: ["billing@example.com"],
  bcc: ["records@example.com"],
  html: "<p>Refund issued for order 1041.</p>",
  text: "Refund issued for order 1041."
}

Resend::Inboxes::Threads::Emails.reply(params)
```

```go
package main

import "github.com/resend/resend-go/v4"

func main() {
	client := resend.NewClient("re_xxxxxxxxx")

	params := &resend.ReplyInboxThreadEmailRequest{
		Cc:   []string{"billing@example.com"},
		Bcc:  []string{"records@example.com"},
		Html: "<p>Refund issued for order 1041.</p>",
		Text: "Refund issued for order 1041.",
	}

	client.Inboxes.Threads.Emails.Reply(
		"b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
		"4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
		"5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
		params,
	)
}
```

```rust
use resend_rs::{
  types::{ReplyInboxThreadEmailOptions},
  Resend, Result,
};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let opts = ReplyInboxThreadEmailOptions::new()
    .with_cc(["billing@example.com"])
    .with_bcc(["records@example.com"])
    .with_html("<p>Refund issued for order 1041.</p>")
    .with_text("Refund issued for order 1041.");

  let _reply = resend
    .inboxes
    .reply_thread_email(
      "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
      "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
      "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
      opts,
    )
    .await?;

  Ok(())
}
```

```java
import com.resend.Resend;
import com.resend.core.exception.ResendException;
import com.resend.services.inboxes.model.ReplyInboxThreadEmailOptions;
import com.resend.services.inboxes.model.ReplyInboxThreadEmailResponseSuccess;

public class Main {
    public static void main(String[] args) throws ResendException {
        Resend resend = new Resend("re_xxxxxxxxx");

        ReplyInboxThreadEmailOptions params = ReplyInboxThreadEmailOptions.builder()
                .cc("billing@example.com")
                .bcc("records@example.com")
                .html("<p>Refund issued for order 1041.</p>")
                .text("Refund issued for order 1041.")
                .build();

        ReplyInboxThreadEmailResponseSuccess data = resend.inboxes().threads().emails().reply(
                "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
                "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12",
                "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60",
                params);
    }
}
```

```dotnet
using Resend;

IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

var resp = await resend.InboxThreadEmailReplyAsync(
    new Guid( "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" ),
    new Guid( "4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12" ),
    new Guid( "5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60" ),
    new InboxThreadEmailReplyData()
    {
        Cc = "billing@example.com",
        Bcc = "records@example.com",
        HtmlBody = "<p>Refund issued for order 1041.</p>",
        TextBody = "Refund issued for order 1041.",
    }
);
Console.WriteLine( "Email Id={0}", resp.Content );
```

```curl
curl -X POST 'https://api.resend.com/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/threads/4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12/emails/5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60/reply' \
     -H 'Authorization: Bearer re_xxxxxxxxx' \
     -H 'Content-Type: application/json' \
     -d $'{
  "cc": ["billing@example.com"],
  "bcc": ["records@example.com"],
  "html": "<p>Refund issued for order 1041.</p>",
  "text": "Refund issued for order 1041."
}'
```

```cli
resend inboxes threads emails reply \
  --inbox_id b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1 \
  --thread_id 4d8e2a1c-9b3f-4c6d-8a21-3e5f7c9c0d12 \
  --email_id 5b1a9f47-2c8d-4e6f-9a03-1d2e3f4a5b60 \
  --cc billing@example.com \
  --bcc records@example.com \
  --html "<p>Refund issued for order 1041.</p>" \
  --text "Refund issued for order 1041."
```
</CodeTabs>

## Primitives built for the inbox

To support building custom experiences, we're releasing a full set of primitives centered on the inbox experience. 

- **Folders** for inbox, archive, spam, trash, and sent.
- **Search** with a Gmail-like query syntax, plus sender and date filters.
- **Labels** for tagging and organizing threads.
- **Drafts** for collaborating on emails before sending them.
- **Forwarding** and **reply all**, with CC, BCC, and [idempotency keys](/docs/dashboard/emails/idempotency-keys).
- **Webhooks** for everything from `inbox.email.received` to `inbox.thread.assigned`.
- **Agent settings** for configuring the built-in agent instructions, tone, and actions.

## Ready for your agents

Connect the agents you already use, like Claude Code, Cursor, Codex, Grok, or Gemini, through [MCP](https://resend.com/docs/mcp-server) or [skills](https://resend.com/docs/resend-skill). 

Build, manage, and triage inboxes with your agents using the API, CLI, or MCP server.

<video
  src="https://cdn.resend.com/posts/announcing-inboxes.mp4"
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth"
/>

Ask your agent to summarize what came in overnight, find the invoice from last month, or draft a reply to the customer who's been waiting since Tuesday.

## Customizable UI layer

The inbox UI includes built-in agents that can build custom, dynamic views of emails and threads to fit your needs.

<video
  src="https://cdn.resend.com/posts/announcing-inboxes-kanban.mp4"
  autoPlay
  loop
  muted
  playsInline
  className="extraWidth border border-slate-6"
/>

## Put your inbox on autopilot

You can also customize built-in agents to help you triage, organize, and respond to email.

Through the dashboard or via the API, give it instructions, a tone, and the actions it's allowed to take. It handles routine email work as it arrives, triggered by webhooks.

<CodeTabs codeHeight={260}>
```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.inboxes.agent.update({
  inboxId: 'b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1',
  instructions: 'Answer refund questions yourself. Escalate legal threats.',
  tone: 'friendly and concise',
  enabledActions: ['draft_reply', 'add_labels'],
});
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->inboxes->agent->update('b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1', [
  'instructions' => 'Answer refund questions yourself. Escalate legal threats.',
  'tone' => 'friendly and concise',
  'enabled_actions' => ['draft_reply', 'add_labels'],
]);
```

```python
import resend

resend.api_key = "re_xxxxxxxxx"

params: resend.Inboxes.Agent.UpdateParams = {
    "inbox_id": "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
    "instructions": "Answer refund questions yourself. Escalate legal threats.",
    "tone": "friendly and concise",
    "enabled_actions": ["draft_reply", "add_labels"],
}

resend.Inboxes.Agent.update(params)
```

```ruby
require "resend"

Resend.api_key = "re_xxxxxxxxx"

params = {
  inbox_id: "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1",
  instructions: "Answer refund questions yourself. Escalate legal threats.",
  tone: "friendly and concise",
  enabled_actions: ["draft_reply", "add_labels"]
}

Resend::Inboxes::Agent.update(params)
```

```go
package main

import "github.com/resend/resend-go/v4"

func main() {
	client := resend.NewClient("re_xxxxxxxxx")

	instructions := "Answer refund questions yourself. Escalate legal threats."
	tone := "friendly and concise"
	params := &resend.UpdateInboxAgentRequest{
		Instructions: &instructions,
		Tone:         &tone,
		EnabledActions: []resend.InboxAgentAction{
			resend.InboxAgentActionDraftReply,
			resend.InboxAgentActionAddLabels,
		},
	}

	client.Inboxes.Agent.Update("b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1", params)
}
```

```rust
use resend_rs::{
  types::{InboxAgentAction, UpdateInboxAgentOptions},
  Resend, Result,
};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let opts = UpdateInboxAgentOptions::new()
    .with_instructions("Answer refund questions yourself. Escalate legal threats.")
    .with_tone("friendly and concise")
    .with_enabled_actions([InboxAgentAction::DraftReply, InboxAgentAction::AddLabels]);

  let _agent = resend
    .inboxes
    .update_agent("b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1", opts)
    .await?;

  Ok(())
}
```

```java
import com.resend.Resend;
import com.resend.core.exception.ResendException;
import com.resend.services.inboxes.model.InboxAgentAction;
import com.resend.services.inboxes.model.UpdateInboxAgentOptions;
import com.resend.services.inboxes.model.UpdateInboxAgentResponseSuccess;

public class Main {
    public static void main(String[] args) throws ResendException {
        Resend resend = new Resend("re_xxxxxxxxx");

        UpdateInboxAgentOptions params = UpdateInboxAgentOptions.builder()
                .instructions("Answer refund questions yourself. Escalate legal threats.")
                .tone("friendly and concise")
                .enabledActions(InboxAgentAction.DRAFT_REPLY, InboxAgentAction.ADD_LABELS)
                .build();

        UpdateInboxAgentResponseSuccess data = resend.inboxes().agent()
                .update("b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1", params);
    }
}
```

```dotnet
using Resend;

IResend resend = ResendClient.Create( "re_xxxxxxxxx" ); // Or from DI

var resp = await resend.InboxAgentUpdateAsync(
    new Guid( "b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1" ),
    new InboxAgentUpdateData()
    {
        Instructions = "Answer refund questions yourself. Escalate legal threats.",
        Tone = "friendly and concise",
        EnabledActions = [ InboxAgentAction.DraftReply, InboxAgentAction.AddLabels ],
    }
);
Console.WriteLine( "Agent Id={0}", resp.Content );
```

```curl
curl -X PATCH 'https://api.resend.com/inboxes/b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1/agent' \
     -H 'Authorization: Bearer re_xxxxxxxxx' \
     -H 'Content-Type: application/json' \
     -d $'{
  "instructions": "Answer refund questions yourself. Escalate legal threats.",
  "tone": "friendly and concise",
  "enabled_actions": ["draft_reply", "add_labels"]
}'
```

```cli
resend inboxes agent update \
  --inbox_id b3e2b2b6-3f0e-4c8e-9ad3-2f43a1e2c7f1 \
  --instructions "Answer refund questions yourself. Escalate legal threats." \
  --tone "friendly and concise" \
  --enabled_actions draft_reply,add_labels
```
</CodeTabs>

The agent can draft replies, forward threads, add labels, assign threads, mark spam, archive, and delete. You decide which of those it gets. Start with drafts and labels, and widen the scope as you build trust.

Your team stays in control the whole time.

## Start today

You can start for free with up to 3 inboxes today.

Additional inboxes are available on paid plans on a pay-as-you-go basis ($1/inbox).

[Get started →](/inboxes)
