> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.agentmail.to/llms.txt. For full content including API reference and SDK examples, see https://docs.agentmail.to/llms-full.txt.

# Inboxes

> Learn how AgentMail Inboxes act as scalable, API-first email accounts for your agents.

## What is an Inbox?

People are used to the traditional Gmail limitations -- only having one inbox. That's of the past.

An `Inbox` is now a fully loaded, programmatically accessible API resource re-designed for the scale of AI Agents.

Think of it as being similar to a Gmail or Outlook account, but built API-first. Each `Inbox` has a unique email address and serves as the primary resource your agent uses to send and receive emails, giving it a first-class identity on the internet.

Unlike traditional email providers that are designed for human scale, AgentMail `Inboxes` are built to scale horizontally. You can create tens, hundreds, or even thousands of `Inboxes` for your agents on demand.

Psst! Rather than sending 1000 emails from 1 `Inbox`, sending 10 emails
across 100 `Inboxes` actually improves deliverability! Read more about
optimizing for deliverability [here](/best-practices/email-deliverability)

### The AgentMail Hierarchy

As the diagram below illustrates, your `organization` is the top-level container that holds all your resources. You can provision many `Inboxes` within your `organization`, each with its own `Threads`, `Messages`, and `Attachments`, allowing you to manage a large fleet of agents seamlessly.

<img src="https://files.buildwithfern.com/https://agentmail-production.docs.buildwithfern.com/800085ec8545f404e194c8c6e463be1677715204ac5705be777fa95ace0e6d26/assets/hierarchy-diagram.png" alt="AgentMail Organizational Hierarchy" />

Your `organization` is the highest-level entity. It acts as a container for
all your `Inboxes`, `Domains`, and API keys, allowing you to manage
everything in one place.

An `Inbox` is a single, scalable "email account" for your agent. You can
create thousands of `Inboxes` within your organization, each with its own
unique email address.

A `Thread` represents a single conversation. It groups together all replies
and forwards related to an initial email, keeping your interactions
organized.

A `Message` is an individual email. It contains the content, sender,
recipients, and any associated metadata or `Attachments`. You can cc humans
at any point in time to keep a "human-in-the-loop"

An `Attachment` is a file that is sent along with a `Message`. You can
programmatically access and download attachments from incoming `Messages`.

## Core Capabilities

Here at AgentMail we've now made an `Inbox` an API resource, meaning you can perform standard CRUD operations on it. Here are the core capabilities you'll use to manage your `Inboxes`.

```python
from agentmail import AgentMail

# Initialize the client
client = AgentMail(api_key="YOUR_API_KEY")

# --- Create an Inbox ---
# Creates a new inbox with a default agentmail.to domain
new_inbox = client.inboxes.create()
print(f"Created Inbox: {new_inbox.inbox_id}")

# --- Retrieve an Inbox ---
# Gets a specific inbox by its ID
retrieved_inbox = client.inboxes.get(inbox_id = 'my_name@domain.com')
print(f"Retrieved Inbox: {retrieved_inbox.inbox_id}")

# --- List Inboxes ---
# Lists all inboxes in your organization
all_inboxes = client.inboxes.list()

print(f"Total Inboxes: {all_inboxes.count}")

```

```typescript title="TypeScript"
import { AgentMailClient } from "agentmail";

// Initialize the client
const client = new AgentMailClient({ apiKey: "YOUR_API_KEY" });

// --- Create an Inbox ---
// Creates a new inbox with a default agentmail.to domain
const newInbox = await client.inboxes.create({
  username: "docs-testing",
  domain: "domain.com",
  displayName: "Docs Tester",
});
console.log(`Created Inbox: ${newInbox.id}`);

// --- Retrieve an Inbox ---
// Gets a specific inbox by its ID
const inboxId = newInbox.id;
const retrievedInbox = await client.inboxes.get(inboxId);
console.log(`Retrieved Inbox: ${retrievedInbox.inbox_id}`);

// --- List Inboxes ---
// Lists all inboxes in your organization
const allInboxes = await client.inboxes.list();
console.log(`Total Inboxes: ${allInboxes.count}`);



```

```bash title="CLI"
# create an inbox
agentmail inboxes create \
  --username docs-testing \
  --domain domain.com \
  --display-name "Docs Tester"

# get an inbox
agentmail inboxes get --inbox-id my_name@domain.com

# list all inboxes
agentmail inboxes list
```

When creating an `Inbox`, the `username` and `domain` are optional. If you
don't provide them, AgentMail will generate a unique address for you using our
default domain. You can also set `domain` to one of your verified custom
domains, or to any subdomain of a domain with [subdomains
enabled](/custom-domains#setting-up-subdomains). Check out our [guide on managing
domains](/managing-domains).

## Metadata

Attach your own key-value data to any `Inbox` with the `metadata` field. Use it to link an inbox to records in your own system: a user ID, an agent name, or feature flags. Metadata is returned on every inbox response.

Values may be a string, number, or boolean. An `Inbox` can hold up to 256 keys, and each key and string value is limited to 256 characters.

```python title="Python"
# Attach metadata when creating an inbox; values may be a string, int, float, or boolean
inbox = client.inboxes.create(
    username="support-agent",
    metadata={
        "tenant_id": "acme",       # string
        "seat_count": 5,           # int
        "monthly_spend": 19.99,    # float
        "active": True,            # boolean
    },
)

# Read it back from any inbox response
print(inbox.metadata)
```

```typescript title="TypeScript"
// Attach metadata when creating an inbox; values may be a string, int, float, or boolean
const inbox = await client.inboxes.create({
  username: "support-agent",
  metadata: {
    tenant_id: "acme", // string
    seat_count: 5, // int
    monthly_spend: 19.99, // float
    active: true, // boolean
  },
});

// Read it back from any inbox response
console.log(inbox.metadata);
```

### Updating metadata

Updates **merge** into the inbox's existing metadata — keys you include are added or overwritten, and keys you omit are preserved.

To remove a single key, send it with a `null` value. To clear all metadata at
once, send `metadata` as `null`. Every update must include either
`display_name` or `metadata`.

```python title="Python"
# Add or overwrite keys; the keys you omit stay unchanged
client.inboxes.update(
    inbox_id="support-agent@agentmail.to",
    metadata={"tier": "enterprise"},
)

# Remove a single key
client.inboxes.update(
    inbox_id="support-agent@agentmail.to",
    metadata={"tier": None},
)

# Clear all metadata
client.inboxes.update(
    inbox_id="support-agent@agentmail.to",
    metadata=None,
)
```

```typescript title="TypeScript"
// Add or overwrite keys; the keys you omit stay unchanged
await client.inboxes.update("support-agent@agentmail.to", {
  metadata: { tier: "enterprise" },
});

// Remove a single key
await client.inboxes.update("support-agent@agentmail.to", {
  metadata: { tier: null },
});

// Clear all metadata
await client.inboxes.update("support-agent@agentmail.to", {
  metadata: null,
});
```

## Inbox-scoped API keys

You can create API keys that are restricted to a single inbox. An inbox-scoped key can only access that inbox's threads, messages, and drafts. This is useful when you want to give an agent or integration the minimum access it needs.

```python
# Create a key scoped to one inbox
key = client.inboxes.api_keys.create(
    new_inbox.inbox_id,
    name="support-agent-key"
)

# The full key is only returned once
print(key.api_key)
```

```typescript title="TypeScript"
const key = await client.inboxes.apiKeys.create(newInbox.id, {
  name: "support-agent-key",
});

// The full key is only returned once
console.log(key.apiKey);
```

See the [Multi-Tenancy guide](/multi-tenancy#inbox-scoped-keys) for more on scoped keys.

## Copy for Cursor / Claude

Copy one of the blocks below into Cursor or Claude for complete Inboxes API knowledge in one shot.

```python title="Python"
"""
AgentMail Inboxes — copy into Cursor/Claude.

Setup: pip install agentmail python-dotenv. Set AGENTMAIL_API_KEY in .env.

API reference:
- inboxes.create(username?, domain?, display_name?, client_id?, metadata?) — client_id for idempotent retries; metadata is custom key-value data
- inboxes.get(inbox_id)
- inboxes.list(limit?, page_token?)
- inboxes.update(inbox_id, display_name?, metadata?) — at least one field required; metadata is merged, not replaced
- inboxes.delete(inbox_id)
- inboxes.api_keys.create(inbox_id, name) — inbox-scoped key
- inboxes.api_keys.list(inbox_id)
- inboxes.api_keys.delete(inbox_id, api_key_id)

Errors: SDK raises on 4xx/5xx. Rate limit: 429 with Retry-After.
"""
import os
from dotenv import load_dotenv
from agentmail import AgentMail

load_dotenv()
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))

# Create (client_id for idempotent retries)
inbox = client.inboxes.create(client_id="my-inbox-v1")

# Get, list
retrieved = client.inboxes.get(inbox.inbox_id)
all_inboxes = client.inboxes.list(limit=20)
print(f"Total: {all_inboxes.count}")
```

```typescript title="TypeScript"
/**
 * AgentMail Inboxes — copy into Cursor/Claude.
 *
 * Setup: npm install agentmail dotenv. Set AGENTMAIL_API_KEY in .env.
 *
 * API reference:
 * - inboxes.create({ username?, domain?, displayName?, clientId?, metadata? }) — metadata is custom key-value data
 * - inboxes.get(inboxId)
 * - inboxes.list({ limit?, pageToken? })
 * - inboxes.update(inboxId, { displayName?, metadata? }) — at least one field required
 * - inboxes.delete(inboxId)
 * - inboxes.apiKeys.create(inboxId, { name }) — inbox-scoped key
 * - inboxes.apiKeys.list(inboxId)
 * - inboxes.apiKeys.delete(inboxId, apiKeyId)
 *
 * Errors: SDK throws on 4xx/5xx. Rate limit: 429 with Retry-After.
 */
import { AgentMailClient } from "agentmail";
import "dotenv/config";

const client = new AgentMailClient({ apiKey: process.env.AGENTMAIL_API_KEY! });

async function main() {
  const inbox = await client.inboxes.create({ clientId: "my-inbox-v1" });
  const retrieved = await client.inboxes.get(inbox.inboxId);
  const allInboxes = await client.inboxes.list({ limit: 20 });
  console.log("Total:", allInboxes.count);
}
main();
```