Guides
Rate limits & security
Understand the budgets, headers, and best practices for a reliable integration. Caps keep the scalpel useful for daily work — not full archive export.
Rate limits
Dual monthly budgets plus burst and daily caps. Exact remaining values are always on GET /stats.
3,000
Requests
per billing month · 1 per successful API call
3,000
Records
per billing month · 1 per row returned in list/dossier
| Cap | Typical value |
|---|---|
| Per-minute burst | 20 |
| Daily requests | 300 |
| Monthly requests | 3,000 |
| Monthly records | 3,000 |
| Monthly page turns | 200 |
| Daily company detail | 100 unique companies |
| Page size max | 50 |
| Query set max | 500 (offset + pageSize bound) |
Good to know
- Only 2xx responses consume request/record budgets. Auth failures and validation errors do not.
- Billing month follows the Stripe subscription period — not the calendar month.
- Firehose delivery does not consume REST budgets.
- On
429, readlimitTypeandresetUnixbefore retrying.
Only successful requests are billed
4xx, 5xx, and 429 do not increment counters. Prefer backing off over tight retry loops.
Rate limit headers
Non-exempt successful responses include monthly request headers.
On every metered 2xx response
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix), X-RateLimit-Policy: monthly_requestsOn 429 (limit reached)
Body includes
limitType, limit, used, remaining, resetUnix. Response also sets Retry-After (seconds).Limit exceeded (429)
Example body when a daily request cap is hit:
429 JSON
{
"error": {
"code": "rate_limit_exceeded",
"message": "Daily request limit reached.",
"status": 429,
"limitType": "daily_requests",
"limit": 300,
"used": 300,
"remaining": 0,
"resetUnix": 1724198400
}
}Real-time usage: GET /api/v1/stats
Exempt from request budget. Use it to pace clients.
cURL
curl -s "${BASE_URL}/api/v1/stats" \
-H "Authorization: Bearer YOUR_API_KEY"JSON (truncated)
{
"period": { "monthStart": "…", "dayStart": "…" },
"rateLimits": {
"perMinute": { "limit": 20, "used": 0, "remaining": 20, "resetUnix": 0 },
"dailyRequests": { "limit": 300, "used": 12, "remaining": 288, "resetUnix": 0 },
"monthlyRequests": { "limit": 3000, "used": 40, "remaining": 2960, "resetUnix": 0 },
"monthlyRecords": { "limit": 3000, "used": 100, "remaining": 2900, "resetUnix": 0 }
},
"staticLimits": { "pageSizeMax": 50, "querySetRecordsMax": 500 }
}Exempt routes
| Route | Why |
|---|---|
| GET /api/v1/health | Uptime / dependency check |
| GET /api/v1/stats | Budget introspection |
Best practices
Caching
Cache filter catalogs and dossiers briefly. Prefer firehose ids over re-searching.
Pagination
Keep
pageSize ≤ 50. Deep pages cost page-turn quota.Tight queries
Narrow signal_query and overlays before paging. Wide scans burn records fast.
Security
Store
vs_ keys as secrets. Rotate if leaked. Use HTTPS in production.See All endpoints for samples and Webhooks for the push path.