Sposób działania
Import rodzin produktowych korzysta z tego samego dwuetapowego endpointu co produkty pojedyncze:
-
POST
/import/products/v2/load_data— wgrywa definicje (plik JSON) do bufora danych.continueUpload=1doklejam kolejne paczki,continueUpload=0czyści bufor przed wgraniem. -
POST
/import/products/v2/run— przenosi bufor do bazy produkcyjnej.
Podczas przenoszenia system sprawdza, czy dany kod (code wariantu) już istnieje. Jeśli istnieje — zostaje pominięty (import nie nadpisuje istniejących produktów).
To jest endpoint do DODAWANIA. Istniejące kody wariantów są pomijane, więc nie da się tym endpointem zaktualizować istniejącego wariantu (jego stock_enabled, cen, jednostek). Do aktualizacji istniejących produktów użyj POST /import/product/update — patrz sekcja Aktualizacja istniejących produktów.
Jak wysłać request
Endpoint load_data przyjmuje dane jako multipart/form-data — NIE jako surowe body JSON. Tablica obiektów (definicja rodziny + warianty) jest wysyłana jako plik w polu formularza file. {instancja} = adres API Twojej instancji Saly (np. https://twoja-domena/api).
Krok 1 — token. Wyślij POST na /user/token w formacie application/x-www-form-urlencoded z polami username oraz hasłem. W odpowiedzi otrzymasz access_token — wstaw go do nagłówka autoryzacji (typ Bearer) w kolejnych żądaniach.
Krok 2 — load_data (POST /import/products/v2/load_data), żądanie typu multipart/form-data:
|
Element żądania |
Wartość |
|---|---|
|
Nagłówek autoryzacji |
typ Bearer z tokenem z kroku 1 |
|
Pole formularza |
plik JSON z tablicą (definicja rodziny + warianty), |
|
Pole formularza |
|
Krok 3 — run (POST /import/products/v2/run): nagłówek Bearer, parametry w query string: truncate_all_products oraz truncate_all_categories (zwykle oba 0). Odpowiedź zawiera report (patrz „Odpowiedź i raport").
Gotowe polecenia curl znajdziesz w zewnętrznej dokumentacji technicznej API. Najważniejsze: payload to plik w polu file (multipart), a nie surowe body JSON.
Rodzina produktów — dwa obiekty
Rodzinę opisują dwa rodzaje obiektów:
-
Definicja rodziny — „parasol": nazwa, cechy różnicujące (
col1–col15), kategorie, atrybuty. Nie jest osobno sprzedawanym produktem — nie ma własnej ceny, stanu ani jednostek. -
Wariant rodziny — właściwy, sprzedawalny produkt (ma
code, cenę, stan i jednostki sprzedażowe), powiązany z definicją przezfamily_idi opisany wartościami cech (col1–col15).
W jednym pliku importu umieść definicję rodziny oraz jej warianty. Definicja (dany family_id) musi istnieć, aby warianty mogły się do niej podpiąć. Cena, stan (stock_enabled) i jednostki sprzedażowe ustawiane są na WARIANTACH (każdy wariant osobno), nie na definicji.
Definicja rodziny — dokumentacja pól
Legenda kolumny typ: * wymagane · X znaki · [0-1] 0/1 · [0-9] liczby · R2 liczba z 2 miejscami · JSON · (x) limit znaków.
family
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Unikalny identyfikator rodziny produktowej. Po nim warianty podpinają się do rodziny. |
|
X (255) * |
|
|
Definicja cechy różnicującej (nazwa cechy) w językach, np. „Kolor", „Rozmiar". |
|
JSON |
information
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Nazwa rodziny w językach (pl, en, de, ru, es, fr, it) |
JSON |
|
|
Opis w językach (HTML dozwolony) |
JSON |
|
|
Publikacja na froncie (0 = nie [domyślnie], 1 = tak) |
[0-1] |
|
|
Promowanie (0 = nie [domyślnie], 1 = tak) |
[0-1] |
metadata
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Dane SEO w językach |
JSON |
|
|
Przyjazny URL w językach |
JSON |
categories
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Kategorie rodziny. Pierwsza = główna. Pełna ścieżka, separator |
JSON |
manufacturer
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Nazwa producenta |
X (45) |
|
|
URL do logo producenta |
X (255) |
collective_packages (opakowania zbiorcze)
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Czy dostępne do zakupu w opakowaniach zbiorczych (0 = nie [domyślnie], 1 = tak) |
|
[0-1] |
|
|
Czy dostępne tylko w opakowaniach zbiorczych (0 = nie [domyślnie], 1 = tak) |
|
[0-1] |
|
|
Procentowa modyfikacja ceny |
|
[0-9] |
|
|
Czy rabat dodawany do ceny w pierwszej kolejności (0 / 1) |
|
[0-1] |
attributes / multimedia
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Parametry techniczne pogrupowane, w językach (format jak w przykładzie) |
JSON |
|
|
Lista URL-i zdjęć (bez limitu) |
JSON |
|
|
Lista par |
JSON |
Przykładowy plik — definicja rodziny
[
{
"family": {
"family_id": "IMPORT-RODZIN-1",
"col1": { "pl": "Kolor", "en": "Color" },
"col2": { "pl": "Materiał", "en": "Material" },
"col3": { "pl": "Rozmiar", "en": "Size" }
},
"information": {
"name": { "pl": "MacBook Air 13", "en": "MacBook Air 13" },
"description": { "pl": "<p>opis rodziny</p>" },
"is_active": "1",
"is_promoted": "0"
},
"metadata": {
"metatitle": { "pl": "MacBook Air 13" },
"keywords": { "pl": "MacBook,Air,13" },
"metadescription": { "pl": "MacBook Air 13 - najlepsza cena" },
"slug": { "pl": "MacBook_Air_13" }
},
"categories": { "paths": [ { "pl": "Laptopy/Apple/MacBook Air 13" } ] },
"manufacturer": { "name": "Apple", "logo": "https://www.apple.com/logo.png" },
"collective_packages": {
"is_active": "0",
"is_only_packages": "0",
"price": { "discount": "10", "is_includes_the_charge": "0" }
},
"attributes": { "pl": [ { "Dane techniczne": [ ["Kolor", "czerwony"] ] } ] },
"multimedia": { "photos": [ "https://example.com/photo1.jpg" ], "files": [] }
}
]
Wariant rodziny — dokumentacja pól
Wariant to sprzedawalny produkt. Poza polami family ma te same sekcje co produkt pojedynczy: code, price, stock, units itd.
family
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Identyfikator rodziny, do której należy wariant (musi zgadzać się z definicją). |
|
X (255) * |
|
|
Nazwa wariantu rodziny |
|
X (255) |
|
|
Czy wariant aktywny (0 = nie, 1 = tak [domyślnie]) |
|
[0-1] |
|
|
Pozycja/kolejność wariantu na liście (niższa = wyżej) |
|
[0-9] (3) |
|
|
Wartość cechy różnicującej (odpowiadającej nazwie z definicji) w językach, np. „Czarny". |
|
JSON |
code wymagane
|
Opis |
Przykład |
Typ |
|---|---|---|
|
Unikalny kod produktu (wariantu) w Saly. Po nim sprawdzane jest, czy produkt już istnieje. |
|
X (255) * |
additional_code
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Numer EAN (13 cyfr) |
[0-9] (13) |
|
|
Stock Keeping Unit |
X (45) |
|
|
Kod produktu nadany przez dostawcę |
X (255) |
price
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Cena katalogowa (sprzedażowa) netto — cena, od której liczone są rabaty i którą widzi klient w jednostce podstawowej. |
|
R2 |
|
|
Minimalna cena netto, za którą produkt może być sprzedany (próg). |
|
R2 |
|
|
Cena zakupu netto. |
|
R2 |
|
|
Stawka VAT (cecha produktu). |
|
[0-9] |
energy_class
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Klasa energetyczna |
[A-G] (1) |
|
|
Link do etykiety klasy energetycznej (PDF) |
X (255) |
|
|
Link do karty informacyjnej (PDF) |
X (255) |
stock — stany magazynowe i flaga "stock impact" (na wariancie)
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Flaga „Włącz stany magazynowe dla produktu" (stock impact). |
|
[0-1] |
Ważne o stock_enabled (dotyczy każdego wariantu osobno):
-
To tylko flaga (czy wariant śledzi stan), NIE ilość. Poziomy stanu wgrywa się osobnym importem stanów (
/import/product_stocks). -
Aktualizacja
stock_enabledistniejącego wariantu nie zadziała przez ten endpoint (istniejące kody są pomijane) — użyj/import/product/update. -
Jednostki sprzedażowe definiuj wyłącznie w bloku
units— polestock.unitnie istnieje i jest ignorowane.
delivery_date — czas dostawy per magazyn (tablica):
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Czas dostawy (w językach). Pusty → dziedziczony z magazynu. |
|
JSON |
|
|
Czas dostawy w godzinach |
|
[0-9] |
|
|
External ID magazynu |
|
[0-9] |
|
|
Spodziewana data uzupełnienia |
|
date |
package
|
Pole |
Opis |
Typ |
|---|---|---|
|
|
Nazwa opakowania zdefiniowanego w systemie |
X (255) |
|
|
Wymiary opakowania (cm) |
R2 |
|
|
Waga opakowania (kg) |
R2 |
units — jednostki sprzedażowe i ich ceny (na wariancie)
Sekcja units to tablica jednostek wariantu. Każda jednostka odwołuje się (przez external_id) do jednostki zdefiniowanej w Słownikach → Jednostki sprzedażowe.
Model i ceny jednostek
-
Jednostka podstawowa (primary) — baza przeliczeń i jednostka stanu magazynowego; jej
rate= 1 (niezmienny). -
rate— ile jednostek podstawowych mieści jedna ta jednostka. Cena jednostki = cena katalogowa (srp_netto) ×rate. -
discount— rabat (%) dla tej jednostki. -
minimum_sales_quantity— minimalna ilość zamówienia w tej jednostce (całkowita > 0). -
Jednostka domyślna (default) — wstępnie wybrana; musi być aktywna.
-
active— czy jednostka widoczna/wybieralna.
Gwarancja integralności (per wariant): każdy wariant po imporcie ma dokładnie jedną aktywną jednostkę podstawową i jedną aktywną jednostkę domyślną. Gdy nie oznaczysz primary_unit=1 (albo jednostka jest nieprawidłowa), importer dobierze jednostkę podstawową ze słownikowych ustawień domyślnych — wariant nigdy nie zostanie bez jednostki podstawowej.
Brak sekcji units — zachowanie słownikowe
Sekcja units jest opcjonalna. Bez niej jednostki wariantu ustawiane są wg flag domyślności w Słowniku, honorowanych niezależnie:
|
Flaga w Słowniku |
Ustawia na wariancie |
|---|---|
|
Domyślnie aktywna |
|
|
Domyślnie prezentowana |
|
|
Domyślna jednostka podstawowa |
|
Np. jednostka z Domyślnie aktywna = ON i Domyślnie prezentowana = OFF będzie aktywna, ale NIE domyślna.
Pola jednostki
|
Pole |
Opis |
Przykład |
Typ |
|---|---|---|---|
|
|
Kod jednostki — musi istnieć w Słowniku. Nieznany kod → jednostka odrzucona (raport). |
|
X (20) |
|
|
Czy jednostka podstawowa (maks. 1 na wariant). |
|
[0-1] |
|
|
Czy jednostka domyślna (maks. 1; musi być aktywna). |
|
[0-1] |
|
|
Czy jednostka aktywna. |
|
[0-1] |
|
|
Przelicznik względem jednostki podstawowej (dla primary = 1). |
|
R2 |
|
|
Rabat (%) dla tej jednostki (≥ 0). |
|
[0-9] |
|
|
Minimalna ilość zamówienia w tej jednostce (całkowita > 0). |
|
[0-9] |
Przykładowy plik — wariant rodziny
[
{
"family": {
"family_id": "IMPORT-RODZIN-1",
"variant_name": "IMPORT-RODZIN-1-1",
"variant_is_active": "1",
"variant_position": "1",
"col1": { "pl": "Czarny", "en": "Black" },
"col2": { "pl": "Tworzywo sztuczne", "en": "Plastic" },
"col3": { "pl": "M", "en": "M" }
},
"code": "5907595646406",
"additional_code": {
"ean": "5907595646406",
"sku": "Mac Book Air 13,3",
"supplier_product_code": "5907595646406"
},
"price": {
"base_netto": "4000.00",
"purchase_netto": "3300.99",
"srp_netto": "4499.99",
"vat": "23"
},
"manufacturer": { "name": "Apple", "logo": "https://www.apple.com/logo.png" },
"energy_class": {
"energy_class": "A",
"energy_label_link": "https://link.pdf",
"energy_card_information_link": "https://link.pdf"
},
"stock": {
"stock_enabled": "1",
"delivery_date": [
{ "delivery_format": {"pl": "7 dni"}, "delivery_hour": "168", "warehouse_external_id": "1", "restocking_date": "2025-02-02" }
]
},
"package": {
"name": "Euro-pallet",
"dimensions": { "height": "100.00", "width": "100.00", "length": "100.00", "weight": "10.00" }
},
"units": [
{ "external_id": "szt.", "primary_unit": "1", "default_unit": "1", "active": "1", "rate": "1.0", "discount": "0", "minimum_sales_quantity": "1" },
{ "external_id": "opk", "primary_unit": "0", "default_unit": "0", "active": "1", "rate": "10.0", "discount": "10", "minimum_sales_quantity": "1" }
]
}
]
Odpowiedź i raport importu
Import jest nieblokujący — poprawne warianty są importowane, a o problemach z jednostkami dowiesz się z odpowiedzi (batch nie jest odrzucany).
-
/load_datazwraca liczniki wgranych wierszy orazstock_unit_ignored— listę kodów, które przysłały nieobsługiwane polestock.unit. -
/runzwraca{"status":"ok","report":{...}}, gdziereportzawiera:-
invalid_units—{product_code, external_id, reason}jednostek odrzuconych (nieznanyexternal_id, nie-całkowite/ujemneminimum_sales_quantity, ujemnyrate/discount, wiele jednostek domyślnych); -
products_without_primary_fallback_applied— warianty, dla których importer automatycznie ustalił jednostkę podstawową; -
proc_errors— błędy procedury.
-
Aktualizacja istniejących produktów
Endpoint /import/products/v2/* tylko dodaje. Aby zmienić dane istniejącego wariantu — stock_enabled, ceny, jednostki sprzedażowe — użyj POST /import/product/update:
-
Aktualizuje wskazane pola istniejących produktów/wariantów (po
code). -
Jednostki — tryb przez
units_increase:0= zastąp komplet jednostek;1= aktualizacja częściowa. Pusta tablicaunits→ istniejące jednostki bez zmian. -
Obowiązują te same reguły integralności jednostek (dokładnie 1 primary, 1 aktywna default).