Rate Limiting
Anonymous requests
Section titled “Anonymous requests”Unauthenticated requests are capped per IP.
The cap:
| Rate | Burst |
|---|---|
| 1000 / hour | 500 |
Reads and writes both count. Authenticate to remove the per-IP cap; authenticated writes are governed by the limits below.
Burst capacity
Section titled “Burst capacity”The 500-token burst means you can fire 500 requests back-to-back when the bucket is full; after that you refill at ~17 requests per minute.
- Steady polling under ~16/minute works forever.
- A burst of 500 requests works once, then you wait ~30 minutes for the bucket to refill.
- Anonymous polling at 50/second drains the burst in 10 seconds, then 429s until the bucket refills.
- Many users sharing one IP (corporate networks, VPNs) — everyone shares the same budget. Authenticate to escape the shared cap.
Anonymous 429 response
Section titled “Anonymous 429 response”When the budget is exhausted, the API returns 429 Too Many Requests with a Retry-After header and this body:
{ "error": { "code": "RATE_LIMITED", "message": "Anonymous request limit reached. Authenticate at https://docs.warmhub.ai/auth/getting-access for higher limits.", "hint": "Authenticate at https://docs.warmhub.ai/auth/getting-access for higher limits.", "retryAfter": 4 }, "scope": "ip", "authenticated": false}error.retryAftermatches theRetry-Afterheader (seconds). After fully draining the bucket this is typically3to4seconds.scopeis always"ip"for anonymous 429s.authenticatedis alwaysfalse— authenticated requests bypass this cap and never produce a 429 here.
Getting higher limits
Section titled “Getting higher limits”Authenticate via the getting-access flow and use a personal access token (PAT) or session token. If you have a legitimate scraping or monitoring use case that needs to remain anonymous and run above 1000/hour from a single IP, contact support — IP-level whitelisting is available case-by-case.
Authenticated writes
Section titled “Authenticated writes”Some authenticated write operations are capped per user and per organization — the same limits apply whichever WarmHub client you use to issue the write. The table under Rate-limited operations below has the full list. Other authenticated writes and all authenticated reads aren’t currently capped.
How it works
Section titled “How it works”| Scope | Key | Description |
|---|---|---|
| Per-user | User ID | Protects against individual abuse. On the free tier, this applies to repo-scoped writes. On paid tiers, the org limit governs instead for shared repo write budgets such as commits. Standalone operations such as org creation and PAT creation, plus destructive repo delete operations, are always per-user regardless of tier. |
| Per-org | Org ID | A shared budget across all org members. Higher tiers receive higher limits. |
Rate-limited operations
Section titled “Rate-limited operations”Only resource-creating and high-cost write operations are rate limited. Many operations on existing resources — such as pause, revoke, and rename — are not rate limited, because they are self-limiting: you can only act on what already exists.
However, some write operations on existing resources are still rate limited. Revising or removing shapes, for example, draws from the same write permission budget as creation. Repository delete is also rate limited separately because it is irreversible and high impact.
| Operation | Scope | Strategy |
|---|---|---|
| Writes to things and assertions — including commits and content updates (README, AGENTS, and generated content) | Per-user + per-org | Token bucket |
| Shape creation | Per-org | Token bucket |
| Shape revise / remove | Per-org | Token bucket |
| Subscription creation | Per-org | Token bucket |
| Credential set creation | Per-org | Fixed window |
| Repository creation | Per-org | Fixed window |
| Repository delete | Per-user | Fixed window |
| Organization creation | Per-user | Fixed window |
| PAT (Personal Access Token) creation | Per-user | Fixed window |
Tier-based limits
Section titled “Tier-based limits”All organizations start on the free tier. Limits increase with higher tiers:
| Tier | Commits/min | Repos/hr | Repo deletes/hr | Shapes/min | Subscriptions/min | Credentials/hr | Orgs/hr | PATs/hr |
|---|---|---|---|---|---|---|---|---|
| Free | 120 (user) / 600 (org) | 20 | 20 (user) | 40 | 20 | 20 | 10 | 20 |
| Pro | 1,000 (org) | 50 | 20 (user) | 60 | 30 | 50 | 10 | 20 |
| Enterprise | 5,000 (org) | 200 | 20 (user) | 200 | 100 | 200 | 10 | 20 |
On paid tiers, shared repo write limits are generally enforced at the org level. Organization creation, PAT creation, and repository delete remain per-user on all tiers.
Write-limit 429 response
Section titled “Write-limit 429 response”When a per-user or per-org limit is exceeded, the API returns HTTP 429 with a RATE_LIMITED error:
HTTP/1.1 429 Too Many RequestsRetry-After: 12Content-Type: application/json
{ "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded", "retryAfter": 12 }}The Retry-After response header carries the number of seconds to wait before retrying. The same value is serialized into error.retryAfter so clients can read it without parsing headers.
Retry strategy
Section titled “Retry strategy”When you receive a 429:
- Read the
Retry-Afterheader — wait at least that many seconds before retrying. - Use exponential backoff as a fallback if the header is missing.
- Don’t retry immediately — rapid retries consume tokens and extend the wait.
What is not rate limited
Section titled “What is not rate limited”- Authenticated read operations —
head,query, andaboutlookups; action-run reads. - Simple operations on existing resources — pause, resume, rename, revoke.
Hit a problem or have a question? Get in touch.