Rate Limiting

The Otesse API enforces rate limits to ensure fair usage and platform stability.

Default Limits

PlanRate LimitBurst Limit
Standard100 requests/minute20 requests/second
Professional500 requests/minute50 requests/second
Enterprise2,000 requests/minute200 requests/second

Limits are applied per API key. If you have multiple keys, each has its own independent limit.

Rate Limit Headers

Every API response includes rate limit information:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1709000400
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Handling 429 Responses

When you exceed the rate limit, the API returns:

HTTP/1.1 429 Too Many Requests
Retry-After: 30
{
  "error": {
    "type": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Please retry after 30 seconds.",
    "retry_after": 30
  }
}

Implementing Backoff

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

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '30');
      console.log(`Rate limited. Retrying after ${retryAfter}s (attempt ${attempt + 1})`);
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      continue;
    }

    return response;
  }

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

Best Practices

  • Cache responses — Store frequently-accessed data locally instead of re-fetching
  • Use webhooks — Subscribe to events instead of polling for changes
  • Batch operations — Use list endpoints with filters instead of individual lookups
  • Monitor usage — Track your X-RateLimit-Remaining to proactively slow down
  • Use exponential backoff — When rate limited, wait progressively longer between retries