API Rate Limits and Retry Strategy

Authentication

All requests to the API must include a valid Bearer Token in the Authorization header (recommended) or in the bearer_token GET parameter:

Authorization: Bearer <your_access_token>

OR

https://www.readycloud.com/api/v2/orgs/?bearer_token=<your_access_token>

Rate Limits

Every bearer token is associated to an API client, which is subject to rate limiting. Our production API enforces strict throttling rules to ensure fair usage and stability:

  • GET requests: up to 30 requests per minute;
  • POST / PATCH / DELETE requests: up to 30 requests per minute.

If these limits are exceeded, the server will respond with:

HTTP 429 Too Many Requests

Handling Throttling

When a 429 Too Many Requests response is received, you must back off before retrying. We recommend using an Exponential Backoff strategy.

Exponential Backoff Algorithm

On the first failure, wait for a short period (e.g., 1 second). On each subsequent failure, double the wait time, until a max time is reached and then repeated (e.g. 128s): 1, 2, 4, 8, 16, 32, 64, 128, 128, 128, ... . Optionally, add a small random “jitter” to avoid collisions between multiple clients retrying at the same time.

Request → Success → Done
   ↓
429 Too Many Requests
   ↓
 Wait 1s → Retry
   ↓
429 Too Many Requests
   ↓
 Wait 2s → Retry
   ↓
429 Too Many Requests
   ↓
 Wait 4s → Retry
   ↓
... (continues with 8s, 16s, etc.)

Python Example

Here’s a simple Python implementation of exponential backoff with requests:

import time
import random
import requests
import itertools

API_URL = "https://www.readycloud.com/api/v2/orgs/"
TOKEN = "<your_access_token>"

headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json"
}

def make_request_with_backoff(max_retries=5, base_delay=1):
    delay = base_delay
    for attempt in itertools.count(1):
        if max_retries and attempt > max_retries:
            break
        response = requests.get(API_URL, headers=headers)

        if response.status_code == 200:
            return response.json()

        if response.status_code == 429:
            print(f"Rate limit hit. Retrying in {delay:.1f}s...")
            time.sleep(delay + random.uniform(0, 0.5))  # adding random jitter
            delay *= 2
        else:
            response.raise_for_status()

    raise Exception("Max retries reached due to throttling.")

# Example usage:
data = make_request_with_backoff()
print(data)

Best Practices

  • Implement exponential backoff with jitter for all API clients.
  • Monitor 429 Too Many Requests responses in your logs.
  • If possible, spread requests evenly instead of sending them in bursts.