Przejdź do treści
Premium Supply Developer

Limity

600 żądań na minutę — i wszystko, co trzeba, żeby ich nie przekraczać

Limit jest liczony na aplikację (client_id), nie na adres IP ani sprzedawcę, w stałym oknie 60 sekund. Stan limitu dostajesz w nagłówkach każdej odpowiedzi, a po przekroczeniu — dokładny czas do wznowienia w Retry-After. Nie trzeba niczego zgadywać ani mierzyć samodzielnie.

Ile i jak liczone#

ParametrWartość
Limit domyślny600 żądań / 60 s na aplikację
OknoStałe, wyrównane do pełnej minuty zegara (koniec okna w X-RateLimit-Reset)
Kluczclient_id aplikacji — wspólny dla wszystkich tokenów i wszystkich sprzedawców korzystających z tej aplikacji
Co się liczyKażde żądanie do /v1/*, które przeszło uwierzytelnienie — także zakończone 4xx (np. 403 insufficient_scope, 404) i same 429
Co się nie liczyŻądania bez tokenu lub z nieważnym tokenem (401), bez User-Agent (400) oraz /oauth/*
ZakresWspólny dla wszystkich zasobów; nie ma osobnych limitów per zasób

Nagłówki#

NagłówekKiedyZnaczenie
X-RateLimit-Limitkażda odpowiedźLimit aplikacji w bieżącym oknie (domyślnie 600).
X-RateLimit-Remainingkażda odpowiedźIle żądań zostało do końca okna. 0 = kolejne dostanie 429.
X-RateLimit-Resetkażda odpowiedźCzas końca okna jako epoch w sekundach (UTC). Różnica do „teraz” = ile czekać na nową pulę.
Retry-Aftertylko 429Liczba sekund do końca okna (min. 1). Po tym czasie limit jest pełny.
X-Trace-Idkażda odpowiedźIdentyfikator żądania — podaj w zgłoszeniu. Możesz nadać własny nagłówkiem X-Request-Id (8–64 znaki [A-Za-z0-9._:-]); wtedy odbijamy Twój.

Odpowiedź 429#

Przykład
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-Trace-Id: b7f3c2e1-4d9a-4c1e-9f2a-1d3e5f7a9b0c
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1788386460
Retry-After: 37

{
  "traceId": "b7f3c2e1-4d9a-4c1e-9f2a-1d3e5f7a9b0c",
  "errors": [
    {
      "code": "rate_limited",
      "message": "Rate limit exceeded. Retry after 37s.",
      "userMessage": "Za dużo żądań — spróbuj za chwilę."
    }
  ]
}

Kod błędu to zawsze rate_limited. Żądania wysłane po 429 w tym samym oknie także wracają jako 429 i również są liczone — ponawianie „na sztywno” co sekundę tylko wydłuża przestój.

Wzorzec ponowień#

Trzy zasady: przy 429 czekaj dokładnie Retry-After; przy 5xx ponawiaj wykładniczo z losowym rozrzutem; 4xx innych niż 429 nie ponawiaj — to błąd w żądaniu, powtórzenie go nie naprawi. Ponowienia zapisów zawsze z tym samym Idempotency-Key.

Pseudokod
funkcja wyślij(żądanie):
  dla próby od 1 do 5:
    odpowiedź = HTTP(żądanie)                 # z nagłówkiem Idempotency-Key przy POST/PATCH/DELETE

    jeśli odpowiedź.status == 429:
      czekaj(odpowiedź.nagłówki["Retry-After"] sekund)   # dokładnie tyle — nie „chwilę”, nie 2^n
      kontynuuj

    jeśli odpowiedź.status >= 500:
      czekaj(min(30 s, 0,5 s × 2^próby) + losowo(0…0,5 s))   # wykładniczo, z jitterem
      kontynuuj

    zwróć odpowiedź                           # 2xx oraz 4xx inne niż 429: NIE ponawiaj

  zgłoś awarię z ostatnim X-Trace-Id


funkcja zwolnij_jeśli_trzeba(odpowiedź):     # hamowanie zanim padnie 429
  pozostało = odpowiedź.nagłówki["X-RateLimit-Remaining"]
  reset     = odpowiedź.nagłówki["X-RateLimit-Reset"]        # epoch, sekundy
  jeśli pozostało < 30:
    czekaj((reset − teraz()) / max(pozostało, 1))            # rozłóż resztę okna równo

Wymagany nagłówek User-Agent#

Każde żądanie do /v1/* musi się przedstawić. Format:

Wzór
User-Agent: NazwaAplikacji/Wersja (+https://adres-dokumentacji-aplikacji)
  • NazwaAplikacji — jak w panelu; spacje zamień na - lub _. Znaki dozwolone: [A-Za-z0-9._-], do 64.
  • Wersja — do 32 znaków [A-Za-z0-9._-]. Zmieniaj ją przy wydaniach; to jedyna część, która ma się zmieniać.
  • (+adres) — link do strony opisującej aplikację (ten sam, co „Link do dokumentacji” w panelu). Formalnie opcjonalny, praktycznie niezbędny: po nim znajdujemy właściciela ruchu w logach.

Bramka sprawdza wyrażenie ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}/[A-Za-z0-9][A-Za-z0-9._-]{0,31}. Brak dopasowania → 400 missing_user_agent, zanim jeszcze sprawdzimy token. Domyślne nagłówki bibliotek (python-requests/2.31, axios/1.7) formalnie przechodzą, ale nie identyfikują Twojej aplikacji — przy problemach nie umiemy się z Tobą skontaktować, a przy nadużyciach blokujemy aplikację, nie IP, więc identyfikacja leży w Twoim interesie.

Generator i walidator#

Generator

Walidator

User-Agent: MojaIntegracja/1.0.0 (+https://example.com/moja-integracja)
  • Format poprawny — bramka przyjmie żądanie.

Jak być dobrym klientem HTTP#

  • Keep-alive. Przy setkach żądań utrzymuj połączenie (HTTP/1.1 keep-alive lub HTTP/2) — uścisk TLS przy każdym żądaniu kosztuje więcej niż samo żądanie.
  • Strony po 200. limit=200 zamiast domyślnych 50 to cztery razy mniej żądań na pełną synchronizację.
  • Tylko potrzebne pola. ?fields=id,price,stock,updated_at przy synchronizacji cen i stanów. Mniej bajtów po obu stronach.
  • Przyrostowo. updated_after (oferty) i placed_after (zamówienia) zamiast pełnego przebiegu. Zapamiętuj znacznik z poprzedniego przebiegu z marginesem kilku sekund.
  • Webhooki zamiast odpytywania. Odpytywanie GET /v1/orders co minutę zużywa 1 440 żądań dziennie na nic. Webhook order.paid przychodzi wtedy, gdy jest co pobrać.
  • Idempotency-Key na każdym zapisie. Wtedy ponowienie po timeoucie jest bezpieczne, a przesyłka nie zgłosi się dwa razy.
  • Własny X-Request-Id. Odbijamy go w X-Trace-Id — jeden identyfikator w Twoich i naszych logach.
  • Zegar w UTC. Wszystkie daty w API są ISO 8601 w UTC (Z). Porównuj instanty, nie łańcuchy.

Potrzebujesz więcej#

Limit jest parametrem aplikacji i możemy go podnieść. Napisz na api@premiumsupply.pl z client_id, opisem przepływu (co, jak często, dla ilu sprzedawców) i szczytową liczbą żądań na minutę, jakiej potrzebujesz. Zanim poprosisz, sprawdź, czy fields, updated_after i webhooki nie rozwiązują sprawy — zwykle tak.