Založte si e-shop zdarma a získejte 10 000 AI kreditů na start. Bez karty, bez závazku.E-shop zdarma + 10 000 AI kreditů na start

Začít zdarma
Přeskočit na obsah

Zápis přes REST API

Jak přes REST API zapisovat: zapnutí zápisu u klíče, Idempotency-Key, tvar odpovědi, ETag, dávky, rizikové zápisy se schválením, vrácení změn, důsledky zápisu, stropy a chyby.

Ověřeno 29. 10. 2026Markdown verze

REST API umí od 29. října 2026 i zapisovat. Zápisových cest je 39 a pokrývají objednávky, zásilky a vratky, katalog a ceny, sklad, zákazníky, slevové kódy a vrácení změn. Hodí se pro ERP, skladový systém, PIM, CRM nebo pokladnu, které mají v obchodě něco měnit, ne jen číst. 10 z nich jsou rizikové (zrušení objednávky, faktura, cenová nabídka, dobropis, vrácení peněz, vyřízení reklamace) a provedou se až po schválení vlastníkem nebo manažerem obchodu v administraci, viz oddíl Rizikové zápisy se schválením.

Každý zápis přes REST provede tentýž nástroj jako asistent přes MCP a Agent v administraci: se stejnou validací, stejnými pravidly obchodu, záznamem v deníku změn a se stejnými e-maily zákazníkům a webhooky. REST k tomu přidává jen to, co potřebuje program: striktní tělo v JSON, hlavičku Idempotency-Key, ETag a dávky.

Zápis je opt-in na klíčZápisové oprávnění samo nestačí. Klíč zapisuje přes REST jen tehdy, když má vlastník obchodu u klíče zaškrtnuté „Povolit zápis přes REST API“. Klíče vydané dřív, které zápisová oprávnění mají kvůli serveru MCP, tak přes REST bez rozhodnutí vlastníka nezačnou zapisovat.

Zapnutí zápisu

Klíč zapisuje přes REST, když platí obojí:

  1. Má zápisové oprávnění té oblasti, do které zapisuje (orders:write, products:write, stock:write, customers:write, marketing:write, undo:write, a na doklady a vrácení peněz documents:write). Zápisová oprávnění dřív platila jen pro server MCP; teď platí pro server MCP vždy a pro REST API, když to klíč dovolí.
  2. Má zaškrtnuté „Povolit zápis přes REST API“.

Zaškrtávátko nastavuje vlastník obchodu v Nastavení → API a MCP, v kartě API klíče, při vytvoření klíče (Vytvořit klíč) nebo u hotového klíče ikonou Upravit klíč:

  1. Klíč musí platit pro REST API: v poli Kde klíč platí volba Jen REST API, nebo REST API i server MCP. Klíč jen pro server MCP zaškrtávátko nenabídne.
  2. Ve skupině Zápis zaškrtněte oprávnění, která integrace potřebuje. Zaškrtávátko Povolit zápis přes REST API se ukáže až s prvním zápisovým oprávněním.
  3. Zaškrtněte ho, uložte a krok potvrďte heslem nebo kódem z e-mailu. Všichni vlastníci obchodu dostanou e-mail a upozornění v administraci, že klíč smí zapisovat i přes REST API.

Rychlá volba v dialogu Nový API klíč nabízí sadu ERP a sklad (REST): plocha jen REST API a oprávnění ke čtení i zápisu objednávek, katalogu, skladu a zákazníků, čtení dokladů, vrácení změn a dokumentace. Zaškrtávátko zápisu přes REST ani u ní nezaškrtne nic za vás.

Když klíči úpravou odeberete poslední zápisové oprávnění, zápis přes REST se vypne sám. Plochu klíče úprava nezmění; klíč jen pro server MCP nahradíte novým.

Jak to ověřit

GET /api/v1/ping vrací v poli rest_write, jestli klíč přes REST zapisovat smí: true znamená zaškrtnutý zápis a aspoň jedno zápisové oprávnění.

{
  "ok": true,
  "key_id": "9d2c1f7a-4b60-4f2e-9a11-8f0d2c3b5e64",
  "scopes": ["orders:read", "orders:write", "stock:read", "stock:write"],
  "rest_write": true,
  "api_version": "v1"
}

Klíč bez zaškrtávátka dostane na zápisové cestě 403 rest_write_not_enabled a klíč bez oprávnění 403 insufficient_scope. 403 rest_write_disabled znamená, že SHOPZI dočasně vypnulo zápisy přes REST pro všechny obchody: čtení a webhooky běží dál a na klíči ani v obchodě se nic měnit nemusí.

Pravidla požadavku

Zápisové cesty odpovídají na POST, PUT, PATCH a DELETE. Platí pro ně:

  • Tělo je JSON s hlavičkou Content-Type: application/json, jinak přijde 415 unsupported_media_type. Akce bez parametrů (DELETE, naskladnění vratky, vrácení změny) tělo mít nemusí; prázdné tělo se čte jako {}.
  • Tělo má nejvýš 256 KB, větší dostane 413 payload_too_large.
  • Tělo je striktní. Pole jsou v snake_case přesně podle smlouvy cesty (najdete je v referenci a v OpenAPI). Chybějící povinné pole, špatný typ i pole, které cesta nezná, vrátí 400 invalid_body s error.pointer, tedy JSON Pointer na místo, které neprošlo. Překlep v názvu pole tak nezapadne jako „nic se nezměnilo“.
  • Žádná hlavička Origin. Požadavek z webové stránky dostane 403 origin_not_allowed. Klíč se zápisem patří na server integrace, nikdy do prohlížeče, kde si ho přečte kdokoli.
  • Identifikátor v cestě je UUID, cokoli jiného vrátí 404 not_found.
  • Částky jsou celá čísla v haléřích (_minor) s DPH a sazba DPH celé procento, stejně jako ve čtení.
{
  "error": {
    "code": "invalid_body",
    "message": "Unknown field(s) at /: quantity_chnage.",
    "pointer": ""
  }
}

Kontroly jdou v tomhle pořadí a odpověď rozhodne první, která neprojde:

  1. hlavička Origin (403 origin_not_allowed);
  2. brány klíče jako u čtení, s dvěma navíc: hned za vypnutím plochy pro všechny obchody přijde 403 rest_write_disabled a za chybějícím oprávněním 403 rest_write_not_enabled; pořadí popisuje článek Autentizace a oprávnění;
  3. strop volání (429 rate_limited);
  4. velikost a typ těla (413, 415, neplatný JSON jako 400 invalid_body);
  5. identifikátor v cestě (404 not_found);
  6. tělo proti smlouvě (400 invalid_body);
  7. Idempotency-Key (428 idempotency_key_required, 400 invalid_idempotency_key);
  8. If-Match (400 invalid_if_match, 412 precondition_failed);
  9. u rizikové cesty to, co by zápis odmítl i po schválení (vratka jiné objednávky jako 404 not_found, chybějící pole jako 422 invalid_input, chybějící documents:write u zrušení objednávky s fakturou jako 403 forbidden), a potom schválení (202, 403 approval_declined);
  10. pravidla obchodu v samotném zápisu (409 conflict, 422 invalid_input, 403 forbidden a další).

Do stropu volání se tedy počítá i zápis, který potom skončí na tělu nebo na pravidlech obchodu.

Idempotency-Key

Síť selhává, a program, který po výpadku zopakuje „naskladni 12 kusů“, nesmí naskladnit 24. Proto zápisy berou hlavičku Idempotency-Key: hodnotu, kterou si vymyslíte pro jednu zamýšlenou změnu a pošlete znovu, když tutéž změnu opakujete.

  • Tvar je ^[A-Za-z0-9._:-]{8,128}$: 8 až 128 znaků z písmen, číslic a znaků ., _, : a -. Jiný tvar vrátí 400 invalid_idempotency_key. Dobře poslouží UUID nebo klíč odvozený z vašeho dokladu, třeba prijemka-2026-1042-radek-3.
  • Cesty, které něco zakládají nebo hýbou zbožím, ho vyžadují a bez něj vrátí 428 idempotency_key_required: POST /api/v1/categories, POST /api/v1/credit-notes/{id}/cancel, POST /api/v1/customers, POST /api/v1/discounts, POST /api/v1/invoices, POST /api/v1/orders/{id}/cancel, POST /api/v1/orders/{id}/invoice, POST /api/v1/orders/{id}/quotation, POST /api/v1/orders/{id}/refunds, POST /api/v1/orders/{id}/reject, POST /api/v1/orders/{id}/returns, POST /api/v1/orders/{id}/shipments, POST /api/v1/products, POST /api/v1/returns/{id}/credit-note, POST /api/v1/returns/{id}/discount-credit-note, POST /api/v1/returns/{id}/reklamace-resolution, POST /api/v1/returns/{id}/restock a POST /api/v1/stock/movements. U ostatních zápisů je nepovinný, ale doporučujeme ho posílat vždycky.
  • Opakování se stejným klíčem a stejným požadavkem neprovede druhý zápis. Vrátí aktuální podobu zdroje, hlavičku Idempotent-Replayed: true a v change.replayed hodnotu true. Druhý zápis ani druhý webhook nevznikne.
  • Stejný klíč s jinou cestou nebo jiným tělem je jiný požadavek a dostane 422 idempotency_key_reused. Na novou změnu pošlete nový klíč.
  • Když zápis pod tím klíčem právě běží, přijde 409 idempotency_in_progress s hlavičkou Retry-After. Počkejte a pošlete týž požadavek znovu: dostanete jeho výsledek.
  • Když zápis selhal a nic se nezapsalo, klíč se uvolní a opakování se stejným klíčem proběhne normálně. Zápis, který se přerušil uprostřed a je starší než deset minut, už se stejným klíčem zopakovat nejde (409 conflict): zkontrolujte výsledek čtením a případnou novou změnu pošlete s novým klíčem.

Klíč idempotence patří vašemu API klíči: dva klíče téhož obchodu se stejnou hodnotou se nesrazí. Pamatuje se tak dlouho, jak dlouho deník drží záznam změny, tedy 30 dní (oddíl Jak dlouho deník změny drží níž).

Ukázka zápisu

Naskladnění dvanácti kusů z příjemky skladového systému:

curl -s -X POST https://muj-eshop.cz/api/v1/stock/movements \
  -H "Authorization: Bearer $SHOPZI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: prijemka-2026-1042-radek-3" \
  -d '{
    "variant_id": "5f0b8a3e-2c71-4d9a-b6e4-0a1c3d5e7f92",
    "type": "receipt",
    "quantity_change": 12,
    "notes": "Příjemka 2026/1042"
  }'

Odpověď 201 Created s hlavičkami X-Shopzi-Change-Id a ETag:

{
  "data": {
    "variant_id": "5f0b8a3e-2c71-4d9a-b6e4-0a1c3d5e7f92",
    "product_id": "b1f0c0de-8f4a-4f6e-9a1c-2d3e4f5a6b70",
    "sku": "NORD-L-CER",
    "title": "Lněná košile Nord",
    "variant": "Černá / L",
    "on_hand": 16,
    "available": 16,
    "updated_at": "2026-10-28T09:14:02.118204Z",
    "created_at": "2026-08-19T11:02:41.512000Z"
  },
  "change": {
    "id": "3c9e5b1d-7a24-4f60-8e1b-6d2f0a4c8b17",
    "operation": "movement",
    "changed_fields": ["movement"],
    "replayed": false,
    "reversible": true
  }
}

Když síť spadne a požadavek pošlete znovu se stejným Idempotency-Key, přijde táž odpověď s "replayed": true a hlavičkou Idempotent-Replayed: true; zásoba zůstane na 16.

Tvar odpovědi

Úspěšný zápis vrací 200, u založení 201, a tělo { "data": …, "change": … }:

  • data je zdroj v témže tvaru, jaký vrací čtení: objednávka jako GET /api/v1/orders/{id}, produkt jako GET /api/v1/products/{id}, zásilka, vratka, doklad, kategorie, zákazník, slevový kód nebo stav skladu varianty jako v příslušném výpisu. Zápis do varianty vrací celý produkt. Dávky vracejí výsledek po položkách (oddíl Dávky); DELETE a storno dobropisu vracejí data: null.
  • change popisuje záznam v deníku změn: id (tentýž jako v hlavičce X-Shopzi-Change-Id), operation, changed_fields (pole, která zápis opravdu změnil), replayed a reversible. reversible je false u cest, které vrátit nejde, a u zápisu, který nic nezměnil.

Ve vzácném případě, kdy se zápis provede, ale zdroj se hned potom nedá přečíst (mezitím ho někdo smazal), přijde 404 not_found a hlavička X-Shopzi-Change-Id nese id změny, která se zapsala. Odmítnutí nástroje nese v message českou větu, kterou můžete ukázat obchodníkovi; rozhodujte se ale podle code.

ETag a If-Match

Detail zdroje (GET /api/v1/orders/{id}, /api/v1/products/{id}, /api/v1/customers/{id}, /api/v1/discounts/{id}, /api/v1/returns/{id}, /api/v1/documents/{id}) i každý zápis, který vrací zdroj, nesou hlavičku ETag ve tvaru W/"…": slabý otisk (SHA-256) zdroje tak, jak ho odpověď vrací.

Pošlete-li ho u zápisu v hlavičce If-Match, zápis proběhne jen tehdy, když zdroj pořád vypadá tak, jak jste ho četli; jinak přijde 412 precondition_failed a nic se nezmění. If-Match: * znamená „cokoli, co existuje“. Hodnota v jiném tvaru vrátí 400 invalid_if_match. U založení se If-Match nepoužije; zásilka a vratka, které se zakládají k objednávce, porovnávají ETag objednávky.

If-Match je best effortPorovnání a zápis nedělí zámek. Podmínka vás ochrání před rozhodnutím nad zastaralým stavem (ERP přecení produkt, který obchodník mezitím upravil), ne před dvěma zápisy v téže milisekundě. Ty hlídají pravidla zápisu a deník změn.

Dávky

Dvě cesty zapisují až 100 položek jedním požadavkem: PUT /api/v1/prices/batch a POST /api/v1/stock/levels/batch. Každá varianta smí být v dávce jen jednou.

  • PUT /api/v1/prices/batch přecení varianty, každou vlastní cenou. Platí celá dávka, nebo nic. Zapíše se jeden záznam v deníku, za každý dotčený produkt přijde jedna událost product.updated a celou dávku vrátí jedno vrácení změny. Každá změna ceny se zapíše do 30denní historie cen podle § 12a zákona o ochraně spotřebitele, stejně jako přecenění v administraci.
  • POST /api/v1/stock/levels/batch nastaví stav skladu variant na čísla, jak je hlásí váš sklad, a vrátí výsledek po položkách: applied (zapsala se korekce), unchanged (stav už seděl), refused (varianta by šla do záporu) a not_found (varianta v obchodě není). Probíhá v jedné transakci a do deníku se zapíše jedním záznamem, takže se i vrací jedním krokem.

Dávka se do stropu volání počítá jako jeden zápis, ať nese jednu položku, nebo sto. Sto jednotlivých volání by spotřebovalo sto zápisů a sto záznamů v deníku.

Vrácení změny a deník změn

GET /api/v1/changes vypisuje deník změn obchodu: co se změnilo přes REST, asistenta přes MCP nebo Agenta, kdy, kterým klíčem (api_key_id), odkud (source: api, mcp, agent, system) a jestli je změna vrácená. Jsou to jen metadata; hodnoty před změnou a po ní REST nevydává. Výpis se stránkuje a synchronizuje jako ostatní, filtrovat jde podle source a status.

POST /api/v1/changes/{id}/revert vrátí jednu změnu, ať ji zapsal REST, asistent nebo Agent. Chce oprávnění undo:write a zápisové oprávnění oblasti, které se změna týká (vrácení ceny chce i products:write). Když položku od té změny někdo upravil, vrácení se odmítne, aby nepřepsalo novější práci. Sklad se nevrací přepsáním čísla, ale vyrovnávacím pohybem, takže historie pohybů dál sedí. Druhé vrácení téže změny nic neudělá.

Vrátit nejde tyhle zápisy: POST /api/v1/credit-notes/{id}/cancel, POST /api/v1/customers, POST /api/v1/invoices, POST /api/v1/orders/{id}/cancel, POST /api/v1/orders/{id}/invoice, POST /api/v1/orders/{id}/payment-status, POST /api/v1/orders/{id}/quotation, POST /api/v1/orders/{id}/refunds, POST /api/v1/orders/{id}/reject, POST /api/v1/orders/{id}/returns, POST /api/v1/orders/{id}/shipments, POST /api/v1/orders/{id}/status, POST /api/v1/returns/{id}/approval, POST /api/v1/returns/{id}/credit-note, POST /api/v1/returns/{id}/discount-credit-note, POST /api/v1/returns/{id}/reklamace-resolution, POST /api/v1/returns/{id}/restock, POST /api/v1/returns/{id}/status, POST /api/v1/shipments/{id}/status a PUT /api/v1/shipments/{id}/tracking. Každý z nich má důsledek, který vrácení řádku v deníku nevezme zpět:

  • Stav objednávky a stav platby posílají zákazníkovi e-mail a zaplacení může vystavit fakturu s číslem z řady dokladů. Peníze se vracejí dobropisem a refundací k vratce, obojí jen po schválení (oddíl Rizikové zápisy se schválením).
  • Zásilky (založení, stav i sledování) žijí zároveň u dopravce: svoz se skutečně objedná, předání pošle zákazníkovi e-mail a zrušení jde i k dopravci. Vrácení řádku v obchodě by to nevzalo zpět.
  • Vratky a reklamace dostávají číslo z řady, u reklamace běží zákonná lhůta a naskladnění vratky je skutečný skladový pohyb. Chybu opraví další zápis, ne vrácení.
  • Založení zákazníka se nevrací: účet se ruší výmazem podle GDPR, který schvaluje člověk.

Co zápis spustí

Zápis přes REST má tytéž důsledky jako totéž v administraci:

CestaCo se stane navíc
POST /api/v1/orders/{id}/statusZákazník dostane e-mail o stavu jako z administrace. S "notify_customer": false se stav zapíše bez e-mailu (dosynchronizování historie). Stav jde jen dopředu; zrušení a zamítnutí jsou vlastní cesty se schválením.
POST /api/v1/orders/{id}/payment-statuspaid pošle zákazníkovi potvrzení platby, zapíše tržbu a podle nastavení obchodu vystaví fakturu. Nechce žádné schválení. refunded a partially_refunded tahle cesta odmítne odpovědí 403 approval_required: peníze se vracejí cestou POST /api/v1/orders/{id}/refunds.
POST /api/v1/orders/{id}/shipmentsBez pole external objedná u dopravce s napojením skutečný svoz. S external (tracking_number, tracking_url) jen zapíše zásilku, kterou jste podali sami, a dopravci nic neposílá.
POST /api/v1/shipments/{id}/statusPředání dopravci pošle zákazníkovi e-mail, doručení dobírky označí platbu a vystaví doklad, zrušení zruší zásilku i u dopravce.
POST /api/v1/orders/{id}/returnsVratka dostane číslo z řady, u reklamace se rozběhne zákonná lhůta.
POST /api/v1/returns/{id}/restockZapíše skladový pohyb za schválené kusy.
PUT /api/v1/variants/{id}/price a PUT /api/v1/prices/batchCena se zapíše do 30denní historie cen podle § 12a.
POST /api/v1/orders/{id}/cancelPo schválení: zrušení tímtéž řetězcem jako v administraci. Zastaví zásilky u dopravce a k vystavené faktuře vystaví storno dobropis (to chce i documents:write). Zákazník dostane e-mail.
POST /api/v1/orders/{id}/rejectPo schválení: zamítnutí objednávky, zákazník dostane e-mail. Dobropis nevzniká.
POST /api/v1/orders/{id}/invoice, POST /api/v1/invoicesPo schválení: faktura s číslem z bezmezerové řady, s "send_email": true hned e-mailem zákazníkovi.
POST /api/v1/orders/{id}/quotationPo schválení: cenová nabídka s číslem z řady k naceněné poptávce. Zákazníkovi se sama neposílá.
POST /api/v1/returns/{id}/credit-note, POST /api/v1/returns/{id}/discount-credit-notePo schválení: dobropis s číslem z řady. Peníze se tím nevracejí.
POST /api/v1/credit-notes/{id}/cancelPo schválení: storno dobropisu, jeho číslo zůstane v řadě jako stornované. Jen dokud se proti vratce nehnuly peníze.
POST /api/v1/orders/{id}/refundsPo schválení: gateway vrátí peníze přes platební bránu, manual zapíše peníze vrácené převodem nebo hotově, shipping nastaví vrácení za dopravu. Zákazník dostane e-mail o vrácení peněz.
POST /api/v1/returns/{id}/reklamace-resolutionPo schválení: vyřízení reklamace podle § 2169 OZ s příznakem zákonné lhůty. Zákazník dostane zprávu.

Webhooky vznikají stejně jako u změny v administraci; které událost která cesta vypouští, uvádí reference a OpenAPI. Opakování se stejným Idempotency-Key žádnou událost nepošle.

Zápis přes REST API nestojí kredity: žádná zápisová cesta nespouští AI a měsíční strop kreditů klíče se REST API netýká.

Zápisové cesty

CestaOprávněníIdempotency-KeyJde vrátitSchválení
POST /api/v1/orders/{id}/statusorders:writenepovinnýnene
POST /api/v1/orders/{id}/payment-statusorders:writenepovinnýnene
POST /api/v1/orders/{id}/shipmentsorders:writepovinnýnene
PUT /api/v1/orders/{id}/chargesorders:writenepovinnýanone
POST /api/v1/orders/{id}/returnsorders:writepovinnýnene
POST /api/v1/shipments/{id}/statusorders:writenepovinnýnene
PUT /api/v1/shipments/{id}/trackingorders:writenepovinnýnene
POST /api/v1/returns/{id}/statusorders:writenepovinnýnene
POST /api/v1/returns/{id}/approvalorders:writenepovinnýnene
POST /api/v1/returns/{id}/restockorders:writepovinnýnene
POST /api/v1/documents/{id}/paidorders:writenepovinnýanone
POST /api/v1/productsproducts:writepovinnýanone
PATCH /api/v1/products/{id}products:writenepovinnýanone
PUT /api/v1/products/{id}/categoriesproducts:writenepovinnýanone
PATCH /api/v1/variants/{id}products:writenepovinnýanone
PUT /api/v1/variants/{id}/priceproducts:writenepovinnýanone
PUT /api/v1/prices/batchproducts:writenepovinnýanone
POST /api/v1/categoriesproducts:writepovinnýanone
PATCH /api/v1/categories/{id}products:writenepovinnýanone
POST /api/v1/stock/movementsstock:writepovinnýanone
PUT /api/v1/stock/{variant_id}stock:writenepovinnýanone
POST /api/v1/stock/levels/batchstock:writenepovinnýanone
POST /api/v1/customerscustomers:writepovinnýnene
PATCH /api/v1/customers/{id}customers:writenepovinnýanone
PUT /api/v1/customers/{id}/tagscustomers:writenepovinnýanone
POST /api/v1/discountsmarketing:writepovinnýanone
PATCH /api/v1/discounts/{id}marketing:writenepovinnýanone
DELETE /api/v1/discounts/{id}marketing:writenepovinnýanone
POST /api/v1/changes/{id}/revertundo:writenepovinnýnene
POST /api/v1/orders/{id}/cancelorders:writepovinnýneano
POST /api/v1/orders/{id}/rejectorders:writepovinnýneano
POST /api/v1/orders/{id}/refundsdocuments:writepovinnýneano
POST /api/v1/orders/{id}/invoicedocuments:writepovinnýneano
POST /api/v1/orders/{id}/quotationdocuments:writepovinnýneano
POST /api/v1/invoicesdocuments:writepovinnýneano
POST /api/v1/returns/{id}/credit-notedocuments:writepovinnýneano
POST /api/v1/returns/{id}/discount-credit-notedocuments:writepovinnýneano
POST /api/v1/credit-notes/{id}/canceldocuments:writepovinnýneano
POST /api/v1/returns/{id}/reklamace-resolutiondocuments:writepovinnýneano

Několik pravidel, na která integrace narazí nejčastěji:

  • PATCH /api/v1/products/{id} mění texty, stav, značku a SEO; status: archived stáhne produkt z prodeje a data zůstanou. Adresu produktu (URL) REST nemění a cenu mění cesta varianty.
  • PUT /api/v1/stock/{variant_id} nastaví celkový stav varianty přes sklady. Rozdíl se spočítá pod zámkem a zapíše jako korekce na výchozím skladu, takže kniha pohybů dál sedí.
  • PATCH /api/v1/customers/{id} mění jméno, telefon, firmu, IČO a DIČ. E-mail ne: je to přihlašovací údaj zákazníka. Vystavené doklady si nesou údaje z okamžiku vystavení.
  • DELETE /api/v1/discounts/{id} smaže jen kód, který nikdo neuplatnil. Uplatněný kód archivujte (PATCH se status: archived): záznamy o použití jsou účetní podklad.
  • Kategorie se zakládají nejvýš do třetí úrovně stromu; adresu a místo kategorie ve stromu REST nemění.

Pole těla, jejich typy a chyby každé cesty vypisuje reference generovaná ze smlouvy (například REST API: objednávky, vratky a zásilky) a strojově OpenAPI popis REST API.

Rizikové zápisy se schválením

Zrušení a zamítnutí objednávky, faktura k objednávce i samostatná, cenová nabídka, dobropis a jeho storno, vrácení peněz a vyřízení reklamace jsou nevratné: doklad je neměnný a jeho číslo z řady se znovu nepoužije, peníze jsou u zákazníka a e-mail mu nikdo nevezme zpátky. Proto je každou z těch cest (POST /api/v1/credit-notes/{id}/cancel, POST /api/v1/invoices, POST /api/v1/orders/{id}/cancel, POST /api/v1/orders/{id}/invoice, POST /api/v1/orders/{id}/quotation, POST /api/v1/orders/{id}/refunds, POST /api/v1/orders/{id}/reject, POST /api/v1/returns/{id}/credit-note, POST /api/v1/returns/{id}/discount-credit-note a POST /api/v1/returns/{id}/reklamace-resolution) potřeba napřed schválit v administraci obchodu, stejně jako tytéž akce přes asistenta MCP.

  1. Pošlete požadavek s hlavičkou Idempotency-Key (u rizikových cest je povinná). Odpověď je 202 Accepted, nic se neprovede a tělo nese schválení:

    {
      "approval": {
        "id": "8c1e4f2a-3b5d-4c6e-9f70-1a2b3c4d5e6f",
        "status": "pending",
        "approval_url": "https://muj-eshop.cz/administrace/schvaleni/8c1e4f2a-3b5d-4c6e-9f70-1a2b3c4d5e6f",
        "expires_at": "2026-10-28T10:15:00.000000Z"
      }
    }

    Hlavička Location vede na GET /api/v1/approvals/{id} a Retry-After říká, za kolik sekund se zeptat znovu. Vlastníci a manažeři obchodu dostanou upozornění v administraci.

  2. Odkaz approval_url otevře vlastník nebo manažer přihlášený do administrace a změnu schválí, nebo zamítne. Editor, účetní ani účet podpory SHOPZI schválit nemůžou. Odkaz nenese žádné přihlášení, takže ho klidně pošlete e-mailem.

  3. Stav sledujte přes GET /api/v1/approvals/{id} (pending, approved, consumed, declined, expired), nebo počkejte na webhook approval.decided. Stav schválení vidí jen klíč, který o něj požádal; jinému klíči vrátí 404 not_found.

  4. Po schválení pošlete týž požadavek se stejným Idempotency-Key. Zápis proběhne právě jednou a odpověď je jako u každého jiného zápisu (200, u vystavení dokladu 201, s data a change). Doklad přijde v témže tvaru jako řádek GET /api/v1/documents, i s číslem z řady.

Co dál platí:

  • Opakování po zápisu vrátí týž výsledek. Když se vám ztratí odpověď, pošlete týž požadavek znovu: dostanete tentýž doklad s týmž číslem, Idempotent-Replayed: true a change.replayed: true. Druhý doklad ani druhá refundace nevznikne.
  • Schválení patří k jednomu Idempotency-Key. Dvě refundace po sto korunách k téže vratce jsou dvě změny, každá s vlastním klíčem a vlastním schválením. Nový klíč se stejným tělem tedy založí nové schválení, neprovede to staré.
  • Zamítnuté schválení vrátí na týž požadavek 403 approval_declined a nic se neprovede. Kdo změnu pořád chce, pošle nový požadavek s novým klíčem.
  • Schválení platí hodinu. Nerozhodnuté, nebo schválené a nepoužité schválení po hodině vyprší a týž požadavek založí nové (202).
  • Na jeden klíč čeká nejvýš dvacet schválení naráz a za hodinu jich vznikne nejvýš třicet; nad to přijde 409 conflict a nic nevznikne.
  • Co by zápis odmítl i po schválení, se odmítne dřív, aby vlastník neschvaloval změnu, která stejně neprojde: vratka jiné objednávky (404), ruční refundace bez method (422), zrušení objednávky s fakturou klíčem bez documents:write (403 forbidden, storno dobropis je doklad).
  • Rizikové zápisy se nevracejí přes POST /changes/{id}/revert. Fakturu opraví dobropis, dobropis jeho storno, oboje zase se schválením.

Co přes REST nejde

Rozeslání kampaně, smazání přesměrování a vyřízení nedodatelné části objednávky u dodavatele umí jen asistent přes MCP (po schválení v prohlížeči) a administrace. Feedy dodavatelů se přes REST jen čtou a zapisují se přes server MCP nebo v administraci, viz REST API: feedy dodavatelů.

Export objednávek, balíčku dokladů pro účetní, katalogu a podkladu k DPH do souboru zápisem není: POST /api/v1/exports je čtení a chce jen čtecí oprávnění té oblasti, viz Endpointy REST API.

Stropy

Zápis je i volání REST API, takže se počítá do obou stropů: do stropu volání (článek Chybové odpovědi, oddíl Objem požadavků) a navíc do stropu zápisů. Oba se počítají na klíč podle tarifu obchodu, v pevném minutovém okně a za kalendářní den v českém čase, a rozhoduje ten, který dojde dřív:

TarifZápisů za minutuZápisů za den
Basic305 000
Standard6015 000
Business12040 000
Enterprise a jednorázová licence15080 000

Nad strop přijde 429 rate_limited s hlavičkou Retry-After; hlavičky X-RateLimit-* popisují okno, které je právě těsnější. Dávka je jeden zápis. Ochranná vrstva sítě navíc pustí z jedné IP adresy zhruba 60 zápisů za minutu, a to ještě před aplikací; takové odmítnutí nemá tvar chyby API. Tisíce změn proto posílejte dávkami, ne jednotlivě.

Chyby

Všechny kódy zápisu i to, co s nimi dělat, vypisuje tabulka v článku Chybové odpovědi. Nejčastěji:

  • 400 invalid_body: tělo neprošlo smlouvou, error.pointer ukazuje kam;
  • 409 conflict: zápis odporuje stavu obchodu (stav jde jen dopředu, nebo by zápis porušil pravidlo obchodu); stejné volání znovu neprojde;
  • 422 invalid_input: hodnotu obchod nepřijme (neexistující kategorie, odkaz bez https);
  • 412 precondition_failed: zdroj se od vašeho čtení změnil;
  • 403 approval_declined: rizikový zápis vlastník nebo manažer zamítl (oddíl Rizikové zápisy se schválením);
  • 428 idempotency_key_required, 422 idempotency_key_reused, 409 idempotency_in_progress: oddíl Idempotency-Key výš.

Jak dlouho deník změny drží

Deník změn drží zápisy přes REST API 30 dní, změny asistenta přes MCP a Agenta 365 dní. Starší záznamy maže pravidelný úklid po dávkách. Potom změna z GET /api/v1/changes zmizí, vrátit ji už nejde a zapomene se i její Idempotency-Key. Integrace, která potřebuje delší historii, si ji vede u sebe.

Když obchodník vymaže zákazníka podle GDPR, smažou se i snímky jeho karty v deníku změn (jméno, telefon, firma). Úprava takového zákazníka pak vrátit nejde, protože není co vrátit.