Error Reference
Standard error response format and common error codes.
Error response format
All errors return a JSON object with an error field:
{
"error": "Human-readable error message",
"upgrade": "POST /v1/billing/upgrade to get a checkout URL"
}The optional upgrade field appears when the error is due to a plan limitation that can be resolved by upgrading.
HTTP status codes
200— Success201— Resource created400— Bad request (invalid input, missing required fields)401— Unauthorized (missing or invalid API key)402— Payment required (monthly inbound limit reached — see below)403— Forbidden (plan limit, scoped key, email not verified)404— Resource not found409— Conflict (duplicate resource)413— Payload too large (file or message size limit)429— Rate limited (daily send limit, monthly send limit, or signup rate limit)500— Internal server error503— Service unavailable (dependency down)
402 INBOUND_LIMIT_EXCEEDED
Returned by GET /v1/mailboxes/:id/messages/:msgId and GET /v1/attachments/:id when the requested resource belongs to a message that was received while the account was over its monthly inbound cap (Free 100 / Developer 2,000 / Growth 20,000 / Scale unlimited). The message is safely persisted — a subsequent upgrade or the monthly reset makes it visible on the list endpoints again.
{
"error": "Monthly inbound limit reached — upgrade to unlock this message",
"code": "INBOUND_LIMIT_EXCEEDED",
"resource": { "type": "message", "id": "b2c3d4e5-..." },
"upgrade": {
"browserUrl": "https://robotomail.com/billing",
"apiEndpoint": { "method": "POST", "path": "/v1/billing/upgrade" },
"hint": "POST /v1/billing/upgrade for a programmatic checkout URL, or visit browserUrl to sign in and upgrade"
},
"resetAt": "2026-05-01T00:00:00.000Z"
}Headers:
Retry-After— seconds until the monthly reset. Long-lived — agents should NOT retry until unlock.X-Robotomail-Retriable: false— this error is non-retriable via backoff; upgrade or wait for the reset.X-Robotomail-Reset-At— matchesresetAtin the body.X-Robotomail-Inbound-Quota— e.g.101/100. Scale accounts are unlimited and never hit this error.X-Robotomail-Inbound-Warning: reached.
List endpoints are unaffected. GET /v1/mailboxes/:id/messages and GET /v1/mailboxes/:id/threads always return 200; they hide over-limit messages from the body and surface the hidden count as metadata.overLimitCount. Use the list envelope to drive your upgrade flow, then re-fetch the single message after the unlock.
Inbound quota headers
Every authenticated JSON response (2xx, 4xx, 5xx) carries two headers so you can surface the account's inbound usage without a dedicated lookup. They are absent on the public /v1/signup routes, unauthenticated 401 responses, and SSE streams (which carry the same data inline at data.account.inbound_usage).
X-Robotomail-Inbound-Quota—<count>/<limit>, e.g.57/100. Renders as<count>/unlimitedfor Scale.X-Robotomail-Inbound-Warning—approaching(≥ 50 %),near(≥ 80 %),reached(≥ 100 %). Absent below 50 % and on unlimited tiers.
Common error scenarios
Rate limiting (429)
{
"error": "Daily send limit reached",
"upgrade": "POST /v1/billing/upgrade to get a checkout URL"
}For send limits, check dailySendCount on the mailbox object or sentToday / sentThisMonth via GET /v1/account to monitor daily and monthly usage.
{
"error": "Monthly send limit reached",
"upgrade": "POST /v1/billing/upgrade to get a checkout URL"
}Plan limits (403)
{
"error": "Free plan limited to 3 mailboxes. Upgrade to create more.",
"upgrade": "POST /v1/billing/upgrade to get a checkout URL"
}Suppressed address (400)
{
"error": "Recipient address is on the suppression list: invalid@example.com"
}Remove the address from the suppression list if you believe it's now valid.