Rate Limits
Per-key request budgets and how to handle 429s.
Each API key has a per-minute request budget. Exceeding it returns 429 Too Many Requests.
Default budgets
| Mode | Budget |
|---|---|
ezp_test_* | 60 requests / minute |
ezp_live_* | 600 requests / minute |
Need more? Contact support — limits can be raised per tenant.
Response headers
Every response (success or error) includes:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 1746450123X-RateLimit-Limit— your budget for the current window.X-RateLimit-Remaining— calls left in the window.X-RateLimit-Reset— Unix epoch seconds at which the window resets.
Handling 429
When you hit the limit you receive:
HTTP/1.1 429 Too Many Requests
Retry-After: 18
Content-Type: application/json
{
"error": { "code": "rate_limited", "message": "Rate limit exceeded.", "request_id": "req_..." }
}Always honor the Retry-After header (in seconds). A simple client looks like:
async function callWithBackoff(req: () => Promise<Response>) {
for (let attempt = 0; attempt < 5; attempt++) {
const res = await req();
if (res.status !== 429) return res;
const retry = Number(res.headers.get('Retry-After') ?? '1');
await new Promise((r) => setTimeout(r, retry * 1000));
}
throw new Error('Rate limited after 5 retries');
}Tips
- Batch operations where possible (e.g.
POST /v1/importsfor up to 1,000 invoices in one request). - Cache
GETresponses on your side using the resource'supdated_attimestamp. - Use webhooks instead of polling.