Rate limits
Two windows, per-key buckets, and a recommended retry strategy.
The public API uses two parallel rate-limit windows per API key. The strictest one wins.
| Window | Limit | Purpose |
|---|---|---|
| Burst | 10 requests / second | Catches accidental loops + thundering herds. |
| Sustained | 60 requests / minute | Fair-use ceiling for long-running ingests. |
Limits are tracked per key, not per IP. Multiple integrations behind the same NAT or load balancer don't share buckets, and a single integration distributed across multiple servers doesn't get N× the limit by accident.
When you hit a limit
You get an HTTP 429 with the standard error envelope:
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Try again later.",
"request_id": "req_…"
}
}Retry strategy
For burst hits (you sent 11 requests in a second), waiting one second is enough. For sustained hits, the bucket replenishes over the next minute.
Recommended: exponential backoff with jitter, max 3 retries.
async function call<T>(url: string, apiKey: string): Promise<T> {
for (let attempt = 0; attempt < 3; attempt++) {
const res = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` },
});
if (res.status !== 429) {
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${error.code}: ${error.message}`);
}
return res.json();
}
// Backoff: 1s, 2s, 4s with ±25% jitter
const base = 2 ** attempt * 1000;
const jitter = base * (Math.random() * 0.5 - 0.25);
await new Promise((r) => setTimeout(r, base + jitter));
}
throw new Error('Rate limit retries exhausted');
}Tips for staying under the limit
- Paginate, don't poll. Use cursor pagination to walk a list once, rather than re-requesting page 1 repeatedly.
- Cache aggressively. The reference data (meeting metadata,
transcripts) is immutable once a transcript is
COMPLETED. Cache in your own store; only refetch when polling for status transitions. - Use one key per integration. Each integration has its own bucket. Splitting across keys means a heavy CRM sync won't starve a real-time Slack bot.
- Pull at off-peak hours. Bulk backfills tolerate latency better than user-triggered requests; schedule them overnight in your time zone.
Custom limits
If your integration has a legitimate reason to need higher limits (large org, real-time-ish needs), reach out via support with your expected QPS and use case. We'll adjust your key's bucket without a contract amendment for reasonable asks.