InboxSpec error reference

Every failure from every surface — REST, MCP, the CLI — carries the same envelope with a stable code. Branch on code and retryable. Never on the HTTP status, and never on the message text. An empty result set is never an error, and a wait timeout is an HTTP 200 with status: "timeout".

CodeHTTPRetryableMeans
unauthenticated 401 no No Authorization header reached us.
invalid_api_key 401 no The key does not exist, or has been revoked.
insufficient_scope 403 no The key is valid but lacks the scope this route needs.
forbidden 403 no Region mismatch, or a bad or expired download signature.
inbox_not_found 404 no No inbox at that id or address, for this project.
message_not_found 404 no Unknown, expired, or erased.
attachment_not_found 404 no No attachment with that id on that message.
domain_not_found 404 no No such domain on this project.
domain_not_verified 409 yes The domain exists but its DNS is not satisfied yet.
project_not_found 404 no The project behind this key or resource is gone.
webhook_not_found 404 no No webhook endpoint with that id on this project.
article_not_found 404 no No published blog article has that slug.
invalid_request 400 no The request could not be interpreted.
unsupported_format 400 no This message has no part in the format you asked for.
payload_too_large 413 no Over a hard size limit.
conflict 409 no Already claimed, or already in that state.
quota_exceeded 402 no The period allowance is spent, and this read was refused.
organisation_limit_exceeded 402 yes An organisation plan, spend or byte limit prevents this operation.
rate_limited 429 yes Too many requests per second on this route class.
concurrency_limit 429 yes Too many blocking waits in flight for this project.
blocked_recipient 403 no The recipient is on the abuse blocklist.
abuse_suspended 403 no The organisation is suspended.
ingest_ceiling_exceeded 429 yes The project's ingest ceiling for the period is reached, so this delivery was refused at SMTP with a transient 452 4.3.1.
storage_unavailable 503 yes The object store could not be read or written.
internal 500 yes An unexpected failure, wrapped so that it still carries a code.

unauthenticated

HTTP 401 · not retryable

No Authorization header reached us.

Do: Send Authorization: Bearer is_live_… or is_test_…. Raised before anything else, so it tells you nothing about whether the resource exists.

invalid_api_key

HTTP 401 · not retryable

The key does not exist, or has been revoked.

Do: Check for a truncated paste, then mint a new key.

insufficient_scope

HTTP 403 · not retryable

The key is valid but lacks the scope this route needs.

Do: Read details.required_scope and mint a key carrying it.

forbidden

HTTP 403 · not retryable

Region mismatch, or a bad or expired download signature.

Do: Call the region named in details.project_region, or re-fetch the presigned URL.

inbox_not_found

HTTP 404 · not retryable

No inbox at that id or address, for this project.

Do: Create it with inboxes.create, or fix the address. Never treat this as "no mail yet" — an empty result set is what that looks like.

message_not_found

HTTP 404 · not retryable

Unknown, expired, or erased.

Do: Messages are deleted at the inbox TTL. Check GET /v1/retention.

attachment_not_found

HTTP 404 · not retryable

No attachment with that id on that message.

Do: Use an id from the message's attachments[].

domain_not_found

HTTP 404 · not retryable

No such domain on this project.

Do: Add it with POST /v1/domains. Another project's domain reports this same code.

domain_not_verified

HTTP 409 · retryable

The domain exists but its DNS is not satisfied yet.

Do: Publish the records from domains.get, call domains.verify, and retry after about 60s.

project_not_found

HTTP 404 · not retryable

The project behind this key or resource is gone.

Do: An internal-consistency failure. Re-resolve the project.

webhook_not_found

HTTP 404 · not retryable

No webhook endpoint with that id on this project.

Do: List this project's endpoints and use an id you own. Another project's reports this same code.

article_not_found

HTTP 404 · not retryable

No published blog article has that slug.

Do: Browse /blog or list articles through /content/v1/articles for a current URL.

invalid_request

HTTP 400 · not retryable

The request could not be interpreted.

Do: Read details. Never retry unchanged.

unsupported_format

HTTP 400 · not retryable

This message has no part in the format you asked for.

Do: details.available lists the parts it does have.

payload_too_large

HTTP 413 · not retryable

Over a hard size limit.

Do: Not raisable by making the same call again. Send less.

conflict

HTTP 409 · not retryable

Already claimed, or already in that state.

Do: Read the current state first. Domain names are globally unique here.

quota_exceeded

HTTP 402 · not retryable

The period allowance is spent, and this read was refused.

Do: Inbound mail is still accepted and stored; only the read failed. Raise the plan limit, or wait for retry_after_seconds.

organisation_limit_exceeded

HTTP 402 · retryable

An organisation plan, spend or byte limit prevents this operation.

Do: Read details.limit_kind and the remedy. An owner can review the plan or budget; accepted mail remains until normal expiry. Sender retries can expire while ingestion is paused.

rate_limited

HTTP 429 · retryable

Too many requests per second on this route class.

Do: Honour retry_after_seconds. If you were polling, replace the loop with messages.wait, which is never rate limited.

concurrency_limit

HTTP 429 · retryable

Too many blocking waits in flight for this project.

Do: Let one finish, or raise max_concurrent_waits.

blocked_recipient

HTTP 403 · not retryable

The recipient is on the abuse blocklist.

Do: Not fixable from the API. Contact the abuse address.

abuse_suspended

HTTP 403 · not retryable

The organisation is suspended.

Do: Contact support. Every request fails until it is lifted.

ingest_ceiling_exceeded

HTTP 429 · retryable

The project's ingest ceiling for the period is reached, so this delivery was refused at SMTP with a transient 452 4.3.1.

Do: Nothing was stored and the sender was told to retry, so honest mail is not lost. If this project is not expected to be this busy, treat its SMTP credential as leaked and rotate it before raising the ceiling.

storage_unavailable

HTTP 503 · retryable

The object store could not be read or written.

Do: Ours. Retry with backoff.

internal

HTTP 500 · retryable

An unexpected failure, wrapped so that it still carries a code.

Do: Ours. Retry, and quote the x-request-id response header.