Přeskočit na obsah
API dokumentace

Šablony a personalizace

Šablona a její obsah

Šablona (template) má název, předmět, preheader a obsah. Obsah je {editor, html, design, version}:

  • editor: "html": obsah je HTML, design je null. Pro API nejjednodušší.
  • editor: "visual": obsah vizuálního editoru (MJML) v design ({"format": "mjml-1", "mjml", "styles"}) a z něj vykreslené html.

Založení se zkopírovaným obsahem jedním voláním:

Požadavek: POST /api/v1/tenants/{tenant}/templates
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/templates" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "name": "Opuštěný košík",
  "subject": "{{df_name|default('Dobrý den', true)}}, něco jste nechali v košíku",
  "preheader": "Váš košík na vás počká ještě pár dní",
  "content": {
    "editor": "html",
    "design": null,
    "html": "<!doctype html><html><body><p>Dobrý den, {{df_salution|default('vážený zákazníku', true)}},</p><p>ve vašem košíku zůstalo {{ metadata.event.attributes.itemCount }} ks zboží za {{ metadata.event.attributes.total }} {{ metadata.event.attributes.currency }}.</p><p><a href=\"https://www.example.cz/kosik/\">Dokončit objednávku</a></p><p style=\"font-size:12px\">{{cl_company}}, {{cl_address}}. <a href=\"{{unsubscribe}}\">Odhlásit odběr</a></p></body></html>"
  }
}
JSON
Odpověď: 201 Created
{
  "id": "301",
  "name": "Opuštěný košík",
  "subject": "{{df_name|default('Dobrý den', true)}}, něco jste nechali v košíku",
  "preheader": "Váš košík na vás počká ještě pár dní",
  "editor": "html",
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "tags": [],
  "size": 465,
  "archived": false,
  "archivedAt": null,
  "readOnly": false,
  "usage": {
    "campaigns": 0,
    "automations": 0
  },
  "lastUsedAt": null,
  "check": {
    "errors": [],
    "warnings": [
      "subject_long"
    ],
    "checkedAt": "2026-10-01T08:00:00.000Z"
  },
  "content": {
    "editor": "html",
    "html": "<!doctype html><html><body><p>Dobrý den, {{df_salution|default('vážený zákazníku', true)}},</p><p>ve vašem košíku zůstalo {{ metadata.event.attributes.itemCount }} ks zboží za {{ metadata.event.attributes.total }} {{ metadata.event.attributes.currency }}.</p><p><a href=\"https://www.example.cz/kosik/\">Dokončit objednávku</a></p><p style=\"font-size:12px\">{{cl_company}}, {{cl_address}}. <a href=\"{{unsubscribe}}\">Odhlásit odběr</a></p></body></html>",
    "design": null,
    "version": 1,
    "updatedAt": "2026-10-01T08:00:00.000Z"
  },
  "settings": {
    "linkParams": [],
    "headers": [],
    "unsubscribePageId": null,
    "footerId": null
  },
  "draft": {
    "pending": false,
    "savedAt": null,
    "publishedAt": null
  },
  "activeUses": {
    "automations": 0,
    "emails": 0,
    "campaigns": 0
  },
  "publicUrl": "https://links.example.cz/template/1/72cf576a-85b2-474e-86e2-bfdbd1f4d38f"
}

Úprava obsahu: PUT /templates/{id}/content s {editor, html, design, baseVersion}; baseVersion je verze, kterou jste načetli (u nové šablony 1). Jiná verze na serveru = 409 conflict / version s params.current. Každé uložení se zapíše do historie (GET /templates/{id}/versions).

  • HTML server před uložením vyčistí: žádné skripty, rámy, atributy on*, odkazy javascript: ani nebezpečné CSS. Čistý vstup zůstane beze změny.
  • HTML nad 102 000 bajtů hlásí kontrola obsahu jako chybu a takový e-mail neodejde (Gmail delší e-mail ořízne).
  • Kampaň má vlastní kopii obsahu (PUT /campaigns/{id}/content); pozdější úprava šablony kampaň nezmění.

Šablona, kterou posílá zapnutá automatizace

Aby se omylem nezměnil e-mail, který právě chodí zákazníkům, uloží se změna obsahu takové šablony do konceptu. E-maily posílají dál publikovanou podobu, dokud koncept nepublikujete:

  • POST /templates/{id}/publish s {"confirm": "<přesný název šablony>"} (klíčem API; přihlášený člověk posílá heslo).
  • DELETE /templates/{id}/draft koncept zahodí.
  • Smazat šablonu, kterou posílá zapnutá automatizace, nejde (409 conflict / in_use).

Kontrola obsahu

POST /content/lint s {html, subject, preheader} vrátí issues s kódy (chyby první). Stejná kontrola běží při schválení kampaně a zapnutí automatizace: chyba odeslání zastaví, upozornění ne.

Požadavek: POST /api/v1/tenants/{tenant}/content/lint
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/content/lint" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "html": "<p>Dobrý den, {{df_jmeno}}</p>",
  "subject": "Podzimní novinky",
  "preheader": ""
}
JSON
Odpověď: 200 OK
{
  "issues": [
    {
      "code": "unknown_tag",
      "severity": "error",
      "params": {
        "tags": "{{df_jmeno}}"
      }
    },
    {
      "code": "no_unsubscribe",
      "severity": "warning",
      "params": {}
    }
  ]
}
KódZávažnostKdy
subject_missingchybaprázdný předmět
subject_too_longchybapředmět nad 200 znaků
content_emptychybažádný text ani obrázek
unknown_tagchybaneznámá zástupná značka (params.tags)
foreign_tagchybaznačky jiných nástrojů (*|X|*, %%x%%, {$x})
script_errorchybaskript Twig nejde spustit (params.line, params.detail)
unsupported_filterchybanepodporovaný filtr (například |raw)
bad_fallbackchybaneplatná náhrada default(...)
emojichybaemoji, když je firma zakázala
forbidden_wordpodle pravidlazakázané slovo podle pravidel firmy
image_placeholder, image_data_urichybanenahrazený zástupný obrázek, obrázek vložený jako data:
banned_hostchybaodkaz nebo obrázek na zakázaném hostiteli
html_too_largechybaHTML nad 102 000 B
no_unsubscribeupozorněníchybí {{unsubscribe}}; Poštárna doplní standardní patičku
footer_incompleteupozorněníodhlášení není odkaz nebo chybí jméno odesílatele; doplní se patička
subject_long, img_without_alt, insecure_image, image_foreign_host, text_image_ratioupozorněnídoporučení

Zástupné značky

ZnačkaHodnota
{{df_name}}, {{df_surname}}křestní jméno, příjmení
{{df_salution}}oslovení v 5. pádě („Petře“)
{{df_emailaddress}}e-mail příjemce
{{df_titlesbefore}}, {{df_titlesafter}}, {{df_gender}}, {{df_birthday}}, {{df_nameday}}, {{df_language}}, {{df_company}}, {{df_street}}, {{df_town}}, {{df_postalcode}}, {{df_country}}, {{df_phone}}, {{df_cellphone}}, {{df_notes}}další pole kontaktu
{{df_id}}, {{df_created}}, {{df_updated}}, {{df_domain}}ID kontaktu, založení, poslední změna, doména adresy
{{cf_<id>}}vlastní pole podle ID (víc hodnot oddělených čárkou)
{{cl_sendername}}, {{cl_senderemail}}jméno a e-mail odesílatele
{{cl_company}}, {{cl_address}}firma a adresa odesílajícího e-shopu
{{unsubscribe}} ({{unsubscribelink}})odkaz na odhlášení jedním kliknutím
{{preferences}} ({{confirmlink}})odkaz na nastavení odběru
{{webversion}} ({{webversionlink}}, {{forwardLink}})webová verze e-mailu
{{coupon_<klíč>}}nový kód ze zásobníku kupónů s tímto klíčem

Náhrada prázdné hodnoty: {{df_name|default('zákazníku', true)}}. Text náhrady má 1 až 40 znaků a nesmí obsahovat ' " \ { } < > | % &.

V testovacím e-mailu se dosadí jméno „Test“ a odkazy na odhlášení vedou na ukázkovou stránku, takže test nikoho neodhlásí.

Skripty (Twig)

Obsah smí obsahovat bezpečnou podmnožinu jazyka Twig, stejně jako SmartEmailing: {% if %}, {% elseif %}, {% else %}, {% for %} (i loop), {% set %}, komentáře {# #}, operátory and, or, not, in, ~, ??, ? :, testy (is defined, empty, null, even, odd, divisible by), filtry (abs, capitalize, date, default, first, join, json_encode, keys, last, length, lower, merge, number_format, replace, reverse, round, slice, sort, split, striptags, title, trim, upper, url_encode) a funkce date(), min(), max(). Každá vypsaná hodnota se escapuje, filtr raw není.

Data pro skripty:

VýrazCo vrátí
data.orders(filtr, řazení, limit)objednávky kontaktu v e-shopu e-mailu (nejvýš 200 nejnovějších); položky items[]
data.products({'item_id': kód}, řazení, limit)produkty produktových feedů e-shopu
data.articles(filtr, řazení, limit)články článkových feedů (nejvýš 25)
data.lists(filtr)seznamy kontaktu a jejich stavy
data.promoCode('<název zásobníku>')nový kód kupónu ze zásobníku s tímto názvem pro každý e-mail
data.promo.assigned('<zásobník>', od, do)kódy, které kontakt už dostal
data.terminate('<důvod>')e-mail tomuto kontaktu neodešle (přeskočí se)
metadata.orderobjednávka, která spustila běh automatizace (jen v e-mailu automatizace)
metadata.event.attributesdata události, která běh spustila (košík: itemCount, total, currency, shopId; vlastní událost: name a data; návštěva: url, visitType, attributes)
Ukázka skriptu v obsahu
{% set o = metadata.order %}
{% if o %}
  <p>Děkujeme za objednávku {{ o.eshop_code }}.</p>
  <ul>{% for item in o.items %}<li>{{ item.name }}</li>{% endfor %}</ul>
{% endif %}
<p>Váš kód: <strong>{{ data.promoCode('Svátek') }}</strong></p>
  • Kupón: {{ data.promoCode('Svátek') }} bere název zásobníku, {{coupon_svatek}} jeho klíč (mergeKey). Když zásobník dojde, e-mail neodejde a automatizace zaznamená selhání customizationDataboxOutOfPromocodes.
  • Skript, který nejde spustit, zastaví e-mail (failed); kontrola obsahu ho najde dřív jako script_error.
  • Nepodporováno: seznam položek košíku v e-mailu (v datech košíku je jen počet kusů a součet), obecné feedy (data.generic.items vrací prázdný seznam).

Testovací e-mail

  • Jde jen na testovací adresy firmy (GET /test-recipients); jiná adresa = 400 validation / to.
  • POST /campaigns/{id}/test s {"to"}, POST /templates/{id}/test s {"shopId", "to"}. Předmět dostane předponu [TEST] , nic se neměří.
  • Nejvýš 10 testů jedné kampaně nebo šablony za 24 hodin (429 rate_limited / test).
Požadavek: POST /api/v1/tenants/{tenant}/campaigns/151/test
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/151/test" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "to": "test@example.cz"
}
JSON
Odpověď: 200 OK
{
  "to": "test@example.cz",
  "sentAt": "2026-10-01T08:00:00.000Z"
}

Patičky, odhlašovací stránky a další obsah

  • Patičky (/footers) a odhlašovací stránky (/unsubscribe-pages) mají výchozí položku firmy; šablona a uzel automatizace mohou mít vlastní.
  • Šablony skriptů (/script-templates), uložené prvky editoru (/editor-elements), správce souborů (/files, /file-folders), landing pages, dotazníky a šablony SMS mají vlastní skupiny v referenci.