Inboxes
An inbox is a mailbox address (local_part@domain) that receives inbound mail and sends
outbound replies on behalf of your organization.
The inbox object
{
"id": "inb_01k2n9v8qf3m7d5b0y6xz4rt1c",
"object": "inbox",
"address": "orders-bot@agentmail.ackuna.com",
"local_part": "orders-bot",
"domain": "agentmail.ackuna.com",
"display_name": "Support desk",
"status": "active",
"thread_count": 42,
"created_at": "2026-08-14T09:00:00.000Z"
}
status is active or paused. A paused inbox means your agent is not processing it:
- Inbound mail is held, not dropped. It is stored and threaded as usual, but no
inbox.message.receivedwebhook fires for it while the inbox is paused. When you resume the inbox, each held message gets itsinbox.message.receivedwebhook once andheldbecomesfalse. The webhooks are dispatched in arrival order, but deliveries are retried independently and mail that arrives just after the resume is not held, so they can reach you out of order: usemessage.created_at, which is when the mail arrived, to order them. Thethreadin such a webhook is the thread as it is at release, so its message count andlast_message_atcan include later mail. - Held mail is readable through the API while the inbox is paused: thread and message
endpoints return it with
held: true, and the thread'slast_message_atmoves. If you poll instead of using webhooks and want pause to mean "not yet", skip messages withheld: true. - Held mail follows your plan's retention windows like any other mail. A message held past the body window is released without its body and attachments, and one held past the record window is deleted without being released.
inbox.message.failedstill fires while the inbox is paused: mail that cannot be parsed or stored is not held.- Sending stops:
POST /v1/inboxes/{inbox}/messagesfails with 409inbox_paused.
An archived inbox receives nothing; mail to its address is not delivered.
List inboxes
GET /v1/inboxes?limit=25
Authorization: Bearer ak_...
{
"data": [
{"id": "inb_01k2n9v8qf3m7d5b0y6xz4rt1c", "object": "inbox", "address": "orders-bot@agentmail.ackuna.com", "local_part": "orders-bot", "domain": "agentmail.ackuna.com", "display_name": null, "status": "active", "thread_count": 42, "created_at": "2026-08-14T09:00:00.000Z"}
],
"next_cursor": "eyJpZCI6MTIzfQ",
"has_more": false
}
Requires scope inboxes:read. Pass ?cursor= from a previous page's next_cursor to
continue; ?limit= is 1–100, default 25.
Create an inbox
POST /v1/inboxes
Authorization: Bearer ak_...
Content-Type: application/json
Idempotency-Key: create-billing-inbox-1
{"username": "ledger-bot"}
{
"data": {
"id": "inb_01k2n9v8qf3m7d5b0y6xz4rt2d",
"object": "inbox",
"address": "ledger-bot@agentmail.ackuna.com",
"local_part": "ledger-bot",
"domain": "agentmail.ackuna.com",
"display_name": null,
"status": "active",
"thread_count": 0,
"created_at": "2026-08-20T14:00:00.000Z"
}
}
Requires scope inboxes:write. Fields:
| Field | Required | Notes |
|---|---|---|
username |
yes | Lowercased local part. [a-z0-9], ., _ or - internally, up to 64 characters. |
domain |
no | A dom_... id of an active receiving domain you own, or the shared platform domain's name (agentmail.ackuna.com). Omitted → the inbox is hosted on agentmail.ackuna.com. The earlier shared domain agents.ackuna.com can no longer be chosen for new inboxes (422 domain_not_allowed); inboxes already on it keep sending and receiving. |
Failure modes specific to this endpoint: 422 address_taken if the address already
exists; 422 local_part_not_allowed if the username is reserved or contains a brand,
payment or sign-in term and the inbox would be on the shared platform domain (see below);
409 domain_not_ready if
domain names a domain that is not yet active; 422 domain_not_allowed if domain
names an older shared domain such as agents.ackuna.com, which keeps its existing inboxes
but takes no new ones;
403 quota_exceeded if the organization's inbox quota is exhausted. An inbox keeps the
domain it was created on.
On the shared platform domain some names are not available, because mail from
agentmail.ackuna.com goes out under Ackuna's own identity. A role address is refused as the
whole name (postmaster, abuse, support, billing, noreply, ...). A few role words
(admin, root, postmaster, abuse, security, official, no-reply, ...) are
refused anywhere in the name, as a word of their own, so security-team is refused while
acme-support is not. A name that contains a brand, payment or sign-in term (paypal,
invoice, login, ...) is refused, digit look-alikes such as paypa1 included. The
error does not say which rule matched. On a custom domain you own, any name is
allowed.
Fetch an inbox
GET /v1/inboxes/inb_01k2n9v8qf3m7d5b0y6xz4rt1c
Authorization: Bearer ak_...
Requires scope inboxes:read. Returns the inbox object, or 404 not_found for an unknown
or cross-organization id.
Pause, resume, or rename an inbox
PATCH /v1/inboxes/inb_01k2n9v8qf3m7d5b0y6xz4rt1c
Authorization: Bearer ak_...
Content-Type: application/json
Idempotency-Key: pause-billing-inbox-1
{"status": "paused"}
{
"data": {
"id": "inb_01k2n9v8qf3m7d5b0y6xz4rt2d",
"object": "inbox",
"address": "ledger-bot@agentmail.ackuna.com",
"local_part": "ledger-bot",
"domain": "agentmail.ackuna.com",
"display_name": null,
"status": "paused",
"thread_count": 0,
"created_at": "2026-08-20T14:00:00.000Z"
}
}
Requires scope inboxes:write. Both fields are optional and independent — send only what
you want to change:
| Field | Notes |
|---|---|
display_name |
Nullable string, up to 255 characters. It becomes the From name of the inbox's mail, so on the shared platform domain a name that contains a brand, payment or sign-in term is refused with 422 display_name_not_allowed. Role words are fine here ("Support desk"). On a custom domain any name is allowed. |
status |
active or paused. Pausing holds inbound mail and stops sending; resuming releases the held mail's webhooks (see the inbox object). |
Archive an inbox
DELETE /v1/inboxes/inb_01k2n9v8qf3m7d5b0y6xz4rt1c
Authorization: Bearer ak_...
Idempotency-Key: archive-billing-inbox-1
Responds 204 No Content. Requires scope inboxes:write.
Archiving frees the inbox's quota slot and hides it everywhere — it stops receiving mail,
no longer appears in GET /v1/inboxes, and no longer resolves by id (a later GET,
PATCH, or DELETE for it returns 404 not_found). Its threads, messages, and
attachments follow the same retention as any other inbox: message bodies and attachments are
removed after 90 days and the messages themselves after 180 days, unless your plan sets
other windows.
The address is not released. The shared platform domain hosts inboxes for many
organizations, so a retired address stays reserved: it can never be re-created (a later
POST /v1/inboxes for the same address returns 422 address_taken), which stops a
different organization from claiming it and receiving the prior owner's mail.
Returns 404 not_found for an unknown or cross-organization id.
Next: Threads group an inbox's messages into conversations, and Messages covers reading and sending.