Retry-After semantics. The no-auth
GET /v1/health and GET /v1/help discovery endpoints have no rate limit.
Headers
Every rate-limited response carries the rate-limit headers, and a429 RATE_LIMITED or
retryable 503 response also carries Retry-After. See Response headers
for the complete header catalog and wire-level examples. This page owns the
policies and recovery behavior.
Per-Route Policies
Each route declares a named policy inlib/api/rate_limit/policy.ts. The
policy name appears in observability dashboards. HTTP rate-limit failures use
the stable RATE_LIMITED error code, with the policy context available in the
message or logs.
Email Audit Admission
Email audits fan out to several external checks. They use these additional limits across the Public API, MCP, and agent calls:
Capacity rejections return
429 RATE_LIMITED with Retry-After. They do not
run or charge the audit.
Session Traffic: 300/min Ceiling
UI-backed session traffic (dashboard, Brew chat orchestrator) gets a flat
300/min ceiling across every policy above except email.audit, which stays
at 6 per minute. API-key traffic uses the strict per-route limits in the
table.
Generosity & Burst Behavior
- The window is a rolling 60 seconds, not a fixed wall-clock minute. A spike at the top of a minute does NOT get a free second budget.
- The store uses Redis sorted-sets (when available); when Redis is unavailable, every rate-limited endpoint fails open with
X-RateLimit-Remaining: <limit>andX-RateLimit-Reset: now+60. You will not see spurious 429s during a Redis blip. - Test mode bypass:
BREW_DISABLE_API_RATE_LIMIT=1on the dev server skips the gate entirely (test-only env var; never set in production).
429 Recovery Cookbook
The canonical retry loop:
- Always honor
Retry-After. Take the max ofRetry-Afterand your own back-off so you don’t out-aggressive yourself. - Reuse the same
Idempotency-Keyon every retry. See Idempotency for replay semantics. - Preemptively pause when
X-RateLimit-Remaininghits 0. The header ships on rate-limited responses, so a well-behaved client can throttle itself before a 429 ever fires.
429 RATE_LIMITED and retryable 503 envelopes, including
error.retryAfter, are documented in Errors. The
header and body carry the same wait duration.
Server-Side Observability
Every rate-limited response records anapi.rate_limit.hit event with the
policy, admission scope, limit, retry interval, request id, and actor scope.
The event does not include request content. If persistent 429 responses do not
match your expected request rate, contact support with the x-request-id from
one response.
See Also
- Idempotency: pair with
Idempotency-Keyso retries are safe. - Errors: full error envelope + every
error.code. - Response headers: every header Brew sets.
- Async jobs & polling: for
POST /v1/sendsandPOST /v1/automations/triggers/{triggerEventId}/fire, you don’t need to call the API again to wait for delivery. Poll the run.
Need Help?
Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:- Self-Service Tools
- Talk to Our Team
Search Documentation
Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.
ChatGPT/Claude Integration
Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.