Skip to main content
The Vendaze API enforces rate limits per app (client_id) per minute to ensure fair usage and protect service availability.

Limits by HTTP method

MethodLimitApplies to
GET1,000 req/minAll /v1/* endpoints
POST200 req/minAll /v1/* endpoints
PATCH200 req/minAll /v1/* endpoints
DELETE100 req/minAll /v1/* endpoints
OAuth endpoints have stricter per-IP limits:
EndpointLimit
POST /oauth/token20 req/min per IP
POST /oauth/revoke20 req/min per IP
GET /oauth/authorize20 req/min per IP
POST /v1/auth/register-app10 req/hour per IP
POST /v1/auth/rotate-app10 req/hour per IP

Rate limit headers

Every response includes headers showing your current usage:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1748000060
HeaderDescription
X-RateLimit-LimitTotal limit for the current window.
X-RateLimit-RemainingRequests remaining in the window.
X-RateLimit-ResetUnix timestamp when the window resets.

When the limit is exceeded

HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Try again in 60 seconds.",
    "request_id": "uuid"
  }
}
Use exponential backoff with jitter when you receive a 429:
async function withRetry(fn, maxAttempts = 3) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await fn();
    if (res.status !== 429) return res;

    const retryAfter = parseInt(res.headers.get('Retry-After') ?? '60');
    const jitter = Math.random() * 1000;
    await new Promise((r) => setTimeout(r, retryAfter * 1000 + jitter));
  }
  throw new Error('Max retry attempts exceeded');
}