Rate Limits
Odin Scan enforces rate limits to ensure fair usage and maintain service reliability. Limits vary by subscription plan and endpoint.
Scan Quotas
| Plan | Scan Quota | Period |
|---|---|---|
| Basic | 10 scans | Per month |
| Pro | 60 scans per seat | Per month |
Pro scan quotas are pooled at the organization level. For example, a team with 2 Pro seats gets 120 scans per month shared across all members.
General API Requests
Standard read endpoints (listing analyses, checking status, fetching results) have higher limits to support polling workflows:
| Plan | Limit | Period |
|---|---|---|
| Basic | 100 requests | Per hour |
| Pro | 1,000 requests | Per hour |
Rate Limit Headers
Every API response includes rate limit information in the response headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1705312800
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum number of requests allowed in the current window |
X-RateLimit-Remaining | Number of requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp (seconds) when the rate limit window resets |
Exceeding the Limit
When you exceed a rate limit, the API returns a 429 Too Many Requests response:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705316400
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again later."
},
"timestamp": "2025-01-15T10:30:00Z",
"requestId": "req-abc123"
}
The Retry-After header indicates how many seconds to wait before making another request.
Best Practices
Poll with backoff. When checking analysis status, start with a 5-second interval and increase to 15-30 seconds as the analysis progresses. Avoid polling more frequently than once per second.
# Good: poll every 10 seconds
while true; do
status=$(curl -s https://api.odinscan.ai/api/v1/analysis/$ID/status \
-H "Authorization: Bearer $API_KEY" | jq -r '.status')
if [ "$status" = "completed" ] || [ "$status" = "failed" ]; then
break
fi
sleep 10
done
Use webhooks instead of polling. When creating an analysis, provide a webhookUrl to receive a notification when the analysis completes. This eliminates the need for status polling entirely.
{
"repositoryUrl": "https://github.com/username/repo",
"webhookUrl": "https://your-server.com/webhook/odinscan"
}
Cache results locally. Analysis results do not change after completion. Fetch the result once and store it locally rather than requesting it repeatedly.
Monitor your usage. Check the X-RateLimit-Remaining header in responses to track how close you are to the limit. If you are consistently approaching the limit, consider upgrading your plan.
Batch operations where possible. Instead of syncing repositories one by one, use the full sync endpoint (POST /api/v1/repositories/sync) which handles all repositories in a single request.
Upgrading Your Plan
If you consistently hit rate limits, consider upgrading your subscription. See Subscription Plans.
Next Steps
- Authentication – set up API keys
- REST API Reference – full endpoint documentation