Rate Limits
Rate limits protect the CronDB API from abuse and ensure fair usage across all customers. Limits are applied per API key and reset every minute.
Rate Limits by Plan
| Plan | Requests per Minute | Monthly Quota |
|---|---|---|
| Free | 10 | 100 |
| Starter | 60 | 10,000 |
| Pro | 300 | 100,000 |
| Enterprise | 1,000 | 999,999 |
Rate limits apply to all endpoints equally. Each API call counts as one request regardless of the endpoint.
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1710764400
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute for your plan |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Handling Rate Limits (429 Responses)
When you exceed the rate limit, the API returns a 429 Too Many Requests response:
{
"detail": "Rate limit exceeded. Try again in 32 seconds."
}
The response includes a Retry-After header:
Retry-After: 32
Implementing Backoff (Python)
import time
import requests
def call_api_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
continue
response.raise_for_status()
raise Exception("Max retries exceeded")
Implementing Backoff (JavaScript)
async function callApiWithRetry(url, headers, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, { headers });
if (response.ok) {
return await response.json();
}
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "60");
console.log(`Rate limited. Waiting ${retryAfter} seconds...`);
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
continue;
}
throw new Error(`API error: ${response.status}`);
}
throw new Error("Max retries exceeded");
}
Rate Limits vs. Monthly Quota
Rate limits and monthly quotas are separate mechanisms:
| Mechanism | What It Controls | Reset Period |
|---|---|---|
| Rate limit | Requests per minute | Every 60 seconds |
| Monthly quota | Total requests per billing cycle | Monthly on billing date |
You can be within your rate limit but exceed your monthly quota, or vice versa.
Optimizing API Usage
Use Bulk Endpoints
Instead of making 100 individual enrichment calls:
# Inefficient: 100 requests
for domain in domains:
GET /v1/enrichment/domain?domain={domain}
Use the bulk endpoint for a single request:
# Efficient: 1 request
POST /v1/enrichment/bulk
{"domains": ["domain1.com", "domain2.com", ...]}
Cache Results
CronDB data updates periodically, not in real time. Cache enrichment results for at least 24 hours to avoid redundant API calls.
Request Only What You Need
If you only need tech stack data, use the /v1/tech-stack endpoint instead of the full enrichment endpoint. Specialized endpoints return faster and use the same quota.
Burst Allowance
CronDB allows short bursts above your rate limit:
- Up to 2x your per-minute limit for bursts lasting under 5 seconds
- After the burst, normal rate limiting resumes
This accommodates applications that send parallel requests in short bursts.
Check the X-RateLimit-Remaining header in every response to proactively throttle your request rate before hitting the limit.
Next Steps
- Errors — Handle error responses
- Bulk Enrichment — Reduce request count
- Usage Dashboard — Monitor your quota consumption