inboxes.md


title: "Inboxes" description: "Create, list, search, read, update, pause and delete MachineMail inboxes, and check whether an address is available. The inbox_id is the email address." canonical: "https://machinemail.dev/docs/reference/api/inboxes"

Inboxes

Create, list, search, read, update, pause and delete MachineMail inboxes, and check whether an address is available. The inbox_id is the email address.

Source: https://machinemail.dev/docs/reference/api/inboxes

Method Path Summary
GET /v0/inboxes List Inboxes
POST /v0/inboxes Create Inbox
GET /v0/inboxes/availability Check Inbox Availability
GET /v0/inboxes/search Search Inboxes
GET /v0/inboxes/{inbox_id} Get Inbox
PATCH /v0/inboxes/{inbox_id} Update Inbox
DELETE /v0/inboxes/{inbox_id} Delete Inbox
GET /v0/pods/{pod_id}/inboxes List Inboxes in Pod
POST /v0/pods/{pod_id}/inboxes Create Inbox in Pod
GET /v0/pods/{pod_id}/inboxes/availability Check Inbox Availability in Pod
GET /v0/pods/{pod_id}/inboxes/search Search Inboxes in Pod
GET /v0/pods/{pod_id}/inboxes/{inbox_id} Get Inbox in Pod
PATCH /v0/pods/{pod_id}/inboxes/{inbox_id} Update Inbox in Pod
DELETE /v0/pods/{pod_id}/inboxes/{inbox_id} Delete Inbox in Pod

List Inboxes

GET /v0/inboxes

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Query parameters

Field Type Description
limit integer Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_token string next_page_token from the previous page.
ascending boolean Sort oldest first.
ephemeral boolean Only ephemeral (true) or only permanent (false) inboxes.

Response

200 A page of inboxes (application/json)

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
inboxes Inbox[] required Ordered by created_at, newest first unless ascending is set.

Each item of inboxes is a Inbox:

Field Type Description
pod_id string required ID of the pod the inbox belongs to.
inbox_id string required ID of the inbox: its email address, as in AgentMail (inbox_id == email).
email string required Email address of the inbox.
display_name string Display name: Display Name username@domain.com.
client_id string Client ID given at creation (idempotency key).
status "active" | "paused" required Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox is paused), and incoming mail is not stored; a message.rejected event with reason inbox_paused is emitted instead. Mail already in the inbox, its drafts and its API keys are kept. Set active to resume.
metadata Record<string, string | number | boolean> Custom key-value pairs attached to the inbox.
updated_at string (date-time) required Time at which the inbox was last updated.
created_at string (date-time) required Time at which the inbox was created.
organization_id string required ID of the organization.
ephemeral boolean required Whether the inbox expires (see ttl_seconds).
ttl_seconds integer TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_at string (date-time) When an ephemeral inbox and its mail are deleted.
created_by "api" | "catch_all" | "dashboard" | "agent" required What created the inbox: the API, a catch-all domain, the dashboard or an agent registration.

Errors

Status Meaning
400 Invalid request: error.type is validation and error.param names the field.
401 Missing, invalid, expired or revoked credential.
403 The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account_suspended: error.message says what still works; do not retry or re-register).
500 Unexpected server error.

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/inboxes" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "count": 1,
  "limit": 50,
  "next_page_token": "eyJvIjo1MH0",
  "inboxes": [
    {
      "pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
      "inbox_id": "agent@machinemail.dev",
      "email": "agent@machinemail.dev",
      "display_name": "Support Agent",
      "client_id": "my-client-id",
      "status": "active",
      "metadata": {
        "key": "value"
      },
      "updated_at": "2026-10-01T12:00:00.000Z",
      "created_at": "2026-10-01T12:00:00.000Z",
      "organization_id": "org_01k6x2m9qd0000a7h3kq9v2c4e",
      "ephemeral": false,
      "ttl_seconds": 1,
      "expires_at": "2026-10-01T12:00:00.000Z",
      "created_by": "api"
    }
  ]
}

Create Inbox

POST /v0/inboxes

ephemeral: true without ttl_seconds creates an inbox with a one hour TTL (3600 seconds).

An organization can have at most 1,000 inboxes on the shared domain; past that the API returns 403. Add your own domain for more. Inbox-scoped credentials cannot create inboxes (403).

A taken address returns 409, and so does a reserved one: role and brand names on the shared domain, and {slug}@ on the shared domain, which only the organization with that slug can create (agent- followed by 16 or more hex digits is reserved the same way).

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_create.

Request body

Content type: application/json.

Field Type Description
username string Local part of the address: a-z, 0-9 and . _ + -, 1 to 64 characters. Randomly generated if omitted. On the shared domain, a username equal to another organization's slug is reserved for that organization (409).
domain string Domain of the address: a domain verified by this organization. Defaults to the shared domain.
display_name string Display name: Display Name username@domain.com.
client_id string Idempotency key: a create with a client_id already used in the organization returns that inbox with 200, or 409 when that inbox is outside the pod of the API key or route.
status "active" | "paused" Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox is paused), and incoming mail is not stored; a message.rejected event with reason inbox_paused is emitted instead. Mail already in the inbox, its drafts and its API keys are kept. Set active to resume.
metadata Record<string, string | number | boolean> Custom key-value pairs attached to the inbox.
pod_id string Pod to create the inbox in. Defaults to the credential pod or the organization default pod.
ephemeral boolean true without ttl_seconds creates an ephemeral inbox with a one hour TTL (3600 seconds).
ttl_seconds integer | null Creates an ephemeral inbox that expires ttl_seconds after creation, extended by each inbound message.
import_source "agentmail" Marks an inbox copied from another provider by an importer (machinemail import agentmail sets agentmail). The only effect: its inbox.created event is not delivered to webhooks or MCP subscribers, so they are not notified about an inbox that already existed elsewhere. The event is still recorded (GET /v0/events, the event stream), marked as an import in its payload, so the event log shows every import. Everything else about the create is unchanged.

Response

200 An inbox with this client_id already exists; it is returned unchanged. (application/json)

201 Created (application/json)

Errors

Error bodies use the error envelope.

Example

curl -X POST "https://api.machinemail.dev/v0/inboxes" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "username": "agent",
  "display_name": "Support Agent"
}'
{
  "pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
  "inbox_id": "agent@machinemail.dev",
  "email": "agent@machinemail.dev",
  "display_name": "Support Agent",
  "client_id": "my-client-id",
  "status": "active",
  "metadata": {
    "key": "value"
  },
  "updated_at": "2026-10-01T12:00:00.000Z",
  "created_at": "2026-10-01T12:00:00.000Z",
  "organization_id": "org_01k6x2m9qd0000a7h3kq9v2c4e",
  "ephemeral": false,
  "ttl_seconds": 1,
  "expires_at": "2026-10-01T12:00:00.000Z",
  "created_by": "api"
}

Check Inbox Availability

GET /v0/inboxes/availability

Whether username@domain can be created by this organization now. Never a 4xx for a bad name: reason says why it is not available.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Query parameters

Field Type Description
username string Local part to check.
domain string Domain to check. Defaults to the shared domain.

Response

200 Availability of the address (application/json)

Field Type Description
available boolean required
email string required The address that was checked (lowercased).
reason "invalid_username" | "domain_not_found" | "taken" Why the address is not available.
message string Human-readable reason.

Errors

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/inboxes/availability" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "available": false,
  "email": "agent@machinemail.dev",
  "reason": "invalid_username",
  "message": "string"
}

Search Inboxes

GET /v0/inboxes/search

Inboxes whose address or display name contains q (case-insensitive), newest first. Searches the newest 500 inboxes in scope; the response has truncated: true when there were more. Not ranked by relevance.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Query parameters

Field Type Description
q string required Text to find in the address or display name (case-insensitive substring). (min length 1)
limit integer Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_token string next_page_token from the previous page.

Response

200 A page of matching inboxes (application/json)

Field Type Description
count integer required Number of items returned.
limit integer Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_token string Page token for pagination. Absent on the last page.
inboxes Inbox[] required Matching inboxes, newest first.
truncated true Present when the organization has more than 500 inboxes in scope: only the newest 500 were searched.

Each item of inboxes is a Inbox:

Errors

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/inboxes/search?q=invoice" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"

Get Inbox

GET /v0/inboxes/{inbox_id}

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Path parameters

Field Type Description
inbox_id string required ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Response

200 The inbox (application/json)

Errors

Status Meaning
401 Missing, invalid, expired or revoked credential.
403 The credential lacks the permission or scope for this request (error.type forbidden), or MachineMail suspended the organization or its sending (account_suspended: error.message says what still works; do not retry or re-register).
404 Not found. Also returned for resources outside the credential scope.
500 Unexpected server error.

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"

Update Inbox

PATCH /v0/inboxes/{inbox_id}

Fields you omit are unchanged. To pause an inbox, set status to paused; set it back to active to resume.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_update.

Path parameters

Request body

Content type: application/json.

Field Type Description
display_name string Display name: Display Name username@domain.com.
status "active" | "paused" Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox is paused), and incoming mail is not stored; a message.rejected event with reason inbox_paused is emitted instead. Mail already in the inbox, its drafts and its API keys are kept. Set active to resume.
metadata (Record<string, string | number | boolean | null>) | null Merged into the existing metadata: keys you send are added or overwritten, keys set to null are removed, other keys are kept. null clears all metadata.
ttl_seconds integer | null Make the inbox ephemeral with this TTL (expires_at restarts from now), or null to make it permanent.
ephemeral boolean false makes the inbox permanent (same as ttl_seconds: null). true alone has no effect; send ttl_seconds.

Response

200 The updated inbox (application/json)

Errors

Error bodies use the error envelope.

Example

curl -X PATCH "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "display_name": "Support Agent"
}'

Delete Inbox

DELETE /v0/inboxes/{inbox_id}

Deletes the inbox with its messages, attachments, threads and drafts. Inbox-scoped credentials cannot delete their own inbox (403).

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_delete.

Path parameters

Response

200 Deleted (application/json)

Field Type Description
ok true required

Errors

Error bodies use the error envelope.

Example

curl -X DELETE "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "ok": true
}

List Inboxes in Pod

GET /v0/pods/{pod_id}/inboxes

Same as List Inboxes (GET /v0/inboxes), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Path parameters

Field Type Description
pod_id string required ID of the pod.

Query parameters

Response

200 A page of inboxes (application/json)

Each item of inboxes is a Inbox:

Errors

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"

Create Inbox in Pod

POST /v0/pods/{pod_id}/inboxes

Same as Create Inbox (POST /v0/inboxes), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_create.

Path parameters

Field Type Description
pod_id string required ID of the pod.

Request body

Content type: application/json.

Response

200 An inbox with this client_id already exists; it is returned unchanged. (application/json)

201 Created (application/json)

Errors

Error bodies use the error envelope.

Example

curl -X POST "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "username": "agent",
  "display_name": "Support Agent"
}'

Check Inbox Availability in Pod

GET /v0/pods/{pod_id}/inboxes/availability

Same as Check Inbox Availability (GET /v0/inboxes/availability), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Path parameters

Field Type Description
pod_id string required ID of the pod.

Query parameters

Response

200 Availability of the address (application/json)

Errors

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/availability" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "available": false,
  "email": "agent@machinemail.dev",
  "reason": "invalid_username",
  "message": "string"
}

Search Inboxes in Pod

GET /v0/pods/{pod_id}/inboxes/search

Same as Search Inboxes (GET /v0/inboxes/search), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Path parameters

Field Type Description
pod_id string required ID of the pod.

Query parameters

Response

200 A page of matching inboxes (application/json)

Each item of inboxes is a Inbox:

Errors

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/search?q=invoice" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"

Get Inbox in Pod

GET /v0/pods/{pod_id}/inboxes/{inbox_id}

Same as Get Inbox (GET /v0/inboxes/{inbox_id}), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_read.

Path parameters

Field Type Description
pod_id string required ID of the pod.
inbox_id string required ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Response

200 The inbox (application/json)

Errors

Error bodies use the error envelope.

Example

curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"

Update Inbox in Pod

PATCH /v0/pods/{pod_id}/inboxes/{inbox_id}

Same as Update Inbox (PATCH /v0/inboxes/{inbox_id}), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_update.

Path parameters

Request body

Content type: application/json.

Response

200 The updated inbox (application/json)

Errors

Error bodies use the error envelope.

Example

curl -X PATCH "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "display_name": "Support Agent"
}'

Delete Inbox in Pod

DELETE /v0/pods/{pod_id}/inboxes/{inbox_id}

Same as Delete Inbox (DELETE /v0/inboxes/{inbox_id}), limited to the pod.

Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: inbox_delete.

Path parameters

Response

200 Deleted (application/json)

Field Type Description
ok true required

Errors

Error bodies use the error envelope.

Example

curl -X DELETE "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
  "ok": true
}