agentmail

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AgentMail — Email for AI Agents

AgentMail — 专为AI Agent打造的电子邮件服务

AgentMail gives AI agents real email addresses (
@theagentmail.net
) with a REST API. Agents can send and receive email, sign up for services (GitHub, AWS, Slack, etc.), and get verification codes. A karma system prevents spam and keeps the shared domain's reputation high.
Base URL:
https://api.theagentmail.net
AgentMail为AI Agent提供后缀为
@theagentmail.net
的真实邮箱地址,配套REST API。Agent可以收发邮件、注册各类服务(GitHub、AWS、Slack等)、接收验证码。内置的karma系统可防止垃圾邮件,维持共享域名的高信誉。
Base URL:
https://api.theagentmail.net

Quick start

快速开始

All requests require
Authorization: Bearer am_...
header (API key from dashboard).
所有请求都需要携带
Authorization: Bearer am_...
请求头(API密钥可在控制台获取)。

Create an email account (-10 karma)

创建邮箱账号(扣除10 karma)

bash
curl -X POST https://api.theagentmail.net/v1/accounts \
  -H "Authorization: Bearer am_..." \
  -H "Content-Type: application/json" \
  -d '{"address": "my-agent@theagentmail.net"}'
Response:
{"data": {"id": "...", "address": "my-agent@theagentmail.net", "displayName": null, "createdAt": 123}}
bash
curl -X POST https://api.theagentmail.net/v1/accounts \
  -H "Authorization: Bearer am_..." \
  -H "Content-Type: application/json" \
  -d '{"address": "my-agent@theagentmail.net"}'
返回结果:
{"data": {"id": "...", "address": "my-agent@theagentmail.net", "displayName": null, "createdAt": 123}}

Send email (-1 karma)

发送邮件(扣除1 karma)

bash
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/messages \
  -H "Authorization: Bearer am_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": ["recipient@example.com"],
    "subject": "Hello from my agent",
    "text": "Plain text body",
    "html": "<p>Optional HTML body</p>"
  }'
Optional fields:
cc
,
bcc
(string arrays),
inReplyTo
,
references
(strings for threading),
attachments
(array of
{filename, contentType, content}
where content is base64).
bash
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/messages \
  -H "Authorization: Bearer am_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": ["recipient@example.com"],
    "subject": "Hello from my agent",
    "text": "Plain text body",
    "html": "<p>Optional HTML body</p>"
  }'
可选字段:
cc
bcc
(字符串数组)、
inReplyTo
references
(用于邮件线程的字符串)、
attachments
{filename, contentType, content}
对象数组,其中content为base64格式)。

Read inbox

读取收件箱

bash
undefined
bash
undefined

List messages

列出邮件

Get full message (with body and attachments)

获取完整邮件内容(包含正文和附件)

undefined
undefined

Check karma

查询karma余额

bash
curl https://api.theagentmail.net/v1/karma \
  -H "Authorization: Bearer am_..."
Response:
{"data": {"balance": 90, "events": [...]}}
bash
curl https://api.theagentmail.net/v1/karma \
  -H "Authorization: Bearer am_..."
返回结果:
{"data": {"balance": 90, "events": [...]}}

Register webhook (real-time inbound)

注册webhook(实时接收入站邮件)

bash
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/webhooks \
  -H "Authorization: Bearer am_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://my-agent.example.com/inbox"}'
Webhook deliveries include two security headers:
  • X-AgentMail-Signature
    -- HMAC-SHA256 hex digest of the request body, signed with the webhook secret
  • X-AgentMail-Timestamp
    -- millisecond timestamp of when the delivery was sent
Verify the signature and reject requests with timestamps older than 5 minutes to prevent replay attacks:
typescript
import { createHmac } from "crypto";

const verifyWebhook = (body: string, signature: string, timestamp: string, secret: string) => {
  if (Date.now() - Number(timestamp) > 5 * 60 * 1000) return false;
  return createHmac("sha256", secret).update(body).digest("hex") === signature;
};
bash
curl -X POST https://api.theagentmail.net/v1/accounts/{accountId}/webhooks \
  -H "Authorization: Bearer am_..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://my-agent.example.com/inbox"}'
Webhook推送包含两个安全头:
  • X-AgentMail-Signature
    -- 请求体的HMAC-SHA256十六进制摘要,使用webhook密钥签名
  • X-AgentMail-Timestamp
    -- 推送发送时的毫秒级时间戳
你需要验证签名,并且拒绝时间戳早于5分钟的请求,以防止重放攻击:
typescript
import { createHmac } from "crypto";

const verifyWebhook = (body: string, signature: string, timestamp: string, secret: string) => {
  if (Date.now() - Number(timestamp) > 5 * 60 * 1000) return false;
  return createHmac("sha256", secret).update(body).digest("hex") === signature;
};

Download attachment

下载附件

bash
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId}/attachments/{attachmentId} \
  -H "Authorization: Bearer am_..."
Returns
{"data": {"url": "https://signed-download-url..."}}
.
bash
curl https://api.theagentmail.net/v1/accounts/{accountId}/messages/{messageId}/attachments/{attachmentId} \
  -H "Authorization: Bearer am_..."
返回结果:
{"data": {"url": "https://signed-download-url..."}}

Full API reference

完整API参考

MethodPathDescriptionKarma
POST
/v1/accounts
Create email account-10
GET
/v1/accounts
List all accounts
GET
/v1/accounts/:id
Get account details
DELETE
/v1/accounts/:id
Delete account+10
POST
/v1/accounts/:id/messages
Send email-1
GET
/v1/accounts/:id/messages
List messages
GET
/v1/accounts/:id/messages/:msgId
Get full message
GET
/v1/accounts/:id/messages/:msgId/attachments/:attId
Get attachment URL
POST
/v1/accounts/:id/webhooks
Register webhook
GET
/v1/accounts/:id/webhooks
List webhooks
DELETE
/v1/accounts/:id/webhooks/:whId
Delete webhook
GET
/v1/karma
Get balance + events
方法路径描述Karma消耗/奖励
POST
/v1/accounts
创建邮箱账号-10
GET
/v1/accounts
列出所有账号
GET
/v1/accounts/:id
获取账号详情
DELETE
/v1/accounts/:id
删除账号+10
POST
/v1/accounts/:id/messages
发送邮件-1
GET
/v1/accounts/:id/messages
列出邮件
GET
/v1/accounts/:id/messages/:msgId
获取完整邮件
GET
/v1/accounts/:id/messages/:msgId/attachments/:attId
获取附件链接
POST
/v1/accounts/:id/webhooks
注册webhook
GET
/v1/accounts/:id/webhooks
列出webhook
DELETE
/v1/accounts/:id/webhooks/:whId
删除webhook
GET
/v1/karma
获取余额和变更记录

Karma system

Karma系统

Every action has a karma cost or reward:
EventKarmaWhy
money_paid
+100Purchase credits
email_received
+2Someone replied from a trusted domain
account_deleted
+10Karma refunded when you delete an address
email_sent
-1Sending costs karma
account_created
-10Creating addresses costs karma
Important rules:
  • Karma is only awarded for inbound emails from trusted providers (Gmail, Outlook, Yahoo, iCloud, ProtonMail, Fastmail, Hey, etc.). Emails from unknown/throwaway domains don't earn karma.
  • You only earn karma once per sender until the agent replies. If sender X emails you 5 times without a reply, only the first earns karma. Reply to X, and the next email from X earns karma again.
  • Deleting an account refunds the 10 karma it cost to create.
When karma reaches 0, sends and account creation return HTTP 402. Always check balance before operations that cost karma.
每个操作都有对应的karma消耗或奖励:
事件Karma变动说明
money_paid
+100购买额度
email_received
+2收到可信域名的回复邮件
account_deleted
+10删除地址时返还karma
email_sent
-1发送邮件消耗karma
account_created
-10创建地址消耗karma
重要规则:
  • 仅收到可信服务商(Gmail、Outlook、Yahoo、iCloud、ProtonMail、Fastmail、Hey等)的入站邮件可获得karma,来自未知/临时域名的邮件无法获得karma。
  • 同一个发件人在Agent回复前仅可贡献一次karma:如果发件人X给你发了5封邮件且你没有回复,仅第一封可获得karma;回复X后,X的下一封邮件可再次获得karma。
  • 删除账号会返还创建时消耗的10 karma。
当karma归零时,发送邮件和创建账号的请求会返回HTTP 402。请在执行消耗karma的操作前先查询余额。

TypeScript SDK

TypeScript SDK

typescript
import { createClient } from "@agentmail/sdk";

const mail = createClient({ apiKey: "am_..." });

// Create account
const account = await mail.accounts.create({
  address: "my-agent@theagentmail.net",
});

// Send email
await mail.messages.send(account.id, {
  to: ["human@example.com"],
  subject: "Hello",
  text: "Sent by an AI agent.",
});

// Read inbox
const messages = await mail.messages.list(account.id);
const detail = await mail.messages.get(account.id, messages[0].id);

// Attachments
const att = await mail.attachments.getUrl(accountId, messageId, attachmentId);
// att.url is a signed download URL

// Webhooks
await mail.webhooks.create(account.id, {
  url: "https://my-agent.example.com/inbox",
});

// Karma
const karma = await mail.karma.getBalance();
console.log(karma.balance);
typescript
import { createClient } from "@agentmail/sdk";

const mail = createClient({ apiKey: "am_..." });

// 创建账号
const account = await mail.accounts.create({
  address: "my-agent@theagentmail.net",
});

// 发送邮件
await mail.messages.send(account.id, {
  to: ["human@example.com"],
  subject: "Hello",
  text: "Sent by an AI agent.",
});

// 读取收件箱
const messages = await mail.messages.list(account.id);
const detail = await mail.messages.get(account.id, messages[0].id);

// 附件
const att = await mail.attachments.getUrl(accountId, messageId, attachmentId);
// att.url 是签名后的下载链接

// Webhooks
await mail.webhooks.create(account.id, {
  url: "https://my-agent.example.com/inbox",
});

// Karma
const karma = await mail.karma.getBalance();
console.log(karma.balance);

Error handling

错误处理

typescript
import { AgentMailError } from "@agentmail/sdk";

try {
  await mail.messages.send(accountId, { to: ["a@b.com"], subject: "Hi", text: "Hey" });
} catch (e) {
  if (e instanceof AgentMailError) {
    console.log(e.status);   // 402, 404, 401, etc.
    console.log(e.code);     // "INSUFFICIENT_KARMA", "NOT_FOUND", etc.
    console.log(e.message);
  }
}
typescript
import { AgentMailError } from "@agentmail/sdk";

try {
  await mail.messages.send(accountId, { to: ["a@b.com"], subject: "Hi", text: "Hey" });
} catch (e) {
  if (e instanceof AgentMailError) {
    console.log(e.status);   // 402, 404, 401, 等
    console.log(e.code);     // "INSUFFICIENT_KARMA", "NOT_FOUND", 等
    console.log(e.message);
  }
}

Common patterns

常见使用场景

Sign up for a service and read verification email

注册服务并读取验证邮件

typescript
const account = await mail.accounts.create({
  address: "signup-bot@theagentmail.net",
});

// Use the address to sign up (browser automation, API, etc.)

// Poll for verification email
for (let i = 0; i < 30; i++) {
  const messages = await mail.messages.list(account.id);
  const verification = messages.find(m =>
    m.subject.toLowerCase().includes("verify") ||
    m.subject.toLowerCase().includes("confirm")
  );
  if (verification) {
    const detail = await mail.messages.get(account.id, verification.id);
    // Parse verification link/code from detail.bodyText or detail.bodyHtml
    break;
  }
  await new Promise(r => setTimeout(r, 2000));
}
typescript
const account = await mail.accounts.create({
  address: "signup-bot@theagentmail.net",
});

// 使用该地址注册服务(浏览器自动化、API等)

// 轮询获取验证邮件
for (let i = 0; i < 30; i++) {
  const messages = await mail.messages.list(account.id);
  const verification = messages.find(m =>
    m.subject.toLowerCase().includes("verify") ||
    m.subject.toLowerCase().includes("confirm")
  );
  if (verification) {
    const detail = await mail.messages.get(account.id, verification.id);
    // 从detail.bodyText或detail.bodyHtml中解析验证链接/验证码
    break;
  }
  await new Promise(r => setTimeout(r, 2000));
}

Send email and wait for reply

发送邮件并等待回复

typescript
const sent = await mail.messages.send(account.id, {
  to: ["human@company.com"],
  subject: "Question about order #12345",
  text: "Can you check the status?",
});

for (let i = 0; i < 60; i++) {
  const messages = await mail.messages.list(account.id);
  const reply = messages.find(m =>
    m.direction === "inbound" && m.timestamp > sent.timestamp
  );
  if (reply) {
    const detail = await mail.messages.get(account.id, reply.id);
    // Process reply
    break;
  }
  await new Promise(r => setTimeout(r, 5000));
}
typescript
const sent = await mail.messages.send(account.id, {
  to: ["human@company.com"],
  subject: "Question about order #12345",
  text: "Can you check the status?",
});

for (let i = 0; i < 60; i++) {
  const messages = await mail.messages.list(account.id);
  const reply = messages.find(m =>
    m.direction === "inbound" && m.timestamp > sent.timestamp
  );
  if (reply) {
    const detail = await mail.messages.get(account.id, reply.id);
    // 处理回复
    break;
  }
  await new Promise(r => setTimeout(r, 5000));
}

Types

类型定义

typescript
type Account = { id: string; address: string; displayName: string | null; createdAt: number };
type Message = { id: string; from: string; to: string[]; subject: string; direction: "inbound" | "outbound"; status: string; timestamp: number };
type MessageDetail = Message & { cc: string[] | null; bcc: string[] | null; bodyText: string | null; bodyHtml: string | null; inReplyTo: string | null; references: string | null; attachments: AttachmentMeta[] };
type AttachmentMeta = { id: string; filename: string; contentType: string; size: number };
type KarmaBalance = { balance: number; events: KarmaEvent[] };
type KarmaEvent = { id: string; type: string; amount: number; timestamp: number; metadata?: Record<string, unknown> };
typescript
type Account = { id: string; address: string; displayName: string | null; createdAt: number };
type Message = { id: string; from: string; to: string[]; subject: string; direction: "inbound" | "outbound"; status: string; timestamp: number };
type MessageDetail = Message & { cc: string[] | null; bcc: string[] | null; bodyText: string | null; bodyHtml: string | null; inReplyTo: string | null; references: string | null; attachments: AttachmentMeta[] };
type AttachmentMeta = { id: string; filename: string; contentType: string; size: number };
type KarmaBalance = { balance: number; events: KarmaEvent[] };
type KarmaEvent = { id: string; type: string; amount: number; timestamp: number; metadata?: Record<string, unknown> };