Import dat — JSONL

Specifikace JSONL formátu importního produktového feedu. XML varianta: Import dat — XML.

Importní feed slouží jako primární zdroj produktů pro jejich import do Cenového automatu. Využívá se u e-shop systémů, ze kterých nelze tato data načítat s pomocí jejich API.

Názvy polí jsou camelCase a odpovídají polím v aplikaci. Soubor může být gzip (magic 1f 8b); HTTP Content-Encoding: gzip stačí tak, jak je.

Struktura souboru

Každý řádek je jeden JSON objekt. Na začátku feedu může být 0–N řádků jen s klíčem meta. Další řádky jsou produkty.

Ve feedu uvádějte jen pole, která chcete v aplikaci využívat. U primárního importu je povinné jediné pole productId, vše ostatní je volitelné.

{"meta":{"pricesIncludeVat":false,"generatedAt":"2026-08-17 22:00:00","generatedBy":"erp-export"}}
{"productId":"K-KU2M07F","productName":"Apple iPhone 12 Pro","vat":21,"shopCurrentPrice":22033.06}
  • Prázdné řádky se ignorují.
  • Neznámé klíče v meta i u produktu se ignorují.
  • meta na stejném řádku jako produkt, nebo až po datech, je chyba.
  • Více meta řádků se slučuje, pozdější hodnota stejného klíče přepíše dřívější.

Meta

Řádky meta jsou volitelné. Nemusí ve feedu být vůbec — pak se použijí výchozí hodnoty: produkty se identifikují podle productId, ceny jsou včetně DPH a nákupní ceny nejsou šifrované.

Kromě klíčů, které čte aplikace, si do meta můžete dát i vlastní pole — neznámé klíče se ignorují.

Aplikace čte tyto klíče:

Pole Popis
lookupField Pole pro spárování produktu u sekundárního importu.
Povolené hodnoty: productId, merchantProductId, shopProductCode, productNo, ean, shopProductId.
Výchozí: productId.
U primárního importu se ignoruje (vždy se používá productId); v logu importu se zapíše upozornění.
pricesIncludeVat Jestli jsou ceny ve feedu včetně DPH.
Formát: true | false
Výchozí: true. Platí pro celý feed, ne po jednotlivých produktech.
encryption Šifrování nákupní ceny. Viz Šifrování nákupních cen.

Identifikace produktů

U primárního importu je povinné pole productId (string). Identifikátory musí být JSON string — číslo (1234) je chyba, neprovádí se převod na text.

Pokud pro identifikaci produktů ve zbožových srovnávačích (vyjma Idealo) používáte jiný identifikátor, uveďte jej v merchantProductId. Pokud pole chybí, použije se productId a hodnota se normalizuje: u e-shopů v CZ a SK se znaky mimo 0-9a-zA-Z_- nahradí _ (charset Heureka / Zboží ITEM_ID).

U sekundárního importu se produkt páruje podle meta.lookupField (výchozí productId).

Typy hodnot

  • Čísla jako JSON number (1234.56), ne jako string "1234.56".
  • Identifikátory a texty jako JSON string.
  • Pravdivostní hodnoty jen true / false.
  • Datum ve formátu YYYY-MM-DD.
  • Primární import: vynechaný klíč i null pole vymažou (uloží se jen to, co je ve feedu).
  • Sekundární import: vynechaný klíč pole nemění, null hodnotu vymaže.

Popis polí

Pole Popis
productId Jednoznačný primární identifikátor produktu v e-shopu.
Formát: string
merchantProductId Jednoznačný identifikátor produktu ve zbožových srovnávačích (vyjma Idealo).
Pokud pole není uvedené, použije se productId a hodnota se normalizuje (u CZ/SK se znaky mimo 0-9a-zA-Z_- nahradí _).
Formát: string
productNo Produktové číslo (většinou identifikátor definovaný výrobcem).
Formát: string
ean EAN kód.
Formát: string
productName Název produktu v e-shopu.
Formát: string
manufacturer Název výrobce.
Formát: string
supplier Název dodavatele.
Formát: string
shopUrl Url produktu v e-shopu.
Formát: string (url)
imageUrl Url obrázku produktu.
Formát: string (url)
shopStockQty Stav skladu, počet kusů skladem.
Formát: celé číslo
weight Hmotnost produktu v kg.
Formát: číslo [1]
isActiveInShop Indikátor, jestli je produkt v e-shopu aktivní (není skrytý, deaktivovaný, smazaný, apod.).
Formát: true | false
shopDefaultCategoryUid Jednoznačný identifikátor výchozí kategorie e-shopu, kde je produkt primárně zařazený. [2]
Formát: string
shopCategoryUids Identifikátory kategorií e-shopu, kde je produkt zařazený. [2]
Formát: pole stringů
vat Sazba DPH v procentních bodech (21). Hodnota v intervalu (0, 1) se vynásobí 100.
Formát: číslo
shopCurrentPrice Aktuální cena v e-shopu.
Formát: číslo [1]
shopMocPrice Doporučená koncová cena.
Formát: číslo [1]
shopCommonPrice Běžná cena.
Formát: číslo [1]
shopActionPrice Akční cena.
Formát: číslo [1]
shopPurchasePrice Nákupní cena. Při zapnutém šifrování string (base64 ciphertext), jinak číslo.
Formát: číslo [1] nebo string
salesVoucher Slevový kupón. Hodnota je včetně DPH. Obě pole jsou povinná.
Formát: { "value": 1000, "unit": "currency" } nebo { "value": 2.5, "unit": "percent" }
shopMinAllowedPrice Minimální povolená cena.
Formát: číslo [1]
shopMaxAllowedPrice Maximální povolená cena.
Formát: číslo [1]
label Příznaky produktu. Pole objektů. Povinné jsou id a name; dateFrom a dateTo jsou volitelné (YYYY-MM-DD). Pokud data neuvedete, je příznak aktuálně platný.
Volitelný katalog všech příznaků e-shopu (i nepoužitých) lze importovat zvlášť.
gift Identifikátory produktů (productId), které jsou k tomuto produktu v e-shopu nastavené jako dárek.
Formát: pole stringů
customNumeric1 … customNumeric5 Uživatelská numerická pole.
Formát: číslo [1]
customText1 … customText5 Uživatelská textová pole.
Formát: string
shopProductId, shopProductCode Další identifikátory použitelné v meta.lookupField u sekundárního importu.
Formát: string

Příklad hodnoty label:

"label": [
  { "id": "akce", "name": "Akce" },
  { "id": "novinka", "name": "Novinka", "dateFrom": "2020-04-15", "dateTo": "2030-04-30" }
]

[1] Formát číslo

Čísla uvádějte jako JSON number s desetinnou tečkou, např. 1234.56. Ceny uvádějte standardně s DPH, ale lze i bez DPH, viz Ceny bez DPH.

[2] Zařazení v e-shop kategorii

Pokud chcete v aplikaci v podmínkách pravidel používat výběr produktů dle jejich zařazení v e-shop kategorii, je třeba do aplikace importovat seznam všech kategorií. Více v Import e-shop kategorií.

Obdobně lze volitelně importovat katalog příznaků.

Příklad importního feedu

{"productId":"K-KU2M07F","merchantProductId":"MP-KU2M07F","productNo":"KU2M07F-001","ean":"8592220013714","productName":"Apple iPhone 12 Pro (128GB, Gold)","manufacturer":"Apple","supplier":"Apcom Czech","shopUrl":"https://www.shop.cz/mobilni-telefony/apple/iphone-12-pro","imageUrl":"https://images.shop.cz/apple-iphone-12-pro.jpg","shopStockQty":55,"weight":0.55,"isActiveInShop":true,"shopCategoryUids":["358","132"],"shopDefaultCategoryUid":"358","vat":21,"shopCurrentPrice":26660,"shopMocPrice":29990,"shopCommonPrice":27990,"shopActionPrice":25990,"shopPurchasePrice":24575.94,"salesVoucher":{"value":1000,"unit":"currency"},"shopMinAllowedPrice":25444.78,"shopMaxAllowedPrice":29990,"label":[{"id":"novinka","name":"Novinka","dateFrom":"2020-04-15","dateTo":"2030-04-30"},{"id":"akce","name":"Akce"}],"gift":["GIFT-CASE","GIFT-CABLE"],"customNumeric1":123.45,"customText1":"V letáku do 15.3."}

Ceny bez DPH

Standardně se očekává zadání všech cen včetně DPH (meta.pricesIncludeVat chybí, případně je true).

Pokud jsou ceny bez DPH, uveďte {"meta":{"pricesIncludeVat":false}}. U produktu musí být vat, jinak se ceny nenaimportují (u primárního importu). U sekundárního importu se DPH dopočítá z již uložené sazby produktu, pokud ve feedu chybí.

{"meta":{"pricesIncludeVat":false}}
{"productId":"K-KU2M07F","vat":21,"shopPurchasePrice":20310.69}

Šifrování nákupních cen

Nákupní ceny lze ve feedu šifrovat. Šifrovací klíč je cryptoKey e-shopu (16 bajtů). Pokud jsou ceny šifrované, musí být meta.encryption kompletní — výchozí algoritmus se nedoplňuje.

Povolené algoritmy:

aes-128-cbc

IV (16 B) je společný pro celý feed v meta.encryption.iv. shopPurchasePrice je base64 ciphertext.

{"meta":{"encryption":{"algorithm":"aes-128-cbc","iv":"abcdefghijklmnop","ivEncoding":"utf8","ciphertextEncoding":"base64"}}}
{"productId":"K-KU2M07F","shopPurchasePrice":"ciL9OjNTl8MYuoN6onjlnA=="}

ivEncoding je utf8, hex nebo base64. ciphertextEncoding musí být "base64".

PHP

$zasifrovane = openssl_encrypt($cena, 'aes-128-cbc', $cryptoKey, 0, $iv);

Node.js

import { createCipheriv } from 'node:crypto'

const cipher = createCipheriv('aes-128-cbc', Buffer.from(cryptoKey), Buffer.from(iv))
const encrypted = Buffer.concat([cipher.update(price, 'utf8'), cipher.final()]).toString('base64')

Python

from base64 import b64encode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

cipher = AES.new(crypto_key.encode(), AES.MODE_CBC, iv.encode())
encrypted = b64encode(cipher.encrypt(pad(price.encode(), AES.block_size))).decode()

aes-128-gcm

IV se do meta neuvádí. Každá shopPurchasePrice je base64(12 B IV ‖ ciphertext ‖ 16 B tag). Chyba dešifrování u jednoho produktu neovlivní další řádky.

{"meta":{"encryption":{"algorithm":"aes-128-gcm","ciphertextEncoding":"base64"}}}
{"productId":"K-KU2M07F","shopPurchasePrice":"...base64..."}

Slučování hodnot u sekundárních importů

U produktových atributů label a gift dochází při sekundárním importu automaticky ke sloučení s hodnotami načtenými z primárního importu. Pomocí sekundárního importu tak můžete k produktům dohrát další příznaky nebo dárky, aniž by došlo k přepsání již existujících hodnot.