Skip to content

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

  1. When you receive 429, read Retry-After header
  2. Wait Retry-After + 1-2 seconds (buffer for clock skew)
  3. Retry the request
  4. 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).