Limity żądań
Jak działają osobne limity odczytu i zapisu, co zużywa każdy z nich, jakie inne ograniczenia możesz napotkać i dlaczego współbieżność to osobna kwestia.
Limit żądań określa, ile żądań możesz wysłać w krótkim czasie. Po jego przekroczeniu API odpowiada 429 („zbyt wiele żądań”), nie wykonuje operacji i informuje, jak długo należy czekać. To zabezpieczenie przed skryptami wymykającymi się spod kontroli, a nie limit ilości generowanych treści.
Zestawienie limitów
| Limit | Wartość domyślna | Odpowiedź po osiągnięciu limitu | Szczegóły |
|---|---|---|---|
| Żądania na konto | 1 000 na 10 sekund dla odczytów i osobno tyle samo dla zapisów | 429 z Retry-After | poniżej |
| Żądania adresów do przesyłania plików | 1 000 na 10 sekund | 429 z Retry-After | poniżej |
| Zamówione, ale jeszcze niewykorzystane adresy do przesyłania plików | 128 plików lub 1 GiB | 429, czekanie nie pomoże | poniżej |
| Raport użycia | 30 na minutę; zakres 92 dni | 429 / 400 | poniżej, Rozliczenia |
| Dostępne saldo | — | 40201 | Rozliczenia |
| Limity wydatków klucza (dzienny / miesięczny / łączny) | Brak, dopóki ich nie ustawisz | 40202 | Rozliczenia |
| Dzienne / miesięczne limity zespołu | Brak | 40202 | Rozliczenia |
| Zespoły, których jesteś właścicielem / członkowie jednego zespołu | 10 / 100 | 409 w konsoli | Konsola i zespoły |
Dwa osobne limity na konto: odczyty i zapisy
Limit żądań API — wszystkich endpointów w /api/v1/* oraz zgodnych endpointów /v1/* i /v1beta/* — jest liczony na konto, a nie na klucz: limit na klucz dałoby się obejść przez tworzenie kolejnych kluczy.
Odczyty i zapisy są liczone w dwóch osobnych pulach o tej samej wielkości. Domyślny próg zabezpieczenia wynosi 1 000 żądań na 10 sekund w każdej z nich: około 100 RPS (żądań na sekundę) przy stałym ruchu, z możliwością krótkiego skoku do 1 000. To ogólne zabezpieczenie przed nadużyciami i klientem wysyłającym niekontrolowany ruch, a nie niski limit zwykłego płatnego generowania.
Mechanizm wykorzystuje token bucket, a nie licznik ze stałym oknem: pojemność wynosi 1 000, a uzupełnianie trwa 10 sekund (około 100 tokenów na sekundę). Każde żądanie zużywa jeden token; tokeny wracają równomiernie. W przeciwieństwie do stałego okna token bucket wygładza uzupełnianie na granicach okien czasowych.
Odczyty i zapisy korzystają z osobnych pul
Odczyty to wszystkie żądania GET — recordInfo, lista jobs, chat/credit, usage, models — oraz jobs/quote, które jedynie wycenia żądanie. Zapisy to wszystkie pozostałe operacje: createTask, retry, stream, purge, common/upload-url, common/download-url i zgodne endpointy generowania chat/completions, messages oraz Gemini. Endpointy natywne i zgodne z innymi protokołami dzielą te same dwie pule, więc przeniesienie integracji tekstowej z /api/v1 do /v1 nie daje dodatkowego limitu.
Odpytywanie nie może już wyczerpać limitu wysyłania zadań. Niekontrolowana pętla odpytywania wyczerpuje tylko pulę odczytów: recordInfo zaczyna zwracać 429, podczas gdy createTask nadal jest przyjmowane. Odpytywanie wciąż zużywa żądania, dlatego integracje produkcyjne powinny nadal preferować webhooki, aby ograniczyć zbędne wywołania i opóźnienia.
Katalog modeli korzysta z puli odczytów. Nie pobieraj niezmienionego schematu przed każdym zadaniem; przechowuj go w pamięci podręcznej według czasu aktualizacji i odświeżaj po błędach walidacji.
Oprócz powyższej puli zapisów upload-url ma własne ogólne zabezpieczenie 1 000 żądań na 10 sekund. Osobno chroni ono autoryzację zapisu w magazynie obiektowym; zwykłe przesyłanie plików nie powinno zbliżać się do tego progu.
usage ma dodatkowe zabezpieczenie w przeciwną stronę: znacznie niższy limit 30 żądań na minutę, oprócz opisanej powyżej puli odczytów. Endpoint agreguje historyczne zadania, więc pojedyncze wywołanie jest znacznie kosztowniejsze obliczeniowo od zwykłego odczytu i samo ogólne zabezpieczenie nie wystarcza. Używaj go do uzgadniania rozliczeń, nie jako endpointu odpytywanego w pętli. Ta pula nigdy też nie przepuszcza żądań przy awarii mechanizmu limitów: gdy nie można rozstrzygnąć limitu, zawsze zwraca 429, podczas gdy inne pule mogą być skonfigurowane tak, aby przepuszczać ruch.
Niewykorzystane adresy do przesyłania plików
Niezależnie od powyższego jedno konto może mieć najwyżej 128 jeszcze niewykorzystanych adresów do przesyłania plików lub łącznie 1 GiB zadeklarowanego rozmiaru plików powiązanych z tymi adresami. Zamówienie kolejnego zwraca 429 z Too many pending uploads; finish existing uploads before requesting more i bez Retry-After.
Czekanie tu nie pomaga, więc nie pozwól ogólnej pętli ponowień nieustannie powtarzać tego żądania. Prześlij i zatwierdź pliki, dla których adresy już zamówiono (lub poczekaj, aż te adresy wygasną, co trwa około 20 minut), a miejsce zostanie natychmiast zwolnione. Zwykle taka sytuacja oznacza, że skrypt zamawia adresy hurtowo, lecz ich nie wykorzystuje. Zobacz Media.
Wszystkie pule limitów
Limity są przypisywane do poszczególnych obszarów API, dlatego wszystko w jednym obszarze przechodzi przez ten sam łańcuch middleware. Jako użytkownik API możesz napotkać pierwszych pięć:
| Pula | Obejmuje | Liczona według | Domyślny limit |
|---|---|---|---|
| (sieć) | każde żądanie API, przed sprawdzeniem klucza | źródłowy adres IP (IPv6: jego sieć /64) | 6 000 na minutę — znacznie więcej niż przy zwykłym użyciu; wiele osób w jednej sieci firmowej dzieli ten limit |
open_api | zapisy w /api/v1/*, /v1/* i /v1beta/* (każda metoda poza GET/HEAD, z wyjątkiem jobs/quote) | konto | 1 000 na 10 sekund (około 100 RPS przy stałym ruchu) |
open_api_read | odczyty w tych samych ścieżkach: GET/HEAD (w tym katalog models) i jobs/quote | konto | 1 000 na 10 sekund (około 100 RPS przy stałym ruchu) |
upload_url | /api/v1/common/upload-url | konto | 1 000 na 10 sekund (oprócz open_api) |
api_usage | /api/v1/usage | konto | 30 na minutę (oprócz open_api_read) |
| obszar konsoli | uwierzytelnione endpointy /console/v1/* | konto | 120 na minutę dla odczytów i osobno tyle samo dla zapisów |
catalog | publiczny, anonimowy katalog używany przez stronę marketingową (nie /api/v1/models) | źródłowy IP | 300 na minutę |
Na konto, nie na klucz
open_api i open_api_read są liczone względem konta. Tworzenie kolejnych kluczy nic nie daje — gdyby limit był liczony na klucz, można byłoby go obejść jednym kliknięciem w konsoli.
Natomiast upload_url i api_usage rzeczywiście są osobnymi pulami: przesłanie obrazu referencyjnego zużywa token z open_api oraz z upload_url, jeden odczyt usage zużywa token z open_api_read oraz z api_usage, a wyczerpanie dowolnej z tych pul zwraca 429.
Podane wartości są domyślne i możemy je zmienić bez wydania nowej wersji. Aktualny limit jest zawsze wskazany w nagłówku X-RateLimit-Limit i w sekcji Overview w konsoli. Ufaj nagłówkowi i nie wpisuj wartości domyślnych na stałe do kodu klienta.
Nagłówki odpowiedzi
| Nagłówek | Kiedy jest obecny | Znaczenie |
|---|---|---|
X-RateLimit-Limit | W każdej odpowiedzi | Limit w aktualnym oknie |
X-RateLimit-Remaining | W każdej odpowiedzi | Pozostałe tokeny |
Retry-After | Przy 429 z mechanizmu limitów | Liczba sekund oczekiwania, co najmniej 1 |
Zwykła odpowiedź dla konta z domyślnym limitem zawiera:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997X-RateLimit-Remaining jest wysyłany także w odpowiedziach zakończonych powodzeniem, więc możesz zwolnić przed otrzymaniem 429, a nie dopiero po nim.
Przy 401 te nagłówki opisują pulę sieciową (6000), nie pulę konta, ponieważ nie rozpoznano klucza.
Jak wygląda przekroczenie limitu
{
"code": 429,
"msg": "Too many requests. Retry in a moment",
"request_id": "req_…"
}Status HTTP 429, z Retry-After.
Żądania ponad limit są odrzucane, a nie kolejkowane
Odpowiedź wraca natychmiast. Kolejkowanie tylko zwiększałoby opóźnienia i pozostawiało otwarte połączenie, które nigdy nie zwraca odpowiedzi — co jest trudniejsze w obsłudze niż jednoznaczne 429. Odrzucone żądanie nigdy nie zostało zaakceptowane, więc nic nie kosztuje.
Obsługa limitów
Odczytuj Retry-After. Nie ponawiaj bez przerwy w stałym odstępie. Przykłady kończą się po pięciu próbach, co zapobiega też nieskończonej pętli przy opisanym wyżej 429 dotyczącym oczekujących plików.
async function callRespectingLimits(url, init) {
for (let i = 0; i < 5; i++) {
const res = await fetch(url, init);
if (res.status !== 429) return res;
// The server already told you how long to wait; don't guess
const wait = Number(res.headers.get('retry-after') ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
}
throw new Error('persistently rate-limited');
}import time, requests
def call_respecting_limits(method: str, url: str, **kwargs) -> requests.Response:
for _ in range(5):
res = requests.request(method, url, **kwargs)
if res.status_code != 429:
return res
# The server already told you how long to wait; don't guess
time.sleep(float(res.headers.get("retry-after", 1)))
raise RuntimeError("persistently rate-limited")Współbieżność to osobna kwestia
Limit dotyczy tempa wysyłania, a nie liczby trwających zadań
Po przyjęciu zadania do kolejki przestaje ono zużywać limit żądań. Sto jednocześnie generujących zadań nie spowoduje 429.
Liczbę trwających zadań faktycznie ograniczają poniższe czynniki, z których żaden nie jest limitem żądań:
- Dostępne saldo — każde trwające zadanie blokuje środki. Gdy saldo się wyczerpie, nowe zadania otrzymują
40201. - Limity wydatków — dzienny, miesięczny i łączny limit klucza, dzienny i miesięczny limit zespołu (dla kluczy należących do zespołu) oraz dzienny limit platformy. Osiągnięcie dowolnego z nich powoduje
40202. Zobacz Limity wydatków. - Możliwość wykonania — gdy model w ogóle nie może wykonać zadania, otrzymujesz
50301.
Dlatego odpowiedzią na „chcę więcej zadań działających naraz” jest zwykle doładowanie konta lub podniesienie limitu wydatków, a nie zwiększenie limitu żądań.
Prośba o zwiększenie limitu
Aktualny limit jest widoczny w sekcji Overview w konsoli. Aby poprosić o większy, rozpocznij rozmowę w sekcji Support (temat: API integration) i opisz swój ruch: szczytową liczbę żądań na sekundę, czy uruchamiasz partie zadań i jak duże są te partie. Znacznie przyspieszy to rozpatrzenie prośby.
Do tego czasu ogranicz współbieżność klienta i przestrzegaj Retry-After. Wybieraj liczbę równoczesnych zadań na podstawie obciążenia, czasu generowania i dostępnego salda, zamiast sztucznie obniżać ją do wartości dopasowanej do domyślnego limitu żądań.
Gdy sam mechanizm limitów jest niedostępny
Mechanizm limitów zależy od zewnętrznego licznika. Gdy licznik zawiedzie, ustawiona strategia określa dalsze działanie: przepuszczanie (dalsza obsługa) lub odrzucanie (ochrona limitu). Domyślnie żądania są odrzucane — „nie mogliśmy odczytać konfiguracji” nigdy nie może oznaczać „nie ma limitu”.
Przy strategii odrzucania otrzymujesz 429 z Retry-After: 1, a nie 500. To celowe: 500 oznacza „mamy awarię”, a większość klienckich SDK natychmiast ponawia takie żądania, zwiększając obciążenie podczas incydentu. 429 z Retry-After oznacza „odczekaj i wróć”, czyli właśnie właściwe działanie.
Nie traktuj więc 429 jako dowodu, że wysyłano żądania zbyt szybko. Przestrzeganie Retry-After jest poprawną reakcją w obu przypadkach.
Błędy
Wszystkie kody biznesowe, odpowiadające im statusy HTTP, sposoby rozwiązania problemów oraz błędy, przy których warto ponowić żądanie.
Kontrakt Spicy Schema
Wspólna struktura żądań, standardowe pola, schemat formularza, cykl życia zadań asynchronicznych, błędy, przechowywanie wyników i zasady zgodności.

