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
| Window | Limit | Type |
|---|---|---|
| Per minute | 2,000 requests | Sliding window |
| Per hour | 20,000 requests | Fixed window |
| Per day | 100,000 requests | Fixed 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:
{
"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
- Check for HTTP 429 status code
- Read
retryAfterfrom the response body - Wait the specified duration before retrying
- Implement exponential backoff if retries continue to fail
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