API 429 inventory
TOO_MANY_REQUESTS is the published HTTP request-rate code. Existing, more specific refusal codes remain distinct. Nest HTTP domain refusals use DomainErrorFilter; A2A and the separate Bridle transport retain their existing protocol envelopes. Retry-After is an integer number of seconds, copied from details.retryAfterSeconds. It is a backoff instruction, not a guarantee that capacity will be available.
| Code / source | What is counted | Window / default | Counting key | Client action |
|---|---|---|---|---|
TOO_MANY_REQUESTS, core HTTP guard, organization credential | Authenticated service-key HTTP requests across routes and credentials | 300/minute, 18,000/hour, 432,000/day; configurable | Verified organization ID, shared Redis | Wait Retry-After; ask platform admin to increase Request rate |
TOO_MANY_REQUESTS, core HTTP guard, other requests | Requests to each controller handler | 300/60 seconds by default; REQUEST_RATE_IP_MINUTE; existing route overrides take precedence | IP + controller + handler, in-process Nest throttler | Wait Retry-After |
| Same, credential auth controller | Password/email operations | 5/min for slow routes; 20/min for steady routes | IP + route, unchanged even if an organization key is supplied | Wait Retry-After; do not rotate keys to retry |
AGENT_CONCURRENCY_LIMIT | Live agent turns | Capacity, default 4 (configured 1–64); no time window | Agent ID, database coordination | Poll no faster than Retry-After: 1, or wait for a turn to finish; windowSeconds: null |
QUOTA_EXCEEDED, team_rate | Agent turns | Team plan turns/minute, sliding 60 seconds | Team ID, in-process | Conservative Retry-After: 60 |
QUOTA_EXCEEDED, team_spend | Tokens used | Subscription period limit | Team ID | Raise budget or wait until details.periodEndsAt; no short Retry-After |
QUOTA_EXCEEDED, org_spend | USD pico spend across teams | UTC calendar month, organization budget | Organization ID | Raise/remove budget or wait until details.periodEndsAt; no short Retry-After |
BROWSER_VIEW_RATE_LIMIT | Browser screenshot requests | 1 per 2 seconds | Agent ID, Redis | Retry-After: 2 |
TOO_MANY_LETTERS | Confirmation emails issued | 3 per sliding hour | Account and link kind | Conservative Retry-After: 3600; anonymous password-reset requests suppress emails without revealing the account |
LLM_RATE_LIMITED | Upstream model provider rate refusal after bounded retries | Provider-specific, not known to this API | Provider credential/model | Provider delay if known, otherwise conservative 60-second backoff; limit/window are null |
KNOWLEDGE_INGEST_TOO_EXPENSIVE | Estimated document token cost against remaining period budget | Current team period | Team + proposed document | Upload a smaller document or raise the budget; retrying unchanged is not a remedy |
TOO_MANY_SUBSCRIPTIONS, partner Bridle subscriber | Live subscriptions | Capacity 32 | WebSocket connection | Unsubscribe before retrying; socket error, no HTTP header |
TOO_MANY_REQUESTS, hub subscriber | Visitor credential mint requests | 600 per sliding minute | Remote address, in-process | Retry-After: 60; Bridle HTTP transport preserves error and adds code/details |
TOO_MANY_REQUESTS, Bridle client repository | Concurrent in-flight message handlers | Capacity 8 | Runtime connection | Wait for work to finish; socket acknowledgment, no HTTP header |
SLOW_CONSUMER, Bridle SDK | Unconsumed local event queue | Capacity 256 | SDK connection | Drain events/reconnect; client-side error, no HTTP response |
A2A JSON-RPC RATE_LIMITED / QUOTA_EXCEEDED | Channel turns or team quota | Sliding 60 seconds: 12/visitor and 60/agent; hands-enabled channels 4/visitor and 15/agent; or team period quota | Agent + visitor, and agent; quota by team | Preserve JSON-RPC envelope; transient channel rate uses Retry-After: 60, period quota has no short retry |
ARTIFACT_QUOTA_EXCEEDED is 400, not 429. Provider HTTP 429s inside repository adapters are upstream responses, not additional public HTTP contracts. Errors after an SSE response has started travel in stream error frames: HTTP status/headers cannot be rewritten after headers are sent.
Organization counter semantics
Only an active, unexpired, non-revoked stored orgk_ credential from the configured partner environment selects the organization bucket. Route authorization still runs and checks scopes, organization and resource access. Invalid keys use the existing IP bucket. Explicit @Throttle route limits always retain their IP behavior. Each Redis window starts on its first admitted request. All three windows are checked atomically; rejected requests neither consume quota nor extend a window. When several windows refuse, the longest remaining wait is returned. Limits are read on every request, so increases apply immediately without resetting usage. Redis/identity-store outages return 503 REQUEST_RATE_UNAVAILABLE, never silently remove the protection. Process restarts retain organization counters in Redis.
October 30 incident
The repository establishes possible causes, not which one occurred at 12:52–13:23 UTC or 15:11. Production logs for those requests were not inspected in this task; no historical cause is claimed. Capture response code, details, Retry-After and request correlation ID when investigating another refusal; never log service keys.