Skip to main content
The AppKittie API enforces rate limits to ensure fair usage and platform stability. Rate limits are applied per API key with a sliding window of 60 seconds.

Rate Limit Headers

Every response includes rate limit information:
HeaderDescription
X-RateLimit-LimitMaximum number of requests allowed per 60-second window
X-RateLimit-RemainingNumber of requests remaining in the current window
X-RateLimit-ResetUnix timestamp (seconds) when the current window resets

Example response headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 47
X-RateLimit-Reset: 1711497600

Rate Limit Exceeded

When you exceed the rate limit, the API returns a 429 status code:
{
  "error": "Rate limit exceeded"
}
The response still includes the rate limit headers, so you know when to retry:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711497600

Handling Rate Limits

import time
import requests

def make_request(url, headers):
    response = requests.get(url, headers=headers)

    if response.status_code == 429:
        reset_at = int(response.headers.get("X-RateLimit-Reset", 0))
        wait_seconds = max(reset_at - int(time.time()), 1)
        print(f"Rate limited. Retrying in {wait_seconds}s...")
        time.sleep(wait_seconds)
        return make_request(url, headers)

    return response

Best Practices

Always check X-RateLimit-Remaining before making requests. If it’s low, space out your calls.
If you receive a 429, wait for the time indicated by X-RateLimit-Reset. If the header is missing, use exponential backoff starting at 1 second.
Use the batch keyword endpoint (POST /api/v1/keywords/difficulty) to check up to 10 keywords in a single request instead of making 10 separate calls.
If you’re making many requests, track remaining quota across all concurrent requests to avoid bursting over the limit.