Skip to main content
The SeamlessOS API implements generous rate limits designed to accommodate normal usage patterns while protecting against abusive calling patterns that could impact service quality.

How It Works

Generous limits: Our rate limits are set well above typical integration needs, allowing you to build robust applications without worrying about hitting limits during normal operation. Fair usage: Rate limiting protects all users by preventing excessive requests that could degrade performance for everyone. We focus on identifying and limiting abusive patterns rather than restricting legitimate usage. Automatic reset: Rate limit windows reset automatically, so temporary spikes in usage won’t permanently impact your integration.

When Limits Apply

Rate limits are applied per API key and are designed to catch:
  • Runaway scripts or infinite loops
  • Bulk operations without proper throttling
  • Unusually high request volumes that exceed normal business patterns

Rate Limit Exceeded

When limits are exceeded, you’ll receive a 429 Too Many Requests response with a Retry-After header indicating how long to wait:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "message": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "hint": "Wait before retrying or reduce request frequency"
}

Best Practices

Respect Retry-After: When you receive a 429 response, use the Retry-After header value to determine how long to wait before retrying. Implement exponential backoff: For retries without a Retry-After header, use exponential backoff with jitter to avoid thundering herd problems. Batch operations: For bulk operations, process items in batches with delays between requests rather than sending all requests simultaneously. Cache responses: Cache API responses when appropriate to reduce the number of requests needed.

Example Retry Logic

async function makeRequestWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

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

    if (attempt === maxRetries) {
      throw new Error('Rate limit exceeded after max retries');
    }

    // Use Retry-After header if provided, otherwise exponential backoff
    const retryAfter = response.headers.get('Retry-After');
    const delay = retryAfter
      ? parseInt(retryAfter) * 1000
      : Math.pow(2, attempt) * 1000;

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