Rate limits and quotas
Several independent limits can affect one request. Read the status, problem code, details, and
Retry-After header instead of inferring the cause from a single counter.
Limit summary
Section titled “Limit summary”| Limit | Unit | Scope |
|---|---|---|
| Enrollment creation limit | Lifetime successful inbox creates | Enrollment key, stored as max_mailboxes and used_count |
| Daily send limit | Recipients delivered in a rolling 24-hour window | Inbox |
| Request rate | API requests in the configured window | Agent key or route |
| Project and inbox capacity | Active resources | Billing plan and project |
| Domain purchase authority | Money, domain count, extension, premium status, and cadence | Matching organization, project, and agent purchase limits |
| Wait budget | Seconds or milliseconds per long-poll | Request and server configuration |
Lifetime inbox creation
Section titled “Lifetime inbox creation”An enrollment key stops creating inboxes after used_count reaches max_mailboxes. The server owns
the counter, so copying the key does not create another allowance. Deleting an inbox does not refund a
lifetime slot.
The wire fields retain mailbox for compatibility. User-facing instructions and console labels use inbox.
Project and plan capacity are separate. A project may reach its active inbox cap before the enrollment key reaches its own lifetime limit.
Rolling recipient accounting
Section titled “Rolling recipient accounting”The default inbox limit is 75 recipients per rolling 24 hours. One message sent to three recipients
uses three units. The effective daily_send_limit may be set from 1 to 10,000 with
mailbox:quota; 0 on an enrollment key means the organization’s default should apply.
The limit is checked when a message is submitted and again before reviewed mail is released. The second check prevents a queued message from bypassing a limit that changed while it waited. Capacity is counted once, only when delivery occurs.
- A queued review has not consumed capacity.
intent_required, suppression, and contact-list rejections consume none.- An over-limit response includes
429andRetry-After.
Request throttles
Section titled “Request throttles”When an API throttle applies, the response uses 429 Too Many Requests and includes Retry-After in
seconds. Back off with jitter and preserve the request’s idempotency value when retrying the same
mutation.
The TypeScript SDK retries eligible idempotent requests for transient failures. It does not make an
unsafe mutation idempotent by guessing. For send, reply, and forward, pass idempotency_key; for MCP
outbound mutations, pass client_id.
Wait limits
Section titled “Wait limits”REST and the TypeScript SDK default wait_for_email to 300 seconds and cap it at 600 seconds. MCP
defaults to 120 seconds and also caps at 600 seconds, subject to the packaged server’s configured
maximum. Client and proxy read timeouts must exceed the requested wait.
Review-event long-polls have their own shorter bounded interval. Follow each tool or endpoint’s published field rather than reusing the email wait budget.
Plan and project capacity
Section titled “Plan and project capacity”Plan limits apply to projects, active inboxes, and customer-controlled domains. They are checked in the same authorization path as resource creation. No credential permission bypasses plan capacity.
An agent can request a plan change with commerce:request, but cannot approve it. Downgrades that do
not fit the current resource count remain pending or blocked and never delete resources automatically.
Purchase limits
Section titled “Purchase limits”Domain purchase requests combine plan capacity with every matching organization, project, and agent purchase limit. Controls may restrict:
- a one-time, weekly, monthly, quarterly, or annual budget;
- maximum amount per purchase;
- maximum domains;
- allowed extensions;
- premium-domain authority.
The most restrictive matching result wins. Budget reservations prevent concurrent requests from overspending the same allowance. Unused recurring budget does not roll over.
Handle failures by code
Section titled “Handle failures by code”| Code or status | Meaning | Response |
|---|---|---|
quota_exceeded | A lifetime, active-resource, or recipient quota blocks the request | Read the detail and current limit; do not retry unchanged |
rate_limited | Request rate is too high | Wait for Retry-After, then retry with jitter |
intent_required | Review policy requires reviewer context | Add intent.summary; nothing was sent or queued |
recipient_suppressed | At least one recipient cannot receive this message | Remove or resolve the blocked recipient before retrying |
awaiting_human_approval | A commerce request needs a person | Surface the approval URL and poll at the recommended interval |