Kompletny przykład#
Dwa polecenia: pobranie tokenu i pierwsze uwierzytelnione żądanie. Podstaw CLIENT_ID i CLIENT_SECRET z panelu aplikacji (krok 1) i wklej do terminala.
# 1. Token na konto właściciela aplikacji (client_credentials, uwierzytelnienie Basic)
TOKEN=$(curl -s -X POST https://api.premiumsupply.pl/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" | jq -r .access_token)
# 2. Kim jestem — sprzedawca, aplikacja, zakresy tokenu
curl -s https://api.premiumsupply.pl/v1/me \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: MojaIntegracja/1.0.0 (+https://example.com/moja-integracja)" \
-H "Accept: application/json"1. Zarejestruj aplikację#
Aplikacje rejestruje się w koncie sprzedawcy: apps.developer.premiumsupply.pl ↗. Nie ma osobnego „konta dewelopera” — klucze API to zakładka w ustawieniach sprzedaży, tak jak u Allegro.
| Pole | Zasady |
|---|---|
| Nazwa aplikacji | 3–40 znaków (litery, cyfry, spacje, . _ -). Unikalna w całym serwisie i niezmienna po rejestracji — trafia na ekran zgody sprzedawcy i do nagłówka User-Agent. |
| Opis | Opcjonalny, tylko dla Ciebie. Nie jest pokazywany innym sprzedawcom. |
| Link do dokumentacji | Wymagany, HTTPS. Strona opisująca, co aplikacja robi — ten adres podajesz też w User-Agent w nawiasie (+https://…). |
| Cel | na własne potrzeby → aplikacja aktywna od razu; dla innych sprzedawców albo inny → status pending do ręcznej akceptacji. Aplikacja pending działa na Twoje konto (client_credentials), ale nie może jeszcze prosić obcych sprzedawców o zgodę. |
| Adresy przekierowania | Tylko dla przepływu authorization_code. Pełny URL z HTTPS, bez fragmentu #, nie może wskazywać localhost ani prywatnego IP. Przy autoryzacji redirect_uri musi być identyczny znak w znak. |
| Zakresy | Co najmniej jeden z listy na stronie Uwierzytelnianie. Proś tylko o te, których używasz — sprzedawca widzi je na ekranie zgody. |
| Akceptacja regulaminu API | Wymagana. Regulamin API jest osobnym dokumentem od regulaminu sprzedaży. |
Po zapisaniu dostajesz client_id (prefiks psa_) i client_secret (prefiks pss_). Sekret jest pokazywany tylko raz — w bazie trzymamy wyłącznie jego hasz. Jeśli go zgubisz, w panelu wygenerujesz nowy („Rotuj sekret”); stary przestaje działać natychmiast, ale tokeny już wydane pozostają ważne do wygaśnięcia.
2. Pobierz token (client_credentials)#
Token na konto właściciela aplikacji. Uwierzytelnienie klienta to standardowy HTTP Basic: Authorization: Basic base64(client_id:client_secret) — curl -u robi to za Ciebie. Ciało w application/x-www-form-urlencoded.
curl -s -X POST https://api.premiumsupply.pl/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials"{
"access_token": "ps_at_Qm9ndXNfdG9rZW5fZG9rdW1lbnRhY2ppXzEyMzQ1Njc4OTA",
"token_type": "Bearer",
"expires_in": 43200,
"scope": "offers:read offers:write orders:read shipments:write"
}expires_in: 43200— token żyje 12 godzin. Odnów go zanim wygaśnie (np. przyexpires_in − 300 s), nie po pierwszym 401.- Bez parametru
scopetoken dostaje wszystkie zakresy aplikacji. Możesz zawęzić:-d "scope=offers:read orders:read". - Przy client_credentials nie ma
refresh_token— po prostu pobierasz nowy token tą samą parą. Refresh dotyczy tylko przepływu z kodem (authorization_code). - Tokeny są nieprzezroczyste (losowe bajty, nie JWT). Nie parsuj ich — źródłem prawdy o zakresach i ważności jest
GET /v1/me.
3. Sprawdź, kim jesteś#
GET /v1/me nie wymaga żadnego zakresu i zwraca wszystko, co trzeba wiedzieć o bieżącym tokenie. Dobre pierwsze wywołanie w każdej integracji — i pierwszy krok diagnostyki, gdy coś zwraca 403.
curl -s https://api.premiumsupply.pl/v1/me \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: MojaIntegracja/1.0.0 (+https://example.com/moja-integracja)" \
-H "Accept: application/json"{
"seller": { "id": "sp_01J8ZK3M4N5P6Q7R8S9T0V1W2X", "seller_no": 12 },
"app": { "client_id": "psa_3f9c1b2a4d5e6f708192a3b4", "name": "MojaIntegracja" },
"scopes": ["offers:read", "offers:write", "orders:read", "shipments:write"],
"token": { "kind": "access", "expires_at": "2026-09-03T10:12:45.000Z" }
}Każda odpowiedź niesie X-Trace-Id oraz X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset — zajrzyj nagłówkami (curl -i), zanim napiszesz obsługę limitów.
4. Pobierz oferty#
GET /v1/offers wymaga zakresu offers:read. Filtry: status (published, draft, proposed, rejected) i updated_after (ISO 8601). Domyślnie 50 pozycji, najnowsze najpierw.
curl -s "https://api.premiumsupply.pl/v1/offers?limit=5&status=published" \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: MojaIntegracja/1.0.0 (+https://example.com/moja-integracja)" \
-H "Accept: application/json"{
"items": [
{
"id": "prod_01J7Q2K3M4N5P6R7S8T9V0W1X2",
"title": "Kołdra całoroczna 160x200 antyalergiczna",
"handle": "koldra-caloroczna-160x200-antyalergiczna",
"status": "published",
"price": { "amount": 12990, "currency": "PLN" },
"stock": 14,
"ean": "5900000000017",
"brand": "Świat Pościeli",
"signature": null,
"thumbnail": "https://cdn.premiumsupply.pl/products/koldra-160x200.jpg",
"url": "https://premiumsupply.pl/products/koldra-caloroczna-160x200-antyalergiczna",
"created_at": "2026-08-30T08:14:02.000Z",
"updated_at": "2026-09-01T17:40:11.000Z"
}
],
"next": "MjAyNi0wOC0zMFQwODoxNDowMi4wMDBafHByb2RfMDFKN1EySzNNNE41UDZSN1M4VDlWMFcxWDI"
}Kolejne strony i wybór pól#
Pole next to kursor następnej strony (null = koniec). Podaj go w after. Kursor jest nieprzezroczysty — nie składaj go samodzielnie; jest ważny tylko dla tego samego zasobu i filtrów. ?fields= ogranicza zwracane pola (id jest zawsze), co przy pełnej synchronizacji cen i stanów zmniejsza transfer wielokrotnie.
curl -s "https://api.premiumsupply.pl/v1/offers?limit=200&fields=id,price,stock,updated_at&after=$NEXT" \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: MojaIntegracja/1.0.0 (+https://example.com/moja-integracja)"5. Zmień cenę — z Idempotency-Key#
PATCH /v1/offers/{id} wymaga zakresu offers:write i zmienia tylko podane pola: price, stock, status. Cena w groszach (integer), waluta PLN. Nagłówek Idempotency-Key (dowolny ciąg ≤ 128 znaków, np. UUID) sprawia, że powtórzenie żądania po zerwanym połączeniu nie wykona zmiany drugi raz — dostaniesz zapamiętaną odpowiedź z nagłówkiem Idempotent-Replayed: true.
curl -s -X PATCH https://api.premiumsupply.pl/v1/offers/prod_01J7Q2K3M4N5P6R7S8T9V0W1X2 \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: MojaIntegracja/1.0.0 (+https://example.com/moja-integracja)" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-d '{ "price": { "amount": 11990, "currency": "PLN" } }'HTTP/1.1 200 OK
Content-Type: application/json
X-Trace-Id: 4c1e9f2a-1d3e-5f7a-9b0c-b7f3c2e14d9a
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 597
X-RateLimit-Reset: 1788386460
{
"id": "prod_01J7Q2K3M4N5P6R7S8T9V0W1X2",
"title": "Kołdra całoroczna 160x200 antyalergiczna",
"status": "published",
"price": { "amount": 11990, "currency": "PLN" },
"stock": 14,
"updated_at": "2026-09-02T11:02:38.000Z"
}Kilka pól w jednym żądaniu:
{ "price": { "amount": 11990, "currency": "PLN" }, "stock": 20, "status": "published" }- Cena ustawiona przez API jest ceną ręczną. Automat wycen marketplace nie nadpisze jej — dokładnie tak samo, jak ceny wpisanej w panelu.
statusprzyjmuje tylkopublished↔draft. Stanyproposedirejectednadaje moderacja karty produktu, nie API.- Oferta bez ceny (
price: null) albo bez stanu (stock: null) zwróci 422 no_price_row / no_inventory_row — API zmienia istniejące wartości, nie tworzy nowych. Uzupełnij je raz w panelu. - Klucz idempotencji jest pamiętany 24 h w parze z aplikacją. Nowa zmiana = nowy klucz; ten sam klucz z innym ciałem także zwróci pierwszą odpowiedź.
Co dalej#
- Referencja — zamówienia (
GET /v1/orders, tylko Twoje pozycje, dane kupującego po opłaceniu) i zgłaszanie wysyłek (POST /v1/orders/{id}/shipments, nieodwracalne — używaj Idempotency-Key). - Uwierzytelnianie — jeśli piszesz aplikację dla innych sprzedawców: przepływ authorization_code + PKCE, ekran zgody, rotacja refresh tokenu.
- Limity — 600 żądań/min, nagłówki, backoff i „jak być dobrym klientem HTTP”.
- Webhooki — zamiast odpytywać o nowe zamówienia, odbieraj podpisane zdarzenia.
- Błędy — każdy kod z odpowiedzi ma tam swoją kotwicę:
/errors#kod.