Endpointy REST API
Všechny cesty REST API i s tím, jaké oprávnění chtějí, co vracejí a čím se dají zúžit. Tabulka se generuje z kódu, který je obsluhuje.
REST API má 24 cest a všechny odpovídají jen na GET. Tabulka
níž se generuje z kódu, který ty cesty obsluhuje, takže nemůže tvrdit nic, co by neplatilo pro
build, na kterém tenhle článek běží. Tentýž popis je strojově čitelný v souboru
/openapi-v1.json, viz článek OpenAPI popis REST API.
| Endpoint | Oprávnění | Co vrátí | Filtry |
|---|---|---|---|
GET /api/v1/catalog-items | products:read | Stránka v data[], kurzor v next_cursorid feed_id external_id group_id ean sku title description brand category_path[] images[] params{} cost_minor cost_includes_vat retail_price_minor min_price_minor currency_code vat_rate stock availability lead_days gone_at created_at updated_at | feed_id include_gone updated_since |
GET /api/v1/categories | products:read | Stránka v data[], kurzor v next_cursorid parent_id name slug full_path depth position is_active show_in_menu created_at updated_at | updated_since |
GET /api/v1/customers | customers:read | Stránka v data[], kurzor v next_cursorid type name company_name ico dic email phone billing_address{} delivery_address{} marketing_consent marketing_consent_at customer_group{} created_at updated_at | updated_since |
GET /api/v1/customers/{id} | customers:read | Jeden objekt v dataid type name company_name ico dic email phone billing_address{} delivery_address{} marketing_consent marketing_consent_at customer_group{} created_at updated_at | bez filtrů |
GET /api/v1/documents | documents:read | Stránka v data[], kurzor v next_cursorid doc_type doc_number order_id issued_at duzp total_minor currency_code tax_regime customer_ico customer_dic created_at | doc_type updated_since |
GET /api/v1/documents/{id} | documents:read | Jeden objekt v dataid doc_type doc_number order_id order_number issued_at issue_date duzp due_date currency_code tax_regime is_vat_payer payment_method variable_symbol is_paid supplier{} customer{} lines[] shipping_gross_minor shipping_vat_rate discount_total_minor rounding_minor vat_breakdown[] total_base_minor total_vat_minor total_gross_minor original_doc_number correction_reason created_at | bez filtrů |
GET /api/v1/documents/{id}/isdoc | documents:read | Soubor ke stažení | bez filtrů |
GET /api/v1/documents/{id}/pdf | documents:read | Soubor ke stažení | bez filtrů |
GET /api/v1/orders | orders:read | Stránka v data[], kurzor v next_cursorid order_number status payment_status payment_method fulfillment_status currency_code subtotal_minor discount_total_minor shipping_price_minor total_minor email phone is_quotation placed_at created_at updated_at | payment_status status updated_since |
GET /api/v1/orders/{id} | orders:read | Jeden objekt v dataid order_number status payment_status payment_method fulfillment_status currency_code subtotal_minor discount_total_minor shipping_price_minor total_minor email phone is_quotation placed_at created_at updated_at billing{} shipping{} variable_symbol notes lines[] | bez filtrů |
GET /api/v1/ping | libovolný platný klíč | Odpověď bez obálkyok key_id scopes[] api_version | bez filtrů |
GET /api/v1/pricing-rules | products:read | Stránka v data[], kurzor v next_cursorid subscription_id scope scope_value markup_pct min_margin_minor rounding target priority is_active updated_at | updated_since |
GET /api/v1/product-source-links | products:read | Stránka v data[], kurzor v next_cursorid product_id variant_id subscription_id catalog_item_id locked_fields[] hidden_by_sync updated_at | updated_since |
GET /api/v1/products | products:read | Stránka v data[], kurzor v next_cursorid slug title status product_type brand price_minor currency_code image_url stock created_at updated_at | status updated_since |
GET /api/v1/products/{id} | products:read | Jeden objekt v dataid slug title status product_type brand price_minor currency_code image_url stock created_at updated_at subtitle description meta_title meta_description published_at variants[] categories[] primary_category_id | bez filtrů |
GET /api/v1/returns | orders:read | Stránka v data[], kurzor v next_cursorid return_number order_id order_number regime status reason refund{} credit_note_id credit_note_number deadline_at items[] created_at updated_at | status updated_since |
GET /api/v1/returns/{id} | orders:read | Jeden objekt v dataid return_number order_id order_number regime status reason refund{} credit_note_id credit_note_number deadline_at items[] created_at updated_at | bez filtrů |
GET /api/v1/shipments | orders:read | Stránka v data[], kurzor v next_cursorid order_id order_number carrier service delivery_type status tracking_number tracking_url pickup_point_id parcel_count weight_grams currency_code cod_amount_minor handed_over_at delivered_at items[] created_at updated_at | status updated_since |
GET /api/v1/stock | stock:read | Stránka v data[], kurzor v next_cursorvariant_id product_id sku title variant on_hand available updated_at created_at | updated_since |
GET /api/v1/stock/movements | stock:read | Stránka v data[], kurzor v next_cursorid variant_id location_id type quantity_change quantity_before quantity_after reason reference{} created_at | type updated_since |
GET /api/v1/supplier-approvals | products:read | Stránka v data[], kurzor v next_cursorid subscription_id kind status product_id variant_id field current_value proposed_value reason decided_via decided_at created_at updated_at | kind status updated_since |
GET /api/v1/supplier-orders | orders:read | Stránka v data[], kurzor v next_cursorid order_id catalog_supplier_id status tracking_number carrier total_cost_minor currency_code sent_at shipped_at created_at updated_at | updated_since |
GET /api/v1/supplier-subscriptions | products:read | Stránka v data[], kurzor v next_cursorid feed_id catalog_supplier_id status trust_level auto_publish oos_behaviour ai_policy price_change_threshold_pct filter{} last_synced_at last_error created_at updated_at | updated_since |
GET /api/v1/supplier-sync-runs | products:read | Stránka v data[], kurzor v next_cursorid subscription_id trigger status started_at finished_at items_seen created updated hidden unhidden held skipped errors error created_at updated_at | subscription_id updated_since |
Základ adresy je doména vašeho obchodu i s cestou /api/v1, tedy třeba
https://muj-eshop.cz/api/v1/products.
Tenhle článek je rozcestník a popisuje to, co platí napříč cestami. Pole odpovědi, parametry a chyby každé cesty vypisuje reference generovaná ze smlouvy:
- REST API: ověření klíče
- REST API: objednávky, vratky a zásilky
- REST API: produkty a kategorie
- REST API: zásoby a skladové pohyby
- REST API: doklady, PDF a ISDOC
- REST API: zákazníci
- REST API: feedy dodavatelů
Obálka odpovědi
Výpisy vracejí { "data": [...], "next_cursor": "...", "next_updated_since": "..." }, detaily
{ "data": {...} } a ověřovací cesta /api/v1/ping odpovídá bez obálky. PDF a ISDOC dokladu
přijdou jako soubor ke stažení. Jednotná obálka u výpisů znamená, že se stránkování i průběžná
synchronizace dají naprogramovat jednou pro všechny; jak, popisuje článek
Stránkování a filtry.
Peníze jsou celá čísla v haléříchKaždé pole končící na _minor je částka v nejmenší jednotce měny, vedle ní stojí currency_code. Nikdy to není desetinné číslo a nikdy se nesmí převádět přes plovoucí čárku. Cena 1 299 Kč přijde jako 129900. Sazba DPH je celé procento: 21, 12 nebo 0.
Čas je vždy ISO 8601 v UTC
Každý čas v každé odpovědi má tvar 2026-09-01T08:14:02.118204Z: ISO 8601 v UTC, s mikrosekundami
a se zónou Z. Datum bez času (datum vystavení, DUZP, splatnost) má tvar RRRR-MM-DD. Čas
z odpovědi jde do adresy dalšího volání vložit bez kódování, třeba šablonou v Make nebo v n8n.
Změna od 15. září 2026Do té doby chodily časy objednávek, produktů, zásob a dokladů v textovém tvaru databáze, tedy 2026-09-01 08:14:02.118204+00 (mezera místo T a posun bez minut). Parser data a času si poradí s oběma tvary; kdo čas porovnával nebo ukládal jako text, má si ho teď převést na skutečný čas. Změnil se i tvar kurzoru, viz článek Stránkování a filtry.
Objednávky, vratky a zásilky
/api/v1/orders je cesta pro účetnictví, ERP a expedici: odpoví, kdo co objednal, v jakém je to
stavu a kolik to stálo. Nákupní ceny, marže, interní poznámky ani identifikátory platby z brány
přes API nechodí, takže report marží se staví nad daty v administraci, ne odsud.
/api/v1/returns vrací vratky (odstoupení od smlouvy) i reklamace. credit_note_id je identifikátor
vystaveného dobropisu a dá se rovnou poslat do /api/v1/documents/{id}.
/api/v1/shipments vrací zásilky. Štítek, stav komunikace s dopravcem ani jeho chybová hlášení ven
nejdou. Pole items bývá prázdné: verze 1 posílá celou objednávku jednou zásilkou a řádky zásilky
nezakládá, takže prázdné pole neznamená prázdnou zásilku.
Stav zásilky posouvá i čas objednávkyfulfillment_status v objednávce je stav nejnovější zásilky. Když zásilka vznikne nebo se posune, posune se i updated_at objednávky, takže změnu zachytí i průběžná synchronizace objednávek. Sledovací číslo, položky a další podrobnosti zásilky čtěte z /api/v1/shipments.
Katalog
/api/v1/products vrací katalog, /api/v1/products/{id} jeden produkt i s variantami. Typický
odběratel je vlastní frontend, mobilní aplikace nebo srovnávač.
Cena je běžná koncová z maloobchodního ceníku. Velkoobchodní a smluvní ceníky se přes API neposílají, protože jsou vázané na konkrétního zákazníka a klíč žádného zákazníka nezastupuje.
/api/v1/categories vrací strom kategorií jako plochý výpis; strom si složíte podle parent_id.
Změna ceny, obrázku ani zásoby čas produktu neposouváupdated_at produktu se mění se záznamem produktu samotného, ne s cenou varianty, obrázkem ani zásobou. Zásoby synchronizujte přes /api/v1/stock; změnu ceny spolehlivě zachytí jen celý průchod katalogu bez updated_since, třeba jednou za noc.
Sklad
/api/v1/stock vrací zásoby po variantách, sečtené přes všechny sklady, a to i u variant, u kterých
se zásoba nevede (ty mají nulu). Je to cesta pro externí sklad nebo WMS.
Řádek nese název produktu v title a název varianty v variant: hodnoty jejích voleb v pořadí,
v jakém je má produkt, oddělené lomítkem, třeba Černá / 42. Je to tentýž název, jaký obchodník
vidí na obrazovce Sklad, takže se podle něj domluvíte i u zboží bez SKU. U jednoduchého produktu,
který žádné volby nemá, je variant null. Tentýž název nese každá varianta v detailu produktu
(/api/v1/products/{id}).
`available` se dnes rovná `on_hand`SHOPZI zásoby nerezervuje a objednávka se zásobou nehýbe vůbec: zásobu mění jen skladové pohyby (naskladnění, odpis, převod, inventura, příjem objednávky zboží nebo vrácení kusů z vratky). available proto dnes vrací totéž číslo co on_hand. Jsou to ale dva různé pojmy a až rezervace přijdou, rozejdou se, takže pro otázku „kolik můžu prodat“ čtěte available. Pole reserved odpověď nese do 11. září 2026 a vždycky v něm byla nula; odebrali jsme ho, aby z něj nikdo nepočítal rozdíly.
/api/v1/stock/movements vrací skladové pohyby. Pohyb je neměnný záznam, opravuje se novým
vyrovnávacím pohybem, ne přepsáním. Nákupní cena ani poznámka k pohybu ven nejdou. SKU, produkt ani
název varianty pohyb nenese: všechno se to může změnit, kdežto pohyb je neměnný a znovu by nepřišel.
Podle variant_id je najdete v /api/v1/stock.
Pole reference říká, k čemu pohyb patří, a jeho výčet hodnot není uzavřený. Běžně v něm
uvidíte objednávku zboží (purchase_order), vratku (return), inventuru (stocktake) nebo
smazání varianty (variant_delete), ale hodnota se vydává tak, jak ji zapsal ten, kdo pohyb
založil, takže může přibýt další a u pohybu bez vazby je reference.type i reference.id null.
Neznámá hodnota proto nesmí odběratele rozbít: větvete se na hodnotách, které znáte, a ostatní
nechte propadnout do obecné větve.
Obchod, který má vypnutý modul Sklad, neotevírá zásoby ani pohyby a obě cesty odpoví 403
s kódem inventory_disabled. Není to chyba oprávnění, je to vypnutá funkce obchodu. Stav zásoby
u produktu a u varianty ve výpisu katalogu ale chodí dál.
Doklady
/api/v1/documents vrací vystavené doklady a filtrovat se dá podle doc_type.
/api/v1/documents/{id} vrací fakturu, proformu nebo dobropis celý, včetně rekapitulace DPH po
sazbách v vat_breakdown. Rekapitulace se čte doslova z vystaveného dokladu a nikdy se
nedopočítává z položek, takže sedí na haléř s tím, co dostal zákazník.
/api/v1/documents/{id}/pdf a /api/v1/documents/{id}/isdoc vydají doklad jako soubor: PDF, tedy
týž soubor, jaký stahuje administrace, a ISDOC 6.0.2 k importu do účetního programu. Odpověď nese
hlavičku Content-Disposition s názvem souboru podle čísla dokladu a Cache-Control: private, no-store, takže ji cestou neuloží žádná sdílená mezipaměť. První stažení PDF, které se ještě
nevykreslovalo, trvá déle; další už jdou z úložiště. Každé stažení se počítá do stropu volání jako
kterékoli jiné volání.
PDF, které ještě nevzniklo, se vyrábí přímo při stažení, a proto jich server naráz vyrábí jen
několik. Když je plno, přijde 503 s kódem pdf_busy a hlavičkou Retry-After; počkejte a zkuste
to znovu. Při stahování dokladů za celé období proto stahujte postupně, ne všechny naráz.
Objednávka, nabídka a účtenka detail nemajíVýpis dokladů vrací všechny druhy, ale daňový detail, PDF a ISDOC mají jen faktura, proforma a dobropis. Na ostatní druhy odpoví všechny tři cesty 422 s kódem unsupported_document_type: doklad existuje, jen nemá tuhle podobu. Stornovaný dobropis zůstává ve výpisu, ale detail, PDF ani ISDOC už nevydá: odpoví 404 not_found. Když se PDF zrovna nepodaří vyrobit, přijde 502 pdf_unavailable a stačí to zkusit s odstupem znovu.
Zákazníci
/api/v1/customers a /api/v1/customers/{id} vracejí zákazníky obchodu a chtějí oprávnění
customers:read. Odpověď obsahuje osobní údaje, a proto nese jen vyjmenovaná pole: druh
zákazníka (osoba, nebo firma), jméno, firmu, IČO a DIČ, e-mail a telefon, fakturační a doručovací
adresu, souhlas se zasíláním obchodních sdělení i s časem, kdy byl udělen, cenovou skupinu a časy
vzniku a poslední změny. Adresa je ta výchozí daného druhu, a když výchozí není, naposledy změněná.
Heslo ani jeho otisk, přihlašovací a ověřovací tokeny, počty neúspěšných přihlášení, vnitřní poznámky obchodu ani nic z žádostí podle GDPR ven nejde, ani s tím nejširším klíčem. Tvar odpovědi je pevný seznam, ne výběr ze sloupců databáze, takže nový sloupec u zákazníka se do API nedostane sám.
updated_at zákazníka se posune i tehdy, když se změní nebo smaže jeho adresa nebo se změní jeho
cenová skupina, takže
průběžná synchronizace s updated_since zachytí i tyhle změny. marketing_consent_at je vyplněné,
jen když souhlas platí.
Oprávnění k zákazníkům dávejte jen tomu, kdo je potřebujeKlíč s customers:read čte osobní údaje všech zákazníků obchodu. Zaškrtávejte ho jen u napojení, které je opravdu potřebuje (CRM, e-mailový nástroj), a pro katalog nebo sklad vytvořte klíč bez něj.
Feedy dodavatelů
Sedm cest popisuje modul Feedy dodavatelů: co obchod odebírá a s jakou mírou automatizace
(/api/v1/supplier-subscriptions), jak dopadly běhy synchronizace (/api/v1/supplier-sync-runs),
co čeká ve frontě ke schválení (/api/v1/supplier-approvals), které produkty pocházejí z feedu
a která pole si obchod převzal (/api/v1/product-source-links), podle jakých pravidel se počítá
prodejní cena (/api/v1/pricing-rules) a co nabízí katalog dodavatelů (/api/v1/catalog-items).
Všech šest chce oprávnění products:read. Sedmá cesta, /api/v1/supplier-orders, vrací dropship
části objednávek poslané dodavatelům a chce orders:read.
Všechny jsou jen ke čtení. Odběr, cenová pravidla, rozhodnutí ve frontě, žádost o přístup
k dodavateli i vlastní feed se zapisují přes server MCP nástrojem shopzi_manage_supply, viz
MCP: sklad a nákup zboží, nebo v administraci.
Nákupní cenu v /api/v1/catalog-items uvidíte jen tam, kde ji obchod smí znát: u vlastního feedu,
u dodavatele bez schvalování přístupu a po schválené žádosti o přístup; jinak je cost_minor
null. Ceny položek katalogu jsou v setinách měny feedu, měnu říká currency_code. Obchod, jehož
tarif feedy dodavatelů nezahrnuje, dostane na téhle cestě 402 plan_required.
Feedy dodavatelů nepatří pod modul Sklad, takže tyhle cesty odpovídají i obchodu s vypnutým skladem.
Změny ze synchronizace navíc ohlašují webhooky (supplier_sync.*, supplier_order.*,
stock.changed a další), viz Webhooky: příjem událostí.
Ověření klíče
/api/v1/ping nevrací data obchodu, jen identitu klíče a jeho oprávnění. Volá se jako první, ještě
než postavíte scénář. Podrobněji v článku
Autentizace a oprávnění.
Strop volání a záznam o volání
Každá cesta počítá volání na klíč podle tarifu obchodu, v pevném minutovém a denním okně.
Odpověď na volání, které prošlo všemi branami, tedy klíčem, plochou, tarifem i oprávněním, nese
hlavičky X-RateLimit-Limit, X-RateLimit-Remaining a X-RateLimit-Reset; nad strop přijde
429 rate_limited s hlavičkou Retry-After a týmiž hlavičkami. Čísla pro jednotlivé tarify
a doporučený postup jsou v článku Chybové odpovědi.
Obchod si o voláních ukládá záznam bez obsahu: čas, šablonu cesty (/api/v1/orders/{id},
ne skutečný identifikátor ani parametry dotazu), výsledek a stavový kód, dobu zpracování, klíč,
IP adresu a název klienta z hlavičky User-Agent. Tělo požadavku ani odpovědi se neukládá nikde.
Neúspěšných volání (chyby, odmítnutí, 429) se takhle zapíše jen omezený počet: bez platného klíče
nejvýš 60 za hodinu na obchod, s platným klíčem nejvýš 1 000 za kalendářní den na klíč a plochu.
Nad tyto počty zůstávají jen denní součty na klíč (kolik volání, chyb, odmítnutí a volání nad
strop), žádný záznam o jednotlivém volání. Úspěšná volání se zapisují vždy. Záznamy mažeme po
30 dnech, denní součty na klíč po 90 dnech.
Záznam vidí vlastník nebo manažer obchodu v Nastavení → API a MCP:
- část Protokol volání ukazuje jednotlivá volání s filtry Plocha, Výsledek a Klíč a u odmítnutí i kód chyby, tentýž, jaký dostal klient;
- část Využití ukazuje za zvolené období součty volání, chyb, odmítnutí a volání nad limit, i po jednotlivých klíčích;
- v kartě API klíče ukazuje u každého klíče sloupec Naposledy čas posledního použití a pod ním počet dnešních volání.
Verzování
Verze je v cestě. Cokoli, co by rozbilo existujícího odběratele (přejmenované pole, zmizelé pole, změněný typ), znamená novou verzi cesty, ne tichou změnu téhle. Nové pole v odpovědi ani nová hodnota výčtu za takovou změnu nepovažujeme, takže parser musí neznámá pole a hodnoty ignorovat, ne na nich padat. Celý slib je v článku OpenAPI popis REST API.