Permissions

Control what your API keys can access with granular permissions.

What are Permissions?

Permissions let you restrict what an API key can do. By default, an API key has full access within its scope (organization, pod, or inbox). When you provide a permissions object, it acts as a whitelist: only the permissions you explicitly set to true are granted. Everything else is denied.

This gives you fine-grained control over which resources and operations each key can access, on top of the existing scope-based isolation provided by pod-scoped and inbox-scoped keys.

How Permissions Work

Whitelist model

When you create an API key with a permissions object, it switches from “full access” mode to “whitelist” mode:

  • No permissions field: The key has full access within its scope. This is the default and is backward compatible with existing keys.
  • permissions present: Only permissions set to true are allowed. Any permission that is omitted or set to false is denied.
Backward compatibility

Existing API keys without a permissions field continue to work exactly as before with full access. The whitelist only activates when you explicitly provide the permissions object.

Intersection with scope

Permissions are intersected with the key’s scope. A key scoped to a single inbox cannot gain organization-level capabilities (like inbox_create or domain_create) even if those permissions are set to true. The effective permissions are always the intersection of what the scope allows and what the permissions object grants.

Privilege escalation protection

A restricted API key cannot create a child key with more permissions than itself. When creating a new key, the child’s permissions are automatically constrained to the parent’s effective permissions. This prevents privilege escalation through key creation.

Permissions Reference

Inboxes

PermissionDescription
inbox_readRead inbox details
inbox_createCreate new inboxes
inbox_updateUpdate inbox settings
inbox_deleteDelete inboxes

Threads

PermissionDescription
thread_readRead threads
thread_deleteDelete threads

Messages

PermissionDescription
message_readRead messages
message_sendSend messages
message_updateUpdate message labels

Label Visibility

PermissionDescription
label_spam_readAccess messages labeled as spam
label_blocked_readAccess messages labeled as blocked
label_trash_readAccess messages labeled as trash

When a label visibility permission is denied, items with that label are automatically excluded from list results and return “not found” on direct access. For example, setting label_spam_read to false means the key will never see spam messages in any listing or lookup.

Event subscriptions

Label visibility permissions also control whether an API key can subscribe to the corresponding event types on webhooks and WebSockets. An API key without label_spam_read cannot create a webhook or WebSocket subscription for message.received.spam events, and an API key without label_blocked_read cannot subscribe to message.received.blocked events.

Drafts

PermissionDescription
draft_readRead drafts
draft_createCreate drafts
draft_updateUpdate drafts
draft_deleteDelete drafts
draft_sendSend drafts

Webhooks

PermissionDescription
webhook_readRead webhook configurations
webhook_createCreate webhooks
webhook_updateUpdate webhooks
webhook_deleteDelete webhooks

Domains

PermissionDescription
domain_readRead domain details
domain_createCreate domains
domain_updateUpdate domains
domain_deleteDelete domains

Lists

PermissionDescription
list_entry_readRead list entries
list_entry_createCreate list entries
list_entry_deleteDelete list entries

Metrics

PermissionDescription
metrics_readRead metrics

API Keys

PermissionDescription
api_key_readRead API keys
api_key_createCreate API keys
api_key_deleteDelete API keys

Pods

PermissionDescription
pod_readRead pods
pod_createCreate pods
pod_deleteDelete pods

Code Examples

Read-only key

Create an API key that can read all resources but cannot create, update, or delete anything.

1from agentmail import AgentMail
2
3client = AgentMail(api_key="YOUR_API_KEY")
4
5key = client.api_keys.create(
6 name="read-only-agent",
7 permissions={
8 "inbox_read": True,
9 "thread_read": True,
10 "message_read": True,
11 "draft_read": True,
12 "webhook_read": True,
13 "domain_read": True,
14 "list_entry_read": True,
15 "metrics_read": True,
16 "api_key_read": True,
17 "pod_read": True,
18 "label_spam_read": True,
19 "label_blocked_read": True,
20 "label_trash_read": True,
21 }
22)
23
24print(key.api_key)

No-spam key

Create a key with full access but block visibility into spam, blocked, and trash content. This is useful for agent-facing keys where you want to prevent the agent from processing unwanted email.

1key = client.api_keys.create(
2 name="clean-inbox-agent",
3 permissions={
4 "inbox_read": True,
5 "inbox_create": True,
6 "inbox_update": True,
7 "inbox_delete": True,
8 "thread_read": True,
9 "thread_delete": True,
10 "message_read": True,
11 "message_send": True,
12 "message_update": True,
13 "label_spam_read": False,
14 "label_blocked_read": False,
15 "label_trash_read": False,
16 "draft_read": True,
17 "draft_create": True,
18 "draft_update": True,
19 "draft_delete": True,
20 "draft_send": True,
21 "webhook_read": True,
22 "webhook_create": True,
23 "webhook_update": True,
24 "webhook_delete": True,
25 "domain_read": True,
26 "domain_create": True,
27 "domain_update": True,
28 "domain_delete": True,
29 "list_entry_read": True,
30 "list_entry_create": True,
31 "list_entry_delete": True,
32 "metrics_read": True,
33 "api_key_read": True,
34 "api_key_create": True,
35 "api_key_delete": True,
36 "pod_read": True,
37 "pod_create": True,
38 "pod_delete": True,
39 }
40)

Copy for Cursor / Claude

Copy one of the blocks below into Cursor or Claude for complete Permissions API knowledge in one shot.

1"""
2AgentMail Permissions — copy into Cursor/Claude.
3
4Permissions are a whitelist on API keys. No `permissions` field = full access.
5When `permissions` is set, only `True` values are granted; omitted or `False` = denied.
6Permissions intersect with scope (pod/inbox). A restricted key cannot create a more privileged child key.
7
8Permission fields (all optional<bool>, resource_action format):
9 Inboxes: inbox_read, inbox_create, inbox_update, inbox_delete
10 Threads: thread_read, thread_delete
11 Messages: message_read, message_send, message_update
12 Label visibility: label_spam_read, label_blocked_read, label_trash_read
13 Drafts: draft_read, draft_create, draft_update, draft_delete, draft_send
14 Webhooks: webhook_read, webhook_create, webhook_update, webhook_delete
15 Domains: domain_read, domain_create, domain_update, domain_delete
16 Lists: list_entry_read, list_entry_create, list_entry_delete
17 Metrics: metrics_read
18 API Keys: api_key_read, api_key_create, api_key_delete
19 Pods: pod_read, pod_create, pod_delete
20
21API: api_keys.create(name, permissions={...})
22"""
23from agentmail import AgentMail
24
25client = AgentMail(api_key="YOUR_API_KEY")
26
27# read-only key
28key = client.api_keys.create(
29 name="read-only",
30 permissions={"inbox_read": True, "message_read": True, "thread_read": True}
31)
32print(key.api_key)

Best Practices

  • Use the principle of least privilege. Only grant the permissions your agent actually needs. A support agent that reads and replies to emails does not need domain_create or inbox_delete.
  • Combine with scopes for defense in depth. Pair permissions with pod-scoped or inbox-scoped keys. Scopes limit which resources a key can see, while permissions limit what it can do.
  • Filter unwanted content from agents. Set label_spam_read, label_blocked_read, and label_trash_read to false on agent-facing keys. This prevents agents from seeing or processing unwanted email, keeping their context clean.