Skip to main content

Rate Limiting

Debitura enforces rate limits on all external APIs to protect system stability. The limiter partitions requests by the literal XApiKey header across three time windows. Requests without that header — including Bearer-token requests — share the fallback partition.

Default Limits

WindowLimitType
Per minute2,000 requestsSliding window
Per hour20,000 requestsFixed window
Per day100,000 requestsFixed 24h window

A request is rejected if it exceeds any of the three limits. Each API key maintains independent counters.

Rate Limit Response

When you exceed a limit, the API returns HTTP 429:

429Too Many Requests
Response
Content-Type: application/json
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please try again later or contact support if you need higher limits.",
"retryAfter": 42.0
}

The retryAfter field in the JSON body indicates seconds until capacity becomes available. Debitura does not set a Retry-After response header — read retryAfter from the body instead.

Handling Rate Limits

  1. Check for HTTP 429 status code
  2. Read retryAfter from the response body
  3. Wait the specified duration before retrying
  4. Implement exponential backoff if retries continue to fail
Example: Retry with backoff
async function makeRequestWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);

if (response.status === 429) {
const { retryAfter } = await response.json();
const delay = (retryAfter || Math.pow(2, attempt)) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}

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

Key Behaviors

Sliding vs fixed windows: The per-minute limit uses a sliding window divided into 10-second segments, providing smooth limiting. The per-hour limit uses a fixed 1-hour window anchored to the partition's first request — once started it advances in 1-hour chunks tied to that anchor, and does not reset at the top of each clock hour. The per-day limit works the same way: a fixed 24-hour window aligned to the partition's first request that advances in 24-hour chunks, and does not reset at midnight UTC.

No queuing: Requests exceeding the limit are immediately rejected. Debitura does not queue requests waiting for capacity.

Requests without XApiKey: Requests with no XApiKey header are tracked under a shared fallback partition and subject to the same limits. This includes unauthenticated requests and requests authenticated with a Bearer token. A nonempty but invalid XApiKey value has its own rate-limit partition even though authentication later rejects it.

Requesting Higher Limits

If your integration requires higher throughput, contact contact@debitura.com with:

  • Your use case and expected request volume
  • Which API and endpoints you're calling
  • Whether you need burst capacity or sustained throughput