Guides

Rate limits

Rate limits protect the platform and keep response times predictable for everyone. Limits are enforced per credential across all Talero servers.

Limits

Scope of limitLimitWindow
API requests, per credential (API key or OAuth access token)100 requests60 seconds
OAuth token endpoint (POST /api/oauth/token), per client and IP10 requests60 seconds

Response headers

Every authenticated response — success or error, including the 429 itself — reports the state of your window. Responses that never identified a credential (for example a 401 for an invalid key) carry no rate-limit headers:

HeaderDescription
X-RateLimit-LimitRequests allowed per window (100).
X-RateLimit-RemainingRequests remaining in the current window.
X-RateLimit-ResetSeconds until the current window resets.

Handling 429

When the limit is exceeded, the API returns 429 with problem code rate_limited and a Retry-After header (seconds):

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 17
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 17

{
  "type": "https://docs.talero.dk/problems/rate_limited",
  "title": "Rate limit exceeded",
  "status": 429,
  "detail": "Rate limit exceeded.",
  "code": "rate_limited"
}

Honor Retry-After when present, and fall back to exponential backoff with jitter:

Node.js
async function taleroFetch(url, options = {}, maxAttempts = 5) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch(url, {
      ...options,
      headers: { 'X-API-Key': process.env.TALERO_API_KEY, ...options.headers },
    });

    if (response.status !== 429) return response;
    if (attempt === maxAttempts) return response;

    const retryAfter = Number(response.headers.get('Retry-After'));
    const backoff = Number.isFinite(retryAfter) && retryAfter > 0
      ? retryAfter * 1000
      : Math.min(60_000, 1000 * 2 ** (attempt - 1));
    const jitter = Math.random() * 250;
    await new Promise((resolve) => setTimeout(resolve, backoff + jitter));
  }
}

Staying under the limit

  • Use webhooks instead of polling for changes.
  • Request up to 200 items per page instead of many small pages — see Pagination.
  • Use since/until filters to fetch only what changed.
  • Watch X-RateLimit-Remaining and slow down before you hit zero.
  • Cache OAuth access tokens for their full one-hour lifetime; do not request a new token per API call.