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 create_inbox or create_domain) 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
read_inboxRead inbox details
create_inboxCreate new inboxes
update_inboxUpdate inbox settings
delete_inboxDelete inboxes

Threads

PermissionDescription
read_threadRead threads
delete_threadDelete threads

Messages

PermissionDescription
read_messageRead messages
send_messageSend messages
update_messageUpdate message labels

Content Filtering

PermissionDescription
read_spamAccess messages labeled as spam
read_blockedAccess messages labeled as blocked
read_trashAccess messages labeled as trash

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

Drafts

PermissionDescription
read_draftRead drafts
create_draftCreate drafts
update_draftUpdate drafts
delete_draftDelete drafts
send_draftSend drafts

Webhooks

PermissionDescription
read_webhookRead webhook configurations
create_webhookCreate webhooks
update_webhookUpdate webhooks
delete_webhookDelete webhooks

Domains

PermissionDescription
read_domainRead domain details
create_domainCreate domains
update_domainUpdate domains
delete_domainDelete domains

Lists

PermissionDescription
read_list_entryRead list entries
create_list_entryCreate list entries
delete_list_entryDelete list entries

Metrics

PermissionDescription
read_metricsRead metrics

API Keys

PermissionDescription
read_api_keyRead API keys
create_api_keyCreate API keys
delete_api_keyDelete API keys

Pods

PermissionDescription
read_podRead pods
create_podCreate pods
delete_podDelete 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 "read_inbox": True,
9 "read_thread": True,
10 "read_message": True,
11 "read_draft": True,
12 "read_webhook": True,
13 "read_domain": True,
14 "read_list_entry": True,
15 "read_metrics": True,
16 "read_api_key": True,
17 "read_pod": True,
18 "read_spam": True,
19 "read_blocked": True,
20 "read_trash": 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 "read_inbox": True,
5 "create_inbox": True,
6 "update_inbox": True,
7 "delete_inbox": True,
8 "read_thread": True,
9 "delete_thread": True,
10 "read_message": True,
11 "send_message": True,
12 "update_message": True,
13 "read_spam": False,
14 "read_blocked": False,
15 "read_trash": False,
16 "read_draft": True,
17 "create_draft": True,
18 "update_draft": True,
19 "delete_draft": True,
20 "send_draft": True,
21 "read_webhook": True,
22 "create_webhook": True,
23 "update_webhook": True,
24 "delete_webhook": True,
25 "read_domain": True,
26 "create_domain": True,
27 "update_domain": True,
28 "delete_domain": True,
29 "read_list_entry": True,
30 "create_list_entry": True,
31 "delete_list_entry": True,
32 "read_metrics": True,
33 "read_api_key": True,
34 "create_api_key": True,
35 "delete_api_key": True,
36 "read_pod": True,
37 "create_pod": True,
38 "delete_pod": 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>):
9 Inboxes: read_inbox, create_inbox, update_inbox, delete_inbox
10 Threads: read_thread, delete_thread
11 Messages: read_message, send_message, update_message
12 Content: read_spam, read_blocked, read_trash (controls label visibility)
13 Drafts: read_draft, create_draft, update_draft, delete_draft, send_draft
14 Webhooks: read_webhook, create_webhook, update_webhook, delete_webhook
15 Domains: read_domain, create_domain, update_domain, delete_domain
16 Lists: read_list_entry, create_list_entry, delete_list_entry
17 Metrics: read_metrics
18 API Keys: read_api_key, create_api_key, delete_api_key
19 Pods: read_pod, create_pod, delete_pod
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={"read_inbox": True, "read_message": True, "read_thread": 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 create_domain or delete_inbox.
  • 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 read_spam, read_blocked, and read_trash to false on agent-facing keys. This prevents agents from seeing or processing unwanted email, keeping their context clean.