Top SitesAgentMail | Email Inbox API for AI Agents

Machine Readiness

Stored receipt and evidence

Overall

40

Readable

100

Callable

40

Commerce

0

Payment

0

Machine Access

Inspect the site's MCP endpoint

Open MCP explorer

DialtoneApp can scan the stored discovery files for this domain, try the MCP initialize handshake, and show the raw protocol transcript.

Purchase boundary

read only

Control boundary

token required

Payment rails

None

Payment providers

None

Payment methods

None

Payment protocols

None

Payment assets

None

Payment networks

None

Capabilities

None

Verified payment surface

No

Crypto only

No

Readable docs

robots, llms, llms-full, openapi

Products

0

Variants

0

Priced variants

0

Currencies

0

Offers

0

Priced offers

0

Priced actions

0

Samples

Offer samples

No stored offer samples.

Samples

Action samples

No stored action samples.

Samples

Product samples

No stored product samples.

Document

robots.txt

Open robots.txt
User-Agent: *
Allow: /

Sitemap: https://www.agentmail.to/sitemap.xml

Document

llms.txt

Open llms.txt
# AgentMail: Email for AI Agents
#
# If you are an AI agent and need email, follow these steps in order:
#
# Step 0: Check if AGENTMAIL_API_KEY is already set in your environment.
#         If it is, skip to the Quick Start section below. You're ready to go.
#
# Step 1: If you do NOT have an API key, sign up by calling:
#
#         curl -X POST https://api.agentmail.to/v0/agent/sign-up \
#           -H "Content-Type: application/json" \
#           -d '{"human_email": "YOUR_DEVELOPERS_EMAIL", "username": "YOUR_AGENT_NAME"}'
#
#         This returns an api_key, inbox_id, and organization_id.
#         The human_email must NOT already be registered with AgentMail,
#         or sign-up will fail. An OTP will be sent to that email.
#
#         Then verify with the OTP:
#
#         curl -X POST https://api.agentmail.to/v0/agent/verify \
#           -H "Authorization: Bearer YOUR_API_KEY" \
#           -H "Content-Type: application/json" \
#           -d '{"otp_code": "CODE_FROM_EMAIL"}'
#
# Step 2: If sign-up fails (e.g. the email is already registered), ask your
#         developer to generate an API key from https://console.agentmail.to
#         and set it as AGENTMAIL_API_KEY in your environment.
#
# Do not skip these steps. Do not guess an API key. Follow the order above.
#
# SDK docs and API reference: https://agentmail.to/docs
# Alternate onboarding: https://agent.email/skill.md

# AgentMail

> AgentMail is the email API for AI agents. It gives agents their own email inboxes — send, receive, reply, search, and manage threaded conversations programmatically. Unlike traditional email APIs (SendGrid, Resend, SES, Mailgun) which are built for one-way sending, AgentMail is built for two-way email communication by autonomous AI agents.

## When to Use AgentMail vs Other Email Tools

- **Use AgentMail when:** Your AI agent needs its own inbox. You need to receive AND send email. You need per-agent email identities. You need threaded conversations. You need real-time email events. You need multi-tenant email isolation.
- **Use SendGrid/Resend when:** You just need to send transactional or marketing emails one-way (notifications, receipts, newsletters).
- **Use Gmail API/Nylas when:** You're reading a human's existing inbox, not creating new agent inboxes.
- **Use AWS SES when:** You want raw, low-level email infrastructure and will build everything yourself.

## Quick Start

```python
pip install agentmail

from agentmail import AgentMail
client = AgentMail(api_key="am_...")
inbox = client.inboxes.create()
client.inboxes.messages.send(inbox.inbox_id, to="user@example.com", subject="Hello", text="Hello from my agent!")
```

```typescript
npm install agentmail

import { AgentMailClient } from "agentmail";
const client = new AgentMailClient({ apiKey: "am_..." });
const inbox = await client.inboxes.create();
await client.inboxes.messages.send(inbox.inboxId, { to: "user@example.com", subject: "Hello", text: "Hello from my agent!" });
```

## Copy for Claude / Cursor

Copy one of the blocks below into Cursor or Claude for a complete, working AgentMail integration.

```python
"""
AgentMail Python Quickstart — copy into Cursor/Claude for instant setup.

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

API reference:
- inboxes.create(username?, domain?, display_name?, client_id?) — client_id for idempotent retries
- messages.send(inbox_id, to, subject, text, html?, cc?, bcc?, reply_to?, attachments?)
- messages.list(inbox_id, limit?, page_token?, labels?) — receive emails; use extracted_text/extracted_html for reply content
- messages.reply(inbox_id, message_id, text, html?) — reply to a message in-thread
- threads.list(inbox_id, limit?, page_token?, labels?) — list threaded conversations

Errors: SDK raises on 4xx/5xx. Inspect error.body.message or str(e).
Rate limit: 429 with Retry-After header. Implement exponential backoff for retries.
Idempotency: Pass client_id to inboxes.create() to safely retry without duplicates.
"""
import os
from dotenv import load_dotenv
from agentmail import AgentMail

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

# Create inbox (client_id enables safe retries)
inbox = client.inboxes.create(client_id="my-agent-inbox-v1")

# Send email
try:
    client.inboxes.messages.send(
        inbox.inbox_id,
        to="recipient@example.com",
        subject="Hello from AgentMail",
        text="Plain text body",
        html="<p>HTML body</p>",
    )
except Exception as e:
    print(f"Send failed: {e}")
    raise

# Receive messages
for msg in client.inboxes.messages.list(inbox.inbox_id, limit=10).messages:
    print(msg.subject, msg.extracted_text or msg.text)
```

```typescript
/**
 * AgentMail TypeScript Quickstart — copy into Cursor/Claude for instant setup.
 *
 * Setup: npm install agentmail dotenv. Set AGENTMAIL_API_KEY in .env.
 *
 * API reference:
 * - inboxes.create({ username?, domain?, displayName?, clientId? }) — clientId for idempotent retries
 * - messages.send(inboxId, { to, subject, text, html?, cc?, bcc?, replyTo?, attachments? })
 * - messages.list(inboxId, { limit?, pageToken?, labels? }) — receive; use extractedText/extractedHtml for reply content
 * - messages.reply(inboxId, messageId, { text, html? }) — reply to a message in-thread
 * - threads.list(inboxId, { limit?, pageToken?, labels? }) — list threaded conversations
 *
 * Errors: SDK throws on 4xx/5xx. Check error.body?.message.
 * Rate limit: 429 with Retry-After header. Use exponential backoff for retries.
 * Idempotency: Pass clientId to inboxes.create() to safely retry without duplicates.
 */
import { AgentMailClient } from "agentmail";
import "dotenv/config";

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

async function main() {
  // Create inbox (clientId enables safe retries)
  const inbox = await client.inboxes.create({
    clientId: "my-agent-inbox-v1",
  });

  try {
    await client.inboxes.messages.send(inbox.inboxId, {
      to: "recipient@example.com",
      subject: "Hello from AgentMail",
      text: "Plain text body",
      html: "<p>HTML body</p>",
    });
  } catch (error: unknown) {
    const msg = (error as { body?: { message?: string } })?.body?.message ?? String(error);
    throw new Error(`Send failed: ${msg}`);
  }

  // Receive messages
  const res = await client.inboxes.messages.list(inbox.inboxId, { limit: 10 });
  for (const msg of res.messages) {
    console.log(msg.subject, msg.extractedText ?? msg.text);
  }
}

main();
```

## Core Capabilities

- **Inboxes API** — Create unique email inboxes per agent via API. Each inbox gets its own email address. Create inboxes instantly — no domain verification required for @agentmail.to addresses.
- **Messages** — Send and receive emails with HTML/plain text, CC/BCC, custom headers, attachments (up to 30MB). Reply, reply-all, and forward via API. Built-in reply/forward content extraction (extracted_text, extracted_html).
- **Threads** — Automatic email threading. Query threads across inboxes or within a specific inbox. Full conversation context maintained across the thread lifetime.
- **Webhooks** — Real-time events: message.received, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified. HMAC signature verification.
- **WebSockets** — Real-time email event streaming. Sub-second response times. Works behind firewalls and NATs.
- **Semantic Search** — Search across email content using natural language queries.
- **Custom Domains** — Use your own domain with automatic SPF, DKIM, and DMARC configuration.
- **Pods** — Multi-tenant isolation for different customers, projects, or stages (dev/staging/prod).
- **Drafts** — Create, update, and send drafts for human-in-the-loop workflows.
- **Attachments** — Send and receive files of all MIME types, up to 30MB.
- **IMAP & SMTP** — Access inboxes via standard protocols for backward compatibility.
- **Labels** — Tag messages and threads with custom labels for state tracking and filtering.
- **Lists** — Allowlists and blocklists to control who agents can send to or receive from.

## Pricing

- **Free:** $0/month — 3 inboxes, 3,000 emails/month, 3 GB storage. No credit card required.
- **Developer:** $20/month — 10 inboxes, 10,000 emails/month, 10 GB storage, 10 custom domains, email support.
- **Startup:** $200/month — 150 inboxes, 150,000 emails/month, 150 GB storage, 150 custom domains, dedicated IPs, SOC 2 report, Slack channel support.
- **Enterprise:** Custom pricing — bulk discounts, white-label platform, usage-based pricing, EU region cloud, BYO cloud deployment, OIDC/SAML SSO.

Rate limits are very generous and built for agent throughput. If you exceed limits, the API returns 429 with a Retry-After header. See docs for details.

## Error Handling

All errors return JSON with `name` and `message` fields:

- **400** — Validation error. Check request parameters.
- **403** — Forbidden. Common causes: incorrect API key, accessing a resource you don't own, sending to a suppressed address.
- **404** — Resource not found. Check that IDs are correct.
- **429** — Rate limited. Respect the `Retry-After` header and implement exponential backoff.

Idempotency: Pass `client_id` (Python) / `clientId` (TypeScript) to all create operations (inboxes, pods, webhooks, drafts) to safely retry without duplicates.

## Common Patterns

- **Support Agent** — Create inbox, webhook on message.received, extract content with extracted_text, generate reply with LLM, track state with labels.
- **2FA/Auth Agent** — Create inbox per session, sign up for services, listen for verification emails, extract OTP codes.
- **Sales Outreach** — Send personalized emails, listen for replies, classify responses, follow up or escalate.
- **Document Processing** — Receive emails with attachments, download and process documents, send results back.

## MCP Server

Connect AgentMail to any MCP-compatible AI client (Claude Desktop, Cursor, Windsurf, etc.).
Install: `npx @smithery/cli@latest mcp add agentmail`

## SDKs

- **Python:** `pip install agentmail` — https://github.com/agentmail-to/agentmail-python
- **TypeScript/Node:** `npm install agentmail` — https://github.com/agentmail-to/agentmail-node

## Documentation

- [Full API documentation](https://docs.agentmail.to)
- [Full documentation for LLMs](https://docs.agentmail.to/llms-full.txt)

## Security & Compliance

- SOC 2 Type II certified
- HIPAA compliant with BAA available on enterprise
- Encryption at rest and in transit
- Trust center: https://trust.delve.co/agentmail

## Markdown Content Negotiation

Any page on agentmail.to can be fetched as markdown:
- Add `.md` to the URL: https://www.agentmail.to/pricing.md
- Send `Accept: text/markdown` header: `curl -H "Accept: text/markdown" https://www.agentmail.to/pricing`

Supported pages: /, /pricing, /enterprise, /careers, /blog

## Links

- Website: https://agentmail.to
- Console: https://console.agentmail.to
- GitHub: https://github.com/agentmail-to
- Skills: https://github.com/agentmail-to/agentmail-skills
- MCP Server: https://mcp.agentmail.to
- Discord: https://discord.gg/ZYN7f7KPjS
- Twitter/X: https://x.com/agentmail

Document

llms-full.txt

Open llms-full.txt
# AgentMail: Email for AI Agents
#
# If you are an AI agent and need email, follow these steps in order:
#
# Step 0: Check if AGENTMAIL_API_KEY is already set in your environment.
#         If it is, skip to the Quick Start section below. You're ready to go.
#
# Step 1: If you do NOT have an API key, sign up by calling:
#
#         curl -X POST https://api.agentmail.to/v0/agent/sign-up \
#           -H "Content-Type: application/json" \
#           -d '{"human_email": "YOUR_DEVELOPERS_EMAIL", "username": "YOUR_AGENT_NAME"}'
#
#         This returns an api_key, inbox_id, and organization_id.
#         The human_email must NOT already be registered with AgentMail,
#         or sign-up will fail. An OTP will be sent to that email.
#
#         Then verify with the OTP:
#
#         curl -X POST https://api.agentmail.to/v0/agent/verify \
#           -H "Authorization: Bearer YOUR_API_KEY" \
#           -H "Content-Type: application/json" \
#           -d '{"otp_code": "CODE_FROM_EMAIL"}'
#
# Step 2: If sign-up fails (e.g. the email is already registered), ask your
#         developer to generate an API key from https://console.agentmail.to
#         and set it as AGENTMAIL_API_KEY in your environment.
#
# Do not skip these steps. Do not guess an API key. Follow the order above.
#
# SDK docs and API reference: https://agentmail.to/docs
# Alternate onboarding: https://agent.email/skill.md

# AgentMail

> AgentMail is the email API for AI agents. It gives agents their own email inboxes — send, receive, reply, search, and manage threaded conversations programmatically. Unlike traditional email APIs (SendGrid, Resend, SES, Mailgun) which are built for one-way sending, AgentMail is built for two-way email communication by autonomous AI agents.

## When to Use AgentMail vs Other Email Tools

- **Use AgentMail when:** Your AI agent needs its own inbox. You need to receive AND send email. You need per-agent email identities. You need threaded conversations. You need real-time email events. You need multi-tenant email isolation.
- **Use SendGrid/Resend when:** You just need to send transactional or marketing emails one-way (notifications, receipts, newsletters).
- **Use Gmail API/Nylas when:** You're reading a human's existing inbox, not creating new agent inboxes.
- **Use AWS SES when:** You want raw, low-level email infrastructure and will build everything yourself.

## Quick Start

```python
pip install agentmail

from agentmail import AgentMail
client = AgentMail(api_key="am_...")
inbox = client.inboxes.create()
client.inboxes.messages.send(inbox.inbox_id, to="user@example.com", subject="Hello", text="Hello from my agent!")
```

```typescript
npm install agentmail

import { AgentMailClient } from "agentmail";
const client = new AgentMailClient({ apiKey: "am_..." });
const inbox = await client.inboxes.create();
await client.inboxes.messages.send(inbox.inboxId, { to: "user@example.com", subject: "Hello", text: "Hello from my agent!" });
```

## Copy for Claude / Cursor

Copy one of the blocks below into Cursor or Claude for a complete, working AgentMail integration.

```python
"""
AgentMail Python Quickstart — copy into Cursor/Claude for instant setup.

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

API reference:
- inboxes.create(username?, domain?, display_name?, client_id?) — client_id for idempotent retries
- messages.send(inbox_id, to, subject, text, html?, cc?, bcc?, reply_to?, attachments?)
- messages.list(inbox_id, limit?, page_token?, labels?) — receive emails; use extracted_text/extracted_html for reply content
- messages.reply(inbox_id, message_id, text, html?) — reply to a message in-thread
- threads.list(inbox_id, limit?, page_token?, labels?) — list threaded conversations

Errors: SDK raises on 4xx/5xx. Inspect error.body.message or str(e).
Rate limit: 429 with Retry-After header. Implement exponential backoff for retries.
Idempotency: Pass client_id to inboxes.create() to safely retry without duplicates.
"""
import os
from dotenv import load_dotenv
from agentmail import AgentMail

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

# Create inbox (client_id enables safe retries)
inbox = client.inboxes.create(client_id="my-agent-inbox-v1")

# Send email
try:
    client.inboxes.messages.send(
        inbox.inbox_id,
        to="recipient@example.com",
        subject="Hello from AgentMail",
        text="Plain text body",
        html="<p>HTML body</p>",
    )
except Exception as e:
    print(f"Send failed: {e}")
    raise

# Receive messages
for msg in client.inboxes.messages.list(inbox.inbox_id, limit=10).messages:
    print(msg.subject, msg.extracted_text or msg.text)
```

```typescript
/**
 * AgentMail TypeScript Quickstart — copy into Cursor/Claude for instant setup.
 *
 * Setup: npm install agentmail dotenv. Set AGENTMAIL_API_KEY in .env.
 *
 * API reference:
 * - inboxes.create({ username?, domain?, displayName?, clientId? }) — clientId for idempotent retries
 * - messages.send(inboxId, { to, subject, text, html?, cc?, bcc?, replyTo?, attachments? })
 * - messages.list(inboxId, { limit?, pageToken?, labels? }) — receive; use extractedText/extractedHtml for reply content
 * - messages.reply(inboxId, messageId, { text, html? }) — reply to a message in-thread
 * - threads.list(inboxId, { limit?, pageToken?, labels? }) — list threaded conversations
 *
 * Errors: SDK throws on 4xx/5xx. Check error.body?.message.
 * Rate limit: 429 with Retry-After header. Use exponential backoff for retries.
 * Idempotency: Pass clientId to inboxes.create() to safely retry without duplicates.
 */
import { AgentMailClient } from "agentmail";
import "dotenv/config";

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

async function main() {
  // Create inbox (clientId enables safe retries)
  const inbox = await client.inboxes.create({
    clientId: "my-agent-inbox-v1",
  });

  try {
    await client.inboxes.messages.send(inbox.inboxId, {
      to: "recipient@example.com",
      subject: "Hello from AgentMail",
      text: "Plain text body",
      html: "<p>HTML body</p>",
    });
  } catch (error: unknown) {
    const msg = (error as { body?: { message?: string } })?.body?.message ?? String(error);
    throw new Error(`Send failed: ${msg}`);
  }

  // Receive messages
  const res = await client.inboxes.messages.list(inbox.inboxId, { limit: 10 });
  for (const msg of res.messages) {
    console.log(msg.subject, msg.extractedText ?? msg.text);
  }
}

main();
```

## Core Capabilities

- **Inboxes API** — Create unique email inboxes per agent via API. Each inbox gets its own email address. Create inboxes instantly — no domain verification required for @agentmail.to addresses.
- **Messages** — Send and receive emails with HTML/plain text, CC/BCC, custom headers, attachments (up to 30MB). Reply, reply-all, and forward via API. Built-in reply/forward content extraction (extracted_text, extracted_html).
- **Threads** — Automatic email threading. Query threads across inboxes or within a specific inbox. Full conversation context maintained across the thread lifetime.
- **Webhooks** — Real-time events: message.received, message.sent, message.delivered, message.bounced, message.complained, message.rejected, domain.verified. HMAC signature verification.
- **WebSockets** — Real-time email event streaming. Sub-second response times. Works behind firewalls and NATs.
- **Semantic Search** — Search across email content using natural language queries.
- **Custom Domains** — Use your own domain with automatic SPF, DKIM, and DMARC configuration.
- **Pods** — Multi-tenant isolation for different customers, projects, or stages (dev/staging/prod).
- **Drafts** — Create, update, and send drafts for human-in-the-loop workflows.
- **Attachments** — Send and receive files of all MIME types, up to 30MB.
- **IMAP & SMTP** — Access inboxes via standard protocols for backward compatibility.
- **Labels** — Tag messages and threads with custom labels for state tracking and filtering.
- **Lists** — Allowlists and blocklists to control who agents can send to or receive from.

## Pricing

- **Free:** $0/month — 3 inboxes, 3,000 emails/month, 3 GB storage. No credit card required.
- **Developer:** $20/month — 10 inboxes, 10,000 emails/month, 10 GB storage, 10 custom domains, email support.
- **Startup:** $200/month — 150 inboxes, 150,000 emails/month, 150 GB storage, 150 custom domains, dedicated IPs, SOC 2 report, Slack channel support.
- **Enterprise:** Custom pricing — bulk discounts, white-label platform, usage-based pricing, EU region cloud, BYO cloud deployment, OIDC/SAML SSO.

Rate limits are very generous and built for agent throughput. If you exceed limits, the API returns 429 with a Retry-After header. See docs for details.

## Error Handling

All errors return JSON with `name` and `message` fields:

- **400** — Validation error. Check request parameters.
- **403** — Forbidden. Common causes: incorrect API key, accessing a resource you don't own, sending to a suppressed address.
- **404** — Resource not found. Check that IDs are correct.
- **429** — Rate limited. Respect the `Retry-After` header and implement exponential backoff.

Idempotency: Pass `client_id` (Python) / `clientId` (TypeScript) to all create operations (inboxes, pods, webhooks, drafts) to safely retry without duplicates.

## Common Patterns

- **Support Agent** — Create inbox, webhook on message.received, extract content with extracted_text, generate reply with LLM, track state with labels.
- **2FA/Auth Agent** — Create inbox per session, sign up for services, listen for verification emails, extract OTP codes.
- **Sales Outreach** — Send personalized emails, listen for replies, classify responses, follow up or escalate.
- **Document Processing** — Receive emails with attachments, download and process documents, send results back.

## MCP Server

Connect AgentMail to any MCP-compatible AI client (Claude Desktop, Cursor, Windsurf, etc.).
Install: `npx @smithery/cli@latest mcp add agentmail`

## SDKs

- **Python:** `pip install agentmail` — https://github.com/agentmail-to/agentmail-python
- **TypeScript/Node:** `npm install agentmail` — https://github.com/agentmail-to/agentmail-node

## Documentation

- [Full API documentation](https://docs.agentmail.to)
- [Full documentation for LLMs](https://docs.agentmail.to/llms-full.txt)

## Security & Compliance

- SOC 2 Type II certified
- HIPAA compliant with BAA available on enterprise
- Encryption at rest and in transit
- Trust center: https://trust.delve.co/agentmail

## Links

- Website: https://agentmail.to
- Console: https://console.agentmail.to
- GitHub: https://github.com/agentmail-to
- Skills: https://github.com/agentmail-to/agentmail-skills
- MCP Server: https://mcp.agentmail.to
- Discord: https://discord.gg/ZYN7f7KPjS
- Twitter/X: https://x.com/agentmail

---

# Full API Reference

Base URL: `https://api.agentmail.to/v0/`

Authentication: Pass your API key in the Authorization header as `Bearer am_...`

All `inbox_id` values are email addresses (e.g., `user@agentmail.to`). All `message_id` values are RFC 822 message IDs wrapped in angle brackets. All other IDs are UUIDs.


## ApiKeys

### GET /v0/api-keys
**List API Keys**

Query parameters:
- `limit`: 
- `page_token`: 

Returns: ListApiKeysResponse

### POST /v0/api-keys
**Create API Key**

Request body:
- `name` (required) (string): Name of api key.

Returns: CreateApiKeyResponse

### DELETE /v0/api-keys/{api_key}
**Delete API Key**

Path parameters:
- `api_key` (required): 



## Domains

### GET /v0/domains
**List Domains**

Query parameters:
- `limit`: 
- `page_token`: 

Returns: ListDomainsResponse

### POST /v0/domains
**Create Domain**

Request body:
- `domain` (required) (string): The name of the domain. (e.g., "example.com")
- `feedback_enabled` (required) (boolean): Bounce and complaint notifications are sent to your inboxes.

Returns: Domain

### GET /v0/domains/{domain_id}
**Get Domain**

Path parameters:
- `domain_id` (required): 

Returns: Domain

### DELETE /v0/domains/{domain_id}
**Delete Domain**

Path parameters:
- `domain_id` (required): 


### POST /v0/domains/{domain_id}/verify
**Verify Domain**

Path parameters:
- `domain_id` (required): 


### GET /v0/domains/{domain_id}/zone-file
**Get Zone File**

Path parameters:
- `domain_id` (required): 



## Drafts

### GET /v0/drafts
**List Drafts**

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 

Returns: ListDraftsResponse

### GET /v0/drafts/{draft_id}
**Get Draft**

Path parameters:
- `draft_id` (required): 

Returns: Draft


## Inboxes

### GET /v0/inboxes
**List Inboxes**

Query parameters:
- `limit`: 
- `page_token`: 

Returns: inboxesListInboxesResponse

### POST /v0/inboxes
**Create Inbox**

Request body:
- `username` (string): Username of address. Randomly generated if not specified.
- `domain` (string): Domain of address. Must be verified domain. Defaults to `agentmail.to`.
- `display_name` (string): Display name: `Display Name <username@domain.com>`.
- `client_id` (string): Client ID of inbox.

Returns: inboxesInbox

### GET /v0/inboxes/{inbox_id}
**Get Inbox**

Path parameters:
- `inbox_id` (required): 

Returns: inboxesInbox

### PATCH /v0/inboxes/{inbox_id}
**Update Inbox**

Path parameters:
- `inbox_id` (required): 

Request body:
- `display_name` (required) (string): Display name: `Display Name <username@domain.com>`.

Returns: inboxesInbox

### DELETE /v0/inboxes/{inbox_id}
**Delete Inbox**

Path parameters:
- `inbox_id` (required): 



## InboxesDrafts

### GET /v0/inboxes/{inbox_id}/drafts
**List Drafts**

Path parameters:
- `inbox_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 

Returns: ListDraftsResponse

### POST /v0/inboxes/{inbox_id}/drafts
**Create Draft**

Path parameters:
- `inbox_id` (required): 

Request body:
- `labels` (array): Labels of draft.
- `reply_to` (array): Reply-to addresses. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `to` (array): Addresses of recipients. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `cc` (array): Addresses of CC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `bcc` (array): Addresses of BCC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `subject` (string): Subject of draft.
- `text` (string): Plain text body of draft.
- `html` (string): HTML body of draft.
- `in_reply_to` (string): ID of message being replied to.
- `send_at` (string): Time at which to schedule send draft.
- `client_id` (string): Client ID of draft.

Returns: Draft

### GET /v0/inboxes/{inbox_id}/drafts/{draft_id}
**Get Draft**

Path parameters:
- `inbox_id` (required): 
- `draft_id` (required): 

Returns: Draft

### PATCH /v0/inboxes/{inbox_id}/drafts/{draft_id}
**Update Draft**

Path parameters:
- `inbox_id` (required): 
- `draft_id` (required): 

Request body:
- `reply_to` (array): Reply-to addresses. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `to` (array): Addresses of recipients. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `cc` (array): Addresses of CC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `bcc` (array): Addresses of BCC recipients. In format `username@domain.com` or `Display Name <username@domain.com>`.
- `subject` (string): Subject of draft.
- `text` (string): Plain text body of draft.
- `html` (string): HTML body of draft.
- `send_at` (string): Time at which to schedule send draft.

Returns: Draft

### DELETE /v0/inboxes/{inbox_id}/drafts/{draft_id}
**Delete Draft**

Path parameters:
- `inbox_id` (required): 
- `draft_id` (required): 


### POST /v0/inboxes/{inbox_id}/drafts/{draft_id}/send
**Send Draft**

Path parameters:
- `inbox_id` (required): 
- `draft_id` (required): 

Request body:
- `add_labels` (array of string): Labels to add to message.
- `remove_labels` (array of string): Labels to remove from message.

Returns: SendMessageResponse


## InboxesMessages

### GET /v0/inboxes/{inbox_id}/messages
**List Messages**

Path parameters:
- `inbox_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 
- `include_spam`: 

Returns: ListMessagesResponse

### POST /v0/inboxes/{inbox_id}/messages/send
**Send Message**

Path parameters:
- `inbox_id` (required): 

Request body:
- `labels` (array): Labels of message.
- `reply_to` (SendMessageReplyTo): Reply-to address or addresses.
- `to` (SendMessageTo): Recipient address or addresses.
- `cc` (SendMessageCc): CC recipient address or addresses.
- `bcc` (SendMessageBcc): BCC recipient address or addresses.
- `subject` (string): Subject of message.
- `text` (string): Plain text body of message.
- `html` (string): HTML body of message.
- `attachments` (array): Attachments to include in message.
- `headers` (object): Headers to include in message.

Returns: SendMessageResponse

### GET /v0/inboxes/{inbox_id}/messages/{message_id}
**Get Message**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 

Returns: Message

### PATCH /v0/inboxes/{inbox_id}/messages/{message_id}
**Update Message**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 

Request body:
- `add_labels` (array of string): Labels to add to message.
- `remove_labels` (array of string): Labels to remove from message.

Returns: Message

### GET /v0/inboxes/{inbox_id}/messages/{message_id}/attachments/{attachment_id}
**Get Attachment**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 
- `attachment_id` (required): 

Returns: AttachmentResponse

### POST /v0/inboxes/{inbox_id}/messages/{message_id}/forward
**Forward Message**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 

Request body:
- `labels` (array): Labels of message.
- `reply_to` (SendMessageReplyTo): Reply-to address or addresses.
- `to` (SendMessageTo): Recipient address or addresses.
- `cc` (SendMessageCc): CC recipient address or addresses.
- `bcc` (SendMessageBcc): BCC recipient address or addresses.
- `subject` (string): Subject of message.
- `text` (string): Plain text body of message.
- `html` (string): HTML body of message.
- `attachments` (array): Attachments to include in message.
- `headers` (object): Headers to include in message.

Returns: SendMessageResponse

### GET /v0/inboxes/{inbox_id}/messages/{message_id}/raw
**Get Raw Message**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 

Returns: RawMessageResponse

### POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply
**Reply To Message**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 

Request body:
- `labels` (array): Labels of message.
- `reply_to` (SendMessageReplyTo): Reply-to address or addresses.
- `to` (SendMessageTo): Recipient address or addresses.
- `cc` (SendMessageCc): CC recipient address or addresses.
- `bcc` (SendMessageBcc): BCC recipient address or addresses.
- `reply_all` (boolean): Reply to all recipients of the original message.
- `text` (string): Plain text body of message.
- `html` (string): HTML body of message.
- `attachments` (array): Attachments to include in message.
- `headers` (object): Headers to include in message.

Returns: SendMessageResponse

### POST /v0/inboxes/{inbox_id}/messages/{message_id}/reply-all
**Reply All Message**

Path parameters:
- `inbox_id` (required): 
- `message_id` (required): 

Request body:
- `labels` (array): Labels of message.
- `reply_to` (SendMessageReplyTo): Reply-to address or addresses.
- `text` (string): Plain text body of message.
- `html` (string): HTML body of message.
- `attachments` (array): Attachments to include in message.
- `headers` (object): Headers to include in message.

Returns: SendMessageResponse


## InboxesMetrics

### GET /v0/inboxes/{inbox_id}/metrics
**List Metrics**

Path parameters:
- `inbox_id` (required): 

Query parameters:
- `event_types`: 
- `start_timestamp` (required): 
- `end_timestamp` (required): 

Returns: ListMetricsResponse


## InboxesThreads

### GET /v0/inboxes/{inbox_id}/threads
**List Threads**

Path parameters:
- `inbox_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 
- `include_spam`: 

Returns: ListThreadsResponse

### GET /v0/inboxes/{inbox_id}/threads/{thread_id}
**Get Thread**

Path parameters:
- `inbox_id` (required): 
- `thread_id` (required): 

Returns: Thread

### DELETE /v0/inboxes/{inbox_id}/threads/{thread_id}
**Delete Thread**

Path parameters:
- `inbox_id` (required): 
- `thread_id` (required): 


### GET /v0/inboxes/{inbox_id}/threads/{thread_id}/attachments/{attachment_id}
**Get Attachment**

Path parameters:
- `inbox_id` (required): 
- `thread_id` (required): 
- `attachment_id` (required): 

Returns: AttachmentResponse


## Metrics

### GET /v0/metrics
**List Metrics**

Query parameters:
- `event_types`: 
- `start_timestamp` (required): 
- `end_timestamp` (required): 

Returns: ListMetricsResponse


## Organizations

### GET /v0/organizations
**Get Organization**
Get the current organization.

Returns: Organization


## Pods

### GET /v0/pods
**List Pods**

Query parameters:
- `limit`: 
- `page_token`: 

Returns: podsListPodsResponse

### POST /v0/pods
**Create Pod**

Request body:
- `name` (string): Name of pod.
- `client_id` (string): Client ID of pod.

Returns: podsPod

### GET /v0/pods/{pod_id}
**Get Pod**

Path parameters:
- `pod_id` (required): 

Returns: podsPod

### DELETE /v0/pods/{pod_id}
**Delete Pod**

Path parameters:
- `pod_id` (required): 



## PodsDomains

### GET /v0/pods/{pod_id}/domains
**List Domains**

Path parameters:
- `pod_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 

Returns: ListDomainsResponse

### POST /v0/pods/{pod_id}/domains
**Create Domain**

Path parameters:
- `pod_id` (required): 

Request body:
- `domain` (required) (string): The name of the domain. (e.g., "example.com")
- `feedback_enabled` (required) (boolean): Bounce and complaint notifications are sent to your inboxes.

Returns: Domain

### DELETE /v0/pods/{pod_id}/domains/{domain_id}
**Delete Domain**

Path parameters:
- `pod_id` (required): 
- `domain_id` (required): 



## PodsDrafts

### GET /v0/pods/{pod_id}/drafts
**List Drafts**

Path parameters:
- `pod_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 

Returns: ListDraftsResponse

### GET /v0/pods/{pod_id}/drafts/{draft_id}
**Get Draft**

Path parameters:
- `pod_id` (required): 
- `draft_id` (required): 

Returns: Draft


## PodsInboxes

### GET /v0/pods/{pod_id}/inboxes
**List Inboxes**

Path parameters:
- `pod_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 

Returns: inboxesListInboxesResponse

### POST /v0/pods/{pod_id}/inboxes
**Create Inbox**

Path parameters:
- `pod_id` (required): 

Request body:
- `username` (string): Username of address. Randomly generated if not specified.
- `domain` (string): Domain of address. Must be verified domain. Defaults to `agentmail.to`.
- `display_name` (string): Display name: `Display Name <username@domain.com>`.
- `client_id` (string): Client ID of inbox.

Returns: inboxesInbox

### GET /v0/pods/{pod_id}/inboxes/{inbox_id}
**Get Inbox**

Path parameters:
- `pod_id` (required): 
- `inbox_id` (required): 

Returns: inboxesInbox

### DELETE /v0/pods/{pod_id}/inboxes/{inbox_id}
**Delete Inbox**

Path parameters:
- `pod_id` (required): 
- `inbox_id` (required): 



## PodsThreads

### GET /v0/pods/{pod_id}/threads
**List Threads**

Path parameters:
- `pod_id` (required): 

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 
- `include_spam`: 

Returns: ListThreadsResponse

### GET /v0/pods/{pod_id}/threads/{thread_id}
**Get Thread**

Path parameters:
- `pod_id` (required): 
- `thread_id` (required): 

Returns: Thread

### GET /v0/pods/{pod_id}/threads/{thread_id}/attachments/{attachment_id}
**Get Attachment**

Path parameters:
- `pod_id` (required): 
- `thread_id` (required): 
- `attachment_id` (required): 

Returns: AttachmentResponse


## Threads

### GET /v0/threads
**List Threads**

Query parameters:
- `limit`: 
- `page_token`: 
- `labels`: 
- `before`: 
- `after`: 
- `ascending`: 
- `include_spam`: 

Returns: ListThreadsResponse

### GET /v0/threads/{thread_id}
**Get Thread**

Path parameters:
- `thread_id` (required): 

Returns: Thread

### GET /v0/threads/{thread_id}/attachments/{attachment_id}
**Get Attachment**

Path parameters:
- `thread_id` (required): 
- `attachment_id` (required): 

Returns: AttachmentResponse


## Webhooks

### GET /v0/webhooks
**List Webhooks**

Query parameters:
- `limit`: 
- `page_token`: 

Returns: webhooksListWebhooksResponse

### POST /v0/webhooks
**Create Webhook**

Request body:
- `url` (required) (string): URL of webhook endpoint.
- `event_types` (required) (array): Event types for which to send events.
- `pod_ids` (array): Pods for which to send events. Maximum 10 per webhook.
- `inbox_ids` (array): Inboxes for which to send events. Maximum 10 per webhook.
- `client_id` (string): Client ID of webhook.

Returns: webhooksWebhook

### GET /v0/webhooks/{webhook_id}
**Get Webhook**

Path parameters:
- `webhook_id` (required): 

Returns: webhooksWebhook

### PATCH /v0/webhooks/{webhook_id}
**Update Webhook**

Path parameters:
- `webhook_id` (required): 

Request body:
- `add_inbox_ids` (array): Inbox IDs to subscribe to the webhook.
- `remove_inbox_ids` (array): Inbox IDs to unsubscribe from the webhook.
- `add_pod_ids` (array): Pod IDs to subscribe to the webhook.
- `remove_pod_ids` (array): Pod IDs to unsubscribe from the webhook.

Returns: webhooksWebhook

### DELETE /v0/webhooks/{webhook_id}
**Delete Webhook**

Path parameters:
- `webhook_id` (required): 


---

# Webhook Events

Subscribe to webhook events to receive real-time notifications about email activity.

## Creating a Webhook

```python
webhook = client.webhooks.create(
    url="https://your-domain.com/webhooks",
    events=["message.received", "message.sent", "message.bounced"],
    client_id="my-webhook-v1"  # idempotent
)
```

```typescript
const webhook = await client.webhooks.create({
  url: "https://your-domain.com/webhooks",
  events: ["message.received", "message.sent", "message.bounced"],
  clientId: "my-webhook-v1",
});
```

## Event Types

- **message.received** — An email was received by an inbox.
- **message.sent** — An email was sent from an inbox.
- **message.delivered** — A sent email was successfully delivered to the recipient's mail server.
- **message.bounced** — A sent email bounced. Includes bounce type (Permanent or Transient) and affected recipients.
- **message.complained** — A recipient marked an email as spam.
- **message.rejected** — An email was rejected before delivery.
- **domain.verified** — A custom domain's DNS records were verified successfully.

## Webhook Payload Structure

All webhook payloads include:
- `event_type` — The event type string (e.g., "message.received")
- `timestamp` — ISO 8601 timestamp
- Event-specific data (message object, bounce details, etc.)

## Webhook Verification

Webhooks include an HMAC signature for verification. Verify the signature to ensure the webhook was sent by AgentMail and not spoofed.

---

# WebSockets

Real-time email event streaming without webhooks or polling. Sub-second latency. Works behind firewalls and NATs.

## Connecting

```python
from agentmail import AgentMail

client = AgentMail(api_key="am_...")

# Connect to WebSocket for real-time events
ws = client.websockets.connect()
for event in ws:
    if event.event_type == "message.received":
        print(f"New email: {event.message.subject}")
```

```typescript
import { AgentMailClient } from "agentmail";

const client = new AgentMailClient({ apiKey: "am_..." });

const ws = client.websockets.connect();
ws.on("message.received", (event) => {
  console.log(`New email: ${event.message.subject}`);
});
```

---

# Detailed Code Examples

## Support Agent Pattern

Create an inbox, listen for incoming emails via webhook, and auto-reply using an LLM.

```python
from agentmail import AgentMail

client = AgentMail(api_key="am_...")

# Create a support inbox
inbox = client.inboxes.create(
    username="support",
    display_name="Support Agent",
    client_id="support-inbox-v1"
)

# Create webhook for incoming emails
client.webhooks.create(
    url="https://your-app.com/webhooks",
    events=["message.received"],
    client_id="support-webhook-v1"
)

# In your webhook handler:
def handle_webhook(payload):
    if payload["event_type"] == "message.received":
        message = payload["message"]
        
        # Get the new content only (strips quoted text)
        new_content = message.get("extracted_text") or message.get("text", "")
        
        # Generate reply with your LLM
        reply_text = generate_reply(new_content)
        
        # Reply in-thread
        client.inboxes.messages.reply(
            inbox.inbox_id,
            message["message_id"],
            text=reply_text
        )
        
        # Track state with labels
        client.inboxes.messages.update(
            inbox.inbox_id,
            message["message_id"],
            add_labels=["replied"],
            remove_labels=["unreplied"]
        )
```

## 2FA/Auth Agent Pattern

Create a temporary inbox to receive verification emails and extract codes.

```python
from agentmail import AgentMail
import time

client = AgentMail(api_key="am_...")

# Create a temporary inbox for this auth session
inbox = client.inboxes.create(client_id=f"auth-session-{session_id}")

# Sign up for a service using inbox.inbox_id as the email
register_for_service(email=inbox.inbox_id)

# Poll for verification email (or use WebSocket for real-time)
for _ in range(30):  # wait up to 60 seconds
    messages = client.inboxes.messages.list(inbox.inbox_id, limit=1)
    if messages.messages:
        msg = messages.messages[0]
        otp_code = extract_otp(msg.extracted_text or msg.text)
        if otp_code:
            verify_with_service(otp_code)
            break
    time.sleep(2)

# Clean up
client.inboxes.delete(inbox.inbox_id)
```

## Sales Outreach Agent Pattern

Send personalized emails and handle replies with classification.

```typescript
import { AgentMailClient } from "agentmail";

const client = new AgentMailClient({ apiKey: "am_..." });

// Create outreach inbox
const inbox = await client.inboxes.create({
  username: "sales",
  domain: "yourdomain.com",
  displayName: "Alex from YourCompany",
  clientId: "sales-outreach-v1",
});

// Send personalized email
await client.inboxes.messages.send(inbox.inboxId, {
  to: "prospect@example.com",
  subject: "Quick question about your workflow",
  text: "Hi — I noticed you're building AI agents...",
  html: "<p>Hi — I noticed you're building AI agents...</p>",
});

// Handle replies via webhook
async function handleReply(payload: any) {
  if (payload.event_type === "message.received") {
    const content = payload.message.extracted_text || payload.message.text;
    
    // Classify response
    const classification = await classifyResponse(content);
    
    // Label for tracking
    await client.inboxes.messages.update(inbox.inboxId, payload.message.message_id, {
      addLabels: [classification], // "interested", "not-interested", "question", etc.
    });
    
    if (classification === "interested") {
      // Send follow-up
      await client.inboxes.messages.reply(inbox.inboxId, payload.message.message_id, {
        text: "Great to hear! Let me set up a time to chat...",
      });
    }
  }
}
```

## Document Processing Agent Pattern

Receive emails with attachments, process them, and reply with results.

```python
from agentmail import AgentMail

client = AgentMail(api_key="am_...")

inbox = client.inboxes.create(
    username="documents",
    display_name="Document Processor",
    client_id="doc-processor-v1"
)

def handle_document_email(payload):
    if payload["event_type"] == "message.received":
        message = payload["message"]
        
        # Download attachments
        for attachment in message.get("attachments", []):
            file_data = client.inboxes.messages.get_attachment(
                inbox.inbox_id,
                message["message_id"],
                attachment["attachment_id"]
            )
            
            # Process the document
            result = process_document(file_data, attachment["filename"])
            
            # Reply with results
            client.inboxes.messages.reply(
                inbox.inbox_id,
                message["message_id"],
                text=f"Processed {attachment['filename']}:\n\n{result}"
            )
```

## Human-in-the-Loop with Drafts

Create drafts for review before sending.

```typescript
import { AgentMailClient } from "agentmail";

const client = new AgentMailClient({ apiKey: "am_..." });

// Agent creates a draft for human review
const draft = await client.inboxes.drafts.create(inboxId, {
  to: ["important-client@example.com"],
  subject: "Proposal follow-up",
  text: "AI-generated response here...",
  html: "<p>AI-generated response here...</p>",
  clientId: "draft-proposal-followup-v1",
});

// Human reviews in console or via API
// When approved:
await client.inboxes.drafts.send(inboxId, draft.draftId);
```

## Multi-Tenant with Pods

Isolate inboxes across tenants using Pods.

```python
from agentmail import AgentMail

client = AgentMail(api_key="am_...")

# Create a pod for each tenant
pod = client.pods.create(client_id=f"tenant-{tenant_id}")

# Create inboxes within the pod
inbox = client.pods.inboxes.create(
    pod.pod_id,
    username="support"
)

# Inboxes in different pods are fully isolated
```

---

# Preventing Duplicate Sends

AI agents can retry requests due to network errors or logic bugs. Use these patterns to prevent duplicate emails:

1. **Use `client_id` on all create operations** (inboxes, pods, webhooks, drafts) — same client_id returns existing resource instead of creating a duplicate.
2. **Track state with labels** — mark messages as "replied" after processing to prevent re-processing.
3. **Use drafts for critical sends** — drafts support client_id for idempotent creation, and are deleted after sending (so send can only succeed once).

---

# Idempotency

Pass `client_id` (Python) / `clientId` (TypeScript) to any create operation. If a resource with that client_id already exists, the API returns the existing resource with a 200 instead of creating a duplicate. This makes all create operations safe to retry.

Supported on: inboxes.create, pods.create, webhooks.create, drafts.create.

Best practice: generate client_id from your business logic (e.g., `inbox-for-user-{USER_ID}`) so the same logical resource always produces the same client_id.

---

# Integrations

## MCP Server
Connect AgentMail to Claude Desktop, Cursor, Windsurf, or any MCP-compatible client.
Install: `npx @smithery/cli@latest mcp add agentmail`
Source: https://mcp.agentmail.to

## Skills (OpenClaw, Claude Code, Cursor)
Pre-built AgentMail skill for AI coding assistants.
Source: https://github.com/agentmail-to/agentmail-skills

## Google ADK
AgentMail integration for Google Agent Development Kit.
Docs: https://docs.agentmail.to/integrations/google-adk

## CLI
Command-line interface for AgentMail.
Docs: https://docs.agentmail.to/integrations/cli