Skip to main content
Every error under /api/v1 uses the same envelope:
Branch on type, never on message. Types are a stable contract; messages get reworded whenever we find a clearer way to say something, and that is not treated as a breaking change.

Error types

Three of these are 429s and they mean genuinely different things, so it is worth handling them separately:
  • rate_limited — slow down. retry-after tells you by how much.
  • quota_exceeded — you are done for the day. Backing off will not help.
  • too_many_waiters — you are at your concurrency cap, not your rate limit. Your request rate is fine; you just have 5 long-polls already open. Lower your test parallelism or use more keys.
not_found on an email you just read is normal, not a bug. Mail is deleted about an hour after arrival, and the API does not distinguish “never existed” from “expired” — doing so would leak whether an address had received mail.

404s on unknown paths

Every unmatched path under /api/v1 returns this same envelope rather than a framework error page, so you never need a second parser for our errors:
If a path contains an empty segment — /api/v1/inboxes//emails, which usually means a variable in your request was empty — the message says so explicitly instead of leaving you to spot the double slash.