lists.md
Lists
Allow and block lists for the organization, a pod or an inbox. A non-empty allow list is allow-only: it blocks mail from every sender not on it.
Source: https://machinemail.dev/docs/reference/api/lists
| Method | Path | Summary |
|---|---|---|
GET |
/v0/inboxes/{inbox_id}/lists/{direction}/{type} |
List Entries in Inbox |
POST |
/v0/inboxes/{inbox_id}/lists/{direction}/{type} |
Create List Entry in Inbox |
GET |
/v0/inboxes/{inbox_id}/lists/{direction}/{type}/{entry} |
Get List Entry in Inbox |
DELETE |
/v0/inboxes/{inbox_id}/lists/{direction}/{type}/{entry} |
Delete List Entry in Inbox |
GET |
/v0/lists/{direction}/{type} |
List Entries |
POST |
/v0/lists/{direction}/{type} |
Create List Entry |
GET |
/v0/lists/{direction}/{type}/{entry} |
Get List Entry |
DELETE |
/v0/lists/{direction}/{type}/{entry} |
Delete List Entry |
GET |
/v0/pods/{pod_id}/lists/{direction}/{type} |
List Entries in Pod |
POST |
/v0/pods/{pod_id}/lists/{direction}/{type} |
Create List Entry in Pod |
GET |
/v0/pods/{pod_id}/lists/{direction}/{type}/{entry} |
Get List Entry in Pod |
DELETE |
/v0/pods/{pod_id}/lists/{direction}/{type}/{entry} |
Delete List Entry in Pod |
List Entries in Inbox
GET /v0/inboxes/{inbox_id}/lists/{direction}/{type}
Same as List Entries (GET /v0/lists/{direction}/{type}), limited to the inbox. While any allow entry applies for a direction, every address that matches none is blocked (allow-only).
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_read.
Path parameters
| Field | Type | Description | |
|---|---|---|---|
inbox_id |
string |
required | ID of the inbox. |
direction |
"send" | "receive" | "reply" |
required | receive: who may send to you (inbound mail from a blocked sender is labeled BLOCKED). send: who you may send to (a blocked recipient is a 403). reply entries are stored and listed but not applied to any mail yet. |
type |
"allow" | "block" |
required | block refuses matching addresses. allow makes the list exclusive: once it has an entry, only matching addresses pass. |
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 |
false sorts by entry descending. Default true. |
Response
200 A page of entries (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. | |
entries |
ListEntry[] |
required | Ordered by entry, ascending unless ascending is false. |
Each item of entries is a ListEntry:
| Field | Type | Description | |
|---|---|---|---|
entry |
string |
required | Email address or domain (lowercased). |
organization_id |
string |
required | ID of the organization. |
pod_id |
string |
ID of the pod, for pod-scoped entries. | |
inbox_id |
string |
ID of the inbox, for inbox-scoped entries. | |
reason |
string |
Reason given when the entry was added. | |
direction |
"send" | "receive" | "reply" |
required | receive: who may send to you (inbound mail from a blocked sender is labeled BLOCKED). send: who you may send to (a blocked recipient is a 403). reply entries are stored and listed but not applied to any mail yet. |
list_type |
"allow" | "block" |
required | block refuses matching addresses. allow makes the list exclusive: once it has an entry, only matching addresses pass. |
entry_type |
"email" | "domain" |
required | Whether the entry is an email address or a domain. |
read_only |
boolean |
required | Always false: every entry can be deleted through the API. |
created_at |
string (date-time) |
required | Time at which the entry was created. |
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). |
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/lists/send/allow" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
"count": 1,
"limit": 50,
"next_page_token": "eyJvIjo1MH0",
"entries": [
{
"entry": "customer@example.com",
"organization_id": "org_01k6x2m9qd0000a7h3kq9v2c4e",
"pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
"inbox_id": "agent@machinemail.dev",
"reason": "string",
"direction": "send",
"list_type": "allow",
"entry_type": "email",
"read_only": false,
"created_at": "2026-10-01T12:00:00.000Z"
}
]
}
Create List Entry in Inbox
POST /v0/inboxes/{inbox_id}/lists/{direction}/{type}
Same as Create List Entry (POST /v0/lists/{direction}/{type}), limited to the inbox. A receive/allow entry here makes this scope allow-only: mail from every sender that matches no allow entry is labeled BLOCKED and withheld from agents. An allow-listed sender reaches verified only with an aligned DMARC pass.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_create.
Path parameters
Request body
Content type: application/json.
| Field | Type | Description | |
|---|---|---|---|
entry |
string |
required | Email address or domain to add. (min length 1) |
reason |
string |
Reason for adding the entry. |
Response
200 The entry (application/json)
Errors
Error bodies use the error envelope.
Example
curl -X POST "https://api.machinemail.dev/v0/inboxes/agent@machinemail.dev/lists/send/allow" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entry": "customer@example.com",
"reason": "string"
}'
{
"entry": "customer@example.com",
"organization_id": "org_01k6x2m9qd0000a7h3kq9v2c4e",
"pod_id": "pod_01k6x2m9qd0001b8j4mr0w3d5f",
"inbox_id": "agent@machinemail.dev",
"reason": "string",
"direction": "send",
"list_type": "allow",
"entry_type": "email",
"read_only": false,
"created_at": "2026-10-01T12:00:00.000Z"
}
Get List Entry in Inbox
GET /v0/inboxes/{inbox_id}/lists/{direction}/{type}/{entry}
Same as Get List Entry (GET /v0/lists/{direction}/{type}/{entry}), limited to the inbox.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_read.
Path parameters
Response
200 The entry (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/lists/send/allow/customer@example.com" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Delete List Entry in Inbox
DELETE /v0/inboxes/{inbox_id}/lists/{direction}/{type}/{entry}
Same as Delete List Entry (DELETE /v0/lists/{direction}/{type}/{entry}), limited to the inbox.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_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/lists/send/allow/customer@example.com" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
"ok": true
}
List Entries
GET /v0/lists/{direction}/{type}
Entries stored at this exact level. Mail is checked against the organization, pod and inbox lists together. An allow entry wins over a block entry; while any allow entry exists for a direction, every address that matches none is blocked (allow-only).
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_read.
Path parameters
| Field | Type | Description | |
|---|---|---|---|
direction |
"send" | "receive" | "reply" |
required | receive: who may send to you (inbound mail from a blocked sender is labeled BLOCKED). send: who you may send to (a blocked recipient is a 403). reply entries are stored and listed but not applied to any mail yet. |
type |
"allow" | "block" |
required | block refuses matching addresses. allow makes the list exclusive: once it has an entry, only matching addresses pass. |
Query parameters
Response
200 A page of entries (application/json)
Each item of entries is a ListEntry:
Errors
Error bodies use the error envelope.
Example
curl "https://api.machinemail.dev/v0/lists/send/allow" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Create List Entry
POST /v0/lists/{direction}/{type}
An address (user@example.com) or a domain (example.com); a domain also matches its subdomains. Adding an entry that exists returns it unchanged.
An allow entry makes its scope allow-only. The first receive/allow entry at the organization (/v0/lists), a pod (/v0/pods/{pod_id}/lists) or an inbox (/v0/inboxes/{inbox_id}/lists) blocks every sender that does not match an allow entry: their mail is labeled BLOCKED, emits message.received.blocked and is withheld from agents. Likewise, a send/allow entry blocks sending to every other recipient. An allow-listed sender reaches trust level verified only when DMARC passes and is aligned; do not add one only to raise trust. Prior correspondence (an inbox in the organization has written to the sender) is the usual way to reach verified.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_create.
Path parameters
Request body
Content type: application/json.
Response
200 The entry (application/json)
Errors
Error bodies use the error envelope.
Example
curl -X POST "https://api.machinemail.dev/v0/lists/send/allow" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entry": "customer@example.com",
"reason": "string"
}'
Get List Entry
GET /v0/lists/{direction}/{type}/{entry}
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_read.
Path parameters
Response
200 The entry (application/json)
Errors
Error bodies use the error envelope.
Example
curl "https://api.machinemail.dev/v0/lists/send/allow/customer@example.com" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Delete List Entry
DELETE /v0/lists/{direction}/{type}/{entry}
Deleting the last allow entry for a direction at every level that applies ends allow-only mode: unmatched addresses are allowed again unless a block entry matches.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_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/lists/send/allow/customer@example.com" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
"ok": true
}
List Entries in Pod
GET /v0/pods/{pod_id}/lists/{direction}/{type}
Same as List Entries (GET /v0/lists/{direction}/{type}), limited to the pod. While any allow entry applies for a direction, every address that matches none is blocked (allow-only).
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_read.
Path parameters
| Field | Type | Description | |
|---|---|---|---|
pod_id |
string |
required | ID of the pod. |
direction |
"send" | "receive" | "reply" |
required | receive: who may send to you (inbound mail from a blocked sender is labeled BLOCKED). send: who you may send to (a blocked recipient is a 403). reply entries are stored and listed but not applied to any mail yet. |
type |
"allow" | "block" |
required | block refuses matching addresses. allow makes the list exclusive: once it has an entry, only matching addresses pass. |
Query parameters
Response
200 A page of entries (application/json)
Each item of entries is a ListEntry:
Errors
Error bodies use the error envelope.
Example
curl "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/lists/send/allow" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
Create List Entry in Pod
POST /v0/pods/{pod_id}/lists/{direction}/{type}
Same as Create List Entry (POST /v0/lists/{direction}/{type}), limited to the pod. A receive/allow entry here makes this scope allow-only: mail from every sender that matches no allow entry is labeled BLOCKED and withheld from agents. An allow-listed sender reaches verified only with an aligned DMARC pass.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_create.
Path parameters
Request body
Content type: application/json.
Response
200 The entry (application/json)
Errors
Error bodies use the error envelope.
Example
curl -X POST "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/lists/send/allow" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entry": "customer@example.com",
"reason": "string"
}'
Get List Entry in Pod
GET /v0/pods/{pod_id}/lists/{direction}/{type}/{entry}
Same as Get List Entry (GET /v0/lists/{direction}/{type}/{entry}), limited to the pod.
Authentication: Authorization: Bearer <api key> or the dashboard mm_session cookie. Permission: list_entry_read.
Path parameters
Response
200 The entry (application/json)
Errors
Error bodies use the error envelope.
Example
curl -X DELETE "https://api.machinemail.dev/v0/pods/pod_01k6x2m9qd0001b8j4mr0w3d5f/lists/send/allow/customer@example.com" \
-H "Authorization: Bearer $MACHINEMAIL_API_KEY"
{
"ok": true
}