FeedHorizon API
Guides

Rate Limits

API rate limiting tiers, headers, and how to handle 429 responses.

Overview

FeedHorizon uses a sliding-window rate limiter per API key. Each key has a maximum number of requests allowed within a rolling time window.

Rate limit tiers

TierRequestsWindowDescription
Default10060 secondsApplied to all API keys

Rate limits are applied per API key, not per user. If you have multiple keys, each has its own independent limit.

Response headers

Every API response includes rate limit headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetSeconds until the window resets

Example response headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 42

Rate limit exceeded

When you exceed the limit, the API returns 429 Too Many Requests:

{
    "error": {
        "code": "RATE_LIMITED",
        "message": "Too many requests"
    }
}

The response still includes rate limit headers so you know when to retry.

Handling rate limits

Best practices

  1. Check headers proactively — Monitor X-RateLimit-Remaining and slow down before hitting 0
  2. Respect X-RateLimit-Reset — Wait the indicated seconds before retrying
  3. Use exponential backoff as a fallback
  4. Batch operations when possible — Create posts with all platforms in one request

Example implementation

Node.js
async function apiCall(url, options, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        const res = await fetch(url, options);

        if (res.status === 429) {
            const resetIn = parseInt(
                res.headers.get('X-RateLimit-Reset') || '60'
            );
            console.log(`Rate limited. Retrying in ${resetIn}s...`);
            await new Promise(r => setTimeout(r, resetIn * 1000));
            continue;
        }

        return res;
    }
    throw new Error('Max retries exceeded');
}
Python
import time
import requests

def api_call(url, headers, max_retries=3):
    for attempt in range(max_retries):
        res = requests.get(url, headers=headers)

        if res.status_code == 429:
            reset_in = int(res.headers.get("X-RateLimit-Reset", 60))
            print(f"Rate limited. Retrying in {reset_in}s...")
            time.sleep(reset_in)
            continue

        return res
    raise Exception("Max retries exceeded")