Error reference

quota_exceeded

HTTP 402 retryable: false REST and MCP

The workspace holds the entitlement for this action, but the metered allowance behind it has no headroom left for the current period.

Why it happens

Quota is reserved, not counted after the fact. The send path runs a conditional UPDATE that only succeeds while used + reserved + this request stays within allowance + additional_allowance, and the absence of an updated row is what raises this error. That is why two concurrent sends cannot both slip past a check-then-write race: the database decides, atomically, and the loser gets this code. An email unit is one message received or one recipient sent to, so a send to three people consumes three.

Every condition below was read in the implementation at the file and line given. They are the branches that raise this code, not a summary of what the name suggests.

How to fix it

  1. Read GET /billing/entitlement for the remaining allowance rather than inferring it from your own send count. Inbound mail consumes units too.
  2. Count recipients, not messages. One send to three addresses is three units, and the deduplicated union of to, cc and bcc is what gets charged.
  3. Move development traffic to a test project. Test mail is never charged against the allowance.
  4. For an oversized export, narrow it by inbox or by date range. The limits are 500 inboxes and 5,000 messages, and exceeding either produces no partial artefact to salvage.
  5. For export storage, wait for expired exports to be purged automatically, then request again.

Why it works this way

Inbound is not symmetric with outbound here. Provider-accepted mail is committed to the workspace even beyond the allowance rather than being dropped for a billing reason, so exhausting quota stops sending and never discards mail that has already arrived.

Messages you will see

The message field is written for a human reading a log and is not a contract value. Branch on code instead. These are the exact strings this code is sent with today, listed so that a search for one of them lands here.

Where it appears

These are the documented surfaces that raise it. The REST base is https://api.emailforagents.ai/v1, and the remote MCP endpoint is https://mcp.emailforagents.ai/mcp.

The response

Read request_id off the body or the x-request-id header before doing anything else. It is the only handle on one specific attempt, and for a 503 it is the only handle at all, because the underlying detail stays server-side.

HTTP/1.1 402
content-type: application/json
x-request-id: req_...

{
  "error": {
    "code": "quota_exceeded",
    "message": "This workspace has exhausted its delivery allowance.",
    "request_id": "req_...",
    "retryable": false
  }
}

Verified against packages/domain/src/billing.ts:773. The status comes from ERROR_STATUS in packages/contracts/src/errors.ts, which is the one place a code is mapped to a status.

All error codes · Documentation · Quickstart