Pierwsze kroki
Każde żądanie do chronionych endpointów wymaga ważnego tokena JWT w nagłówku. Poniżej trzyetapowy quick-start.
POST /api/token/ z loginem i hasłem. Otrzymasz access (ważny 5 min) oraz refresh.Authorization: Bearer <access_token>POST /api/token/refresh/ z polem refresh, by dostać nowy access bez ponownego logowania.Autoryzacja JWT
API używa JWT (JSON Web Token). Token przekazuj w nagłówku Authorization przy każdym żądaniu.
POST /api/token/ Content-Type: application/json { "username": "twoj_login", "password": "twoje_haslo" }
{ "access": "eyJhbGci...", // <-- używaj tego, wygasa po 5 min "refresh": "eyJhbGci..." // <-- do odświeżenia, ważny 1 dzień }
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
access wygasa po 5 minutach. Odświeżaj go przez POST /api/token/refresh/ z ciałem {"refresh": "..."}.Produkty — przegląd
API udostępnia kilka endpointów produktowych zoptymalizowanych pod różne przypadki użycia: pełne dane, stany magazynowe, aktualizacje i katalogi.
indexid)Pełna lista produktów
Endpoint /api/products-index/ zwraca aktywne produkty ze wszystkimi powiązanymi danymi zagnieżdżonymi w jednej odpowiedzi.
GET /api/products-index/ // lista wszystkich GET /api/products-index/ABC-123/ // jeden produkt po indeksie Authorization: Bearer <token>
Co zawiera jeden produkt:
| Pole | Typ | Opis |
|---|---|---|
index | string | Unikalny kod produktu (klucz w URL) |
quantity | integer | Aktualny stan magazynowy |
active | boolean | Czy produkt jest aktywny |
names[] | array | Nazwy w językach: name_pl, name_en, name_de, name_fr, name_cz |
descriptions[] | array | Opisy wielojęzyczne |
prices[] | array | Ceny: pln, eur, chf, czk |
madeof[] | array | Skład materiałowy (wielojęzyczny) |
image[] | array | Adresy URL zdjęć produktu |
additional[] | array | Atrybuty dodatkowe (klucz–wartość) |
future_delivery[] | array | Planowane dostawy: data + ilość |
marking_data[] | array | Dane znakowania (nested: miejsca, opcje) |
category / subcategory | integer | ID kategorii i podkategorii |
new_product, promotion, sale | boolean | Flagi statusu produktu |
Stany magazynowe
Lekki endpoint zwracający wyłącznie indeks i ilość — idealny do częstej synchronizacji stanów.
GET /api/stock-info/ Authorization: Bearer <token> // Odpowiedź: { "count": 1250, "next": "/api/stock-info/?page=2", "previous": null, "results": [ { "index": "ABC-123", "quantity": 450 }, { "index": "XYZ-007", "quantity": 0 }, ... ] }
/api/last-update/ zwraca produkty zmienione w ostatnich 45 minutach — używaj go do inkrementalnej synchronizacji zamiast pobierania całego katalogu.Filtrowanie i wyszukiwanie
Wszystkie endpointy produktowe obsługują filtrowanie przez parametry GET i paginację (100 wyników na stronę).
Parametry /api/products-index/:
// Produkty z kategorii ID=5 z rabatem GET /api/products-index/?category=5&discount_prices=true // Nowości - strona 2 GET /api/products-index/?new_product=true&page=2 // Szukaj po fragmencie indeksu GET /api/products-index/?search=ABC // Kategorie i podkategorie GET /api/categories/ GET /api/subcategories/
Struktura odpowiedzi produktu
Pełna struktura JSON jednego produktu z /api/products-index/{index}/.
{ "id": 142, "index": "ABC-123", "quantity": 450, "active": true, "new_product": false, "promotion": false, "sale": false, "discount_prices": true, "category": 5, "subcategory": 12, "names": [ { "id": 1, "language": "name_pl", "title": "Kubek termiczny 350ml" }, { "id": 2, "language": "name_en", "title": "Thermal mug 350ml" } ], "prices": [ { "pln": "24.90", "eur": "5.80", "chf": "5.50", "czk": "138.00" } ], "image": [ { "url": "https://cdn.example.com/products/abc-123-1.jpg" }, { "url": "https://cdn.example.com/products/abc-123-2.jpg" } ], "future_delivery": [ { "quantity": 200, "date": "2026-03-15" } ], "additional": [ { "item": "wymiary", "value": "8.5 x 8.5 x 12 cm" }, { "item": "waga", "value": "210g" } ], "marking_data": [ /* patrz sekcja Znakowanie */ ], // ... names, descriptions, madeof, marking (text) }
Znakowanie — architektura danych
Dane znakowania mają hierarchiczną strukturę. Każdy produkt może mieć wiele miejsc znakowania, a każde miejsce — kilka opcji z różnymi cenami.
Jeden produkt → wiele miejsc (np. “Front”, “Tył”) → wiele opcji (np. “Sitodruk”, “Grawerowanie”) → cena zależy od ilości zamówionych sztuk.
Pojęcia kluczowe:
| Obiekt | Opis | Kluczowe pola |
|---|---|---|
MarkingData | Główny węzeł znakowania produktu. Zawiera domyślną metodę. | product, default_marking_code |
MarkingPlace | Miejsce na produkcie gdzie można nanieść oznaczenie. | code, name_pl |
MarkingOption | Konkretna technika znakowania w danym miejscu. | marking_code, option_code, price_code, max_colors |
MarkingVariant | Wariant opcji (np. rozmiar pola znakowania). | variant_code, variant_label |
MarkingPriceCode | Klucz cenowy — łączy opcję z progami cenowymi. | code |
PriceCode | Próg cenowy dla danej ilości zamówionych sztuk. | from_qty, to_qty, price_pln |
AdditionalService | Usługi dodatkowe do znakowania (np. setup, przesyłka wzoru). | service_id, service_price_pln |
Endpointy znakowania
Dwa tryby dostępu: zagnieżdżony (nested — pełna hierarchia w jednym żądaniu) lub płaski (solo — każdy obiekt osobno, lżejsze odpowiedzi).
Tryb zagnieżdżony (nested):
product__index)Tryb płaski (solo — do szczegółowego zapytania):
?search=<index>?marking_data=ID?marking_place=ID?marking_data=ID// Krok 1 — znajdź ID produktu GET /api/products-index/ABC-123/ // → w odpowiedzi znajdziesz "id": 142 oraz zagnieżdżone "marking_data" // Krok 2 — lub bezpośrednio przez marking-data GET /api/marking-data/?product=142 // Odpowiedź (nested): { "id": 18, "product": 142, "default_marking_code": "TS-F1", "marking_place": [ { "id": 55, "code": "F1", "name_pl": "Przód", "marking_option": [ { "id": 201, "marking_code": "TS-F1", "option_code": "TS", // kod techniki "price_code": 7, // ID → /api/marking-price/ "max_colors": 4, "realisation_time_id": 3, "marking_variant": [] } ] } ], "additional_service": [ { "service_id": "SETUP", "service_price_pln": "35.00" } ] }
Progi cenowe znakowania
Cena za sztukę znakowania zależy od zamówionej ilości. Progi pobierasz przez price_code z opcji znakowania.
GET /api/marking-price/?code=P3 // Odpowiedź: { "id": 7, "code": "P3", "main_marking_price": [ { "from_qty": 25, "to_qty": 49, "price_pln": "2.80" }, { "from_qty": 50, "to_qty": 99, "price_pln": "2.20" }, { "from_qty": 100, "to_qty": 249, "price_pln": "1.60" }, { "from_qty": 250, "to_qty": 499, "price_pln": "1.10" } ] }
Typowy przepływ integracji znakowania
Jak zbudować konfigurator znakowania krok po kroku.
GET /api/products-index/ABC-123/ — w odpowiedzi masz zagnieżdżone marking_data z miejscami i opcjami.marking_place[] wybierz miejsce (np. “Przód”), z marking_option[] wybierz technikę (np. “Sitodruk”). Zanotuj price_code i marking_code.GET /api/marking-price/?code=P3 (lub /api/marking-tierprice/?marking_option=ID) — wyświetl progi cenowe dla ilości klienta.GET /api/marking-additional/?marking_data=ID — dodaj koszty setup, przesyłki wzoru itp.Kody odpowiedzi
Żądanie GET zakończone sukcesem.
Zasób (zamówienie) utworzony pomyślnie.
Błąd walidacji — sprawdź treść odpowiedzi.
Brak lub nieważny token JWT.
Brak uprawnień do zasobu.
Zasób nie istnieje (np. błędny indeks).
Przykłady kodu
# 1. Pobierz token TOKEN=$(curl -s -X POST https://developers.bluecollection.eu/api/token/ \ -H "Content-Type: application/json" \ -d '{"username":"login","password":"haslo"}' \ | python3 -c "import sys,json; print(json.load(sys.stdin)['access'])") # 2. Lista produktów (paginowana) curl https://developers.bluecollection.eu/api/products/ \ -H "Authorization: Bearer $TOKEN" # 3. Szczegóły produktu po indeksie curl https://developers.bluecollection.eu/api/products-index/ABC-123/ \ -H "Authorization: Bearer $TOKEN" # 4. Stany magazynowe curl https://developers.bluecollection.eu/api/stock-info/ \ -H "Authorization: Bearer $TOKEN"
import requests BASE = "https://developers.bluecollection.eu" # 1. Token token = requests.post(f"{BASE}/api/token/", json={ "username": "login", "password": "haslo" }).json()["access"] headers = {"Authorization": f"Bearer {token}"} # 2. Lista produktów (pierwsza strona) products = requests.get(f"{BASE}/api/products/", headers=headers).json() print(f"Łącznie produktów: {products['count']}") # 3. Szczegóły produktu po indeksie product = requests.get(f"{BASE}/api/products-index/ABC-123/", headers=headers).json() print(f"Stan: {product['quantity']} szt.") # 4. Znakowanie produktu marking = requests.get(f"{BASE}/api/marking-data/?product={product['id']}", headers=headers).json() print(marking)
const BASE = "https://developers.bluecollection.eu"; const post = (url, body, tok) => fetch(BASE + url, { method: "POST", headers: { "Content-Type": "application/json", ...(tok && { "Authorization": `Bearer ${tok}` }) }, body: JSON.stringify(body) }).then(r => r.json()); // 1. Token const { access } = await post("/api/token/", { username: "login", password: "haslo" }); // 2. Lista produktów const get = (url) => fetch(BASE + url, { headers: { "Authorization": `Bearer ${access}` } }).then(r => r.json()); const products = await get("/api/products/"); console.log(`Łącznie produktów: ${products.count}`); // 3. Szczegóły produktu po indeksie const product = await get("/api/products-index/ABC-123/"); console.log(`Stan: ${product.quantity} szt.`); // 4. Znakowanie produktu const marking = await get(`/api/marking-data/?product=${product.id}`); console.log(marking);
<?php $base = "https://developers.bluecollection.eu"; function apiPost($url, $data, $token = null) { $ch = curl_init($url); $headers = ["Content-Type: application/json"]; if ($token) $headers[] = "Authorization: Bearer $token"; curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => $headers, CURLOPT_POSTFIELDS => json_encode($data)]); return json_decode(curl_exec($ch)); } // 1. Token $auth = apiPost("$base/api/token/", ["username"=>"login","password"=>"haslo"]); $token = $auth->access; // 2. Lista produktów $ch = curl_init("$base/api/products/"); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"]]); $products = json_decode(curl_exec($ch)); echo "Łącznie produktów: {$products->count}\n"; // 3. Szczegóły produktu po indeksie $ch = curl_init("$base/api/products-index/ABC-123/"); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"]]); $product = json_decode(curl_exec($ch)); echo "Stan: {$product->quantity} szt.\n"; print_r($product);
developers.bluecollection.eu. Dane logowania uzyskasz od administratora.