Rate limits
Daily budgets, per-minute burst caps, and how team workspaces share a single pool.
Rate limits protect the platform from runaway workloads and prevent one noisy neighbor from degrading everyone else. They come in two shapes: a daily budget (total requests per day) and a burst cap (requests per minute).
Plan limits
| Plan | Daily | Burst | Batch size |
|---|---|---|---|
| Free | 500 / day | 20 / min | 10 indicators |
| Starter | 5,000 / day | 60 / min | 10 indicators |
| Pro | 25,000 / day | 120 / min | 50 indicators |
| Team | 100,000 / day | 300 / min | 100 indicators |
| Enterprise | Unlimited | 1,000 / min | 100 indicators |
A request is one call to /lookup, regardless of how many indicators you pack into the batch. Sending 100 indicators in one request counts as 1, not 100.
Response headers
Every /lookup response includes rate-limit headers so your client can shape traffic without extra round trips:
X-RateLimit-Limit-Daily: 25000
X-RateLimit-Remaining-Daily: 24,987
X-RateLimit-Limit-Burst: 120
X-RateLimit-Remaining-Burst: 118
- Limit-Daily / Remaining-Daily: your plan's daily budget and how much is left. Resets at midnight UTC.
- Limit-Burst / Remaining-Burst: per-minute burst cap and the remaining slots in the current minute window.
On Enterprise (unlimited daily), X-RateLimit-Limit-Daily and X-RateLimit-Remaining-Daily are omitted.
When you hit a limit
The API returns 429 Too Many Requests with a body like:
{
"error": "Rate limit exceeded",
"message": "Daily team limit exceeded (25001/25000 requests). Resets at midnight UTC.",
"limit_type": "daily",
"limit": 25000,
"reset_time": "2026-05-01T23:59:59Z"
}
The response also sets:
Retry-After: 60
X-RateLimit-Reset: 2026-05-01T23:59:59Z
Handling 429
Respect Retry-After. If you're doing bulk enrichment from a SIEM,
chunk your workload so you stay under the burst cap — a simple
semaphore with plan-appropriate concurrency is usually enough.
Team workspaces share one pool
If you're on Team (or Enterprise) and have invited analysts to your workspace:
- The daily limit is a shared pool — usage from the owner + all members sums against the same 100k/day budget
- The burst cap is also shared — all members combined can't exceed 300 requests/minute on Team
- Usage is still tracked per member on the dashboard — you see who did what, but the budget is collective
Rationale: a team of 5 analysts investigating a live incident shouldn't be artificially limited to 20% of the plan each — they should all burn rubber when needed. Fair-share / per-seat caps are not in the current model.
See Teams for the full team model.
Subscription downgrades
When Paddle reports a subscription as past_due, paused, or canceled, we temporarily downgrade the customer to Free-tier rate limits (500/day, 20/min, 10 per batch) until the status resolves. This protects us from abuse of expired plans without locking out the customer completely — a legitimate customer whose card just failed can still run low-volume lookups while they update their payment method.
The downgrade applies to viewer keys inheriting the owner's plan as well: if your Team workspace goes past-due, viewers drop to Free quotas too.
Fail-closed policy
If our rate-limiter backing store (Redis) is unreachable, the API returns 503 Service Unavailable rather than allowing unchecked traffic. This is a deliberate safety measure — an attacker could otherwise exploit a Redis outage to bypass limits entirely. Your retry logic should treat 503 the same as 429: back off and try again.