Rate Limits & Errors
Understanding rate limits, response headers, and error formats.
Rate Limit Tiers
Three windows per plan: per-minute (abuse cap, all plans), per-day (rolling 24h, free only), and per-period (your billing window). See Pricing for prices.
| Plan | Per Minute | Per Day (rolling 24h) | Per Period | Period |
|---|---|---|---|---|
| Free | 10 | 20 | 600 | rolling 30 days |
| Dev | 100 | — | 20,000 | Stripe billing cycle |
| Pro | 300 | — | 100,000 | Stripe billing cycle |
| Enterprise | 1,000 | — | Unlimited | — |
Paid plans reset on the first day of each Stripe billing cycle. The free tier uses a rolling 30-day window over your audit log — old requests age out one at a time, no hard reset. MCP protocol handshake (initialize, tools/list) does not count against your quota; only actual tool calls do.
Rate Limit Headers
Every response includes headers so you can track your usage in real time. Headers use lowercase names per HTTP/2.
| Header | Description |
|---|---|
x-ratelimit-limit-minute | Requests allowed per minute (abuse cap, all plans) |
x-ratelimit-remaining-minute | Requests remaining this minute |
x-ratelimit-limit-day | Rolling 24h cap (free plan only) |
x-ratelimit-remaining-day | Requests remaining in the last 24h window |
x-ratelimit-limit-period | Period quota (Stripe billing window for paid; rolling 30d for free) |
x-ratelimit-remaining-period | Requests remaining in the current period |
x-ratelimit-period-type | stripe (paid) or rolling_30d (free) |
x-ratelimit-reset-period | ISO-8601 reset timestamp (paid only; omitted for rolling windows) |
Retry-After | Seconds to wait (only on 429 responses) |
429 Too Many Requests
When you exceed a quota the API returns a 429 status with a structured error body.
{
"type": "error",
"error": {
"type": "rate_limit_error",
"message": "Plan quota exceeded for current billing period (free plan). Resets as old requests age out. Upgrade: https://legaldatahunter.com/pricing",
"limit_type": "period",
"plan": "free",
"upgrade_url": "/pricing",
"period_resets_at": null
}
}
The limit_type field indicates which quota was exceeded: minute, day, or period. MCP requests receive the same payload wrapped in a JSON-RPC 2.0 error with code -32029.
Exempt Endpoints
The following endpoints are not rate-limited and do not count against your quotas:
GET /v1/discover/*— Discovery endpointsGET /v1/stats— StatisticsGET /v1/manifest— ManifestGET /v1/billing/*— Billing endpointsGET /v1/usage/*— Usage endpointsGET /v1/keys— Key managementGET /auth/*— Authentication
HTTP Status Codes
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad request — invalid parameters |
401 | Unauthorized — missing or invalid authentication |
404 | Not found — document or resource doesn't exist |
429 | Rate limit exceeded |
500 | Internal server error |
Error Response Format
All errors follow a standard format with a detail field containing a human-readable message.
General errors
{
"detail": "Human-readable error message"
}
Validation errors (400)
{
"detail": [
{
"loc": ["body", "q"],
"msg": "field required",
"type": "value_error.missing"
}
]
}