Skip to main content
Skip table of contents

Dodawanie rodziny produktowej

Sposób działania

Import rodzin produktowych korzysta z tego samego dwuetapowego endpointu co produkty pojedyncze:

  1. POST /import/products/v2/load_data — wgrywa definicje (plik JSON) do bufora danych. continueUpload=1 doklejam kolejne paczki, continueUpload=0 czyści bufor przed wgraniem.

  2. 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-dataNIE 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 file

plik JSON z tablicą (definicja rodziny + warianty), type=application/jsontutaj trafia payload (nie do treści żądania)

Pole formularza continueUpload

0 = czyści bufor przed wgraniem; 1 = doklej kolejną paczkę

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 (col1col15), 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ą przez family_id i opisany wartościami cech (col1col15).

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

family_id WYMAGANE

Unikalny identyfikator rodziny produktowej. Po nim warianty podpinają się do rodziny.

IMPORT-RODZIN-1

X (255) *

col1col15

Definicja cechy różnicującej (nazwa cechy) w językach, np. „Kolor", „Rozmiar".

{"pl":"Kolor","en":"Color"}

JSON

information

Pole

Opis

Typ

name

Nazwa rodziny w językach (pl, en, de, ru, es, fr, it)

JSON

description

Opis w językach (HTML dozwolony)

JSON

is_active

Publikacja na froncie (0 = nie [domyślnie], 1 = tak)

[0-1]

is_promoted

Promowanie (0 = nie [domyślnie], 1 = tak)

[0-1]

metadata

Pole

Opis

Typ

metatitle / keywords / metadescription

Dane SEO w językach

JSON

slug

Przyjazny URL w językach

JSON

categories

Pole

Opis

Typ

paths

Kategorie rodziny. Pierwsza = główna. Pełna ścieżka, separator /, w językach.

JSON

manufacturer

Pole

Opis

Typ

name

Nazwa producenta

X (45)

logo

URL do logo producenta

X (255)

collective_packages (opakowania zbiorcze)

Pole

Opis

Przykład

Typ

is_active

Czy dostępne do zakupu w opakowaniach zbiorczych (0 = nie [domyślnie], 1 = tak)

0

[0-1]

is_only_packages

Czy dostępne tylko w opakowaniach zbiorczych (0 = nie [domyślnie], 1 = tak)

0

[0-1]

price.discount

Procentowa modyfikacja ceny

10

[0-9]

price.is_includes_the_charge

Czy rabat dodawany do ceny w pierwszej kolejności (0 / 1)

0

[0-1]

attributes / multimedia

Pole

Opis

Typ

attributes

Parametry techniczne pogrupowane, w językach (format jak w przykładzie)

JSON

multimedia.photos

Lista URL-i zdjęć (bez limitu)

JSON

multimedia.files

Lista par [nazwa, URL] plików (bez limitu)

JSON

Przykładowy plik — definicja rodziny

JSON
[
  {
    "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

family_id WYMAGANE

Identyfikator rodziny, do której należy wariant (musi zgadzać się z definicją).

IMPORT-RODZIN-1

X (255) *

variant_name

Nazwa wariantu rodziny

IMPORT-RODZIN-1-1

X (255)

variant_is_active

Czy wariant aktywny (0 = nie, 1 = tak [domyślnie])

1

[0-1]

variant_position

Pozycja/kolejność wariantu na liście (niższa = wyżej)

1

[0-9] (3)

col1col15

Wartość cechy różnicującej (odpowiadającej nazwie z definicji) w językach, np. „Czarny".

{"pl":"Czarny","en":"Black"}

JSON

code WYMAGANE

Opis

Przykład

Typ

Unikalny kod produktu (wariantu) w Saly. Po nim sprawdzane jest, czy produkt już istnieje.

5907595646406

X (255) *

additional_code

Pole

Opis

Typ

ean

Numer EAN (13 cyfr)

[0-9] (13)

sku

Stock Keeping Unit

X (45)

supplier_product_code

Kod produktu nadany przez dostawcę

X (255)

price

Pole

Opis

Przykład

Typ

srp_netto

Cena katalogowa (sprzedażowa) netto — cena, od której liczone są rabaty i którą widzi klient w jednostce podstawowej.

4499.99

R2

base_netto

Minimalna cena netto, za którą produkt może być sprzedany (próg).

4000.00

R2

purchase_netto

Cena zakupu netto.

3300.99

R2

vat

Stawka VAT (cecha produktu).

23

[0-9]

energy_class

Pole

Opis

Typ

energy_class

Klasa energetyczna

[A-G] (1)

energy_label_link

Link do etykiety klasy energetycznej (PDF)

X (255)

energy_card_information_link

Link do karty informacyjnej (PDF)

X (255)

stock — stany magazynowe i flaga "stock impact" (na wariancie)

Pole

Opis

Przykład

Typ

stock_enabled

Flaga „Włącz stany magazynowe dla produktu" (stock impact). 1 = wariant podlega kontroli stanu; 0 = nie wpływa na stan (np. usługa). Gdy pominięte — domyślnie 1 (TRUE).

1

[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).

  • Aktualizacjastock_enabled istnieją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 — pole stock.unitnie istnieje i jest ignorowane.

delivery_date — czas dostawy per magazyn (tablica):

Pole

Opis

Przykład

Typ

delivery_format

Czas dostawy (w językach). Pusty → dziedziczony z magazynu.

{"pl":"7 dni"}

JSON

delivery_hour

Czas dostawy w godzinach

168

[0-9]

warehouse_external_id

External ID magazynu

1

[0-9]

restocking_date

Spodziewana data uzupełnienia

2025-02-02

date

package

Pole

Opis

Typ

name

Nazwa opakowania zdefiniowanego w systemie

X (255)

dimensions.height / width / length

Wymiary opakowania (cm)

R2

dimensions.weight

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

active = 1

Domyślnie prezentowana

default_unit = 1

Domyślna jednostka podstawowa

primary_unit = 1

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

external_id

Kod jednostki — musi istnieć w Słowniku. Nieznany kod → jednostka odrzucona (raport).

szt.

X (20)

primary_unit

Czy jednostka podstawowa (maks. 1 na wariant).

1

[0-1]

default_unit

Czy jednostka domyślna (maks. 1; musi być aktywna).

1

[0-1]

active

Czy jednostka aktywna.

1

[0-1]

rate

Przelicznik względem jednostki podstawowej (dla primary = 1).

10.00

R2

discount

Rabat (%) dla tej jednostki (≥ 0).

10

[0-9]

minimum_sales_quantity

Minimalna ilość zamówienia w tej jednostce (całkowita > 0).

1

[0-9]

Przykładowy plik — wariant rodziny

JSON
[
  {
    "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_data zwraca liczniki wgranych wierszy oraz stock_unit_ignored — listę kodów, które przysłały nieobsługiwane pole stock.unit.

  • /run zwraca {"status":"ok","report":{...}}, gdzie report zawiera:

    • invalid_units{product_code, external_id, reason} jednostek odrzuconych (nieznany external_id, nie-całkowite/ujemne minimum_sales_quantity, ujemny rate/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 tablica units → istniejące jednostki bez zmian.

  • Obowiązują te same reguły integralności jednostek (dokładnie 1 primary, 1 aktywna default).

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.