> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate-limit and cooldown collector: how the API request boundary maps every bucket

> The single model for Orbit's request-level limiters — per-route buckets (public, authenticated read/write, money-moving, webhook inbound, agent invoke) and their cooldown mechanics — what fired, what an exceeding request sees, and how retry-idempotency keeps a 429 from costing you.

# Rate-limit and cooldown collector

Orbit's request boundary has one job: decide whether a request should run now, later, or never. It answers that with a taxonomy of buckets — each with its own scope, its own cap, its own retry posture — rather than a single "slow down" gate. When you read a `429` as "one of these named buckets fired," a rejected request stops being noise and becomes a handle-able signal.

This page collects the API-request limiters into one model and names the cooldown classes that pace sends and recipients, so you know which layer fired and which lever moves it. (Sibling page [Rate-limit and cooldown taxonomy](/concepts/rate-limit-and-cooldown-taxonomy) covers the message- and verify-level 429 families — frequency caps, recipient cooldowns, Meta's WhatsApp tiers; here the scope is the request boundary itself.)

## Why traffic classes exist

Rate-limit buckets aren't only an absolute-abuse defense. Orbit paces traffic on per-channel, per-credential, and per-recipient tiers as well: sender-warming states that ramp a new number gradually, per-API-key windows so one noisy integration throttles only itself, and cooldowns that protect a recipient or a route-family. Each bucket answers a different question — the platform ceiling, a tenant's shared quota, a single key's leak-containment, a provider's inbound flood — and the response headers name the one that fired.

## The taxonomy table

Every bucket has four attributes: the **scope** it isolates (tenant, key, route family, or recipient), the **guarantee** it gives (an HTTP `429` plus the response header naming the bucket), the **idempotency pair** so the retry never double-charges, and a **retry posture** that tells your client when it is safe to come back.

| Bucket                                   | Scope (key)            | Cap (route-level) | Guarantee                  | Idempotency pair                 | Retry posture                     |
| ---------------------------------------- | ---------------------- | ----------------- | -------------------------- | -------------------------------- | --------------------------------- |
| `public-unauth`                          | IP                     | 10/min            | HTTP 429                   | n/a (read-only public endpoints) | Honor `retry_after`               |
| `public-read`                            | IP                     | 60/min            | HTTP 429                   | n/a                              | Honor `retry_after`               |
| `auth-read`                              | Tenant/API-key hash/IP | 120/min           | HTTP 429                   | n/a (safe GET)                   | Honor `Retry-After`               |
| `auth-write`                             | Tenant/API-key hash/IP | 60/min            | HTTP 429                   | `Idempotency-Key` on POST        | Back off; retry safe              |
| `money` (top-ups, refunds, purchases)    | Tenant/API-key hash/IP | 20/min            | HTTP 429                   | **Required** `Idempotency-Key`   | Back off; retry safe even mid-cap |
| `webhook-inbound` (provider DLR/inbound) | Provider IP            | 50,000/min        | HTTP 429 + per-tenant gate | Event-level dedup key            | Treat 429 as a healthy signal     |
| `agent-invoke` (LLM-fronted)             | Tenant/API-key hash/IP | 30/min            | HTTP 429                   | `Idempotency-Key`                | Exponential backoff               |

Billing tiers feed the global cap: your plan's `requestsPerSecond` ceiling (Starter 50, Growth 100, Business 500, Enterprise 1000) is the starter-tier safety net that sits under every endpoint; per-route buckets then tighten or loosen it. When a route doesn't declare one of these named buckets, the boundary falls back to the plan ceiling. A global safety net like this is the foundation — the route buckets are what you triage against.

For the message- and verify-level family tree (frequency caps you create, per-recipient cooldown counters, Meta/WhatsApp tier caps) see [Rate-limit and cooldown taxonomy](/concepts/rate-limit-and-cooldown-taxonomy). For the retry contract itself see [Idempotency and safe retries](/concepts/idempotency-and-safe-retries).

## Where it's enforced

Enforcement lives in one place: the route boundary config passed to the API's rate-limit plugin. When a bucket fires the limiter runs at the route's `preHandler` (before auth completes), so the guarantee — `HTTP 429` with a `Retry-After` header and a `retry_after` body field — travels with the rejection. Route families map onto the buckets above consistently: `auth-read` and `auth-write` on the CRUD surface (messages, numbers, verify, contacts), `money` on anything that moves credits (top-ups, refunds, purchases), `agent-invoke` on any LLM-fronted call, and the `webhook-inbound` lane pairing a high per-IP ceiling with a per-tenant gate after tenant resolution so one tenant's inbound burst never exhausts another's. An inline `max`/`timeWindow` config that bypasses the named buckets still emits a `custom:<max>/<window>` label — observability kept either way.

## Cooldown classes

A cooldown is a deliberate "not yet" that resets on its own clock — different from a rate window that refills on a cadence and different from a hard block. Orbit's request boundary leans on three of them:

* **Warmed senders** — a new number ramps on a warming curve; sends above the curve wait until it advances. See [Sender warming and reputation](/concepts/sender-warming-and-reputation) and the [Number warming](/guides/number-warming) guide.
* **Quiet-hours parking** — a send inside a tenant-configured quiet window parks rather than dispatches, so it's delivered at the boundary instead of rejected. See [Send gating and quiet hours](/concepts/send-gating-and-quiet-hours) and [Quiet hours configuration](/guides/quiet-hours-configuration).
* **Consent refresh sweeps** — a re-check cadence on consent-required lanes paces how often a recipient is re-asked. See [Consent and suppression model](/concepts/consent-and-suppression-model).

Each class is tenant-owned and defaults open, in line with Orbit's compliance posture: the platform owns only the US TCPA federal voice dialing-window guard — everything else is a control you hold, not a gate Orbit imposes.

## Operator levers

You move these, not us:

* **Per-key rate limits and quotas** — set each API key's own per-minute window and monthly request quota in the console so one noisy integration trips its own 429 without spending a sibling key's budget. See [API rate limits console](/guides/api-rate-limits-console).
* **Usage and telemetry dashboards** — the operational sentinels surface charts the request boundary's counters and buckets so you can see a bucket firing before a client reports it. See [Operational sentinels](/concepts/operational-sentinels) and [Insights dashboards](/guides/insights-dashboards).

## Failure model

When a request exceeds a bucket the response is **429 Too Many Requests** with a `Retry-After` header and a `retry_after` body field. Rate-limit overage itself is not billed — only requests the platform actually processes (sends, invocations, lookups) consume credits.

Safe retry works because of the idempotency pair: every write and money endpoint expects an `Idempotency-Key` header, and every webhook event carries a dedup key. Replaying the same payload under the same key after a 429 collapses to the original — the platform never double-charges you for your own backoff. For inbound webhooks a 429 is a healthy rate-limiter responding to a provider flood, not a dropped event — the provider retries and the per-tenant gate scopes the blast to one tenant. For full retry semantics see [Idempotency and safe retries](/concepts/idempotency-and-safe-retries), and for 429 handling mechanics see [Rate limits](/guides/rate-limits).

## See also

* [Rate-limit and cooldown taxonomy](/concepts/rate-limit-and-cooldown-taxonomy) — message/verify 429 families, the sibling page
* [Idempotency and safe retries](/concepts/idempotency-and-safe-retries) — the replay contract every bucket leans on
* [Rate limits](/guides/rate-limits) — how to call, read headers, and back off
* [API rate limits console](/guides/api-rate-limits-console) — set per-key windows and monthly quotas
* [Sender warming and reputation](/concepts/sender-warming-and-reputation) and [Number warming](/guides/number-warming) — the warm-up cooldown class
* [Send gating and quiet hours](/concepts/send-gating-and-quiet-hours) and [Quiet hours configuration](/guides/quiet-hours-configuration) — the parking cooldown class
* [Consent and suppression model](/concepts/consent-and-suppression-model) — the consent-refresh cooldown class
* [Operational sentinels](/concepts/operational-sentinels) — watching the buckets live
