Error Reference

Every error response from the AgentMail API includes a stable, machine-readable code you can branch on, a message describing what went wrong, and a docs link pointing to the matching entry on this page. Most responses also include a fix describing the concrete next action that resolves it; fix is omitted when no generic remedy applies.

1{
2 "name": "ForbiddenError",
3 "code": "missing_permission",
4 "message": "Forbidden",
5 "fix": "This API key does not have the 'message_send' permission. Retry with an API key that includes 'message_send' — note a key cannot create a new key with permissions it lacks itself, so the new key must come from a credential that already holds 'message_send' (an unrestricted key via POST /v0/api-keys, or the console at https://console.agentmail.to). If no such key exists, the permission may be outside your credential's scope — use a key with a broader scope (organization-scoped keys hold the widest permissions).",
6 "docs": "https://docs.agentmail.to/errors#missing_permission"
7}

Branch on code, not on name or message: the name and message fields keep their long-standing pre-code values for backward compatibility (a permission denial still reads Forbidden), so they neither identify the specific cause nor carry the remedy — code and fix do.

Authentication (401)

missing_authorization

The Authorization header was missing, did not use the required case-sensitive Bearer scheme, used the scheme correctly but carried no key value after Bearer , or carried whitespace inside the key value (no credential contains whitespace) — the message states which. Send your API key as Authorization: Bearer <api_key>. Create a key at console.agentmail.to or via POST /v0/api-keys.

invalid_token_type

The endpoint requires an API key, but the request carried a console session token (JWT). Authenticate with an API key instead: keys start with am_. Create one at console.agentmail.to or via POST /v0/api-keys.

unknown_api_key

The API key was not recognized. Confirm you copied the full value (keys start with am_) and that the key has not been revoked. Create a new key at console.agentmail.to or via POST /v0/api-keys.

unauthorized

Generic authentication failure. Send a valid API key in the Authorization: Bearer <api_key> header. Create or rotate keys at console.agentmail.to or via POST /v0/api-keys.

Authorization (403)

missing_permission

The credential lacks a specific required permission (for example message_send). For backward compatibility the message stays Forbidden (event-type permission checks on webhooks and WebSocket subscriptions keep their own legacy form, <permission> is forbidden); the missing permission is named in the fix. The fix also names the remedy for the actual cause: a restricted key may need the permission granted (retry with a key that includes it, or create one via POST /v0/api-keys from a credential that already holds it — a key cannot grant a permission it lacks), while other denials come from the credential’s scope or the organization’s state, where creating another key at the same scope cannot help — for example organization_read requires an organization-scoped key, some permissions (like creating API keys or send-list entries) require completing agent verification via POST /v0/agent/verify first, and agent_verify itself is only available while an unverified agent organization still needs verification.

permission_escalation

A create or update API key request asked for a permission the calling key does not hold itself. A key cannot grant more than it has. Remove the extra permissions from the request, or retry with a key that already holds them.

unrestricted_key_required

Creating an unrestricted child key (permissions: null), clearing a key’s permissions, or changing the permissions of a currently-unrestricted key requires an unrestricted credential: a dashboard session or an API key stored without a permissions attribute. Retry with one; the fix on the response says which gate fired.

forbidden

The authenticated API key is not allowed to perform this action, usually because of its scope (organization, pod, or inbox). Retry with a key whose scope and permissions cover this resource.

Request errors (400 / 404 / 422)

validation_error

One or more request fields failed validation. Inspect the errors array in the response: each entry has a path and a message identifying the invalid field. Correct the offending fields and resend. Two common cases carry field-specific messages: an invalid page_token (restart pagination by omitting page_token, then follow next_page_token) and a malformed Idempotency-Key header.

not_found

No resource with the given identifier is visible to this credential. That can mean the ID is wrong — but the same response also deliberately hides resources outside your credential’s scope (organization, pod, or inbox) and resources behind a restricted-label read permission you lack (spam, blocked, unauthenticated, trash), so a correct ID can still return not_found. Check the ID, your credential’s scope, and your label-read permissions; list endpoints return only the IDs visible to you.

unprocessable

The request was well-formed but cannot be processed as-is (for example, a send with no recipients in to, cc, or bcc). Adjust the request per the message and retry.

query_range_too_wide

A metrics query requested too wide a time range. Narrow the requested time range, or increase the period/bucket size, then retry.

Resource state (403 / 409)

already_exists

A resource with these details already exists. Fetch or update the existing resource instead of creating a duplicate.

resource_taken

The requested value (for example, an inbox username) is already in use. Choose a different value and retry.

limit_exceeded

A resource limit has been reached (for example, the webhook endpoint limit). Remove an existing resource before adding another, or email support@agentmail.to to raise your limit. For agent-verification OTP attempts, the fix distinguishes the two states: while the exhausted code is still live, every submission is rejected (even the correct code) until it expires 24 hours from issue, after which POST /v0/agent/sign-up issues a fresh code with a reset attempt count; if the code has already expired, sign up again immediately.

domain_not_verified

The sending domain has not completed DNS verification. Add the DNS records returned by GET /v0/domains/{domain}, then call POST /v0/domains/{domain}/verify before sending from an address on this domain.

conflict

The request conflicts with another request under the same Idempotency-Key. Either the original send is still in progress — wait briefly and retry the identical request: once the first attempt completes the retry returns its send, and if the first attempt failed without completing, the key becomes retryable again after a short window — or the key was already used for a different message (generate a new key for new messages). See Idempotency.

race_condition

A concurrent modification conflicted with your request. Re-fetch the resource to get its latest state, then retry.

resource_deleting

The resource is currently being deleted and cannot be used. Wait for deletion to finish, or use a different resource.

cannot_delete

The resource cannot be deleted yet, usually because dependent resources still exist. Resolve the blocker described in the message, then retry.

Sending (403)

message_rejected

The message was not sent. The message names the reason, and the fix states which case applies:

  • Recipients on a send block list — remove them from the request, or delete the matched block entry. The fix names the stored entry (which may be a domain rather than the recipient address) and the exact DELETE /v0/…/lists/send/block/{entry} path at the scope where it lives. Deleting an entry at a broader scope than your key (an organization-level block hit by a pod- or inbox-scoped key) requires a key scoped at that level. Read-only entries — added automatically from bounces, complaints, and unsubscribes — cannot be deleted via the API; email support@agentmail.to to have one reviewed.
  • Recipients missing from an active send allow list — add them via POST /v0/lists/send/allow (there is no block entry to delete). On an agent organization that has not completed verification, sending is restricted to the human’s email and list entries cannot be created yet — complete POST /v0/agent/verify instead.
  • A suspended account — email support@agentmail.to; retrying will keep failing until the suspension is resolved.
  • An unfetchable attachment URL — use a URL that returns 200 without authentication, or send the attachment inline as base64.

Transient errors (429 / 500 / 503)

rate_limit_exceeded

You are sending requests too quickly or have hit a usage limit. Honor the Retry-After header when present, and retry with exponential backoff.

service_unavailable

A downstream service is temporarily unavailable. Retry the request after a short delay with exponential backoff.

internal_error

A server-side error, not a problem with your request. Retry with exponential backoff; if it persists, email support@agentmail.to.