Live — produkcja

Asgard API
Kompleksowa dokumentacja

Produkty, znakowania i zamówienia w jednym miejscu. REST API gotowe do integracji.

GET  /api/products-index/ GET  /api/marking-data/ 🔒 JWT Bearer
🔒  Zaloguj się do panelu Dokumentacja Swagger

Pierwsze kroki

Każde żądanie do chronionych endpointów wymaga ważnego tokena JWT w nagłówku. Poniżej trzyetapowy quick-start.

1
Pobierz token JWT
Wyślij POST /api/token/ z loginem i hasłem. Otrzymasz access (ważny 5 min) oraz refresh.
2
Dodaj nagłówek do każdego żądania
Authorization: Bearer <access_token>
3
Odświeżaj token przed wygaśnięciem
Użyj POST /api/token/refresh/ z polem refresh, by dostać nowy access bez ponownego logowania.
👥
Konto dostępowe przyznaje administrator. Swagger UI z pełnym podglądem endpointów dostępny pod adresem /docs/.
🔒

Autoryzacja JWT

API używa JWT (JSON Web Token). Token przekazuj w nagłówku Authorization przy każdym żądaniu.

POST /api/token/
POST /api/token/
Content-Type: application/json

{
  "username": "twoj_login",
  "password": "twoje_haslo"
}
Odpowiedź 200 OK
{
  "access":  "eyJhbGci...",   // <-- używaj tego, wygasa po 5 min
  "refresh": "eyJhbGci..."    // <-- do odświeżenia, ważny 1 dzień
}
Nagłówek w każdym żądaniu
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Token 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.

GET/api/products-index/pełne dane, lookup po index
GET/api/products-index/{index}/jeden produkt po indeksie
GET/api/products/lista aktywnych (lookup po id)
GET/api/stock-info/tylko indeks + stan magazynowy
GET/api/last-update/zaktualizowane w ostatnich 45 min
GET/api/catalogue/produkty katalogowe (z cenami katalog.)
GET/api/christmas-catalogue/katalog świąteczny
GET/api/product-base/wszystkie produkty (aktywne i nieaktywne)admin
Do codziennej synchronizacji polecamy /api/products-index/ — dane zwracane po indeksie produktu, co upraszcza mapowanie do własnych systemów.
📄

Pełna lista produktów

Endpoint /api/products-index/ zwraca aktywne produkty ze wszystkimi powiązanymi danymi zagnieżdżonymi w jednej odpowiedzi.

Pobierz wszystkie produkty
GET  /api/products-index/             // lista wszystkich
GET  /api/products-index/ABC-123/      // jeden produkt po indeksie
Authorization: Bearer <token>

Co zawiera jeden produkt:

PoleTypOpis
indexstringUnikalny kod produktu (klucz w URL)
quantityintegerAktualny stan magazynowy
activebooleanCzy produkt jest aktywny
names[]arrayNazwy w językach: name_pl, name_en, name_de, name_fr, name_cz
descriptions[]arrayOpisy wielojęzyczne
prices[]arrayCeny: pln, eur, chf, czk
madeof[]arraySkład materiałowy (wielojęzyczny)
image[]arrayAdresy URL zdjęć produktu
additional[]arrayAtrybuty dodatkowe (klucz–wartość)
future_delivery[]arrayPlanowane dostawy: data + ilość
marking_data[]arrayDane znakowania (nested: miejsca, opcje)
category / subcategoryintegerID kategorii i podkategorii
new_product, promotion, salebooleanFlagi statusu produktu
📈

Stany magazynowe

Lekki endpoint zwracający wyłącznie indeks i ilość — idealny do częstej synchronizacji stanów.

GET /api/stock-info/
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 },
    ...
  ]
}
Endpoint /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/:

?search=ABC ?index=ABC-123 ?category=5 ?new_product=true ?discount_prices=true ?promotion=true ?sale=true ?page=2
Przykłady filtrowania
// 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}/.

Przykład odpowiedzi
{
  "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.

Produkt
Product
Dane znakowania
MarkingData
Miejsce
MarkingPlace
Opcja / Metoda
MarkingOption
Progi cenowe
PriceCode

Jeden produkt → wiele miejsc (np. “Front”, “Tył”) → wiele opcji (np. “Sitodruk”, “Grawerowanie”) → cena zależy od ilości zamówionych sztuk.

Pojęcia kluczowe:

ObiektOpisKluczowe pola
MarkingDataGłówny węzeł znakowania produktu. Zawiera domyślną metodę.product, default_marking_code
MarkingPlaceMiejsce na produkcie gdzie można nanieść oznaczenie.code, name_pl
MarkingOptionKonkretna technika znakowania w danym miejscu.marking_code, option_code, price_code, max_colors
MarkingVariantWariant opcji (np. rozmiar pola znakowania).variant_code, variant_label
MarkingPriceCodeKlucz cenowy — łączy opcję z progami cenowymi.code
PriceCodePróg cenowy dla danej ilości zamówionych sztuk.from_qty, to_qty, price_pln
AdditionalServiceUsł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):

GET/api/marking-data/pełna hierarchia w jednym żądaniu
GET/api/marking-data/?product=IDznakowanie konkretnego produktu
GET/api/marking-default/domyślna metoda per produkt (szukaj po product__index)

Tryb płaski (solo — do szczegółowego zapytania):

GET/api/marking-solodata/MarkingData, szukaj: ?search=<index>
GET/api/marking-soloplace/MarkingPlace, filtruj: ?marking_data=ID
GET/api/marking-solooption/MarkingOption, filtruj: ?marking_place=ID
GET/api/marking-additional/AdditionalService, filtruj: ?marking_data=ID
GET/api/marking-name/słownik etykiet technik znakowania
Pobierz znakowanie produktu ABC-123 (nested)
// 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/kody cenowe z progami (nested)
GET/api/marking-tierprice/?marking_option=IDprogi dla konkretnej opcji
Progi cenowe dla kodu “P3”
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.

1
Pobierz produkt
GET /api/products-index/ABC-123/ — w odpowiedzi masz zagnieżdżone marking_data z miejscami i opcjami.
2
Wybierz miejsce i opcję znakowania
Z marking_place[] wybierz miejsce (np. “Przód”), z marking_option[] wybierz technikę (np. “Sitodruk”). Zanotuj price_code i marking_code.
3
Pobierz ceny dla wybranej opcji
GET /api/marking-price/?code=P3 (lub /api/marking-tierprice/?marking_option=ID) — wyświetl progi cenowe dla ilości klienta.
4
Pobierz usługi dodatkowe
GET /api/marking-additional/?marking_data=ID — dodaj koszty setup, przesyłki wzoru itp.

Kody odpowiedzi

200
OK

Żądanie GET zakończone sukcesem.

201
Created

Zasób (zamówienie) utworzony pomyślnie.

400
Bad Request

Błąd walidacji — sprawdź treść odpowiedzi.

401
Unauthorized

Brak lub nieważny token JWT.

403
Forbidden

Brak uprawnień do zasobu.

404
Not Found

Zasób nie istnieje (np. błędny indeks).

Przykłady kodu

cURL — token + dane produktów
# 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"
Python (requests)
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)
JavaScript (fetch)
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 (cURL)
<?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);
🔗
Adres serwera API: developers.bluecollection.eu. Dane logowania uzyskasz od administratora.