Skip to content
machinemail

Inboxes

Inboxes. inbox_id is the email address.

MethodPathSummary
GET/v0/inboxesList Inboxes
POST/v0/inboxesCreate Inbox
GET/v0/inboxes/availabilityCheck Inbox Availability
GET/v0/inboxes/searchSearch 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}/inboxesList Inboxes in Pod
POST/v0/pods/{pod_id}/inboxesCreate Inbox in Pod
GET/v0/pods/{pod_id}/inboxes/availabilityCheck Inbox Availability in Pod
GET/v0/pods/{pod_id}/inboxes/searchSearch 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

http
GET /v0/inboxes

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

Query parameters

limitinteger
Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_tokenstring
next_page_token from the previous page.
ascendingboolean
Sort oldest first.
ephemeralboolean
Only ephemeral (true) or only permanent (false) inboxes.

Response

200 A page of inboxes (application/json)

countintegerRequired
Number of items returned.
limitinteger
Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_tokenstring
Page token for pagination. Absent on the last page.
inboxesInbox[]Required
Ordered by created_at, newest first unless ascending is set.

Each item of inboxes is a Inbox:

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
curl "https://api.machinemail.dev/v0/inboxes" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response 200
{
  "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

http
POST /v0/inboxes

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

An organization can have at most 1000 inboxes on the shared domain (deployment setting); past that the API returns 403. Inbox-scoped credentials cannot create inboxes (403).

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

Request body

Content type: application/json.

usernamestring
Local part of the address: a-z, 0-9 and . _ + -, 1 to 64 characters. Randomly generated if omitted.
domainstring
Domain of the address: a domain verified by this organization. Defaults to the shared domain.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
Idempotency key: a create with a client_id already used in the organization returns that inbox with 200.
status"active" | "paused"
Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
pod_idstring
Pod to create the inbox in. Defaults to the credential pod or the organization default pod.
ephemeralboolean
true without ttl_seconds creates an ephemeral inbox with a one hour TTL (3600 seconds).
ttl_secondsinteger | null
Creates an ephemeral inbox that expires ttl_seconds after creation, extended by each inbound message.

Response

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

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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.

201 Created (application/json)

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
409Conflicts with an existing resource.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
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"
}'
Response 200
{
  "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

http
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

usernamestring
Local part to check.
domainstring
Domain to check. Defaults to the shared domain.

Response

200 Availability of the address (application/json)

availablebooleanRequired
emailstringRequired
The address that was checked (lowercased).
reason"invalid_username" | "domain_not_found" | "taken"
Why the address is not available.
messagestring
Human-readable reason.

Errors

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
500Unexpected server error.

Error bodies use the error envelope.

Example

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

Search Inboxes

http
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

qstringRequired
Text to find in the address or display name (case-insensitive substring). (min length 1)
limitinteger
Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_tokenstring
next_page_token from the previous page.

Response

200 A page of matching inboxes (application/json)

countintegerRequired
Number of items returned.
limitinteger
Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_tokenstring
Page token for pagination. Absent on the last page.
inboxesInbox[]Required
Matching inboxes, newest first.
truncatedtrue
Present when the organization has more than 500 inboxes in scope: only the newest 500 were searched.

Each item of inboxes is a Inbox:

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
curl "https://api.machinemail.dev/v0/inboxes/search?q=invoice" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response 200
{
  "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"
    }
  ],
  "truncated": true
}

Get Inbox

http
GET /v0/inboxes/{inbox_id}

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

Path parameters

inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Response

200 The inbox (application/json)

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
curl "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response 200
{
  "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"
}

Update Inbox

http
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

inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Request body

Content type: application/json.

display_namestring
Display name: Display Name <username@domain.com>.
status"active" | "paused"
Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox <inbox_id> 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_secondsinteger | null
Make the inbox ephemeral with this TTL (expires_at restarts from now), or null to make it permanent.
ephemeralboolean
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)

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
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"
}'
Response 200
{
  "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"
}

Delete Inbox

http
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

inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Response

200 Deleted (application/json)

oktrueRequired

Errors

StatusMeaning
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

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

List Inboxes in Pod

http
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

pod_idstringRequired
ID of the pod.

Query parameters

limitinteger
Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_tokenstring
next_page_token from the previous page.
ascendingboolean
Sort oldest first.
ephemeralboolean
Only ephemeral (true) or only permanent (false) inboxes.

Response

200 A page of inboxes (application/json)

countintegerRequired
Number of items returned.
limitinteger
Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_tokenstring
Page token for pagination. Absent on the last page.
inboxesInbox[]Required
Ordered by created_at, newest first unless ascending is set.

Each item of inboxes is a Inbox:

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response 200
{
  "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 in Pod

http
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

pod_idstringRequired
ID of the pod.

Request body

Content type: application/json.

usernamestring
Local part of the address: a-z, 0-9 and . _ + -, 1 to 64 characters. Randomly generated if omitted.
domainstring
Domain of the address: a domain verified by this organization. Defaults to the shared domain.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
Idempotency key: a create with a client_id already used in the organization returns that inbox with 200.
status"active" | "paused"
Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
pod_idstring
Pod to create the inbox in. Defaults to the credential pod or the organization default pod.
ephemeralboolean
true without ttl_seconds creates an ephemeral inbox with a one hour TTL (3600 seconds).
ttl_secondsinteger | null
Creates an ephemeral inbox that expires ttl_seconds after creation, extended by each inbound message.

Response

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

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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.

201 Created (application/json)

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
409Conflicts with an existing resource.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
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"
}'
Response 200
{
  "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 in Pod

http
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

pod_idstringRequired
ID of the pod.

Query parameters

usernamestring
Local part to check.
domainstring
Domain to check. Defaults to the shared domain.

Response

200 Availability of the address (application/json)

availablebooleanRequired
emailstringRequired
The address that was checked (lowercased).
reason"invalid_username" | "domain_not_found" | "taken"
Why the address is not available.
messagestring
Human-readable reason.

Errors

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

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

Search Inboxes in Pod

http
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

pod_idstringRequired
ID of the pod.

Query parameters

qstringRequired
Text to find in the address or display name (case-insensitive substring). (min length 1)
limitinteger
Maximum number of items to return. Default 50, maximum 500; larger values are capped.
page_tokenstring
next_page_token from the previous page.

Response

200 A page of matching inboxes (application/json)

countintegerRequired
Number of items returned.
limitinteger
Maximum number of items per page. Default 50, maximum 500; larger values are capped.
next_page_tokenstring
Page token for pagination. Absent on the last page.
inboxesInbox[]Required
Matching inboxes, newest first.
truncatedtrue
Present when the organization has more than 500 inboxes in scope: only the newest 500 were searched.

Each item of inboxes is a Inbox:

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/search?q=invoice" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response 200
{
  "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"
    }
  ],
  "truncated": true
}

Get Inbox in Pod

http
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

pod_idstringRequired
ID of the pod.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Response

200 The inbox (application/json)

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/inboxes/agent@machinemail.dev" \
  -H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Response 200
{
  "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"
}

Update Inbox in Pod

http
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

pod_idstringRequired
ID of the pod.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Request body

Content type: application/json.

display_namestring
Display name: Display Name <username@domain.com>.
status"active" | "paused"
Whether the inbox sends and receives mail. paused stops both: sends return 403 (Inbox <inbox_id> 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_secondsinteger | null
Make the inbox ephemeral with this TTL (expires_at restarts from now), or null to make it permanent.
ephemeralboolean
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)

pod_idstringRequired
ID of the pod the inbox belongs to.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).
emailstringRequired
Email address of the inbox.
display_namestring
Display name: Display Name <username@domain.com>.
client_idstring
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 <inbox_id> 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.
metadataRecord<string, string | number | boolean>
Custom key-value pairs attached to the inbox.
updated_atstring (date-time)Required
Time at which the inbox was last updated.
created_atstring (date-time)Required
Time at which the inbox was created.
organization_idstringRequired
ID of the organization.
ephemeralbooleanRequired
Whether the inbox expires (see ttl_seconds).
ttl_secondsinteger
TTL of an ephemeral inbox. Each inbound message pushes expires_at to now + ttl_seconds.
expires_atstring (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

StatusMeaning
400Invalid request: error.type is validation and error.param names the field.
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

Request
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"
}'
Response 200
{
  "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"
}

Delete Inbox in Pod

http
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

pod_idstringRequired
ID of the pod.
inbox_idstringRequired
ID of the inbox: its email address, as in AgentMail (inbox_id == email).

Response

200 Deleted (application/json)

oktrueRequired

Errors

StatusMeaning
401Missing, invalid, expired or revoked credential.
403The 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).
404Not found. Also returned for resources outside the credential scope.
500Unexpected server error.

Error bodies use the error envelope.

Example

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