Rate limits
Two windows are enforced per CF-Connecting-IP. Both must pass — exceeding either returns HTTP 429 with a Retry-After header in seconds.
Why it's loose-by-design
Cairn is a public verification directory — paywalling reads would defeat the point. The free tier is sized for a developer building a wallet integration, an analytics dashboard, or an indexer mirror. If you're hitting the limits, either:
- You're polling the same endpoint inside the 30s cache window — fetch once, cache locally.
- You're scanning the entire dataset — use
/data/agents.json(one call, 5K agents) instead of paginating/api/discovery. - You're doing genuine high-throughput indexing — get in touch and we'll set up an API key with raised limits (coming soon).
429 response shape
Retry-After: 60
Content-Type: application/json
{
"error": "ERR_RATE_LIMIT",
"detail": "Free tier: 60 requests/minute per IP. Slow down.",
"limits": { "perMinute": 60, "perDay": 2000 },
"retryAfterSeconds": 60
}What counts
Every request to /api/*, /data/*, and /feed.atom counts toward both limits. The health-check endpoint GET / is exempt.
Caching is your friend
Every successful response includes Cache-Control: public, max-age=N (typically 30s for live data, 60s for stats, 300s for the feed and bulk dump). A respectful HTTP client honors these and won't hit your rate limit on every request.