Rate Limits
Rate limits protect the API from abuse and ensure fair usage across all clients.
Rate Limit Headers
Every API response includes these headers:
| Header | Description | Example |
|---|---|---|
X-RateLimit-Limit | Max requests per minute for your plan | 240 |
X-RateLimit-Remaining | Requests remaining in current window | 235 |
X-RateLimit-Reset | Unix timestamp when window resets | 1704067200 |
The value of X-RateLimit-Limit depends on your plan tier (see Plan Limits below). The examples here use the Growth tier value of 240.
Example response headers:
HTTP/1.1 200 OK
X-RateLimit-Limit: 240
X-RateLimit-Remaining: 235
X-RateLimit-Reset: 1704067200
Content-Type: application/json
Rate Limit Exceeded (429)
When you exceed the limit, you receive:
HTTP/1.1 429 Too Many Requests
Retry-After: 15
X-RateLimit-Limit: 240
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704067200
Content-Type: application/json
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 15 seconds."
},
"request_id": "req_abc123"
}
The Retry-After header indicates how many seconds to wait.
There is no soft-limiting, warning, or throttling phase: requests within the limit return normally, and once the limit is exceeded the API returns 429 Too Many Requests directly. Use the X-RateLimit-Remaining header to track how close you are to the limit.
Plan Limits
Rate limits are applied per minute, based on your account's plan tier:
| Plan tier | Requests per minute |
|---|---|
| Free | 240 |
| Growth | 240 |
| Scale | 480 |
| Enterprise | 10000 (effectively unlimited) |
Requests that are not authenticated (or where the plan tier can't be resolved) fall back to a default limit of 60 requests per minute, applied per IP address.
Per-Endpoint Adjustments
Stats endpoints (/api/v1/stats/*) run heavier queries, so requests authenticated with an API key are limited to 50% of the plan limit (with a floor of 30 requests per minute). Requests authenticated via a dashboard session (JWT Bearer token or cookie) keep the full plan limit.
| Request type | Limit on /api/v1/stats/* |
|---|---|
API key (X-API-Key) | 50% of plan limit (minimum 30/min) |
| Dashboard session (JWT / cookie) | 100% of plan limit |
| All other endpoints | 100% of plan limit |
Endpoints Without Rate Limits
These endpoints are excluded from rate limiting:
/health- Health check/livez- Liveness probe/readyz- Readiness probe/docs- Swagger documentation/redoc- ReDoc documentation/openapi.json- OpenAPI specification
Best Practices
1. Monitor Rate Limit Headers
def make_request(url, headers):
response = requests.get(url, headers=headers)
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
if remaining < 10:
print(f"Warning: Only {remaining} requests remaining")
return response
2. Implement Exponential Backoff
import time
import random
def request_with_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code != 429:
return response
retry_after = int(response.headers.get('Retry-After', 1))
# Add jitter to prevent thundering herd
sleep_time = retry_after + random.uniform(0, 1)
time.sleep(sleep_time)
raise Exception("Max retries exceeded")
3. Cache Responses
from functools import lru_cache
import time
# Cache stats for 5 minutes
@lru_cache(maxsize=100)
def get_stats_cached(site_id, period, cache_key):
return get_stats(site_id, period)
def get_stats(site_id, period):
# Create cache key that expires every 5 minutes
cache_key = int(time.time() / 300)
return get_stats_cached(site_id, period, cache_key)
4. Batch Requests When Possible
Instead of:
# Bad: 10 separate requests
for site_id in site_ids:
stats = get_stats(site_id)
Consider:
# Better: Fewer requests with more data per request
stats = get_stats_batch(site_ids) # If batch endpoint available
5. Use Webhooks for Real-Time Data
For real-time updates, use webhooks instead of polling:
# Bad: Polling every second (60 req/min just for one metric)
while True:
stats = get_stats(site_id)
time.sleep(1)
# Better: Configure webhook for real-time updates
# (No API calls needed - data pushed to you)
Enterprise Custom Limits
Enterprise plans can negotiate custom limits:
- Per-endpoint limits
- Higher burst allowances
- Dedicated API instances
- SLA guarantees
Contact sales@sealmetrics.com for Enterprise pricing.