# REST API: slevové kódy

> Referenční popis cest slevových kódů: výpis a detail s podmínkami a počtem použití, založení, úprava a smazání neuplatněného kódu, s tělem, idempotencí a chybami.

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

---

Čtení s oprávněním `marketing:read`: slevové kódy s druhem a výší slevy, platností, limity, počtem použití a cílením na produkty a kategorie. Zápis s oprávněním `marketing:write` a s povoleným zápisem přes REST u klíče: založení kódu (ve výchozím stavu jako koncept), jeho úprava a smazání kódu, který nikdo neuplatnil. Uplatněný kód se jen archivuje, protože záznamy o použití jsou účetní podklad, a kampaně REST nerozesílá.

Cesty odpovídají na `GET`, `POST`, `PUT`, `PATCH` a `DELETE` na doméně vašeho obchodu, například `https://muj-eshop.cz/api/v1/…`, a klíč se posílá v hlavičce `Authorization: Bearer` nebo `x-api-key`. Parametry, pole i chyby na téhle stránce se generují ze smlouvy, podle které API odpovídá, takže platí pro build, na kterém stránka běží. Každá cesta může navíc vrátit chyby společné všem cestám: `invalid_api_key`, `missing_api_key`, `external_access_disabled`, `external_access_not_enabled`, `external_access_suspended`, `key_surface_mismatch`, `plan_required`, `rest_write_disabled`, `rest_write_not_enabled`, `shop_unavailable`, `shop_not_found`, `rate_limited` a `server_error`. Co znamenají, popisuje článek [Chybové odpovědi](/dokumentace/vyvojari/chybove-odpovedi), klíč a oprávnění [Autentizace a oprávnění](/dokumentace/vyvojari/autentizace-a-opravneni) a průchod výpisem [Stránkování a filtry](/dokumentace/vyvojari/strankovani-a-filtry).

## `GET /api/v1/discounts` [#get-api-v1-discounts]

Slevové kódy s druhem a výší slevy, platností, limity, počtem použití a cílením na produkty a kategorie.

* **Oprávnění:** `marketing:read`, u klíče „Marketing: slevy, feedy, kampaně, segmenty (čtení)“.
* **Odpověď:** stránka výpisu, záznamy jsou v `data` a jak otevřít další stránku, říká seznam Obálka odpovědi.
* **Synchronizace:** s `updated_since` se výpis řadí podle pole `updated_at` od nejstarší změny, bez něj od nejnovějšího záznamu. Pole `updated_at`: Poslední změna slevové akce. Počet použití ho neposouvá.

```bash
curl -s "https://muj-eshop.cz/api/v1/discounts?limit=100" \
  -H "Authorization: Bearer $SHOPZI_API_KEY"
```

**Parametry dotazu**

* `limit` (celé číslo od 1 do 100, výchozí `25`; nepovinný): Počet řádků na stránku, výchozí 25. Vyšší hodnota se ořízne na 100, nesmysl spadne na výchozí.
* `cursor` (text; nepovinný): Hodnota `next_cursor` z předchozí stránky, beze změny. Platí jen pro tentýž dotaz.
* `updated_since` (čas ISO 8601; nepovinný): ISO 8601 se zónou `Z` nebo s číselným posunem (`+02:00`). Vrátí záznamy změněné od té chvíle včetně, seřazené od nejstarší změny, a stránkuje stabilně: řádek změněný během průchodu se v něm neopakuje a přijde v příštím. Hodnota `next_updated_since` jde do adresy vložit bez kódování; `+` z nezakódované adresy se čte jako `+`.
* `status` (jedna z hodnot `draft`, `active`, `paused` a `archived`; nepovinný): Uložený stav slevy.

**Obálka odpovědi**

* `data` (pole záznamů): Záznamy stránky, jejich pole popisuje seznam Pole záznamu.
* `next_cursor` (text nebo `null`): Kurzor další stránky, `null` = tohle je poslední stránka.
* `next_updated_since` (čas ISO 8601): Hodnota `updated_since` pro příští průchod: začátek tohoto průchodu mínus 5 minut. Na všech stránkách jednoho průchodu je stejná a do adresy jde vložit bez kódování.

**Pole záznamu**

* `id` (UUID): Id slevové akce (promo akce s kódem).
* `code` (text): Kód, který zákazník zadá v košíku.
* `name` (text): Interní název, vidí ho jen obchodník.
* `public_title` (text nebo `null`): Popisek slevy v košíku pro zákazníka.
* `status` (jedna z hodnot `draft`, `scheduled`, `active`, `paused`, `expired` a `archived`): `scheduled` a `expired` se počítají z `starts_at` a `ends_at` u aktivní slevy.
* `kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`)
* `percent_bp` (celé číslo nebo `null`): Sleva v setinách procenta: 1000 = 10 %.
* `currency_code` (text se vzorem `^[A-Z]{3}$`): Kód měny podle ISO 4217, dnes vždy CZK.
* `amount_minor` (celé číslo nebo `null`): Pevná sleva v haléřích, jen u `fixed`.
* `max_discount_minor` (celé číslo nebo `null`): Strop procentní slevy v haléřích.
* `min_subtotal_minor` (celé číslo nebo `null`): Nejnižší hodnota košíku v haléřích.
* `starts_at` (čas ISO 8601 nebo `null`)
* `ends_at` (čas ISO 8601 nebo `null`)
* `usage_count` (celé číslo): Kolikrát byl kód použit.
* `usage_limit` (celé číslo nebo `null`)
* `total_usage_limit` (celé číslo nebo `null`)
* `per_customer_limit` (celé číslo nebo `null`)
* `single_use` (`true` nebo `false`)
* `first_order_only` (`true` nebo `false`)
* `exclude_discounted_items` (`true` nebo `false`)
* `redemptions` (celé číslo): Uplatnění v objednávkách (bez stornovaných).
* `targets` (pole objektů): Cílení. Prázdné = celý košík.
* `targets[].target_type` (jedna z hodnot `product` a `category`)
* `targets[].target_id` (UUID)
* `targets[].mode` (jedna z hodnot `include` a `exclude`)
* `created_at` (čas ISO 8601)
* `updated_at` (čas ISO 8601): Poslední změna slevové akce. Počet použití ho neposouvá.

**Chyby této cesty**

* **400** `invalid_query`: Parametr dotazu má neplatnou hodnotu: čas v updated\_since bez časového posunu, nebo hodnota filtru, kterou výčet nezná. Zpráva jmenuje parametr, u filtru i povolené hodnoty.
* **400** `invalid_cursor`: Kurzor je poškozený, nebo patří k jinému dotazu (jiná cesta, jiný filtr nebo jiné updated\_since). Začněte průchod znovu bez cursor.
* **403** `insufficient_scope`: Klíč je platný, ale nemá oprávnění, které cesta vyžaduje. Zpráva vypíše, co klíči chybí a co má.

## `GET /api/v1/discounts/{id}` [#get-api-v1-discounts-id]

Jeden slevový kód, v témže tvaru jako ve výpisu, i s ETagem pro podmíněnou úpravu.

* **Oprávnění:** `marketing:read`, u klíče „Marketing: slevy, feedy, kampaně, segmenty (čtení)“.
* **Odpověď:** jeden záznam v `data`.

```bash
curl -s "https://muj-eshop.cz/api/v1/discounts/$ID" \
  -H "Authorization: Bearer $SHOPZI_API_KEY"
```

**Parametry v cestě**

* `id` (UUID; povinný): Identifikátor záznamu (UUID) z výpisu.

**Obálka odpovědi**

* `data` (záznam): Jeho pole popisuje seznam Pole záznamu.

**Pole záznamu**

* `id` (UUID): Id slevové akce (promo akce s kódem).
* `code` (text): Kód, který zákazník zadá v košíku.
* `name` (text): Interní název, vidí ho jen obchodník.
* `public_title` (text nebo `null`): Popisek slevy v košíku pro zákazníka.
* `status` (jedna z hodnot `draft`, `scheduled`, `active`, `paused`, `expired` a `archived`): `scheduled` a `expired` se počítají z `starts_at` a `ends_at` u aktivní slevy.
* `kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`)
* `percent_bp` (celé číslo nebo `null`): Sleva v setinách procenta: 1000 = 10 %.
* `currency_code` (text se vzorem `^[A-Z]{3}$`): Kód měny podle ISO 4217, dnes vždy CZK.
* `amount_minor` (celé číslo nebo `null`): Pevná sleva v haléřích, jen u `fixed`.
* `max_discount_minor` (celé číslo nebo `null`): Strop procentní slevy v haléřích.
* `min_subtotal_minor` (celé číslo nebo `null`): Nejnižší hodnota košíku v haléřích.
* `starts_at` (čas ISO 8601 nebo `null`)
* `ends_at` (čas ISO 8601 nebo `null`)
* `usage_count` (celé číslo): Kolikrát byl kód použit.
* `usage_limit` (celé číslo nebo `null`)
* `total_usage_limit` (celé číslo nebo `null`)
* `per_customer_limit` (celé číslo nebo `null`)
* `single_use` (`true` nebo `false`)
* `first_order_only` (`true` nebo `false`)
* `exclude_discounted_items` (`true` nebo `false`)
* `redemptions` (celé číslo): Uplatnění v objednávkách (bez stornovaných).
* `targets` (pole objektů): Cílení. Prázdné = celý košík.
* `targets[].target_type` (jedna z hodnot `product` a `category`)
* `targets[].target_id` (UUID)
* `targets[].mode` (jedna z hodnot `include` a `exclude`)
* `created_at` (čas ISO 8601)
* `updated_at` (čas ISO 8601): Poslední změna slevové akce. Počet použití ho neposouvá.

**Chyby této cesty**

* **403** `insufficient_scope`: Klíč je platný, ale nemá oprávnění, které cesta vyžaduje. Zpráva vypíše, co klíči chybí a co má.
* **404** `not_found`: Záznam s tímhle identifikátorem v obchodě není.

## `POST /api/v1/discounts` [#post-api-v1-discounts]

Nový slevový kód, ve výchozím stavu jako koncept, i s limity a cílením. Chce `Idempotency-Key`.

* **Oprávnění:** `marketing:write`, u klíče „Marketing: slevové kódy, vyskakovací okna, koncepty kampaní, segmenty, feedy (zápis)“.
* **Odpověď:** stav 201, zdroj v `data` v témže tvaru, jaký vrací čtení, a změna v deníku v `change`.
* **Zápis:** jen klíčem s povoleným zápisem přes REST. `Idempotency-Key` je povinný; změnu jde vrátit přes `POST /api/v1/changes/{id}/revert`.

```bash
curl -s -X POST https://muj-eshop.cz/api/v1/discounts \
  -H "Authorization: Bearer $SHOPZI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"code":"…","name":"…","kind":"percent"}'
```

**Tělo požadavku** (JSON, pole navíc se odmítnou)

* `code` (text se vzorem `^[A-Za-z0-9._-]{2,40}$`, nejvýš 40 znaků; povinný): A-Z, 0-9 a . \_ - (2 až 40 znaků).
* `name` (text, 1 až 200 znaků; povinný): Interní název akce, vidí ho jen obchodník.
* `public_title` (text, nejvýš 200 znaků nebo `null`; nepovinný)
* `status` (jedna z hodnot `draft`, `active`, `paused` a `archived`; nepovinný): Výchozí `draft`.
* `kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`; povinný)
* `percent_bp` (celé číslo od 1 do 10000 nebo `null`; nepovinný)
* `amount_minor` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `max_discount_minor` (celé číslo aspoň 0 nebo `null`; nepovinný)
* `min_subtotal_minor` (celé číslo aspoň 0 nebo `null`; nepovinný)
* `starts_at` (čas ISO 8601 nebo `null`; nepovinný)
* `ends_at` (čas ISO 8601 nebo `null`; nepovinný)
* `total_usage_limit` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `per_customer_limit` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `usage_limit` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `single_use` (`true` nebo `false`; nepovinný)
* `first_order_only` (`true` nebo `false`; nepovinný)
* `exclude_discounted_items` (`true` nebo `false`; nepovinný)
* `targets` (pole objektů, nejvýš 200 položek; nepovinný): Cílení; vynechané = celý košík.
* `targets[].target_type` (jedna z hodnot `product` a `category`; povinný)
* `targets[].target_id` (UUID; povinný)
* `targets[].mode` (jedna z hodnot `include` a `exclude`; povinný): `include` = jen na tyto, `exclude` = na tyto ne.

**Obálka odpovědi**

* `data` (záznam): Zdroj po zápisu, přečtený znovu; jeho pole popisuje seznam Pole záznamu.
* `change` (objekt): Změna, kterou zápis vyrobil.

**Pole záznamu**

* `id` (UUID): Id slevové akce (promo akce s kódem).
* `code` (text): Kód, který zákazník zadá v košíku.
* `name` (text): Interní název, vidí ho jen obchodník.
* `public_title` (text nebo `null`): Popisek slevy v košíku pro zákazníka.
* `status` (jedna z hodnot `draft`, `scheduled`, `active`, `paused`, `expired` a `archived`): `scheduled` a `expired` se počítají z `starts_at` a `ends_at` u aktivní slevy.
* `kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`)
* `percent_bp` (celé číslo nebo `null`): Sleva v setinách procenta: 1000 = 10 %.
* `currency_code` (text se vzorem `^[A-Z]{3}$`): Kód měny podle ISO 4217, dnes vždy CZK.
* `amount_minor` (celé číslo nebo `null`): Pevná sleva v haléřích, jen u `fixed`.
* `max_discount_minor` (celé číslo nebo `null`): Strop procentní slevy v haléřích.
* `min_subtotal_minor` (celé číslo nebo `null`): Nejnižší hodnota košíku v haléřích.
* `starts_at` (čas ISO 8601 nebo `null`)
* `ends_at` (čas ISO 8601 nebo `null`)
* `usage_count` (celé číslo): Kolikrát byl kód použit.
* `usage_limit` (celé číslo nebo `null`)
* `total_usage_limit` (celé číslo nebo `null`)
* `per_customer_limit` (celé číslo nebo `null`)
* `single_use` (`true` nebo `false`)
* `first_order_only` (`true` nebo `false`)
* `exclude_discounted_items` (`true` nebo `false`)
* `redemptions` (celé číslo): Uplatnění v objednávkách (bez stornovaných).
* `targets` (pole objektů): Cílení. Prázdné = celý košík.
* `targets[].target_type` (jedna z hodnot `product` a `category`)
* `targets[].target_id` (UUID)
* `targets[].mode` (jedna z hodnot `include` a `exclude`)
* `created_at` (čas ISO 8601)
* `updated_at` (čas ISO 8601): Poslední změna slevové akce. Počet použití ho neposouvá.

### `POST /api/v1/discounts`: chyby [#post-api-v1-discounts-chyby]

* **400** `invalid_body`: Tělo zápisu není platný JSON nebo neodpovídá smlouvě cesty: chybí povinné pole, hodnota má špatný typ, nebo je v těle pole, které cesta nezná. Pole pointer v chybě ukazuje (JSON Pointer) na místo, které neprošlo.
* **400** `invalid_idempotency_key`: Hlavička Idempotency-Key nemá povolený tvar: 8 až 128 znaků z písmen, číslic a znaků tečka, podtržítko, dvojtečka a pomlčka.
* **400** `invalid_if_match`: Hlavička If-Match nenese ETag v tvaru, v jakém ho vrací odpověď (W/ a hodnota v uvozovkách), ani hvězdičku.
* **402** `credit_cap_exceeded`: Akce by překročila měsíční strop kreditů klíče, nebo ho teď nejde ověřit. Nestrhlo se nic.
* **402** `payment_declined`: Uložená karta platbu odmítla. Nic se nezměnilo a nic se nestrhlo.
* **402** `plan_required`: Tarif obchodu tuhle akci nezahrnuje. U katalogu dodavatelů jsou to feedy dodavatelů, které otevírá tarif Basic a vyšší (ostatní cesty feedů vracejí, co obchod už má uložené); u zápisu třeba strop počtu produktů nebo funkce, kterou tarif nemá. Opakování nepomůže, pomůže vyšší tarif.
* **403** `insufficient_scope`: Klíč je platný, ale nemá oprávnění, které cesta vyžaduje. Zpráva vypíše, co klíči chybí a co má.
* **403** `approval_required`: Akci musí schválit člověk v administraci obchodu a k tomuhle volání žádné platné schválení nepatří (schválení vypršelo, nebo ho použil jiný požadavek). Pošlete požadavek znovu s novým Idempotency-Key; vrátí 202 s novým schválením.
* **403** `forbidden`: Klíč na zápis dosáhne, ale tuhle konkrétní akci obchod nepustí, třeba kvůli vypnutému modulu nebo funkci mimo tarif. Věta ve zprávě říká proč; opakování nepomůže.
* **403** `origin_not_allowed`: Požadavek nese hlavičku Origin, tedy přišel z webové stránky. Klíč patří na server integrace, nikdy do prohlížeče; volejte ze serveru.
* **403** `shop_unavailable`: Obchod je deaktivovaný nebo pozastavený, takže požadavky přes API ani MCP neobsluhuje. Klíč s tím nic nezmůže; otevře ho až obnovení obchodu.
* **404** `not_found`: Záznam s tímhle identifikátorem v obchodě není.
* **409** `approval_pending`: Na schválení akce se pořád čeká. Rizikové cesty REST to hlásí odpovědí 202 se stavem schválení, ne touhle chybou.
* **409** `confirmation_declined`: Člověk akci odmítl. Dnešní zápisové cesty REST potvrzení nechtějí.
* **409** `confirmation_required`: Akce by se musela napřed potvrdit. Dnešní zápisové cesty REST potvrzení nechtějí.
* **409** `conflict`: Zápis odporuje stavu obchodu: stav jde jen dopředu, záznam se mezitím změnil, nebo by porušil pravidlo obchodu. Věta ve zprávě říká, co se stalo; stejné volání znovu neprojde.
* **409** `idempotency_in_progress`: Zápis pod tímhle Idempotency-Key právě běží. Počkejte tolik sekund, kolik říká hlavička Retry-After, a pošlete týž požadavek znovu; dostanete jeho výsledek.
* **409** `plan_change_limited`: Tarif obchodu se za posledních 24 hodin už měnil. Nestrhlo se nic.
* **409** `quote_changed`: Potvrzená částka už neplatí. Nestrhlo se nic.
* **412** `precondition_failed`: Zdroj se od vašeho čtení změnil: If-Match neodpovídá aktuálnímu ETagu. Přečtěte ho znovu a rozhodněte se nad aktuálním stavem.
* **413** `payload_too_large`: Tělo zápisu je větší, než cesta přijme. Dávku rozdělte na menší požadavky.
* **415** `unsupported_media_type`: Tělo zápisu musí být JSON s hlavičkou Content-Type: application/json.
* **422** `idempotency_key_reused`: Týž Idempotency-Key už patří jinému požadavku (jiná cesta nebo jiné tělo). Na novou změnu pošlete nový klíč.
* **422** `invalid_input`: Tělo je ve správném tvaru, ale hodnotu obchod nepřijme (neexistující kategorie, cena mimo rozsah, odkaz bez https). Věta ve zprávě jmenuje pole a důvod.
* **428** `idempotency_key_required`: Cesta zakládá něco nového nebo hýbe zbožím a bez hlavičky Idempotency-Key ji nepustíme. Pošlete nový klíč pro každou zamýšlenou změnu a týž klíč, když ji opakujete.

## `PATCH /api/v1/discounts/{id}` [#patch-api-v1-discounts-id]

Úprava slevového kódu. U kódu, který už někdo uplatnil, jde měnit jen název, 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)“.
* **Odpověď:** stav 200, zdroj v `data` v témže tvaru, jaký vrací čtení, a změna v deníku v `change`.
* **Zápis:** jen klíčem s povoleným zápisem přes REST. `Idempotency-Key` je nepovinný; změnu jde vrátit přes `POST /api/v1/changes/{id}/revert`.

```bash
curl -s -X PATCH "https://muj-eshop.cz/api/v1/discounts/$ID" \
  -H "Authorization: Bearer $SHOPZI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
```

**Parametry v cestě**

* `id` (UUID; povinný): Identifikátor záznamu (UUID) z výpisu.

**Tělo požadavku** (JSON, pole navíc se odmítnou)

* `code` (text se vzorem `^[A-Za-z0-9._-]{2,40}$`, nejvýš 40 znaků; nepovinný)
* `name` (text, nejvýš 200 znaků; nepovinný)
* `public_title` (text, nejvýš 200 znaků nebo `null`; nepovinný)
* `status` (jedna z hodnot `draft`, `active`, `paused` a `archived`; nepovinný)
* `kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`; nepovinný)
* `percent_bp` (celé číslo od 1 do 10000 nebo `null`; nepovinný)
* `amount_minor` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `max_discount_minor` (celé číslo aspoň 0 nebo `null`; nepovinný)
* `min_subtotal_minor` (celé číslo aspoň 0 nebo `null`; nepovinný)
* `starts_at` (čas ISO 8601 nebo `null`; nepovinný)
* `ends_at` (čas ISO 8601 nebo `null`; nepovinný)
* `total_usage_limit` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `per_customer_limit` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `usage_limit` (celé číslo aspoň 1 nebo `null`; nepovinný)
* `single_use` (`true` nebo `false`; nepovinný)
* `first_order_only` (`true` nebo `false`; nepovinný)
* `exclude_discounted_items` (`true` nebo `false`; nepovinný)
* `targets` (pole objektů, nejvýš 200 položek; nepovinný): PLNÁ náhrada cílení; `[]` = celý košík.
* `targets[].target_type` (jedna z hodnot `product` a `category`; povinný)
* `targets[].target_id` (UUID; povinný)
* `targets[].mode` (jedna z hodnot `include` a `exclude`; povinný): `include` = jen na tyto, `exclude` = na tyto ne.

**Obálka odpovědi**

* `data` (záznam): Zdroj po zápisu, přečtený znovu; jeho pole popisuje seznam Pole záznamu.
* `change` (objekt): Změna, kterou zápis vyrobil.

**Pole záznamu**

* `id` (UUID): Id slevové akce (promo akce s kódem).
* `code` (text): Kód, který zákazník zadá v košíku.
* `name` (text): Interní název, vidí ho jen obchodník.
* `public_title` (text nebo `null`): Popisek slevy v košíku pro zákazníka.
* `status` (jedna z hodnot `draft`, `scheduled`, `active`, `paused`, `expired` a `archived`): `scheduled` a `expired` se počítají z `starts_at` a `ends_at` u aktivní slevy.
* `kind` (jedna z hodnot `percent`, `fixed` a `free_shipping`)
* `percent_bp` (celé číslo nebo `null`): Sleva v setinách procenta: 1000 = 10 %.
* `currency_code` (text se vzorem `^[A-Z]{3}$`): Kód měny podle ISO 4217, dnes vždy CZK.
* `amount_minor` (celé číslo nebo `null`): Pevná sleva v haléřích, jen u `fixed`.
* `max_discount_minor` (celé číslo nebo `null`): Strop procentní slevy v haléřích.
* `min_subtotal_minor` (celé číslo nebo `null`): Nejnižší hodnota košíku v haléřích.
* `starts_at` (čas ISO 8601 nebo `null`)
* `ends_at` (čas ISO 8601 nebo `null`)
* `usage_count` (celé číslo): Kolikrát byl kód použit.
* `usage_limit` (celé číslo nebo `null`)
* `total_usage_limit` (celé číslo nebo `null`)
* `per_customer_limit` (celé číslo nebo `null`)
* `single_use` (`true` nebo `false`)
* `first_order_only` (`true` nebo `false`)
* `exclude_discounted_items` (`true` nebo `false`)
* `redemptions` (celé číslo): Uplatnění v objednávkách (bez stornovaných).
* `targets` (pole objektů): Cílení. Prázdné = celý košík.
* `targets[].target_type` (jedna z hodnot `product` a `category`)
* `targets[].target_id` (UUID)
* `targets[].mode` (jedna z hodnot `include` a `exclude`)
* `created_at` (čas ISO 8601)
* `updated_at` (čas ISO 8601): Poslední změna slevové akce. Počet použití ho neposouvá.

### `PATCH /api/v1/discounts/{id}`: chyby [#patch-api-v1-discounts-id-chyby]

* **400** `invalid_body`: Tělo zápisu není platný JSON nebo neodpovídá smlouvě cesty: chybí povinné pole, hodnota má špatný typ, nebo je v těle pole, které cesta nezná. Pole pointer v chybě ukazuje (JSON Pointer) na místo, které neprošlo.
* **400** `invalid_idempotency_key`: Hlavička Idempotency-Key nemá povolený tvar: 8 až 128 znaků z písmen, číslic a znaků tečka, podtržítko, dvojtečka a pomlčka.
* **400** `invalid_if_match`: Hlavička If-Match nenese ETag v tvaru, v jakém ho vrací odpověď (W/ a hodnota v uvozovkách), ani hvězdičku.
* **402** `credit_cap_exceeded`: Akce by překročila měsíční strop kreditů klíče, nebo ho teď nejde ověřit. Nestrhlo se nic.
* **402** `payment_declined`: Uložená karta platbu odmítla. Nic se nezměnilo a nic se nestrhlo.
* **402** `plan_required`: Tarif obchodu tuhle akci nezahrnuje. U katalogu dodavatelů jsou to feedy dodavatelů, které otevírá tarif Basic a vyšší (ostatní cesty feedů vracejí, co obchod už má uložené); u zápisu třeba strop počtu produktů nebo funkce, kterou tarif nemá. Opakování nepomůže, pomůže vyšší tarif.
* **403** `insufficient_scope`: Klíč je platný, ale nemá oprávnění, které cesta vyžaduje. Zpráva vypíše, co klíči chybí a co má.
* **403** `approval_required`: Akci musí schválit člověk v administraci obchodu a k tomuhle volání žádné platné schválení nepatří (schválení vypršelo, nebo ho použil jiný požadavek). Pošlete požadavek znovu s novým Idempotency-Key; vrátí 202 s novým schválením.
* **403** `forbidden`: Klíč na zápis dosáhne, ale tuhle konkrétní akci obchod nepustí, třeba kvůli vypnutému modulu nebo funkci mimo tarif. Věta ve zprávě říká proč; opakování nepomůže.
* **403** `origin_not_allowed`: Požadavek nese hlavičku Origin, tedy přišel z webové stránky. Klíč patří na server integrace, nikdy do prohlížeče; volejte ze serveru.
* **403** `shop_unavailable`: Obchod je deaktivovaný nebo pozastavený, takže požadavky přes API ani MCP neobsluhuje. Klíč s tím nic nezmůže; otevře ho až obnovení obchodu.
* **404** `not_found`: Záznam s tímhle identifikátorem v obchodě není.
* **409** `approval_pending`: Na schválení akce se pořád čeká. Rizikové cesty REST to hlásí odpovědí 202 se stavem schválení, ne touhle chybou.
* **409** `confirmation_declined`: Člověk akci odmítl. Dnešní zápisové cesty REST potvrzení nechtějí.
* **409** `confirmation_required`: Akce by se musela napřed potvrdit. Dnešní zápisové cesty REST potvrzení nechtějí.
* **409** `conflict`: Zápis odporuje stavu obchodu: stav jde jen dopředu, záznam se mezitím změnil, nebo by porušil pravidlo obchodu. Věta ve zprávě říká, co se stalo; stejné volání znovu neprojde.
* **409** `idempotency_in_progress`: Zápis pod tímhle Idempotency-Key právě běží. Počkejte tolik sekund, kolik říká hlavička Retry-After, a pošlete týž požadavek znovu; dostanete jeho výsledek.
* **409** `plan_change_limited`: Tarif obchodu se za posledních 24 hodin už měnil. Nestrhlo se nic.
* **409** `quote_changed`: Potvrzená částka už neplatí. Nestrhlo se nic.
* **412** `precondition_failed`: Zdroj se od vašeho čtení změnil: If-Match neodpovídá aktuálnímu ETagu. Přečtěte ho znovu a rozhodněte se nad aktuálním stavem.
* **413** `payload_too_large`: Tělo zápisu je větší, než cesta přijme. Dávku rozdělte na menší požadavky.
* **415** `unsupported_media_type`: Tělo zápisu musí být JSON s hlavičkou Content-Type: application/json.
* **422** `idempotency_key_reused`: Týž Idempotency-Key už patří jinému požadavku (jiná cesta nebo jiné tělo). Na novou změnu pošlete nový klíč.
* **422** `invalid_input`: Tělo je ve správném tvaru, ale hodnotu obchod nepřijme (neexistující kategorie, cena mimo rozsah, odkaz bez https). Věta ve zprávě jmenuje pole a důvod.

## `DELETE /api/v1/discounts/{id}` [#delete-api-v1-discounts-id]

Smazání kódu, který nikdo neuplatnil. Uplatněný kód se archivuje (`PATCH` se `status: archived`), záznamy o použití jsou účetní podklad.

* **Oprávnění:** `marketing:write`, u klíče „Marketing: slevové kódy, vyskakovací okna, koncepty kampaní, segmenty, feedy (zápis)“.
* **Odpověď:** stav 200, `data: null` a změna v deníku v `change`.
* **Zápis:** jen klíčem s povoleným zápisem přes REST. `Idempotency-Key` je nepovinný; změnu jde vrátit přes `POST /api/v1/changes/{id}/revert`.

```bash
curl -s -X DELETE "https://muj-eshop.cz/api/v1/discounts/$ID" \
  -H "Authorization: Bearer $SHOPZI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
```

**Parametry v cestě**

* `id` (UUID; povinný): Identifikátor záznamu (UUID) z výpisu.

**Obálka odpovědi**

* `data` (záznam): Zdroj po zápisu, přečtený znovu; jeho pole popisuje seznam Pole záznamu.
* `change` (objekt): Změna, kterou zápis vyrobil.

**Chyby této cesty**

* **400** `invalid_body`: Tělo zápisu není platný JSON nebo neodpovídá smlouvě cesty: chybí povinné pole, hodnota má špatný typ, nebo je v těle pole, které cesta nezná. Pole pointer v chybě ukazuje (JSON Pointer) na místo, které neprošlo.
* **400** `invalid_idempotency_key`: Hlavička Idempotency-Key nemá povolený tvar: 8 až 128 znaků z písmen, číslic a znaků tečka, podtržítko, dvojtečka a pomlčka.
* **400** `invalid_if_match`: Hlavička If-Match nenese ETag v tvaru, v jakém ho vrací odpověď (W/ a hodnota v uvozovkách), ani hvězdičku.
* **402** `credit_cap_exceeded`: Akce by překročila měsíční strop kreditů klíče, nebo ho teď nejde ověřit. Nestrhlo se nic.
* **402** `payment_declined`: Uložená karta platbu odmítla. Nic se nezměnilo a nic se nestrhlo.
* **402** `plan_required`: Tarif obchodu tuhle akci nezahrnuje. U katalogu dodavatelů jsou to feedy dodavatelů, které otevírá tarif Basic a vyšší (ostatní cesty feedů vracejí, co obchod už má uložené); u zápisu třeba strop počtu produktů nebo funkce, kterou tarif nemá. Opakování nepomůže, pomůže vyšší tarif.
* **403** `insufficient_scope`: Klíč je platný, ale nemá oprávnění, které cesta vyžaduje. Zpráva vypíše, co klíči chybí a co má.
* **403** `approval_required`: Akci musí schválit člověk v administraci obchodu a k tomuhle volání žádné platné schválení nepatří (schválení vypršelo, nebo ho použil jiný požadavek). Pošlete požadavek znovu s novým Idempotency-Key; vrátí 202 s novým schválením.
* **403** `forbidden`: Klíč na zápis dosáhne, ale tuhle konkrétní akci obchod nepustí, třeba kvůli vypnutému modulu nebo funkci mimo tarif. Věta ve zprávě říká proč; opakování nepomůže.
* **403** `origin_not_allowed`: Požadavek nese hlavičku Origin, tedy přišel z webové stránky. Klíč patří na server integrace, nikdy do prohlížeče; volejte ze serveru.
* **403** `shop_unavailable`: Obchod je deaktivovaný nebo pozastavený, takže požadavky přes API ani MCP neobsluhuje. Klíč s tím nic nezmůže; otevře ho až obnovení obchodu.
* **404** `not_found`: Záznam s tímhle identifikátorem v obchodě není.
* **409** `approval_pending`: Na schválení akce se pořád čeká. Rizikové cesty REST to hlásí odpovědí 202 se stavem schválení, ne touhle chybou.
* **409** `confirmation_declined`: Člověk akci odmítl. Dnešní zápisové cesty REST potvrzení nechtějí.
* **409** `confirmation_required`: Akce by se musela napřed potvrdit. Dnešní zápisové cesty REST potvrzení nechtějí.
* **409** `conflict`: Zápis odporuje stavu obchodu: stav jde jen dopředu, záznam se mezitím změnil, nebo by porušil pravidlo obchodu. Věta ve zprávě říká, co se stalo; stejné volání znovu neprojde.
* **409** `idempotency_in_progress`: Zápis pod tímhle Idempotency-Key právě běží. Počkejte tolik sekund, kolik říká hlavička Retry-After, a pošlete týž požadavek znovu; dostanete jeho výsledek.
* **409** `plan_change_limited`: Tarif obchodu se za posledních 24 hodin už měnil. Nestrhlo se nic.
* **409** `quote_changed`: Potvrzená částka už neplatí. Nestrhlo se nic.
* **412** `precondition_failed`: Zdroj se od vašeho čtení změnil: If-Match neodpovídá aktuálnímu ETagu. Přečtěte ho znovu a rozhodněte se nad aktuálním stavem.
* **413** `payload_too_large`: Tělo zápisu je větší, než cesta přijme. Dávku rozdělte na menší požadavky.
* **415** `unsupported_media_type`: Tělo zápisu musí být JSON s hlavičkou Content-Type: application/json.
* **422** `idempotency_key_reused`: Týž Idempotency-Key už patří jinému požadavku (jiná cesta nebo jiné tělo). Na novou změnu pošlete nový klíč.
* **422** `invalid_input`: Tělo je ve správném tvaru, ale hodnotu obchod nepřijme (neexistující kategorie, cena mimo rozsah, odkaz bez https). Věta ve zprávě jmenuje pole a důvod.
