# MCP: slevy, kampaně a feedy

> Nástroje MCP pro slevové kódy, vyskakovací okna, koncepty kampaní, segmenty zákazníků a nastavení feedů: oprávnění, potvrzení, důsledky zápisu a parametry.

- Sekce: Pro vývojáře
- Stránka: https://shopzi.cz/dokumentace/vyvojari/mcp-marketing
- Ověřeno: 2026-09-16

---

Slevové kódy i s cílením na produkty a kategorie, feedy do srovnávačů zboží, kampaně i s výsledky rozeslání, vyskakovací okna a segmenty zákazníků. Rozeslání kampaně ani vygenerování feedu mezi nástroji není, obojí zůstává v administraci.

Nástroje volá klient přes server MCP na doméně obchodu, například `https://muj-eshop.cz/api/mcp`, a v odpovědi na `tools/list` dostane jen ty, na jejichž oprávnění klíč dosáhne. Jak server mluví, kdy se ptá člověka a jak se změny vracejí, popisuje článek [MCP server](/dokumentace/vyvojari/mcp-server).

U každého nástroje stojí oprávnění, které chce, jestli se server před provedením zeptá člověka a kudy, jestli volání strhne kredity obchodu nebo peníze z karty, co vrací pro deník změn a jakou větu o důsledku člověk v potvrzení uvidí. Všechno z toho se vyhodnocuje z téhož kódu, podle kterého se server rozhoduje. Popisy parametrů jsou převzaté ze schématu, které server posílá v `tools/list`; kde se v něm text obrací přímo k modelu, je tady převedený do vykání. Povinnost parametru platí uvnitř objektu, ve kterém parametr leží.

Před zápisem, který přepisuje nebo maže, před útratou kreditů nebo platbou kartou a před hledáním mimo obchod se server ptá člověka a do té doby neprovede nic. Nejdřív použije schválení, které pro totéž volání se stejnými hodnotami už v administraci leží schválené. Jinak se zeptá formulářem, když ho klient deklaruje a politika akce ho dovoluje; formulář potvrzuje ten, kdo drží klíč, takže před ukradeným klíčem takové potvrzení nechrání. Otázka ve formuláři nese pod nadpisem „Co se změní“ tytéž řádky jako stránka schválení. Klient s elicitací URL dostane odkaz na stránku schválení v administraci a klient bez elicitace odmítnutí `approval_required` s odkazem v `_meta`; po schválení volání zopakuje se stejnými hodnotami. Na stránce schválení rozhoduje jen přihlášený člověk, kterého u každé akce jmenuje odrážka Potvrzení přes MCP, a účet podpory SHOPZI nikdy. Když politika nedovoluje nic, co klient umí, přijde odmítnutí `confirmation_required` a neprovede se nic. Výsledek potvrzeného volání nese v `_meta["cz.shopzi/confirmation"]` údaj, že akci potvrdil člověk a kde (`form` nebo `approval`), a v obsahu českou větu pro model, u placené akce i s cenou a zůstatkem kreditů z dotazu. Na otázku formulářem je 15 minut, schválení na stránce platí 60 minut, pokud u akce není uvedeno jinak.

Zápisové nástroje vracejí v poli `change_id` ID záznamu v deníku změn; co pole u kterého nástroje nese, říká jeho odrážka Deník změn. Změnu z deníku vrací `shopzi_undo_change` podle jejího druhu: obnoví předchozí hodnoty, u skladu zapíše vyrovnávací pohyb, u běžné ceny zapíše návrat do 30denní historie cen (nic z ní nemaže) a změnu, která už opustila obchod nebo stála peníze (odeslaný e-mail, stržené kredity, platbu kartou), odmítne s vysvětlením.

## `shopzi_list_marketing` [#shopzi-list-marketing]

Vrátí podle `resource` slevové kódy i s počtem uplatnění a cílením na produkty a kategorie, stav feedů do srovnávačů zboží, kampaně i s výsledky rozeslání (s `entityId` jednu kampaň i s tělem e-mailu), vyskakovací okna, nebo segmenty zákazníků.

* **Oprávnění:** `marketing:read`, u klíče „Marketing: slevy, feedy, kampaně, segmenty (čtení)“.
* **Druh:** čtení (`readOnlyHint`).
* **Potvrzení přes MCP:** ne.
* **Kredity a platba kartou:** ne.

### `shopzi_list_marketing`: oblasti [#shopzi-list-marketing-oblasti]

* `discounts`
* `feeds`
* `campaigns`
* `popups`
* `segments`

## `shopzi_list_marketing`: parametry [#shopzi-list-marketing-parametry]

* `resource` (jedna z hodnot `discounts`, `feeds`, `campaigns`, `popups` a `segments`; povinný)
* `status` (jedna z hodnot `draft`, `scheduled`, `active`, `paused`, `expired`, `archived`, `sending`, `sent` a `canceled`; nepovinný): Filtr stavu. `discounts`: draft | scheduled | active | paused | expired | archived. `campaigns`: draft | scheduled | sending | sent | paused | canceled.
* `search` (text; nepovinný): Hledá v kódu a názvu (`discounts`), v názvu a předmětu (`campaigns`) nebo v nadpisu (`popups`).
* `discountKind` (jedna z hodnot `percent`, `fixed` a `free_shipping`; nepovinný): Jen `discounts`: `percent` = procentní sleva, `fixed` = pevná částka, `free_shipping` = doprava zdarma.
* `entityId` (UUID; nepovinný): Jen `campaigns`: jedna kampaň i s `body_html`.
* `limit` (celé číslo od 1 do 100, výchozí `25`; nepovinný): Počet položek na stránku, 1 až 100. Velká stránka se do jedné odpovědi nemusí vejít a nástroj ji pak odmítne, což stojí krok navíc: berte jen tolik položek, kolik na odpověď opravdu potřebujete.
* `offset` (celé číslo od 0 do 100000, výchozí `0`; nepovinný): Kolik položek přeskočit. 0 = první stránka.

## `shopzi_save_discount_code` [#shopzi-save-discount-code]

Založí nebo upraví slevový kód včetně cílení na vybrané produkty a kategorie (seznam se nahrazuje celý), smaže kód, který nikdo neuplatnil, nebo přepne stav více vyjmenovaným kódům naráz. Nový kód vzniká jako koncept; u uplatněného kódu jde měnit jen název, veřejný popisek, stav a konec platnosti.

* **Oprávnění:** `marketing:write`, u klíče „Marketing: slevové kódy, vyskakovací okna, koncepty kampaní, segmenty, feedy (zápis)“.
* **Druh:** zápis, který umí přepsat nebo smazat existující data (`destructiveHint`).
* **Potvrzení přes MCP:** ano: formulář v klientu, který potvrdí ten, kdo drží klíč; jinak odkaz na stránku schválení přes elicitaci URL; jinak odkaz na stránku schválení v odmítnutí `approval_required`. Na stránce schválení rozhoduje vlastník nebo manažer obchodu.
* **Kredity a platba kartou:** ne.
* **Deník změn:** výsledek nese `change_id`. ID záznamu v deníku. Předejte ho do `shopzi_undo_change`.
* **Věta o důsledku, kterou člověk uvidí v potvrzení:**

  > Aktivace kódu ho pustí do košíků zákazníků, pozastavení a archivace ho z nich vezmou. Hromadná změna se provede na VŠECH kódech vypsaných níž, naráz a přesně na nich; vrátit to jde jedním krokem, celou dávku najednou. Smazat lze jen kód, který nikdo neuplatnil.

### `shopzi_save_discount_code`: operace [#shopzi-save-discount-code-operace]

* `save` (uložit)
* `delete` (smazat)
* `bulk_status` (hromadně přepnout stav)

## `shopzi_save_discount_code`: parametry [#shopzi-save-discount-code-parametry]

* `operation` (jedna z hodnot `save`, `delete` a `bulk_status`; nepovinný): `save` (výchozí) = založit nebo upravit, `delete` = smazat jeden neuplatněný kód, `bulk_status` = přepnout stav víc kódům najednou.
* `discountId` (text; nepovinný): ID promo akce (`promotion_id`) existujícího kódu. Vynechte pro založení nového. Povinné u `delete`.
* `discountIds` (pole, položka: text, nejvýš 100 položek; nepovinný): Jen `bulk_status`: VÝSLOVNÝ seznam ID kódů ze `shopzi_list_marketing` (`resource: discounts`), nejvýš sto. Filtr se poslat nedá schválně: schvalovací karta ukazuje počet, který v ní stojí, a provede se přesně tolik kódů.
* `fields` (objekt; nepovinný): Pole ke změně. Vynechané pole zůstane beze změny. U `delete` se nepoužívá, u `bulk_status` se z něj čte jen `status`.
* `fields.code` (text; nepovinný): Kód, který zákazník zadá v košíku. Jen A-Z, 0-9 a . \_ - (2 až 40 znaků). Povinný při zakládání.
* `fields.name` (text; nepovinný): Interní název akce. Vidí ho jen obchodník.
* `fields.publicTitle` (text nebo `null`; nepovinný): Popisek slevy v košíku, který uvidí zákazník.
* `fields.status` (jedna z hodnot `draft`, `active`, `paused` a `archived`; nepovinný): draft = koncept, active = platí, paused = pozastaveno, archived = archiv. U `bulk_status` jsou povolené jen active, paused, archived.
* `fields.kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`; nepovinný): percent = procenta, fixed = pevná částka, free\_shipping = doprava zdarma.
* `fields.percentBp` (celé číslo od 1 do 10000 nebo `null`; nepovinný): Sleva v setinách procenta: 1000 = 10 %, 10000 = 100 %.
* `fields.amountMinor` (celé číslo aspoň 1 nebo `null`; nepovinný): Pevná sleva v haléřích: 20000 = 200 Kč.
* `fields.maxDiscountMinor` (celé číslo aspoň 0 nebo `null`; nepovinný): Strop procentuální slevy v haléřích. null = bez stropu.
* `fields.minSubtotalMinor` (celé číslo aspoň 0 nebo `null`; nepovinný): Minimální hodnota košíku v haléřích. null = bez limitu.
* `fields.startsAt` (text nebo `null`; nepovinný): Začátek platnosti v ISO tvaru. null = ihned.
* `fields.endsAt` (text nebo `null`; nepovinný): Konec platnosti v ISO tvaru. null = bez konce.
* `fields.totalUsageLimit` (celé číslo aspoň 1 nebo `null`; nepovinný): Maximální počet uplatnění celkem. null = bez limitu.
* `fields.perCustomerLimit` (celé číslo aspoň 1 nebo `null`; nepovinný): Maximální počet uplatnění na zákazníka.
* `fields.usageLimit` (celé číslo aspoň 1 nebo `null`; nepovinný): Maximální počet uplatnění tohoto konkrétního kódu.
* `fields.singleUse` (`true` nebo `false`; nepovinný): true = kód lze uplatnit jen jednou.
* `fields.firstOrderOnly` (`true` nebo `false`; nepovinný): true = jen pro první objednávku zákazníka.
* `fields.excludeDiscountedItems` (`true` nebo `false`; nepovinný): true = neplatí na zboží, které už je zlevněné.
* `fields.targets` (pole objektů, nejvýš 200 položek; nepovinný): PLNÁ NÁHRADA cílení: celý výsledný seznam, `[]` = celý košík. Na uplatněném kódu nejde měnit.
* `fields.targets[].targetType` (jedna z hodnot `product` a `category`; povinný)
* `fields.targets[].targetId` (UUID; povinný): ID produktu nebo kategorie ze `shopzi_list_catalog`.
* `fields.targets[].mode` (jedna z hodnot `include` a `exclude`; povinný): include = jen na tyto, exclude = na tyto ne.
* `idempotencyKey` (text, 1 až 200 znaků; nepovinný): Klíč idempotence. Stejný klíč = stejný zápis: opakované volání vrátí původní výsledek a NEZAPÍŠE podruhé. Použijte vlastní náhodný řetězec pro každou zamýšlenou změnu; při opakování po chybě sítě pošlete tentýž.

## `shopzi_save_marketing_entity` [#shopzi-save-marketing-entity]

Založí, upraví nebo smaže vyskakovací okno, koncept kampaně, segment zákazníků a nastavení feedů do srovnávačů. Vyskakovací okno vzniká zhasnuté a rozsvítit ho jde, jen když žádné jiné nesvítí. Rozeslat kampaň tudy nejde a změna feedu se do srovnávače propíše až při jeho nejbližším vygenerování.

* **Oprávnění:** `marketing:write`, u klíče „Marketing: slevové kódy, vyskakovací okna, koncepty kampaní, segmenty, feedy (zápis)“.
* **Druh:** zápis, který umí přepsat nebo smazat existující data (`destructiveHint`).
* **Potvrzení přes MCP:** ano: formulář v klientu, který potvrdí ten, kdo drží klíč; jinak odkaz na stránku schválení přes elicitaci URL; jinak odkaz na stránku schválení v odmítnutí `approval_required`. Na stránce schválení rozhoduje vlastník nebo manažer obchodu.
* **Kredity a platba kartou:** ne.
* **Deník změn:** výsledek nese `change_id`. ID záznamu v deníku. Předejte ho do `shopzi_undo_change`.
* **Věta o důsledku, kterou člověk uvidí v potvrzení:**

  > Smazat lze jen KONCEPT kampaně, zhasnuté okno a segment, který nemá navázanou žádnou kampaň; všechno tři se dá vrátit i s obsahem. Nic z toho nikomu nic neodesílá: rozeslat kampaň umí jen člověk v administraci. ZAPNUTÍ FEEDU zveřejní adresu s katalogem obchodu, ze které si ho srovnávač (Heureka, Zboží.cz, Google a další) stahuje; vypnutím se zase zavře. Zařazení kategorií a výjimky u položek se do srovnávače propíšou až při nejbližším vygenerování feedu, tedy při ranní automatické aktualizaci, nebo když v sekci Feedy kliknete na Generovat u kanálu či na Generovat vše. Vygenerovat a zveřejnit feed sám agent neumí.

### `shopzi_save_marketing_entity`: oblasti [#shopzi-save-marketing-entity-oblasti]

* `popup` (Vyskakovací okno)
* `campaign` (Kampaň)
* `segment` (Segment zákazníků)
* `feed_channel` (Kanál feedu)
* `feed_category` (Zařazení kategorie ve feedu)
* `feed_item` (Výjimka položky ve feedu)

### `shopzi_save_marketing_entity`: operace [#shopzi-save-marketing-entity-operace]

* `save` (uložit)
* `delete` (smazat)

## `shopzi_save_marketing_entity`: parametry [#shopzi-save-marketing-entity-parametry]

* `resource` (jedna z hodnot `popup`, `campaign`, `segment`, `feed_channel`, `feed_category` a `feed_item`; povinný): Která položka. Pole musí patřit k ní.
* `operation` (jedna z hodnot `save` a `delete`; nepovinný): `save` (výchozí) = založit nebo upravit, `delete` = smazat. Mazání chce `entityId` a žádná `fields`. U `feed_category` a `feed_item` znamená `delete` zrušení zařazení nebo výjimky; `feed_channel` se nemaže, jen vypíná (`enabled: false`).
* `channel` (jedna z hodnot `heureka`, `zbozi`, `google_merchant`, `glami`, `favi`, `biano`, `meta_catalog` a `microsoft_merchant`; nepovinný): Jen feedy: který srovnávač. Povinné u `feed_channel`, `feed_category` i `feed_item`.
* `entityId` (UUID; nepovinný): ID existující položky (UUID) ze `shopzi_list_marketing`. Vynechte pro založení nové. U `feed_item` je to ID VARIANTY produktu (ze `shopzi_get_product`).
* `fields` (objekt; nepovinný): Pole ke změně. Vynechané pole zůstane beze změny. U `operation: delete` se nepoužívá.
* `fields.title` (text; nepovinný): Jen `popup`: nadpis okna, nejvýše 60 znaků. Povinný při zakládání.
* `fields.content` (text nebo `null`; nepovinný): Jen `popup`: text okna (HTML), nejvýše 1000 znaků prostého textu.
* `fields.template` (jedna z hodnot `announcement`, `promo`, `welcome`, `newsletter` a `discount_code`; nepovinný): Jen `popup`: vzhled okna. `discount_code` navíc vyžaduje `discountCodeId`.
* `fields.ctaText` (text nebo `null`; nepovinný): Jen `popup`: text tlačítka, nejvýše 50 znaků.
* `fields.imageUrl` (text nebo `null`; nepovinný): Jen `popup`: adresa obrázku v okně.
* `fields.delaySeconds` (celé číslo od 0 do 120; nepovinný): Jen `popup`: za kolik sekund se okno ukáže (0 až 120).
* `fields.isDismissible` (`true` nebo `false`; nepovinný): Jen `popup`: lze okno zavřít křížkem.
* `fields.showFrequency` (jedna z hodnot `once_session`, `once_ever` a `every_visit`; nepovinný): Jen `popup`: once\_session = jednou za návštěvu, once\_ever = jednou navždy, every\_visit = pokaždé.
* `fields.discountCodeId` (UUID nebo `null`; nepovinný): Jen `popup`: ID slevového kódu (UUID), který okno nabízí. Povinné u šablony `discount_code`.
* `fields.isActive` (`true` nebo `false`; nepovinný): Jen `popup`: `false` zhasne, `true` rozsvítí existující okno, jen když žádné jiné nesvítí.
* `fields.subject` (text nebo `null`; nepovinný): Jen `campaign`: předmět e-mailu.
* `fields.preheader` (text nebo `null`; nepovinný): Jen `campaign`: úvodní řádek, který se ukáže v seznamu zpráv vedle předmětu.
* `fields.bodyHtml` (text nebo `null`; nepovinný): Jen `campaign`: tělo e-mailu (HTML).
* `fields.ctaLabel` (text nebo `null`; nepovinný): Jen `campaign`: text tlačítka v e-mailu.
* `fields.couponCode` (text nebo `null`; nepovinný): Jen `campaign`: slevový kód uvedený v e-mailu. Kód se tím nezakládá, jen se do zprávy vypíše.
* `fields.segmentId` (UUID nebo `null`; nepovinný): Jen `campaign`: ID segmentu (UUID), kterému je kampaň určená. Neodesílá, jen vybírá publikum.
* `fields.description` (text nebo `null`; nepovinný): Jen `segment`: k čemu segment je. Vidí ho jen obchodník.
* `fields.criteria` (objekt nebo `null`; nepovinný): Jen `segment`: pravidlo výběru. `all` = všechny podmínky zároveň, `any` = aspoň jedna. Segment bez podmínek nevybere NIKOHO (prázdné pravidlo se schválně nepřekládá na „všichni“). `total_spent_minor` je v haléřích, `within_days`/`older_than_days` berou počet dní.
* `fields.criteria.all` (pole objektů, nejvýš 20 položek; nepovinný)
* `fields.criteria.all[].field` (jedna z hodnot `newsletter_subscribed`, `sms_marketing_consent`, `auth_provider`, `customer_group_id`, `marketing_tags`, `orders_count`, `total_spent_minor`, `last_order_at`, `first_order_at`, `created_at`, `locale`, `is_business` a `b2b_status`; povinný)
* `fields.criteria.all[].op` (jedna z hodnot `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `has_tag`, `within_days`, `older_than_days`, `is_set` a `is_not_set`; povinný)
* `fields.criteria.all[].value` (text nebo číslo nebo `true` nebo `false` nebo `null`; nepovinný)
* `fields.criteria.any` (pole objektů, nejvýš 20 položek; nepovinný)
* `fields.criteria.any[].field` (jedna z hodnot `newsletter_subscribed`, `sms_marketing_consent`, `auth_provider`, `customer_group_id`, `marketing_tags`, `orders_count`, `total_spent_minor`, `last_order_at`, `first_order_at`, `created_at`, `locale`, `is_business` a `b2b_status`; povinný)
* `fields.criteria.any[].op` (jedna z hodnot `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains`, `has_tag`, `within_days`, `older_than_days`, `is_set` a `is_not_set`; povinný)
* `fields.criteria.any[].value` (text nebo číslo nebo `true` nebo `false` nebo `null`; nepovinný)
* `fields.name` (text; nepovinný): `campaign` a `segment`: název. Vidí ho jen obchodník. Povinný při zakládání.
* `fields.ctaUrl` (text nebo `null`; nepovinný): `popup` a `campaign`: adresa tlačítka. U okna buď cesta v obchodě (např. /produkty), nebo odkaz na https\://.
* `fields.enabled` (`true` nebo `false`; nepovinný): Jen `feed_channel`: zapnout kanál. `true` ZVEŘEJNÍ adresu s katalogem, ze které si ho srovnávač stahuje; `false` ji zase zavře a nastavení zůstane zachované.
* `fields.defaultCpcMinor` (celé číslo aspoň 0 nebo `null`; nepovinný): Jen `feed_channel`: výchozí cena za proklik v HALÉŘÍCH (2 Kč = 200). Čtou ji Heureka a Zboží.cz. `null` ji zruší.
* `fields.includeOutOfStock` (`true` nebo `false`; nepovinný): Jen `feed_channel`: posílat i zboží, které není skladem. `false` ho z feedu vynechá.
* `fields.categories` (pole objektů; nepovinný): Jen `feed_category`: kategorie k zařazení (i víc najednou). U `operation: delete` stačí u každé `categoryId`.
* `fields.categories[].categoryId` (UUID; povinný): ID kategorie obchodu ze `shopzi_list_catalog` (resource `categories`).
* `fields.categories[].externalCategoryId` (text nebo `null`; nepovinný): Číslo kategorie ve stromu srovnávače. Čte ho Google, Meta a Microsoft; neexistující číslo nástroj odmítne.
* `fields.categories[].externalCategoryPath` (text nebo `null`; nepovinný): Cesta ve stromu srovnávače, například „Heureka.cz | Dům a zahrada | Nábytek“. Čte ji Heureka, Zboží.cz, Glami, Favi i Biano.
* `fields.exclude` (`true` nebo `false`; nepovinný): Jen `feed_item`: `true` položku z feedu vyřadí, `false` ji tam vrátí.
* `fields.availability` (jedna z hodnot `in_stock` a `out_of_stock`, nebo `null`; nepovinný): Jen `feed_item`: přebije dostupnost hlášenou srovnávači. `null` vrátí rozhodování skladu.
* `idempotencyKey` (text, 1 až 200 znaků; nepovinný): Klíč idempotence. Stejný klíč = stejný zápis: opakované volání vrátí původní výsledek a NEZAPÍŠE podruhé. Použijte vlastní náhodný řetězec pro každou zamýšlenou změnu; při opakování po chybě sítě pošlete tentýž.
