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

Permission Description
inbox_read Read inbox details
inbox_create Create new inboxes
inbox_update Update inbox settings
inbox_delete Delete inboxes

Threads

Permission Description
thread_read Read threads
thread_delete Delete threads

Messages

Permission Description
message_read Read messages
message_send Send messages
message_update Update message labels

Label Visibility

Permission Description
label_spam_read Access messages labeled as spam
label_blocked_read Access messages labeled as blocked
label_trash_read Access 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

Permission Description
draft_read Read drafts
draft_create Create drafts
draft_update Update drafts
draft_delete Delete drafts
draft_send Send drafts

Webhooks

Permission Description
webhook_read Read webhook configurations
webhook_create Create webhooks
webhook_update Update webhooks
webhook_delete Delete webhooks

Domains

Permission Description
domain_read Read domain details
domain_create Create domains
domain_update Update domains
domain_delete Delete domains

Lists

Permission Description
list_entry_read Read list entries
list_entry_create Create list entries
list_entry_delete Delete list entries

Metrics

Permission Description
metrics_read Read metrics

API Keys

Permission Description
api_key_read Read API keys
api_key_create Create API keys
api_key_delete Delete API keys

Pods

Permission Description
pod_read Read pods
pod_create Create pods
pod_delete Delete pods

Code Examples

Read-only key

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

PythonTypeScriptCLI

from agentmail import AgentMail

client = AgentMail(api_key="YOUR_API_KEY")

key = client.api_keys.create(
    name="read-only-agent",
    permissions={
        "inbox_read": True,
        "thread_read": True,
        "message_read": True,
        "draft_read": True,
        "webhook_read": True,
        "domain_read": True,
        "list_entry_read": True,
        "metrics_read": True,
        "api_key_read": True,
        "pod_read": True,
        "label_spam_read": True,
        "label_blocked_read": True,
        "label_trash_read": True,
    }
)

print(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.

PythonTypeScriptCLI

key = client.api_keys.create(
    name="clean-inbox-agent",
    permissions={
        "inbox_read": True,
        "inbox_create": True,
        "inbox_update": True,
        "inbox_delete": True,
        "thread_read": True,
        "thread_delete": True,
        "message_read": True,
        "message_send": True,
        "message_update": True,
        "label_spam_read": False,
        "label_blocked_read": False,
        "label_trash_read": False,
        "draft_read": True,
        "draft_create": True,
        "draft_update": True,
        "draft_delete": True,
        "draft_send": True,
        "webhook_read": True,
        "webhook_create": True,
        "webhook_update": True,
        "webhook_delete": True,
        "domain_read": True,
        "domain_create": True,
        "domain_update": True,
        "domain_delete": True,
        "list_entry_read": True,
        "list_entry_create": True,
        "list_entry_delete": True,
        "metrics_read": True,
        "api_key_read": True,
        "api_key_create": True,
        "api_key_delete": True,
        "pod_read": True,
        "pod_create": True,
        "pod_delete": True,
    }
)

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.