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 |
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 |
|
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 |
|
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
}