Rate Limits
Understand API rate limiting and how to handle it. BlockSecOps API implements rate limiting to ensure fair usage and platform stability. Limits vary by plan....
Rate Limits
Understand API rate limiting and how to handle it.
Overview
BlockSecOps API implements rate limiting to ensure fair usage and platform stability. Limits vary by plan.
Rate Limits by Plan
| Plan | Requests/Minute | Requests/Hour | Requests/Day |
|---|---|---|---|
| Free | 10 | 100 | 500 |
| Developer | 60 | 1,000 | 10,000 |
| Startup | 120 | 5,000 | 50,000 |
| Professional | 300 | Unlimited | Unlimited |
| Enterprise | Custom | Custom | Custom |
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: 1705323600
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed in window |
X-RateLimit-Remaining |
Requests remaining in current window |
X-RateLimit-Reset |
Unix timestamp when limit resets |
Rate Limit Response
When you exceed the limit, you receive:
HTTP Status: 429 Too Many Requests
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Please retry after 45 seconds.",
"retry_after": 45
}
}
Headers:
Retry-After: 45
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705323600
Handling Rate Limits
Check Before Hitting Limit
Monitor remaining requests:
const response = await fetch('/api/v1/scans', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
if (remaining < 10) {
console.log(`Low on requests. Resets at ${new Date(reset * 1000)}`);
}
Implement Exponential Backoff
async function apiCallWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
const delay = retryAfter * 1000 * Math.pow(2, attempt);
console.log(`Rate limited. Waiting ${delay}ms before retry.`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Python Example
import time
import requests
def api_call_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
delay = retry_after * (2 ** attempt)
print(f"Rate limited. Waiting {delay}s before retry.")
time.sleep(delay)
continue
return response
raise Exception("Max retries exceeded")
Endpoint-Specific Limits
Some endpoints have additional limits:
| Endpoint | Additional Limit | Notes |
|---|---|---|
POST /contracts/upload |
50/hour | File upload limit |
POST /scans |
Based on plan | Scan concurrency limit |
GET /scans/{id}/results |
100/minute | Result fetching |
POST /webhooks |
10/hour | Webhook creation |
Scan Concurrency Limits
Concurrent scan limits by plan:
| Plan | Concurrent Scans |
|---|---|
| Free | 1 |
| Developer | 3 |
| Startup | 10 |
| Professional | 25 |
| Enterprise | Custom |
When limit is reached:
{
"error": {
"code": "CONCURRENT_LIMIT",
"message": "Maximum concurrent scans reached. Please wait for a scan to complete.",
"current_scans": 3,
"max_scans": 3
}
}
Best Practices
Batch Operations
Instead of many individual requests, use batch endpoints:
# Instead of multiple individual uploads
# Use batch upload
curl -X POST "https://api.blocksecops.com/api/v1/contracts/upload" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "[email protected]"
Cache Results
Cache scan results locally to avoid repeated fetches:
const cache = new Map();
async function getScanResults(scanId) {
if (cache.has(scanId)) {
return cache.get(scanId);
}
const results = await fetchScanResults(scanId);
cache.set(scanId, results);
return results;
}
Use Webhooks
Instead of polling for scan completion, use webhooks:
# Start scan with webhook
curl -X POST "https://api.blocksecops.com/api/v1/scans" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contract_id": "abc123",
"webhook_url": "https://your-server.com/webhook"
}'
Spread Requests
Space out non-urgent requests:
async function processContracts(contracts) {
for (const contract of contracts) {
await uploadContract(contract);
// Add delay between requests
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
Rate Limit Exemptions
Enterprise customers can request:
- Higher rate limits
- Burst allowances for specific operations
- Dedicated API endpoints
- Custom rate limit windows
Contact support for Enterprise rate limit adjustments.
Monitoring Usage
Via Dashboard
Go to Settings → API Usage to see:
- Requests per day/week/month
- Top endpoints
- Rate limit events
- Usage trends
Via API
curl -X GET "https://api.blocksecops.com/api/v1/usage" \
-H "Authorization: Bearer YOUR_API_KEY"
Response:
{
"period": "2025-01",
"requests": {
"total": 15420,
"by_endpoint": {
"/scans": 5230,
"/contracts": 3120,
"/vulnerabilities": 7070
}
},
"rate_limit_events": 3,
"current_usage": {
"minute": 45,
"hour": 823
}
}
Troubleshooting
Unexpected Rate Limiting
- Check all API keys: Multiple keys share org limits
- Review automated scripts: CI/CD may be making many calls
- Check for retry loops: Failed retries consume quota
- Monitor webhooks: Webhook failures trigger retries
Optimizing Usage
- Use efficient endpoints (batch operations)
- Cache frequently accessed data
- Implement proper retry logic with backoff
- Use webhooks instead of polling
- Review and optimize CI/CD scripts
Next Steps
- API Overview - Full API documentation
- Webhooks - Reduce polling
- Common Tasks - Efficient patterns