Limity zapytań
API stosuje limity zapytań, aby zapewnić szybkość i równe traktowanie. Limity są liczone dla aplikacji (konta API), którą identyfikuje token, a nie dla adresu IP. Są najbardziej restrykcyjne dla kosztownych endpointów:
| Endpoint | Limit |
|---|---|
POST /documents |
30 zapytań / 60 s |
POST /documents/validate |
30 zapytań / 60 s |
POST /warehouse/documents |
30 zapytań / 60 s |
GET /documents |
10 zapytań / 30 s |
GET /clients |
10 zapytań / 30 s |
GET /products |
10 zapytań / 30 s |
POST /documents/{id}/send-to-ksef |
10 zapytań / 60 s |
GET /company/nip-lookup |
10 zapytań / 60 s |
GET /documents/{id}/download |
5 zapytań / 60 s |
GET /documents/{id}/ksef-status |
5 zapytań / 60 s |
POST /ksef/connection/test |
5 zapytań / 60 s |
POST /webhooks/{id}/test |
5 zapytań / 60 s |
| Pozostałe endpointy | 45 zapytań / 60 s (wspólny licznik) |
Każda aplikacja ma własne liczniki, niezależnie od adresu IP, z którego wysyła zapytania. Kilka integracji działających na jednym serwerze nie dzieli więc limitu, jeśli każda używa własnej aplikacji, a jedna aplikacja wywoływana z kilku serwerów ma jeden wspólny limit. Każdy endpoint z tabeli ma osobny licznik, a wszystkie pozostałe endpointy dzielą jeden wspólny. Odpowiedzi niosą nagłówki X-RateLimit-Limit, X-RateLimit-Remaining i X-RateLimit-Reset (czas uniksowy końca okna); przy zapytaniu z prawidłowym tokenem opisują limit aplikacji dla wywołanego endpointu. Limit każdego endpointu jest też wypisany w jego opisie w specyfikacji OpenAPI.
Dodatkowo obowiązuje ogólny limit 240 zapytań na minutę z jednego adresu IP, łącznie dla wszystkich endpointów i aplikacji. Jest sprawdzany przed uwierzytelnieniem, więc liczy też zapytania z brakującym, błędnym albo wygasłym tokenem. Takie zapytania nie zużywają limitu aplikacji. Przy zwykłym ruchu tego limitu nie odczujesz. Ma znaczenie, gdy wiele aplikacji wysyła zapytania z jednego adresu (np. zza wspólnego NAT-u) albo gdy klient ponawia zapytania z nieprawidłowym tokenem.
Po przekroczeniu któregokolwiek limitu otrzymasz odpowiedź 429 z kodem RATE_LIMIT_EXCEEDED i nagłówkiem Retry-After (liczba sekund). Wycofaj się i ponów zapytanie, najlepiej z wykładniczym wycofywaniem i losowym odchyleniem (jitter). Jeśli zapytanie zawierało nagłówek Idempotency-Key, ponawianie jest bezpieczne.
async function withRetry<T>(fn: () => Promise<Response>): Promise<T> {
for (let i = 0; i < 5; i++) {
const res = await fn();
if (res.status !== 429) return res.json() as Promise<T>;
const retryAfter = Number(res.headers.get('Retry-After') ?? 0) * 1000;
const wait = Math.max(retryAfter, Math.min(2 ** i * 500 + Math.random() * 250, 8000));
await new Promise(r => setTimeout(r, wait));
}
throw new Error('rate limited');
}
Projektuj z myślą o limitach: buforuj token OAuth, grupuj zapytania tam, gdzie to możliwe, i zamiast odpytywania preferuj webhooki.
Uczciwe korzystanie
Limity zapytań istnieją po to, by API było szybkie dla wszystkich. Po przekroczeniu limitu uszanuj nagłówek Retry-After i wycofaj się (wykładniczy backoff z jitterem). Klient, który ignoruje 429 i dalej zarzuca endpoint zapytaniami, zostaje objęty krótkim automatycznym cooldownem, który wydłuża się przy kontynuacji, więc zawsze opłaca się zwolnić, a nie ponawiać agresywniej. Uporczywe lub rażące nadużycia mogą skończyć się czasowym zawieszeniem klienta API. Jeśli Twój przypadek naprawdę wymaga wyższych limitów, skontaktuj się z pomocą zamiast obchodzić ograniczenia.