Working With Rate Limits

A rate limit is like having a bucket with a limited number of tokens. Each API request uses one token from your bucket. The bucket refills with new tokens over time, but if you use all your tokens, you’ll need to wait for more to be added before making additional requests.

How Rate Limits Work

Think of rate limiting like a water faucet with a flow regulator:

  1. Token Bucket: You start with a full bucket of 100 request tokens
  2. Request Consumption: Each API call uses one token from your bucket
  3. Bucket Refill: Your bucket refills completely every 60 seconds
  4. Overflow Protection: If your bucket is empty, you must wait for it to refill before making more requests

The system tracks your usage in real-time and provides information about your current status through response headers.

Rate Limit Tracking

Rate limits work differently depending on your authentication method:

When using OAuth 2.0 with Bearer tokens, rate limits are tracked per-user. Each user who authorizes your application gets their own separate rate limit bucket. This means:

  • User A’s API usage doesn’t affect User B’s limits
  • Multiple applications using the same user’s token share that user’s rate limit
  • This provides fair usage distribution across all users

Tracking Your Usage

Every API response includes headers that tell you about your current rate limit status:

Response Headers

X-RateLimit-Limit
The total number of requests allowed in the current time window.

X-RateLimit-Limit: 100

X-RateLimit-Remaining
The number of requests you have left in the current time window.

X-RateLimit-Remaining: 75

X-RateLimit-Reset
A Unix timestamp indicating when your rate limit will reset (when your bucket refills).

X-RateLimit-Reset: 1672531200

Retry-After (when rate limited)
When you exceed your rate limit, this header tells you how many seconds to wait before trying again.

Retry-After: 30

Example Response Headers

Here’s what you might see in a successful response:

1HTTP/1.1 200 OK
2X-RateLimit-Limit: 100
3X-RateLimit-Remaining: 45
4X-RateLimit-Reset: 1672531200
5Content-Type: application/json
6
7{
8 "uuid": "123e4567-e89b-12d3-a456-426614174000",
9 "email": "user@example.com"
10}

When You Exceed Rate Limits

If you make too many requests and exceed your rate limit, you’ll receive a 429 Too Many Requests response:

1HTTP/1.1 429 Too Many Requests
2X-RateLimit-Limit: 100
3X-RateLimit-Remaining: 0
4X-RateLimit-Reset: 1672531200
5Retry-After: 45
6Content-Type: application/json
7
8{
9 "error": "Too many requests"
10}

This response tells you:

  • You’ve used all 100 of your allowed requests
  • You have 0 requests remaining
  • Your limit will reset at timestamp 1672531200
  • You should wait 45 seconds before making another request

Working with Rate Limits In Your App

Handle Rate Limit Errors

Implement proper error handling for rate limit responses:

1async function makeAPIRequest(url, accessToken) {
2 const response = await fetch(url, {
3 headers: {
4 Authorization: `Bearer ${accessToken}`,
5 },
6 });
7
8 if (response.status === 429) {
9 const retryAfter = response.headers.get("Retry-After");
10 console.log(`Rate limited. Retry after ${retryAfter} seconds`);
11
12 // Wait and retry
13 await new Promise((resolve) => setTimeout(resolve, retryAfter * 1000));
14 return makeAPIRequest(url, accessToken);
15 }
16
17 return response.json();
18}

Best Practices

Implement Exponential Backoff
When you hit rate limits, wait progressively longer between retry attempts.

Batch Your Requests
If possible, combine multiple operations into fewer API calls.

Cache Responses
Store API responses locally to reduce the number of requests you need to make.

Monitor Continuously
Keep track of your rate limit headers to avoid hitting limits unexpectedly.

Plan for Peak Usage
Consider your application’s peak usage patterns and design accordingly.

Python Example

1import requests
2import time
3
4def make_request_with_retry(url, access_token, max_retries=3):
5 headers = {
6 'Authorization': f'Bearer {access_token}'
7 }
8
9 for attempt in range(max_retries + 1):
10 response = requests.get(url, headers=headers)
11
12 # Check rate limit headers
13 remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
14 print(f"Requests remaining: {remaining}")
15
16 if response.status_code == 429:
17 if attempt < max_retries:
18 retry_after = int(response.headers.get('Retry-After', 60))
19 print(f"Rate limited. Waiting {retry_after} seconds...")
20 time.sleep(retry_after)
21 continue
22 else:
23 raise Exception("Max retries exceeded")
24
25 return response.json()