Rate Limits & Quotas
The two layers of rate limits and monthly quotas — every limit point, the 429 response-header conventions, and caller best practices.
CiteArk's limits come in two layers:
- Rate limits: protect infrastructure from short bursts, counted in fixed per-minute or per-hour windows;
- Monthly quotas: manage scarce resources (compute and storage), counted per calendar month.
Exceeding either layer returns 429, with a uniform error shape:
{ "error": "Too many requests. Please try again later." }Rate limits
| Endpoint | Limit | Dimension |
|---|---|---|
| All calls carrying an API Key | 120 requests/minute | Per Key (built into better-auth) |
POST /api/runs | 10 requests/hour | Account |
POST /api/repositories | 5 requests/hour | Account |
POST /api/forks | 20 requests/hour | Account |
POST /api/stars, /api/requests, /api/follows | 60 requests/hour each | Account |
GET /api/arxiv (metadata query) | 30 requests/hour | Account |
GET /api/arxiv?pdf=1 (fetch PDF) | 10 requests/hour | Account |
POST /api/contact | 5 requests/hour | IP |
POST /api/account/avatar (account avatar) | 10 requests/hour | Account (browser session only) |
/api/auth/** (sign-in/sign-up, etc.) | 120 requests/minute globally; sign-in 10/minute; sign-up 5/minute; password-reset requests and verification-email resends 3/minute each | better-auth built-in rate limiting |
Except for the built-in limits on API Keys and /api/auth/**, hitting any limit in the table above returns these response headers:
Retry-After: seconds until the current fixed window ends;X-RateLimit-Limit: the window's cap;X-RateLimit-Remaining: 0.
A 429 triggered by an API Key's built-in limit only carries Retry-After: 60.
Monthly quotas
| Quota | Default cap |
|---|---|
| Reproduction runs (run quota) | 10 per account per month |
| Paper uploads | 25 per account per month, with a total-bytes cap (default 500 MB) |
Quotas are per account: the browser session and all API Keys under the account share one quota. Only runs that actually enter the queue consume quota; failed requests are automatically refunded. Upload quota works the same way — failed uploads refund both the count and the bytes. Current remaining quota is visible on the Agent API Key or Security & Usage page.
The 429 when quota is exhausted
An exhausted monthly quota returns 429 (e.g. { "error": "This month's reproduction quota has been used up" }) with these headers:
Retry-After: seconds until the quota resets;X-Quota-Limit: the monthly cap;X-Quota-Used: usage so far this month;X-Quota-Remaining: 0;X-Quota-Reset: reset time in ISO format (UTC, midnight on the first of next month).
Caller best practices
- Always respect
Retry-After— retry at that point, not immediately; - Add exponential backoff with random jitter to batch jobs, so a whole queue of requests doesn't hit the same window at once;
- Read the repository snapshot before requesting a reproduction to confirm the claim and experiment exist and are executable — don't spend monthly quota on requests doomed to fail;
- Check each Key's rate-limit window usage on Agent API Key and this month's quota consumption on Security & Usage, and slow down proactively before you hit the ceiling.