Rate limits
Every API key has a request budget per minute. Hitting the budget returns
429 Too Many Requests.
Defaults
| Plan | REST requests / min | WebSocket connections | MCP calls / min |
|---|---|---|---|
| Trial | 60 | 2 | 30 |
| Starter | 300 | 5 | 120 |
| Growth | 1,200 | 20 | 600 |
| Scale | Negotiated | Negotiated | Negotiated |
/health and /readyz are not rate-limited.
Headers
Every response carries:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 287
X-RateLimit-Reset: 1746369120
When Remaining hits 0, further calls return 429 with a Retry-After
header (seconds).
Backoff strategy
import time, requests
def call(url, headers):
while True:
r = requests.get(url, headers=headers)
if r.status_code != 429:
return r
wait = int(r.headers.get('Retry-After', 1))
time.sleep(wait)
For higher-throughput workloads, throttle proactively using Remaining so
you never trip 429:
def throttle(r):
remaining = int(r.headers.get('X-RateLimit-Remaining', 1))
reset = int(r.headers.get('X-RateLimit-Reset', 0))
if remaining < 5:
time.sleep(max(0, reset - time.time()))
Concurrency
The limit is request-rate, not concurrency. You can have many requests in flight as long as the rate stays under the budget. A semaphore of ~10 concurrent calls comfortably fits within the Growth plan.
WebSocket
WebSocket connections count against the connection budget, not the request budget. Each connection has unlimited inbound messages — there is no per-message rate limit.
Need more?
Email support@scorelytics.pro — Scale-tier limits are negotiated per workload.