Skip to main content
The API enforces rate limits to ensure fair usage and protect infrastructure. Limits are applied per merchant for authenticated requests and per IP address for unauthenticated requests.

Rate limit tiers

TierScopeLimitWindow
AuthenticatedPer merchant1,500 requests1 minute
Sensitive endpointsPer merchant10 requests1 minute
UnauthenticatedPer IP address100 requests1 minute

Sensitive endpoints

The following endpoints have stricter rate limits due to their security-sensitive nature:
  • /v1/api_keys — API key management

Rate limit headers

Every API response includes headers to help you track your usage:
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds to wait before retrying (only on 429 responses)

Rate limit error response

When you exceed the rate limit, the API returns a 429 status code:
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after the period specified in the Retry-After header.",
    "param": null,
    "doc_url": "https://docs.leanrails.com/guides/rate-limiting"
  }
}

Handling rate limits

Implement exponential backoff with jitter to handle rate limit responses gracefully:
async function requestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

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

    const retryAfter = parseInt(response.headers.get("Retry-After") || "1", 10);
    const jitter = Math.random() * 0.5;
    const delay = (retryAfter + jitter) * 1000;

    console.warn(`Rate limited. Retrying in ${delay / 1000}s...`);
    await new Promise((resolve) => setTimeout(resolve, delay));
  }

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

Best practices

Distribute requests evenly. Avoid sending large bursts of requests. Spread API calls over time to stay within limits.
  • Cache responses when possible to reduce unnecessary API calls
  • Use exponential backoff with jitter to avoid thundering herd problems when retrying
  • Monitor rate limit headers to proactively throttle before hitting limits
  • Use idempotency keys so retried requests don’t create duplicate resources