Skip to content

Rate Limits & Quotas

Chronary enforces two types of limits to ensure fair usage and platform stability: per-key rate limits and monthly quotas.

Every API key is limited to 10 requests per second. Requests that exceed this limit receive a 429 response with a Retry-After header indicating how many seconds to wait.

{
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded. Retry after 1 second.",
"param": null,
"request_id": "req_abc123"
}
}

The Retry-After response header contains the number of seconds to wait before retrying.

Monthly quotas reset automatically at the start of each billing cycle. Exceeding a quota returns a 429 response with "type": "quota_exceeded".

MetricFreeProScale
Agents5UnlimitedUnlimited
Calendars10UnlimitedUnlimited
iCal Subscriptions3 per agentUnlimitedUnlimited
Events created5,000/moUnlimitedUnlimited
API Calls50,000/moUnlimitedUnlimited
Webhook Deliveries10,000/moUnlimitedUnlimited
Availability Queries10,000/moUnlimitedUnlimited

When querying availability across multiple agents (e.g., finding a common free slot), additional limits apply:

ParameterFreeProScale
Max agents per query52050
Max date range30 days90 days365 days

Call GET /v1/usage to see your current consumption against your plan limits:

Terminal window
curl https://api.chronary.ai/v1/usage \
-H "Authorization: Bearer chr_sk_live_your_key_here"

Example response:

{
"plan": "free",
"period_start": "2026-04-01T00:00:00Z",
"period_end": "2026-05-01T00:00:00Z",
"usage": {
"agents": { "used": 3, "limit": 5 },
"calendars": { "used": 7, "limit": 10 },
"events": { "used": 1842, "limit": 5000 },
"api_calls": { "used": 12034, "limit": 50000 },
"webhook_deliveries": { "used": 956, "limit": 10000 },
"availability_queries": { "used": 304, "limit": 10000 }
}
}

When you receive a 429 response, implement exponential backoff with jitter to avoid thundering-herd problems.

async function fetchWithRetry(url, options, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status !== 429) {
return response;
}
// Use Retry-After header if present, otherwise calculate backoff
const retryAfter = response.headers.get('Retry-After');
const baseDelay = retryAfter
? parseFloat(retryAfter) * 1000
: Math.min(1000 * Math.pow(2, attempt), 30000);
// Add jitter: random delay between 0% and 100% of base delay
const jitter = Math.random() * baseDelay;
const delay = baseDelay + jitter;
console.log(`Rate limited. Retrying in ${Math.round(delay)}ms (attempt ${attempt + 1}/${maxRetries})`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
throw new Error('Max retries exceeded');
}

Quotas reset automatically at the start of each billing period. The reset is handled via KV TTL — no manual action is required. You can check your current period and usage at any time with GET /v1/usage.