API reference
Base path /v0. Authenticate with Authorization: Bearer <api_key>. Lists return { count, limit, next_page_token?, <plural> } and accept limit (1 to 100) and page_token. Missing resources and anything outside your key's scope return 404.
This reference is checked against the server's registered routes in CI, so a route cannot ship undocumented, and the permission shown for each route is probed against the server. The request and response examples were recorded from the running application, with ids, timestamps and secrets replaced by stable look-alikes and long lists shortened. Field-level details are in the guides. Which routes also have a dashboard screen, SDK method or MCP tool is in the feature table.
Organizations and agent sign-up#
Bootstrap and self-serve agent onboarding. Humans normally sign up in the dashboard instead.
/v0/agent/sign-upCreate an organization, an inbox and an API key in one call. No auth; rate limited per IP. Sending stays locked until a human is attached and verified.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/agent/sign-up" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"username":"my-agent","human_email":"owner@example.com"}'{
"organization_id": "org_c9c37ce2e4f2a1279e83f57a",
"inbox_id": "inbox_e3b8714e669f7f03aadf2880",
"api_key": "am_bd48fa291f9292daa2953e3f4d7252ff3a916dfdfd7cda1c"
}/v0/agent/attach-humanAttach (or replace, at most twice) the human who must verify the agent. Emails a 6-digit code.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/agent/attach-human" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"human_email":"owner@example.com"}'{
"human_email": "owner@example.com",
"instructions": "A 6-digit verification code was sent to owner@example.com. Submit it to POST /v0/agent/verify as otp_code."
}/v0/agent/verifySubmit the 6-digit code to unlock sending.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/agent/verify" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"otp_code":"123456"}'{
"verified": true
}Pods#
Isolated sub-tenants inside an organization.
/v0/podsCreate a pod.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/pods" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Corp","client_id":"acme"}'{
"pod_id": "pod_5ea618a82d38c4b9d0322273",
"name": "Acme Corp",
"client_id": "acme",
"created_at": "2026-03-01T11:00:07.000Z",
"updated_at": "2026-03-01T11:00:07.000Z"
}/v0/podsList pods.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/pods" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 50,
"pods": [
{
"pod_id": "pod_5ea618a82d38c4b9d0322273",
"name": "Acme Corp",
"client_id": "acme",
"created_at": "2026-03-01T11:00:07.000Z",
"updated_at": "2026-03-01T11:00:07.000Z"
},
{
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"name": "Default Pod",
"created_at": "2026-03-01T11:00:14.000Z",
"updated_at": "2026-03-01T11:00:14.000Z"
}
]
}/v0/pods/:pod_idGet a pod.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/pods/pod_5ea618a82d38c4b9d0322273" \
-H "Authorization: Bearer $API_KEY"{
"pod_id": "pod_5ea618a82d38c4b9d0322273",
"name": "Acme Corp",
"client_id": "acme",
"created_at": "2026-03-01T11:00:07.000Z",
"updated_at": "2026-03-01T11:00:07.000Z"
}/v0/pods/:pod_idDelete a pod. Fails while it still has child resources.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/pods/pod_1006a522b3866744235688db" \
-H "Authorization: Bearer $API_KEY"(empty body)Inboxes#
/v0/inboxes/v0/pods/:pod_id/inboxesCreate an inbox. Omit username for a random one. domain defaults to the server's base domain; any other domain must be a verified custom domain of yours (or a subdomain of one with subdomains_enabled). Returns the inbox: inbox_id, email, display_name, status, pod_id, created_at, updated_at. 402 plan_limit_exceeded when the plan's inbox limit is reached; 422 reserved_username for reserved names.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"username":"support-agent","display_name":"Support Agent","client_id":"support-v1","metadata":{"team":"support"}}'{
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"email": "support-agent@agents.example.com",
"display_name": "Support Agent",
"client_id": "support-v1",
"status": "active",
"metadata": {
"team": "support"
},
"created_at": "2026-03-01T11:00:28.000Z",
"updated_at": "2026-03-01T11:00:28.000Z"
}/v0/inboxes/v0/pods/:pod_id/inboxesList inboxes: { count, limit, next_page_token?, inboxes[] }, newest first.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes?limit=2" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 2,
"inboxes": [
{
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"email": "support-agent@agents.example.com",
"display_name": "Support Agent",
"client_id": "support-v1",
"status": "active",
"metadata": {
"team": "support"
},
"created_at": "2026-03-01T11:00:28.000Z",
"updated_at": "2026-03-01T11:00:28.000Z"
},
{
"pod_id": "pod_5ea618a82d38c4b9d0322273",
"inbox_id": "inbox_bafed46d2e293c0b5c5cfcf7",
"email": "acme-support@agents.example.com",
"status": "active",
"created_at": "2026-03-01T11:00:21.000Z",
"updated_at": "2026-03-01T11:00:21.000Z"
}
]
}/v0/inboxes/:inbox_idGet an inbox. :inbox_id is the inbox_id or the full email address, on every inbox route.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e" \
-H "Authorization: Bearer $API_KEY"{
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"email": "support-agent@agents.example.com",
"display_name": "Support Agent",
"client_id": "support-v1",
"status": "active",
"metadata": {
"team": "support"
},
"created_at": "2026-03-01T11:00:28.000Z",
"updated_at": "2026-03-01T11:00:28.000Z"
}/v0/inboxes/:inbox_idUpdate display_name, status (active or paused) or metadata.
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"display_name":"Support","metadata":{"team":"support","tier":"1"}}'{
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"email": "support-agent@agents.example.com",
"display_name": "Support",
"client_id": "support-v1",
"status": "active",
"metadata": {
"team": "support",
"tier": "1"
},
"created_at": "2026-03-01T11:00:28.000Z",
"updated_at": "2026-03-01T11:00:35.000Z"
}/v0/inboxes/:inbox_id/v0/pods/:pod_id/inboxes/:inbox_idDelete an inbox and its data.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/inboxes/inbox_6fb378a4cb6950fb2ad6af74" \
-H "Authorization: Bearer $API_KEY"(empty body)Messages#
Send, reply, forward, list, search and label messages. Send endpoints accept an Idempotency-Key header.
/v0/inboxes/:inbox_id/messages/sendSend a message. Returns { message_id, thread_id }. At least one of to, cc or bcc is required (400 validation_error); 403 message_rejected when the provider refuses a recipient; 402 plan_limit_exceeded over the plan's send caps; 403 email_unverified until the account email is verified.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/send" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4821-shipped" \
-d '{"to":"maria@northwind.example","subject":"Your order #4821","text":"Hi Maria, it shipped yesterday."}'{
"message_id": "msg_92253243f3471651d425293d",
"thread_id": "thr_8a0dd6009c22913f7b6e1396"
}/v0/inboxes/:inbox_id/messages/:message_id/replyReply to the sender (threaded).
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829/reply" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"You are welcome."}'{
"message_id": "msg_231cf49d59380f36c61d1a7b",
"thread_id": "thr_8a0dd6009c22913f7b6e1396"
}/v0/inboxes/:inbox_id/messages/:message_id/reply-allReply to everyone on the message.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829/reply-all" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Thanks everyone."}'{
"message_id": "msg_7d2e1591f4f2dbb0fe599d30",
"thread_id": "thr_8a0dd6009c22913f7b6e1396"
}/v0/inboxes/:inbox_id/messages/:message_id/forwardForward a message with its attachments.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829/forward" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"ops@example.com","text":"FYI"}'{
"message_id": "msg_ef4bc57db6967a0cdfef7d2a",
"thread_id": "thr_7268b4e2ae6593f1bfbd24de"
}/v0/inboxes/:inbox_id/messagesList messages. Filters: labels, from, to, subject, before, after, ascending, limit, page_token.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages?labels=received&limit=10" \
-H "Authorization: Bearer $API_KEY"{
"count": 1,
"limit": 10,
"messages": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"unread"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:00:49.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
]
}
]
}/v0/inboxes/:inbox_id/messages/searchRanked full-text search (q) over from, to, subject and body.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/search?q=thank" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 50,
"messages": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"unread"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:00:49.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
],
"highlights": {
"text": "Great, **thank** you!\n\nOn Fri, Oct 3, 2026 Support Agent wrote:\n> Hi Maria, it shipped yesterday.\n"
}
},
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_7268b4e2ae6593f1bfbd24de",
"message_id": "msg_ef4bc57db6967a0cdfef7d2a",
"rfc_message_id": "<8f3c2a91-5b1e-4c7d-9a60-2d41e7b0c5aa@agents.example.com>",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:00:56.000Z",
"from": "Support <support-agent@agents.example.com>",
"to": [
"ops@example.com"
],
"size": 619,
"updated_at": "2026-03-01T11:00:56.000Z",
"created_at": "2026-03-01T11:00:56.000Z",
"subject": "Fwd: Re: Your order #4821",
"preview": "FYI ---------- Forwarded message --------- From: Maria Costa <maria@northwind.example> Date: 2026-03-01T11:00:42.000Z Subject: Re: Your order #4821 To: support-agent@agents.example.com Great, thank yo",
"highlights": {
"text": "FYI\n\n---------- Forwarded message ---------\nFrom: Maria Costa <maria@northwind.example>\nDate: 2026-03-01T11:00:42.000Z\nSubject: Re: Your order #4821\nTo: support-agent@agents.example.com\n\nGreat, **thank** you!\n\nOn Fri, Oct 3, 2026 Support Agent wrote:\n> Hi Maria, it shipped yesterday."
}
}
]
}/v0/inboxes/:inbox_id/messages/searchSame as the GET form, parameters in the body.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/search" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"q":"thank","limit":5}'{
"count": 2,
"limit": 5,
"messages": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"unread"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:00:49.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
],
"highlights": {
"text": "Great, **thank** you!\n\nOn Fri, Oct 3, 2026 Support Agent wrote:\n> Hi Maria, it shipped yesterday.\n"
}
},
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_7268b4e2ae6593f1bfbd24de",
"message_id": "msg_ef4bc57db6967a0cdfef7d2a",
"rfc_message_id": "<8f3c2a91-5b1e-4c7d-9a60-2d41e7b0c5aa@agents.example.com>",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:00:56.000Z",
"from": "Support <support-agent@agents.example.com>",
"to": [
"ops@example.com"
],
"size": 619,
"updated_at": "2026-03-01T11:00:56.000Z",
"created_at": "2026-03-01T11:00:56.000Z",
"subject": "Fwd: Re: Your order #4821",
"preview": "FYI ---------- Forwarded message --------- From: Maria Costa <maria@northwind.example> Date: 2026-03-01T11:00:42.000Z Subject: Re: Your order #4821 To: support-agent@agents.example.com Great, thank yo",
"highlights": {
"text": "FYI\n\n---------- Forwarded message ---------\nFrom: Maria Costa <maria@northwind.example>\nDate: 2026-03-01T11:00:42.000Z\nSubject: Re: Your order #4821\nTo: support-agent@agents.example.com\n\nGreat, **thank** you!\n\nOn Fri, Oct 3, 2026 Support Agent wrote:\n> Hi Maria, it shipped yesterday."
}
}
]
}/v0/inboxes/:inbox_id/messages/batch-getFetch up to 100 messages by id.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/batch-get" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"message_ids":["msg_f6bca2ea669a35112ab2a829"]}'{
"count": 1,
"messages": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"unread"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:00:49.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
]
}
]
}/v0/inboxes/:inbox_id/messages/batch-updateAdd or remove labels on up to 100 messages.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/batch-update" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"message_ids":["msg_f6bca2ea669a35112ab2a829"],"add_labels":["handled"]}'{
"count": 1,
"messages": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"vip",
"handled"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:01:10.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
]
}
]
}/v0/inboxes/:inbox_id/messages/:message_idGet one message with text, html and extracted_text.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829" \
-H "Authorization: Bearer $API_KEY"{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"unread"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:00:49.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"text": "Great, thank you!\n\nOn Fri, Oct 3, 2026 Support Agent wrote:\n> Hi Maria, it shipped yesterday.\n",
"extracted_text": "Great, thank you!",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
],
"headers": {
"from": "\"Maria Costa\" <maria@northwind.example>",
"to": "support-agent@agents.example.com",
"subject": "Re: Your order #4821",
"message-id": "<reply-1@northwind.example>",
"date": "2026-03-01T11:00:42.000Z",
"in-reply-to": "<msg-ref@x>",
"references": "<msg-ref@x>",
"content-type": "{\"value\":\"text/plain\",\"params\":{\"charset\":\"utf-8\"}}"
}
}/v0/inboxes/:inbox_id/messages/:message_idAdd or remove labels.
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"add_labels":["vip"],"remove_labels":["unread"]}'{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"message_id": "msg_f6bca2ea669a35112ab2a829",
"rfc_message_id": "<reply-1@northwind.example>",
"labels": [
"received",
"vip"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Maria Costa <maria@northwind.example>",
"to": [
"support-agent@agents.example.com"
],
"size": 94,
"updated_at": "2026-03-01T11:01:03.000Z",
"created_at": "2026-03-01T11:00:49.000Z",
"subject": "Re: Your order #4821",
"preview": "Great, thank you! On Fri, Oct 3, 2026 Support Agent wrote: > Hi Maria, it shipped yesterday.",
"text": "Great, thank you!\n\nOn Fri, Oct 3, 2026 Support Agent wrote:\n> Hi Maria, it shipped yesterday.\n",
"extracted_text": "Great, thank you!",
"in_reply_to": "<msg-ref@x>",
"references": [
"<msg-ref@x>"
],
"headers": {
"from": "\"Maria Costa\" <maria@northwind.example>",
"to": "support-agent@agents.example.com",
"subject": "Re: Your order #4821",
"message-id": "<reply-1@northwind.example>",
"date": "2026-03-01T11:00:42.000Z",
"in-reply-to": "<msg-ref@x>",
"references": "<msg-ref@x>",
"content-type": "{\"value\":\"text/plain\",\"params\":{\"charset\":\"utf-8\"}}"
}
}/v0/inboxes/:inbox_id/messages/:message_idDelete a message.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/inboxes/inbox_6fb378a4cb6950fb2ad6af74/messages/msg_c5535d8ba2efb95d5c54ba3c" \
-H "Authorization: Bearer $API_KEY"(empty body)/v0/inboxes/:inbox_id/messages/:message_id/rawGet a short-lived download_url for the raw .eml: { message_id, size, expires_at, download_url }. The message source itself is at /raw/download.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829/raw" \
-H "Authorization: Bearer $API_KEY"{
"message_id": "msg_f6bca2ea669a35112ab2a829",
"size": 383,
"expires_at": "2026-03-01T11:01:17.000Z",
"download_url": "https://mail.example.com/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_f6bca2ea669a35112ab2a829/raw/download"
}/v0/inboxes/:inbox_id/messages/:message_id/raw/downloadDownload the raw RFC 822 message.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_6fb378a4cb6950fb2ad6af74/messages/msg_c5535d8ba2efb95d5c54ba3c/raw/download" \
-H "Authorization: Bearer $API_KEY"From: Pat <pat@example.com>
To: scratch-bot@agents.example.com
Subject: Scratch
Message-ID: <scratch-1@example.com>
Date: Fri, 03 Oct 2026 10:00:00 +0000
Content-Type: text/plain; charset=utf-8
Scratch replyAttachments#
Downloads are served with Content-Disposition: attachment, X-Content-Type-Options: nosniff and Content-Security-Policy: sandbox.
/v0/inboxes/:inbox_id/messages/:message_id/attachments/:attachment_idAttachment metadata and a download_url.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_5614c0c994194fc530fb1b0d/attachments/att_31a6c30df6a314a70fe36ae2" \
-H "Authorization: Bearer $API_KEY"{
"attachment_id": "att_31a6c30df6a314a70fe36ae2",
"size": 26,
"filename": "invoice.txt",
"content_type": "text/plain",
"download_url": "https://mail.example.com/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_5614c0c994194fc530fb1b0d/attachments/att_31a6c30df6a314a70fe36ae2/raw",
"expires_at": "2026-03-01T11:01:24.000Z"
}/v0/inboxes/:inbox_id/messages/:message_id/attachments/:attachment_id/raw/v0/inboxes/:inbox_id/messages/:message_id/attachments/:attachment_id/downloadDownload the attachment bytes.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/messages/msg_5614c0c994194fc530fb1b0d/attachments/att_31a6c30df6a314a70fe36ae2/raw" \
-H "Authorization: Bearer $API_KEY"Invoice 4821
Total: 42.00Threads#
/v0/threads/v0/pods/:pod_id/threads/v0/inboxes/:inbox_id/threadsList threads.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/threads?limit=2" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 2,
"next_page_token": "Mg",
"threads": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_ce84e98d61f7bcf20b274ddc",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:01:31.000Z",
"senders": [
"Support <support-agent@agents.example.com>"
],
"recipients": [
"maria@northwind.example"
],
"last_message_id": "msg_5614c0c994194fc530fb1b0d",
"message_count": 1,
"size": 35,
"sent_timestamp": "2026-03-01T11:01:31.000Z",
"subject": "Invoice",
"preview": "Attached.",
"updated_at": "2026-03-01T11:01:31.000Z",
"created_at": "2026-03-01T11:01:31.000Z"
},
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_7268b4e2ae6593f1bfbd24de",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:00:56.000Z",
"senders": [
"Support <support-agent@agents.example.com>"
],
"recipients": [
"ops@example.com"
],
"last_message_id": "msg_ef4bc57db6967a0cdfef7d2a",
"message_count": 1,
"size": 619,
"sent_timestamp": "2026-03-01T11:00:56.000Z",
"subject": "Fwd: Re: Your order #4821",
"preview": "FYI ---------- Forwarded message --------- From: Maria Costa <maria@northwind.example> Date: 2026-03-01T11:00:42.000Z Subject: Re: Your order #4821 To: support-agent@agents.example.com Great, thank yo",
"updated_at": "2026-03-01T11:01:38.000Z",
"created_at": "2026-03-01T11:00:56.000Z"
}
]
}/v0/threads/search/v0/pods/:pod_id/threads/search/v0/inboxes/:inbox_id/threads/searchRanked search over threads (q).
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/threads/search?q=order" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 50,
"threads": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396",
"labels": [
"received",
"vip",
"handled",
"sent"
],
"timestamp": "2026-03-01T11:01:45.000Z",
"senders": [
"Maria Costa <maria@northwind.example>",
"Support <support-agent@agents.example.com>"
],
"recipients": [
"support-agent@agents.example.com",
"maria@northwind.example",
"Maria Costa <maria@northwind.example>"
],
"last_message_id": "msg_7d2e1591f4f2dbb0fe599d30",
"message_count": 4,
"size": 157,
"received_timestamp": "2026-03-01T11:00:42.000Z",
"sent_timestamp": "2026-03-01T11:01:45.000Z",
"subject": "Your order #4821",
"preview": "Thanks everyone.",
"updated_at": "2026-03-01T11:01:52.000Z",
"created_at": "2026-03-01T11:01:59.000Z"
},
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_7268b4e2ae6593f1bfbd24de",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:00:56.000Z",
"senders": [
"Support <support-agent@agents.example.com>"
],
"recipients": [
"ops@example.com"
],
"last_message_id": "msg_ef4bc57db6967a0cdfef7d2a",
"message_count": 1,
"size": 619,
"sent_timestamp": "2026-03-01T11:00:56.000Z",
"subject": "Fwd: Re: Your order #4821",
"preview": "FYI ---------- Forwarded message --------- From: Maria Costa <maria@northwind.example> Date: 2026-03-01T11:00:42.000Z Subject: Re: Your order #4821 To: support-agent@agents.example.com Great, thank yo",
"updated_at": "2026-03-01T11:01:38.000Z",
"created_at": "2026-03-01T11:00:56.000Z"
}
]
}/v0/threads/:thread_id/v0/inboxes/:inbox_id/threads/:thread_idGet a thread with its messages (messages[], oldest first; thread.messages.length equals message_count). Sent messages carry the sent label, received ones received.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/threads/thr_ce84e98d61f7bcf20b274ddc" \
-H "Authorization: Bearer $API_KEY"{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_ce84e98d61f7bcf20b274ddc",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:01:31.000Z",
"senders": [
"Support <support-agent@agents.example.com>"
],
"recipients": [
"maria@northwind.example"
],
"last_message_id": "msg_5614c0c994194fc530fb1b0d",
"message_count": 1,
"size": 35,
"sent_timestamp": "2026-03-01T11:01:31.000Z",
"subject": "Invoice",
"preview": "Attached.",
"updated_at": "2026-03-01T11:01:31.000Z",
"created_at": "2026-03-01T11:01:31.000Z",
"attachments": [
{
"attachment_id": "att_31a6c30df6a314a70fe36ae2",
"filename": "invoice.txt",
"content_type": "text/plain",
"content_disposition": "attachment",
"size": 26
}
],
"count": 1,
"limit": 50,
"messages": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_ce84e98d61f7bcf20b274ddc",
"message_id": "msg_5614c0c994194fc530fb1b0d",
"rfc_message_id": "<8f3c2a91-5b1e-4c7d-9a60-2d41e7b0c5aa@agents.example.com>",
"labels": [
"sent"
],
"timestamp": "2026-03-01T11:01:31.000Z",
"from": "Support <support-agent@agents.example.com>",
"to": [
"maria@northwind.example"
],
"subject": "Invoice",
"preview": "Attached.",
"text": "Attached.",
"extracted_text": "Attached.",
"size": 35,
"attachments": [
{
"attachment_id": "att_31a6c30df6a314a70fe36ae2",
"filename": "invoice.txt",
"content_type": "text/plain",
"content_disposition": "attachment",
"size": 26
}
],
"created_at": "2026-03-01T11:01:31.000Z",
"updated_at": "2026-03-01T11:01:31.000Z"
}
]
}/v0/threads/:thread_id/v0/inboxes/:inbox_id/threads/:thread_idAdd or remove labels on every message in the thread.
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/threads/thr_ce84e98d61f7bcf20b274ddc" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"add_labels":["resolved"]}'{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_ce84e98d61f7bcf20b274ddc",
"labels": [
"sent",
"resolved"
],
"timestamp": "2026-03-01T11:01:31.000Z",
"senders": [
"Support <support-agent@agents.example.com>"
],
"recipients": [
"maria@northwind.example"
],
"last_message_id": "msg_5614c0c994194fc530fb1b0d",
"message_count": 1,
"size": 35,
"sent_timestamp": "2026-03-01T11:01:31.000Z",
"subject": "Invoice",
"preview": "Attached.",
"updated_at": "2026-03-01T11:02:06.000Z",
"created_at": "2026-03-01T11:01:31.000Z"
}/v0/threads/:thread_id/v0/inboxes/:inbox_id/threads/:thread_idDelete a thread.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/inboxes/inbox_6fb378a4cb6950fb2ad6af74/threads/thr_aaa80e4eb84817354bfe92d6" \
-H "Authorization: Bearer $API_KEY"(empty body)Drafts#
Drafts can be scheduled with send_at. A draft that comes due while its inbox is paused fails and is not retried.
/v0/inboxes/:inbox_id/draftsCreate a draft.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/drafts" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"maria@northwind.example","subject":"Follow-up","text":"Checking in.","send_at":"2026-12-01T09:00:00Z"}'{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"draft_id": "draft_9a793a7ce9e58c68abc4125a",
"labels": [
"draft",
"scheduled"
],
"to": [
"maria@northwind.example"
],
"subject": "Follow-up",
"preview": "Checking in.",
"text": "Checking in.",
"send_status": "scheduled",
"send_at": "2026-03-01T11:02:13.000Z",
"updated_at": "2026-03-01T11:02:20.000Z",
"created_at": "2026-03-01T11:02:20.000Z"
}/v0/drafts/v0/inboxes/:inbox_id/draftsList drafts across all inboxes (each item carries inbox_id): { count, limit, next_page_token?, drafts[] }. Fields that were never set (to, subject, text) are absent, not null.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/drafts" \
-H "Authorization: Bearer $API_KEY"{
"count": 1,
"limit": 50,
"drafts": [
{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"draft_id": "draft_9a793a7ce9e58c68abc4125a",
"labels": [
"draft",
"scheduled"
],
"to": [
"maria@northwind.example"
],
"subject": "Follow-up",
"preview": "Checking in.",
"text": "Checking in.",
"send_status": "scheduled",
"send_at": "2026-03-01T11:02:13.000Z",
"updated_at": "2026-03-01T11:02:20.000Z",
"created_at": "2026-03-01T11:02:20.000Z"
}
]
}/v0/drafts/:draft_id/v0/inboxes/:inbox_id/drafts/:draft_idGet a draft.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/drafts/draft_9a793a7ce9e58c68abc4125a" \
-H "Authorization: Bearer $API_KEY"{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"draft_id": "draft_9a793a7ce9e58c68abc4125a",
"labels": [
"draft",
"scheduled"
],
"to": [
"maria@northwind.example"
],
"subject": "Follow-up",
"preview": "Checking in.",
"text": "Checking in.",
"send_status": "scheduled",
"send_at": "2026-03-01T11:02:13.000Z",
"updated_at": "2026-03-01T11:02:20.000Z",
"created_at": "2026-03-01T11:02:20.000Z"
}/v0/inboxes/:inbox_id/drafts/:draft_idUpdate a draft (nullable fields clear it).
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/drafts/draft_9a793a7ce9e58c68abc4125a" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"subject":"Follow-up on your order"}'{
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"draft_id": "draft_9a793a7ce9e58c68abc4125a",
"labels": [
"draft",
"scheduled"
],
"to": [
"maria@northwind.example"
],
"subject": "Follow-up on your order",
"preview": "Checking in.",
"text": "Checking in.",
"send_status": "scheduled",
"send_at": "2026-03-01T11:02:13.000Z",
"updated_at": "2026-03-01T11:02:27.000Z",
"created_at": "2026-03-01T11:02:20.000Z"
}/v0/inboxes/:inbox_id/drafts/:draft_idDelete a draft.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/inboxes/inbox_6fb378a4cb6950fb2ad6af74/drafts/draft_d5597c16704a3536ee942724" \
-H "Authorization: Bearer $API_KEY"(empty body)/v0/inboxes/:inbox_id/drafts/:draft_id/sendSend a draft now. Returns { message_id, thread_id }; the draft is consumed, so GET on it afterwards is 404.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/inboxes/inbox_bac2d3c9c3d41de7622edf3e/drafts/draft_9a793a7ce9e58c68abc4125a/send" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{}'{
"message_id": "msg_251a027005556a5921d41389",
"thread_id": "thr_5c75dc4a06e42831e19e462c"
}Allow and block lists#
direction is send, receive or reply; type is allow or block. Org, pod and inbox scopes.
/v0/lists/:direction/:type/v0/pods/:pod_id/lists/:direction/:type/v0/inboxes/:inbox_id/lists/:direction/:typeAdd an entry (address or domain).
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/lists/send/allow" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"entry":"northwind.example"}'{
"entry": "northwind.example",
"direction": "send",
"list_type": "allow",
"organization_id": "org_81e8bc749d45a4d9aa68b3cf",
"created_at": "2026-03-01T11:02:41.000Z"
}/v0/lists/:direction/:type/v0/pods/:pod_id/lists/:direction/:type/v0/inboxes/:inbox_id/lists/:direction/:typeList entries.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/lists/send/allow" \
-H "Authorization: Bearer $API_KEY"{
"count": 1,
"limit": 50,
"entries": [
{
"entry": "northwind.example",
"direction": "send",
"list_type": "allow",
"organization_id": "org_81e8bc749d45a4d9aa68b3cf",
"created_at": "2026-03-01T11:02:41.000Z"
}
]
}/v0/lists/:direction/:type/:entry/v0/pods/:pod_id/lists/:direction/:type/:entry/v0/inboxes/:inbox_id/lists/:direction/:type/:entryGet an entry.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/lists/send/allow/northwind.example" \
-H "Authorization: Bearer $API_KEY"{
"entry": "northwind.example",
"direction": "send",
"list_type": "allow",
"organization_id": "org_81e8bc749d45a4d9aa68b3cf",
"created_at": "2026-03-01T11:02:41.000Z"
}/v0/lists/:direction/:type/:entry/v0/pods/:pod_id/lists/:direction/:type/:entry/v0/inboxes/:inbox_id/lists/:direction/:type/:entryRemove an entry.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/lists/send/allow/northwind.example" \
-H "Authorization: Bearer $API_KEY"(empty body)Suppressions#
Addresses that bounced or complained are suppressed automatically.
/v0/suppressionsList suppressed addresses.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/suppressions" \
-H "Authorization: Bearer $API_KEY"{
"count": 1,
"suppressions": [
{
"address": "gone@example.org",
"reason": "bounce",
"source_message_id": "msg_92253243f3471651d425293d",
"created_at": "2026-03-01T11:04:33.000Z",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_8a0dd6009c22913f7b6e1396"
}
],
"limit": 50
}/v0/suppressions/:addressRemove an address so you can send to it again.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/suppressions/gone@example.org" \
-H "Authorization: Bearer $API_KEY"(empty body)Webhooks#
Signed deliveries with svix-id, svix-timestamp and svix-signature headers; see the webhooks guide.
/v0/webhooks/v0/pods/:pod_id/webhooks/v0/inboxes/:inbox_id/webhooksCreate a webhook. The signing secret (whsec_...) is returned only in this response; get, list and update never include it. event_types defaults to the eight default events. 400 invalid_webhook_url unless the URL is a public https URL; 402 plan_limit_exceeded at the plan's webhook limit.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/webhooks" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/hooks/mail","event_types":["message.received","message.bounced"]}'{
"webhook_id": "wh_cda90e6267fa3c9d2fbc06f8",
"url": "https://example.com/hooks/mail",
"secret": "whsec_MfKQ9r8GR4tJ7xP2Yb6mWq1Zs0Vn5Ae3",
"enabled": true,
"event_types": [
"message.received",
"message.bounced"
],
"updated_at": "2026-03-01T11:02:48.000Z",
"created_at": "2026-03-01T11:02:48.000Z"
}/v0/webhooks/v0/pods/:pod_id/webhooks/v0/inboxes/:inbox_id/webhooksList webhooks: { count, limit, next_page_token?, webhooks[] }. Items never include the secret.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/webhooks" \
-H "Authorization: Bearer $API_KEY"{
"count": 1,
"limit": 50,
"webhooks": [
{
"webhook_id": "wh_cda90e6267fa3c9d2fbc06f8",
"url": "https://example.com/hooks/mail",
"enabled": true,
"event_types": [
"message.received",
"message.bounced"
],
"updated_at": "2026-03-01T11:02:48.000Z",
"created_at": "2026-03-01T11:02:48.000Z"
}
]
}/v0/webhooks/:webhook_id/v0/pods/:pod_id/webhooks/:webhook_id/v0/inboxes/:inbox_id/webhooks/:webhook_idGet a webhook.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/webhooks/wh_cda90e6267fa3c9d2fbc06f8" \
-H "Authorization: Bearer $API_KEY"{
"webhook_id": "wh_cda90e6267fa3c9d2fbc06f8",
"url": "https://example.com/hooks/mail",
"enabled": true,
"event_types": [
"message.received",
"message.bounced"
],
"updated_at": "2026-03-01T11:02:48.000Z",
"created_at": "2026-03-01T11:02:48.000Z"
}/v0/webhooks/:webhook_id/v0/pods/:pod_id/webhooks/:webhook_id/v0/inboxes/:inbox_id/webhooks/:webhook_idUpdate url, enabled, event_types, scope.
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/webhooks/wh_cda90e6267fa3c9d2fbc06f8" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"enabled":false}'{
"webhook_id": "wh_cda90e6267fa3c9d2fbc06f8",
"url": "https://example.com/hooks/mail",
"enabled": false,
"event_types": [
"message.received",
"message.bounced"
],
"updated_at": "2026-03-01T11:02:55.000Z",
"created_at": "2026-03-01T11:02:48.000Z"
}/v0/webhooks/:webhook_id/v0/pods/:pod_id/webhooks/:webhook_id/v0/inboxes/:inbox_id/webhooks/:webhook_idDelete a webhook.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/webhooks/wh_f9fc112fdaf52e085c35fddf" \
-H "Authorization: Bearer $API_KEY"(empty body)/v0/webhooks/:webhook_id/headers/v0/pods/:pod_id/webhooks/:webhook_id/headers/v0/inboxes/:inbox_id/webhooks/:webhook_id/headersList the names of custom headers (values are write-only).
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/webhooks/wh_cda90e6267fa3c9d2fbc06f8/headers" \
-H "Authorization: Bearer $API_KEY"{
"headers": [
"X-Source"
]
}/v0/webhooks/:webhook_id/headers/v0/pods/:pod_id/webhooks/:webhook_id/headers/v0/inboxes/:inbox_id/webhooks/:webhook_id/headersSet or remove custom headers.
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/webhooks/wh_cda90e6267fa3c9d2fbc06f8/headers" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"set":{"X-Source":"mail"}}'{
"headers": [
"X-Source"
]
}/v0/webhooks/:webhook_id/deliveriesList recent delivery attempts for a webhook, newest first: { count, limit, next_page_token?, deliveries[] } where each delivery has delivery_id, event_id, event_type, status (pending, sending, delivered, failed), status_code (when the endpoint answered), attempts, error (http_4xx, http_5xx, timeout, ...) and timestamps. Supports limit (max 100) and page_token.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/webhooks/wh_cda90e6267fa3c9d2fbc06f8/deliveries" \
-H "Authorization: Bearer $API_KEY"{
"count": 0,
"limit": 20,
"deliveries": []
}Events and WebSocket#
/v0/eventsList recent events.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/events?limit=2" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 2,
"next_page_token": "Mg",
"events": [
{
"type": "event",
"event_type": "message.sent",
"event_id": "evt_e7c523914124347f5c4bcdfe",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"created_at": "2026-03-01T11:03:02.000Z",
"send": {
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_5c75dc4a06e42831e19e462c",
"message_id": "msg_251a027005556a5921d41389",
"timestamp": "2026-03-01T11:03:02.000Z",
"recipients": [
"maria@northwind.example"
]
}
},
{
"type": "event",
"event_type": "message.sent",
"event_id": "evt_549daa0c133fe17d77b17f06",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"created_at": "2026-03-01T11:03:09.000Z",
"send": {
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"thread_id": "thr_ce84e98d61f7bcf20b274ddc",
"message_id": "msg_5614c0c994194fc530fb1b0d",
"timestamp": "2026-03-01T11:01:31.000Z",
"recipients": [
"maria@northwind.example"
]
}
}
]
}/v0/inboxes/:inbox_id/eventsList recent events for one inbox.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/inboxes/inbox_6fb378a4cb6950fb2ad6af74/events?limit=2" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 2,
"events": [
{
"type": "event",
"event_type": "message.received",
"event_id": "evt_bd13dfa858979da25eca160c",
"inbox_id": "inbox_6fb378a4cb6950fb2ad6af74",
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"created_at": "2026-03-01T11:04:05.000Z",
"message": {
"inbox_id": "inbox_6fb378a4cb6950fb2ad6af74",
"thread_id": "thr_aaa80e4eb84817354bfe92d6",
"message_id": "msg_c5535d8ba2efb95d5c54ba3c",
"rfc_message_id": "<scratch-1@example.com>",
"labels": [
"received",
"unread"
],
"timestamp": "2026-03-01T11:00:42.000Z",
"from": "Pat <pat@example.com>",
"to": [
"scratch-bot@agents.example.com"
],
"size": 14,
"updated_at": "2026-03-01T11:04:12.000Z",
"created_at": "2026-03-01T11:04:12.000Z",
"subject": "Scratch",
"preview": "Scratch reply",
"text": "Scratch reply\n",
"extracted_text": "Scratch reply",
"headers": {
"from": "\"Pat\" <pat@example.com>",
"to": "scratch-bot@agents.example.com",
"subject": "Scratch",
"message-id": "<scratch-1@example.com>",
"date": "2026-03-01T11:00:42.000Z",
"content-type": "{\"value\":\"text/plain\",\"params\":{\"charset\":\"utf-8\"}}"
}
},
"thread": {
"inbox_id": "inbox_6fb378a4cb6950fb2ad6af74",
"thread_id": "thr_aaa80e4eb84817354bfe92d6",
"labels": [
"received",
"unread",
"sent"
],
"timestamp": "2026-03-01T11:04:19.000Z",
"senders": [
"Pat <pat@example.com>",
"scratch-bot@agents.example.com"
],
"recipients": [
"scratch-bot@agents.example.com",
"x@example.com"
],
"subject": "Scratch",
"preview": "Scratch.",
"last_message_id": "msg_6ba0bb5675a04881e2df2ae6",
"message_count": 2,
"size": 22,
"updated_at": "2026-03-01T11:04:05.000Z",
"created_at": "2026-03-01T11:04:19.000Z"
}
},
{
"type": "event",
"event_type": "message.sent",
"event_id": "evt_63bc9f6f3b62134fac1e0d53",
"inbox_id": "inbox_6fb378a4cb6950fb2ad6af74",
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"created_at": "2026-03-01T11:04:26.000Z",
"send": {
"inbox_id": "inbox_6fb378a4cb6950fb2ad6af74",
"thread_id": "thr_aaa80e4eb84817354bfe92d6",
"message_id": "msg_6ba0bb5675a04881e2df2ae6",
"timestamp": "2026-03-01T11:04:19.000Z",
"recipients": [
"x@example.com"
]
}
}
]
}/v0/websocketUpgrade to a WebSocket and send a subscribe message. Accepts ?api_key= for browsers.
Custom domains#
Plan-limited. See the domains guide.
/v0/domains/v0/pods/:pod_id/domainsAdd a domain. Returns the full domain: status NOT_STARTED and the DNS records to publish. 402 plan_limit_exceeded when the plan allows no more domains (Free allows none).
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/domains" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"domain":"agents.northwind.example"}'{
"domain_id": "agents.northwind.example",
"domain": "agents.northwind.example",
"feedback_enabled": true,
"subdomains_enabled": false,
"tracking_enabled": false,
"created_at": "2026-03-01T11:03:16.000Z",
"updated_at": "2026-03-01T11:03:16.000Z",
"status": "NOT_STARTED",
"records": [
{
"type": "MX",
"name": "agents.northwind.example",
"value": "inbound-smtp.us-east-1.amazonaws.com",
"priority": 10,
"status": "MISSING"
},
{
"type": "TXT",
"name": "agents.northwind.example",
"value": "v=spf1 include:amazonses.com ~all",
"status": "MISSING"
}
]
}/v0/domains/v0/pods/:pod_id/domainsList domains: { count, limit, next_page_token?, domains[] }. Items are summaries (domain_id, domain, flags, timestamps) WITHOUT status or records; fetch GET /v0/domains/:domain_id for those.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/domains" \
-H "Authorization: Bearer $API_KEY"{
"count": 1,
"limit": 50,
"domains": [
{
"domain_id": "agents.northwind.example",
"domain": "agents.northwind.example",
"feedback_enabled": true,
"subdomains_enabled": false,
"tracking_enabled": false,
"created_at": "2026-03-01T11:03:16.000Z",
"updated_at": "2026-03-01T11:03:16.000Z"
}
]
}/v0/domains/:domain_id/v0/pods/:pod_id/domains/:domain_idGet a domain with status (NOT_STARTED, PENDING, VERIFYING, VERIFIED, FAILED), a reason while it is not verified (for example dns_records_missing) and its DNS records (type, name, value, priority for MX, per-record status MISSING, INVALID or VALID). :domain_id may also be the domain name.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/domains/agents.northwind.example" \
-H "Authorization: Bearer $API_KEY"{
"domain_id": "agents.northwind.example",
"domain": "agents.northwind.example",
"feedback_enabled": true,
"subdomains_enabled": false,
"tracking_enabled": false,
"created_at": "2026-03-01T11:03:16.000Z",
"updated_at": "2026-03-01T11:03:16.000Z",
"status": "NOT_STARTED",
"records": [
{
"type": "MX",
"name": "agents.northwind.example",
"value": "inbound-smtp.us-east-1.amazonaws.com",
"priority": 10,
"status": "MISSING"
},
{
"type": "TXT",
"name": "agents.northwind.example",
"value": "v=spf1 include:amazonses.com ~all",
"status": "MISSING"
}
]
}/v0/domains/:domain_id/v0/pods/:pod_id/domains/:domain_idUpdate feedback, subdomain and tracking flags.
Example request and response (recorded from the running server)
curl -X PATCH "$BASE_URL/v0/domains/agents.northwind.example" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"tracking_enabled":true}'{
"domain_id": "agents.northwind.example",
"domain": "agents.northwind.example",
"feedback_enabled": true,
"subdomains_enabled": false,
"tracking_enabled": true,
"created_at": "2026-03-01T11:03:16.000Z",
"updated_at": "2026-03-01T11:04:40.000Z",
"status": "PENDING",
"records": [
{
"type": "MX",
"name": "agents.northwind.example",
"value": "inbound-smtp.us-east-1.amazonaws.com",
"priority": 10,
"status": "MISSING"
},
{
"type": "TXT",
"name": "agents.northwind.example",
"value": "v=spf1 include:amazonses.com ~all",
"status": "MISSING"
}
],
"reason": "dns_records_missing"
}/v0/domains/:domain_id/v0/pods/:pod_id/domains/:domain_idDelete a domain. Responds 204.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/domains/scratch.example.net" \
-H "Authorization: Bearer $API_KEY"(empty body)/v0/domains/:domain_id/verify/v0/pods/:pod_id/domains/:domain_id/verifyCheck DNS now and update the status. Responds 200 with an empty body; read the domain again for the new status.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/domains/agents.northwind.example/verify" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{}'(empty body)/v0/domains/:domain_id/zone-file/v0/pods/:pod_id/domains/:domain_id/zone-fileDownload the records as a zone file.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/domains/agents.northwind.example/zone-file" \
-H "Authorization: Bearer $API_KEY"$ORIGIN agents.northwind.example.
$TTL 3600
agents.northwind.example. IN MX 10 inbound-smtp.us-east-1.amazonaws.com.
agents.northwind.example. IN TXT "v=spf1 include:amazonses.com ~all"
mail1._domainkey.agents.northwind.example. IN TXT "v=DKIM1; k=rsa; p=A7ebpssajPq9QCKWW6rXe+huSd3hO0eQe3OkPDGusrY="
_dmarc.agents.northwind.example. IN TXT "v=DMARC1; p=none"API keys#
/v0/api-keysCreate a key, optionally scoped to a pod or inbox and limited to named permissions. The secret (api_key, starting with the returned prefix) is shown once in this response; list never returns it. 403 email_unverified until the account email is verified.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/api-keys" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"support-reader","inbox_id":"inbox_bac2d3c9c3d41de7622edf3e","permissions":["inbox_read","message_read"]}'{
"api_key_id": "key_8ca0692fef99229301a9c46e",
"prefix": "am_af3f6ce",
"name": "support-reader",
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"permissions": [
"inbox_read",
"message_read"
],
"created_at": "2026-03-01T11:03:23.000Z",
"api_key": "am_b774b982ad17764f5783632b0c4c841b80ec78ee67f3ccc5"
}/v0/api-keysList keys: { count, limit, next_page_token?, api_keys[] } with api_key_id, prefix, name, permissions, scope and created_at. Never the secret.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/api-keys" \
-H "Authorization: Bearer $API_KEY"{
"count": 2,
"limit": 50,
"api_keys": [
{
"api_key_id": "key_8ca0692fef99229301a9c46e",
"prefix": "am_af3f6ce",
"name": "support-reader",
"pod_id": "pod_7279e37cebf9a9b8e62c8cb2",
"inbox_id": "inbox_bac2d3c9c3d41de7622edf3e",
"permissions": [
"inbox_read",
"message_read"
],
"created_at": "2026-03-01T11:03:23.000Z"
},
{
"api_key_id": "key_be6463cd7e9e1395bb53c80d",
"prefix": "am_b875258",
"name": "default",
"created_at": "2026-03-01T11:03:30.000Z"
}
]
}/v0/api-keys/:api_key_idRevoke a key immediately. Responds 204.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/v0/api-keys/key_8ca0692fef99229301a9c46e" \
-H "Authorization: Bearer $API_KEY"(empty body)Metrics#
/v0/metrics/usage/v0/pods/:pod_id/metrics/usage/v0/inboxes/:inbox_id/metrics/usageRunning totals over time (storage_bytes, message_count, thread_count, inbox_count, domain_count, pod_count) for the last 90 days at most.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/metrics/usage?usage_types=message_count&period=86400&limit=2" \
-H "Authorization: Bearer $API_KEY"{
"message_count": [
{
"timestamp": "2026-03-01T11:03:37.000Z",
"value": 0
},
{
"timestamp": "2026-03-01T11:03:44.000Z",
"value": 7
}
]
}/v0/metrics/eventsEvent counts by type between start and end.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/metrics/events?event_types=message.sent&period=86400&limit=2" \
-H "Authorization: Bearer $API_KEY"{
"total": 7,
"counts": {
"message.sent": 7
}
}/v0/metrics/rates/v0/pods/:pod_id/metrics/rates/v0/inboxes/:inbox_id/metrics/ratesRolling bounce and complaint rates (plus open rate when tracking data exists) sampled every period over a trailing window. Each point has timestamp, sent (per recipient) and rate (null when nothing was sent).
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/metrics/rates?rate_types=bounce&period=86400&limit=2" \
-H "Authorization: Bearer $API_KEY"{
"bounce": [
{
"timestamp": "2026-03-01T11:03:51.000Z",
"sent": 0,
"rate": null
},
{
"timestamp": "2026-03-01T11:03:58.000Z",
"sent": 6,
"rate": 0
}
]
}Billing#
Account billing endpoints used by the dashboard. Authenticated like the rest of /v0; billing permissions are never granted to scoped or permission-restricted API keys. GET /public/plans (no auth) lists plans as { id, name, prices: { usd | inr: { monthly, yearly } }, limits }.
/v0/billingCurrent plan and usage: plan (free, pro, scale), plan_name, status (none, active, past_due, canceled, incomplete), source (free, admin, subscription), provider and interval (null on Free), current_period_end (null on Free), cancel_at_period_end, grace_ends_at while past_due, limits { inboxes, sends_per_month, sends_per_day (null = no daily cap), domains, webhooks } and usage { inboxes, sends_this_month, sends_today, domains, webhooks }. Needs an unrestricted key or an owner/admin dashboard session (permission billing_read).
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/billing" \
-H "Authorization: Bearer $API_KEY"{
"plan": "free",
"plan_name": "Free",
"status": "none",
"source": "free",
"provider": null,
"interval": null,
"current_period_end": null,
"cancel_at_period_end": false,
"limits": {
"inboxes": 3,
"sends_per_month": 300,
"sends_per_day": 100,
"domains": 0,
"webhooks": 1
},
"usage": {
"inboxes": 2,
"sends_this_month": 0,
"sends_today": 0,
"domains": 1,
"webhooks": 1
}
}/v0/billing/usageOnly plan, limits and usage from the summary above.
Example request and response (recorded from the running server)
curl "$BASE_URL/v0/billing/usage" \
-H "Authorization: Bearer $API_KEY"{
"plan": "free",
"limits": {
"inboxes": 3,
"sends_per_month": 300,
"sends_per_day": 100,
"domains": 0,
"webhooks": 1
},
"usage": {
"inboxes": 2,
"sends_this_month": 0,
"sends_today": 0,
"domains": 1,
"webhooks": 1
}
}/v0/billing/checkoutStart a checkout for plan (pro or scale) and interval (monthly or yearly). Returns { url, provider }; send the user to url. country IN selects Razorpay unless provider is given. 503 billing_not_configured when that provider is not set up; 409 already_subscribed when an active subscription exists (use the portal).
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/billing/checkout" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"plan":"pro","interval":"monthly"}'{
"url": "https://checkout.example/session/cs_1",
"provider": "stripe"
}/v0/billing/portalLink to manage the subscription: { provider, url } (Stripe) or { provider, instructions } (Razorpay). 503 billing_not_configured when the provider is not set up.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/billing/portal" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{}'{
"name": "ConflictError",
"code": "no_subscription",
"message": "No Stripe customer for this organization yet",
"fix": "Start a subscription with POST /v0/billing/checkout first"
}/v0/billing/cancelCancel at period end. Returns the billing summary with cancel_at_period_end true and a message. 409 no_subscription when there is nothing to cancel.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/v0/billing/cancel" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{}'{
"name": "ConflictError",
"code": "no_subscription",
"message": "No active subscription to cancel"
}Inbound mail (operators)#
Used by the mail forwarder you deploy, not by agents. Guarded by the x-inbound-secret header; the un-prefixed form exists because /v0 requires a Bearer key.
/inbound/rawDeliver a raw RFC 822 message. Query: to=addr[,addr]. Headers: x-inbound-secret, optional x-auth-spf / x-auth-dkim / x-auth-dmarc.
/inbound/resend-eventsReceiver for the email provider's delivery events (signature verified). Operator route; not for API clients.
Hosted MCP endpoint#
Remote Model Context Protocol server (Streamable HTTP, stateless) exposing the mail tools to MCP clients. Authenticate with Authorization: Bearer <api key>. Add ?read_only=1 to hide every tool that sends or changes data. Each tool call runs as the same REST request with your key, so permissions, plan limits and tenant isolation are identical. Body limit 256 KB; no CORS; responses are never cached. See the MCP guide.
/mcpJSON-RPC 2.0 over HTTP: initialize, tools/list, tools/call. Missing or invalid key returns 401 with a WWW-Authenticate: Bearer header.
Example request and response (recorded from the running server)
curl -X POST "$BASE_URL/mcp" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'{
"result": {
"tools": [
{
"name": "create_inbox",
"description": "Create a new email inbox. Returns its inbox_id and email address.",
"inputSchema": "..."
},
{
"name": "list_inboxes",
"description": "List inboxes",
"inputSchema": "..."
}
]
},
"jsonrpc": "2.0",
"id": 1
}/mcp405 Method Not Allowed. The endpoint is stateless and has no server-initiated stream.
Example request and response (recorded from the running server)
curl "$BASE_URL/mcp" \
-H "Authorization: Bearer $API_KEY"{
"jsonrpc": "2.0",
"error": {
"code": -32000,
"message": "Method not allowed: this server is stateless; use POST"
},
"id": null
}/mcp405 Method Not Allowed. There are no sessions to terminate.
Example request and response (recorded from the running server)
curl -X DELETE "$BASE_URL/mcp" \
-H "Authorization: Bearer $API_KEY"{
"jsonrpc": "2.0",
"error": {
"code": -32000,
"message": "Method not allowed: this server is stateless; use POST"
},
"id": null
}