Rate Limiting
Rate limit policies, response headers, and backoff strategies.
Limits
The API enforces two levels of rate limiting:
| Scope | Limit | Window |
|---|---|---|
| Per API key | 1,000 requests | 1 hour |
| Per team (all keys combined) | 3,000 requests | 1 hour |
Both limits apply simultaneously. The more restrictive limit takes effect first.
Response headers
Every successful response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp (milliseconds) when the window resets |
When you hit the limit
When either limit is exceeded, the API returns a 429 response with:
{
"error": "Rate limit exceeded",
"code": "rate_limit"
}Additional headers on 429 responses:
| Header | Description |
|---|---|
Retry-After | Seconds to wait before retrying |
Backoff strategy
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options)
if (response.status !== 429) return response
const retryAfter = response.headers.get('Retry-After')
const delay = retryAfter
? Number(retryAfter) * 1000
: Math.min(1000 * Math.pow(2, attempt), 30000)
console.log(`Rate limited. Retrying in ${delay}ms...`)
await new Promise(resolve => setTimeout(resolve, delay))
}
throw new Error('Max retries exceeded')
}Tips
Reduce API calls
Cache responses — deal room metadata doesn't change frequently. A 1-5 minute cache can dramatically reduce your request count.
- Use pagination wisely — Request
per_page=100to reduce the number of requests needed for large datasets. - Distribute load — If you have multiple integrations, give each its own API key so one hitting the limit doesn't block others.