LedgerCore
Getting Started

Rate Limits

Understanding API rate limits and how to work within them.

Rate Limit Tiers

LedgerLink implements tiered rate limiting based on your subscription:

TierRequests/MinuteRequests/HourRequests/Day
Free601,00010,000
Pro30010,000100,000
EnterpriseCustomCustomCustom

Rate Limit Headers

Every API response includes rate limit information in the headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1642694400
  • X-RateLimit-Limit - Maximum requests allowed in the current window
  • X-RateLimit-Remaining - Requests remaining in the current window
  • X-RateLimit-Reset - Unix timestamp when the rate limit resets

Handling Rate Limits

429 Too Many Requests

When you exceed the rate limit, you'll receive a 429 response:

{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Please retry after 30 seconds.",
    "retryAfter": 30
  }
}

Best Practices

1. Monitor Headers

const response = await fetch(url, options);
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');

if (remaining < 10) {
  console.warn('Approaching rate limit');
}

2. Implement Exponential Backoff

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);
    
    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      continue;
    }
    
    return response;
  }
  throw new Error('Max retries exceeded');
}

3. Batch Requests

// Instead of multiple single requests
const symbols = ['BTC-USD', 'ETH-USD', 'SOL-USD'];

// Use the unified query engine
const response = await fetch('http://localhost:8090/api/v1/query', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    connector: 'market-data',
    filters: {
      symbol: { $in: symbols }
    }
  })
});

4. Cache Responses

const cache = new Map();
const CACHE_TTL = 60000; // 1 minute

async function fetchWithCache(url, options) {
  const cacheKey = url;
  const cached = cache.get(cacheKey);
  
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }
  
  const response = await fetch(url, options);
  const data = await response.json();
  
  cache.set(cacheKey, {
    data,
    timestamp: Date.now()
  });
  
  return data;
}

Upgrading Your Tier

Need higher rate limits? Contact us:

WebSocket Alternative

For real-time data, consider using our WebSocket API which has separate, more generous limits:

const ws = new WebSocket('ws://localhost:8090/ws/ws');

ws.onopen = () => {
  ws.send(JSON.stringify({
    action: 'subscribe',
    channel: 'candles',
    symbol: 'BTC-USD'
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('New candle:', data);
};

Next Steps

Was this page helpful?