Skip to content

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.

LimitUnitScope
Enrollment creation limitLifetime successful inbox createsEnrollment key, stored as max_mailboxes and used_count
Daily send limitRecipients delivered in a rolling 24-hour windowInbox
Request rateAPI requests in the configured windowAgent key or route
Project and inbox capacityActive resourcesBilling plan and project
Domain purchase authorityMoney, domain count, extension, premium status, and cadenceMatching organization, project, and agent purchase limits
Wait budgetSeconds or milliseconds per long-pollRequest and server configuration

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.

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 429 and Retry-After.

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.

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 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.

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.

Code or statusMeaningResponse
quota_exceededA lifetime, active-resource, or recipient quota blocks the requestRead the detail and current limit; do not retry unchanged
rate_limitedRequest rate is too highWait for Retry-After, then retry with jitter
intent_requiredReview policy requires reviewer contextAdd intent.summary; nothing was sent or queued
recipient_suppressedAt least one recipient cannot receive this messageRemove or resolve the blocked recipient before retrying
awaiting_human_approvalA commerce request needs a personSurface the approval URL and poll at the recommended interval