Skip to main content
The Clix API enforces rate limits to maintain service quality and fair resource allocation. Rate limiting ensures all projects can reliably use the platform without any single project impacting others.

How Rate Limiting Works

The Clix API uses a token bucket algorithm to manage request rates. Here’s how it works:
  1. Token Bucket - Each project starts with a fixed number of tokens
  2. Request Cost - Each API request consumes one token
  3. Refill - The token bucket refills at regular intervals
  4. Tracking - Rate limits are tracked per project using the X-Clix-Project-ID header
When your bucket has tokens available, requests succeed. When tokens are exhausted, requests receive a 429 Too Many Requests response until the bucket refills.

Rate Limit Policy

API GroupLimitTime Window
Management Operations1,000 requests1 second
Management Operations include:
  • User management endpoints (create, update, delete users)
  • Message sending endpoints
  • Campaign triggering endpoints

Understanding Response Headers

Every API response includes rate limit information in the response headers:
HeaderDescriptionExample
X-RateLimit-LimitTotal tokens in your bucket (requests per refill period)1000
X-RateLimit-RemainingTokens available right now842
X-RateLimit-ResetUnix timestamp (seconds) when bucket refills1699617005
These headers let you monitor your current token balance and plan your requests accordingly.

When You Hit a Rate Limit

Exceeding your rate limit results in a 429 Too Many Requests HTTP response:
{
  "error": "Too Many Requests"
}

What Happens Next

  • Your bucket is temporarily empty (no tokens available)
  • The bucket automatically refills after the interval specified in your rate limit
  • For Management API: The bucket refills every 1 second with 1,000 tokens
  • You can immediately retry after the refill time shown in X-RateLimit-Reset header

Retry-After Header

When rate limited, the response includes:
Retry-After: 1
This tells you how many seconds to wait before your next request will likely succeed.

Designing for Scale

Strategy 1: Exponential Backoff Retry Logic

When receiving a 429 response, automatically retry with increasing delays:
async function retryWithBackoff(makeRequest, maxRetries = 3) {
  let lastError;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await makeRequest();
    } catch (error) {
      if (error.status !== 429) throw error;

      lastError = error;
      if (attempt < maxRetries - 1) {
        // Exponential backoff: 1s, 2s, 4s, etc.
        const delay = Math.pow(2, attempt) * 1000;
        await new Promise(resolve => setTimeout(resolve, delay));
      }
    }
  }

  throw lastError;
}

Strategy 2: Request Batching and Sequencing

Group operations and spread them over time to avoid burst traffic:
// Batch user creation across time intervals
async function createUsersBatched(users, batchDelayMs = 100) {
  for (const user of users) {
    await api.createUser(user);
    await new Promise(resolve => setTimeout(resolve, batchDelayMs));
  }
}

// Call it
await createUsersBatched(['user1', 'user2', 'user3'], 50);

Strategy 3: Monitor Token Bucket State

Use response headers to track your token consumption and adjust pacing:
const response = await fetch(url, options);
const limit = parseInt(response.headers.get('X-RateLimit-Limit'), 10);
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'), 10);
const resetTime = parseInt(response.headers.get('X-RateLimit-Reset'), 10);
const now = Math.floor(Date.now() / 1000);

console.log(`Tokens: ${remaining}/${limit}`);
console.log(`Refill in: ${resetTime - now} seconds`);

// If approaching empty bucket, slow down
if (remaining < 100) {
  console.log('Approaching rate limit - reducing request pace');
  // Implement adaptive throttling
}
This approach prevents hitting the limit by detecting high consumption patterns early.

Token Bucket Example

Here’s a visual representation of how tokens flow:
Time 0s:   [Bucket: 1000 tokens]
           Request 1 → [Remaining: 999 tokens]
           Request 2 → [Remaining: 998 tokens]
           ...
           Request 500 → [Remaining: 500 tokens]

Time 0.5s: [Bucket: 500 tokens] (still in current refill period)
           Request 501 → [Remaining: 499 tokens]
           Request 502 → [Remaining: 498 tokens]
           ...
           Request 1000 → RATE LIMITED (429)

Time 1s:   [Bucket: REFILLS to 1000 tokens]
           (Retry your request)
           Request 1000 → [Remaining: 999 tokens]

Calculating Request Rates

With a 1,000 token limit per 1 second refill:
  • Sustained rate: ~1,000 requests/second
  • Burst capacity: Up to 1,000 consecutive requests before rate limiting
  • Recovery time: 1 second for full bucket refill
Plan your integration accordingly:
  • For steady workloads: Distribute requests evenly across the 1-second window
  • For bursty workloads: Use retries and backoff when approaching the limit

Request Higher Limits

If your use case requires higher rate limits: Include your expected request patterns (steady vs. bursty) and peak throughput needs.