Rate Limits and Quotas¶
This document describes rate limiting enforcement for the Integration API.
What Are Rate Limits¶
Rate limits prevent excessive API usage and ensure fair resource allocation. When your usage exceeds the configured limit, requests return HTTP 429 until the window resets.
Rate Limit Buckets¶
Different operations are grouped into buckets with independent limits.
Current Limits¶
| Bucket | Default Limit | Applies To |
|---|---|---|
read |
60 requests/minute | GET /api/v1/events, searches |
write |
100 requests/minute | POST, PATCH, DELETE operations |
admin |
200 requests/minute | Test events, webhook operations |
Limits are per API key, per minute.
Read Bucket¶
Operations:
- GET /api/v1/events - Polling for events
- GET /api/v1/webhooks/subscriptions - Listing subscriptions
- Search endpoints (Find Client, Find Lead)
Limit: 60 requests/minute
Use case: High-frequency polling or bulk lookups
Write Bucket¶
Operations: - Creating records (leads, clients, affiliates) - Updating records - Adding notes - Deleting subscriptions
Limit: 100 requests/minute
Use case: Inbound data sync, bulk imports
Admin Bucket¶
Operations:
- POST /api/v1/events/test - Generate test events
- POST /api/v1/webhooks/subscriptions - Create subscriptions
- PATCH /api/v1/webhooks/subscriptions/{id} - Update subscriptions
Limit: 200 requests/minute
Use case: Administrative setup and testing
Rate Limit Headers¶
Every successful API response includes rate limit information in headers.
Response Headers¶
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1737739532
X-RateLimit-Window: 1m
X-RateLimit-Policy: read:60/1m
Fields:
- X-RateLimit-Limit - Total requests allowed in the window
- X-RateLimit-Remaining - Requests remaining before limit
- X-RateLimit-Reset - Unix timestamp when the window resets
- X-RateLimit-Window - Window duration (e.g., 1m)
- X-RateLimit-Policy - Bucket identifier and policy
Checking Before Requests¶
Monitor X-RateLimit-Remaining before bulk operations:
- If remaining count is low, pause or slow down
- Wait until X-RateLimit-Reset timestamp to resume full speed
Rate Limit Exceeded (429)¶
When It Happens¶
You receive HTTP 429 when:
- Request count exceeds the bucket limit within the window
- Example: 61st request within 1 minute for read bucket
Response Format¶
{
"error": "Rate limit exceeded",
"retryAfter": 12,
"limit": 60,
"window": "1m",
"policy": "read:60/1m",
"resetUtc": "2026-01-28T18:45:32.000Z",
"currentUsage": 61
}
Fields:
- retryAfter - Seconds to wait before retrying
- limit - Total allowed requests
- window - Window duration
- policy - Which bucket was exceeded
- resetUtc - When the window resets
- currentUsage - How many requests were made
Retry-After Header¶
The Retry-After header contains the recommended wait time in seconds.
Retry-After: 12
Handling Rate Limits¶
Recommended Retry Strategy¶
- When you receive 429, read
Retry-Afterheader - Wait
Retry-After + 1-2 seconds(buffer for clock skew) - Retry the request
- Respect exponential backoff if multiple 429s occur
Example (pseudocode):
if status == 429:
retry_after = response.headers['Retry-After']
sleep(retry_after + 2)
retry_request()
Proactive Throttling¶
Instead of hitting limits, monitor X-RateLimit-Remaining:
- If remaining < 10, slow down request rate
- Distribute requests evenly across the window
- Use batch endpoints if available (future enhancement)
Backoff for Repeated 429s¶
If you receive multiple 429s in succession:
- First 429: Wait Retry-After seconds
- Second 429: Wait Retry-After * 2 seconds
- Third 429: Wait Retry-After * 4 seconds
This indicates sustained overuse; adjust your request pattern.
System Contention (503)¶
What It Means¶
HTTP 503 with "reason": "lock_timeout" is not a rate limit violation. It means the rate limit system is temporarily busy.
Response:
{
"error": "Rate limit check busy",
"reason": "lock_timeout",
"retryAfter": 1,
"message": "Rate limiting backend is experiencing high contention."
}
Resolution: Retry after 1-2 seconds. This is transient, not a usage issue.
Best Practices¶
Request Pacing¶
- Polling: Poll at reasonable intervals (30-60 seconds, not every second)
- Batch operations: Spread writes over time; don't burst 100 requests instantly
- Off-peak usage: Schedule bulk imports during low-traffic periods if possible
Separate API Keys¶
Use different API keys for different integrations: - Each key has its own rate limit counters - Prevents one integration from exhausting quota for another - Example: Separate keys for Zapier and HubSpot sync
Caching Results¶
For read-heavy operations: - Cache search results locally - Avoid re-fetching the same event multiple times - Use webhook subscriptions instead of polling when possible
Monitoring Usage¶
Track your rate limit consumption:
- Log X-RateLimit-Remaining after each request
- Alert if consistently hitting limits
- Adjust request patterns proactively
Quota Increases¶
When to Request¶
Default limits are sufficient for most integrations. Request an increase if: - You consistently hit limits during normal operations - Your use case requires higher throughput (document the reason)
How to Request¶
Contact your account manager or WhiteLabelCRO support to request quota increases. Include use case details and expected request volume.
Temporary vs Permanent¶
Both temporary (for one-time bulk operations) and permanent quota increases may be available based on your account and use case.
Troubleshooting¶
Constant 429 Errors¶
Symptom: Every request or most requests return 429
Causes: - Requests too frequent (bursting) - Multiple integrations using same API key - Polling interval too aggressive
Resolution: - Slow down request rate - Use separate API keys per integration - Increase polling interval (e.g., 60 seconds instead of 5 seconds)
Intermittent 429 Errors¶
Symptom: Occasional 429s during bulk operations
Expected behavior: You're near the limit. This is normal during high-volume periods.
Resolution:
- Implement proper retry logic with Retry-After
- Spread bulk operations over longer time windows
429 on Single Request¶
Symptom: First request of the day returns 429
Unlikely: Rate limits are per-minute windows; a single request shouldn't trigger 429.
Check: - Another process using the same API key? - Key shared across multiple systems?
Wrong Bucket Enforced¶
Symptom: Receiving 429 sooner than expected based on bucket limit
Check:
- Which bucket the endpoint uses (see error response policy field)
- Some endpoints may use different buckets than expected
Example: Webhook operations use admin bucket (200/min), not write (100/min).