Rate Limiting

Understanding and handling API rate limits to build reliable integrations.

Rate Limit Overview

Rate limits protect the platform and ensure fair usage. Limits are applied per API key and vary by endpoint and plan.

Default Limits

PlanRequests/SecondRequests/Day
Starter1010,000
Professional50100,000
EnterpriseCustomCustom

Endpoint-Specific Limits

Endpoint CategoryLimitNotes
Read operations100/sGET requests
Write operations20/sPOST, PUT, DELETE
Transaction signing5/sSecurity measure
AI inference10/sModel dependent

Rate Limit Headers

Every response includes rate limit information:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1705312800
Retry-After: 60
HeaderDescription
X-RateLimit-LimitMaximum requests in the window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the limit resets
Retry-AfterSeconds to wait (only on 429 response)

Handling Rate Limits

429 Too Many Requests

When you exceed rate limits, the API returns a 429 status:

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after 60 seconds.",
    "retryAfter": 60
  }
}

Exponential Backoff

Implement exponential backoff for retry logic:

async function requestWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 3
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    const retryAfter = response.headers.get('Retry-After');
    const delay = retryAfter
      ? parseInt(retryAfter) * 1000
      : Math.pow(2, attempt) * 1000;

    await new Promise(r => setTimeout(r, delay));
  }

  throw new Error('Max retries exceeded');
}

Best Practices

Request Batching

Batch multiple operations when possible:

// Instead of multiple requests
for (const wallet of wallets) {
  await api.getWallet(wallet.id);
}

// Use batch endpoint
const wallets = await api.getWallets({ ids: walletIds });

Caching

Cache responses when appropriate:

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

async function getCachedWallet(id: string) {
  const cached = cache.get(id);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  const wallet = await api.getWallet(id);
  cache.set(id, { data: wallet, timestamp: Date.now() });
  return wallet;
}

Client-Side Rate Limiting

Implement client-side limits to prevent hitting server limits:

import Bottleneck from 'bottleneck';

const limiter = new Bottleneck({
  minTime: 100,      // 10 requests per second
  maxConcurrent: 5   // Max 5 concurrent requests
});

const limitedFetch = limiter.wrap(fetch);

// All requests go through the limiter
const response = await limitedFetch('/api/wallet/list');

Monitoring Usage

Track your API usage to avoid hitting limits:

  • Monitor X-RateLimit-Remaining headers
  • Set up alerts when usage exceeds 80%
  • Review usage patterns in the console dashboard
  • Contact support to increase limits if needed