Automatizace
Automatizace (scénář) je graf: uzly (spouštěče, operátory, akce) spojené hranami. Kontakt do scénáře vstoupí spouštěčem, prochází uzly po hranách a scénář opustí na uzlu Konec, na výstupu bez hrany nebo splněním cíle. Každý průchod jednoho kontaktu je běh (run).
Přesná schémata všech uzlů, událostí, podmínek a časových údajů: Reference automatizací. Hotové scénáře: recepty.
Graf
{
"nodes": [
{"id": "kosik", "type": "trigger_event", "name": "Změna košíku", "config": {"event": "cart_updated", "reentry": "restart"}},
{"id": "pockat", "type": "wait", "config": {"mode": "duration", "value": 2, "unit": "hours"}},
{"id": "stale-v-kosiku", "type": "condition", "config": {"definition": {"type": "group", "match": "all", "rules": [
{"type": "cart_items_count", "operator": "gt", "value": 0},
{"type": "ordered_since_entry", "operator": "no"}]}}},
{"id": "email", "type": "send_email", "config": {"templateId": "301"}}
],
"edges": [
{"source": "kosik", "target": "pockat", "branch": "next"},
{"source": "pockat", "target": "stale-v-kosiku", "branch": "next"},
{"source": "stale-v-kosiku", "target": "email", "branch": "yes"}
]
}iduzlu je klíč, který si zvolíte: písmena, číslice,-a_, nejvýš 40 znaků, v grafu jedinečný. Při dalších uloženích ho nechte stejný: běhy, historie a e-maily se na uzel odkazují klíčem.typevybírá druh uzlu,configjeho nastavení. Neznámé klíče vconfigserver při uložení zahodí. Volitelněname(do 100 znaků),note(do 1 000) aposition{x, y}pro plátno v aplikaci.- Hrana vede z výstupu (
branch) zdroje do cíle:next(jediný výstup),yes/no(podmínka),v1ažv10(A/B test). Každý výstup má nejvýš jednu hranu; výstup bez hrany = kontakt scénář opustí. - Graf nesmí mít cyklus (ani přes uzel
goto), do spouštěče a cíle nevede hrana. Scénář smí mít víc spouštěčů. Nejvýš 300 uzlů a 600 hran. - Automatizace patří jednomu e-shopu (odesílatel, patička, objednávky spouštěčů); e-shop se po založení nemění.
Druhy uzlů
| Skupina | Typy |
|---|---|
| Spouštěče | trigger_event (událost), trigger_date (svátek, narozeniny, datum, svátky v roce, první objednávka), trigger_reorder (kupte si znovu), trigger_repeat (opakovaně), trigger_scheduled (jednou v čase), trigger_now (jednou při zapnutí) |
| Operátory | condition (ano / ne), wait (čekání), ab_test, holding (odkladiště), goal (cíl scénáře) |
| Akce | send_email, list_change, set_field, webhook, fire_event, notify, reset, goto, end |
| Zatím nedostupné | send_sms, send_viber, whatsapp, fb_audience, sklik_retargeting, motionlab_adina (uložit nejdou, chyba unavailable) |
Spouštěč při události (trigger_event)
config.event vybírá událost; některé mají vlastní nastavení:
| Událost | Kdy | Nastavení |
|---|---|---|
order_created | nová objednávka | shopId |
order_completed | objednávka dokončena (zaplacena, odeslána, doručena) | shopId |
order_changed | objednávka změnila stav | shopId, state |
cart_updated | změna košíku (POST /contact-events typ cart) | shopId |
page_visit | návštěva stránky (POST /contact-events typ visit) | shopId, url, urlOperator, visitType |
custom | vlastní událost (POST /contact-events typ custom, nebo uzel fire_event jiného scénáře) | customEvent |
subscribed | kontakt se přihlásil k odběru | sources |
contact_created | nový kontakt | |
contact_updated | změna pole kontaktu | fieldFilter |
list_added | přidání do seznamu | listId |
list_status_changed | změna stavu v seznamu | listId, status |
form_submitted | odeslaný a potvrzený formulář | formId |
email_sent, link_clicked | e-mail nebo klik z uzlu jiného scénáře | emailNode, link, compareParams |
engagement_changed | změna angažovanosti | |
blacklisted | kontakt na blacklistu | |
action_failed | selhala akce automatizace | failureType, failureNode |
manual | ručně přidané kontakty (POST /automations/{id}/contacts) |
Počítají se jen události po zapnutí automatizace. Co zapsal hromadný zápis (import, synchronizace e-shopu), automatizace nespustí, pokud import výslovně nepovolí runAutomations: true. Objednávka zapsaná přes POST /orders spouštěče objednávek spouští.
Opakovaný vstup (reentry)
Každý spouštěč má reentry:
parallel: kontakt smí mít ve scénáři víc běhů současně (nejvýš 10); výchozí pro nové spouštěče.restart: nový vstup ukončí rozběhnutý běh (typicky košík).skip: dokud běh kontaktu trvá, znovu nevstoupí.once: jednou provždy.
Jazyk podmínek
Uzel condition, cíl (goal) a filtr časových spouštěčů (filter) mají definici: stejný strom jako segment, jehož pravidla smí být i podmínky automatizace.
{"type": "group", "match": "all", "rules": [
{"type": "contact_in_list", "listId": "41", "state": "confirmed"},
{"type": "orders_total_value", "operator": "gte", "value": "3000", "currency": "CZK",
"period": {"from": {"variant": "interval", "sign": "-", "value": 1, "unit": "years"}, "to": null}},
{"type": "email_activity", "operator": "opened", "nodeId": "email-1", "negate": true}
]}match:all(a zároveň) neboany(nebo). Skupiny lze vnořovat (nejvýš 8 úrovní, 50 pravidel).- Každé pravidlo smí mít
"negate": true(neplatí, že). - Pravidla s obdobím mají
period{from, to}; strany jsou časové údaje relativní k teď,null= bez omezení. - Podmínky automatizací (37 podle SmartEmailingu a vlastní): kontakt v seznamu, v automatizaci, pole kontaktu, výročí (narozeniny, svátek), odeslané a otevřené e-maily, počet a hodnota objednávek, objednaný produkt nebo atribut, košík, den v měsíci a týdnu, hodina, kupón, skript, kliky, návštěvy, feed, vítěz A/B testu, angažovanost.
- Pravidla, která čtou běh (
email_activity,passed_node,ordered_since_entry,event_attribute,script), nejde použít ve filtru spouštěče (běh tam ještě není). - Hodnoty podmínek automatizací smí být čísla (
"value": 0) i řetězce číslic; pravidla segmentu mají hodnoty jako řetězce.
Přesná pole každého pravidla: Reference automatizací.
Podmínka s čekáním na splnění
condition.config.waitUntilMet {"value": 3, "unit": "days"}: kontakt v uzlu čeká, dokud podmínka neplatí (pak výstup yes), nejdéle po zadanou dobu (pak no). Kontrola běží každých 20 minut až jednou denně podle délky čekání.
Čekání a čas
Uzel wait má mode:
mode | Čeká |
|---|---|
duration | value jednotek unit (minuty až roky) |
time_of_day | na nejbližší time ("09:00") |
weekday | na nejbližší den z weekdays (1 = pondělí) v čase time |
date | na místní datum a čas date ("2026-12-24T09:00") |
time | na časový údaj spec (countFrom node = od příchodu do uzlu, scenario = od vstupu do scénáře) |
preferred | na obvyklou dobu, kdy kontakt otevírá e-maily (bez historie nečeká) |
spread | rozloží kontakty rovnoměrně do období spread |
Nejdelší čekání je 10 let. Časové údaje (spec, period) mají tři varianty: calendar (konkrétní den), interval (posun o jednotky), event (pojmenovaný den: zítra, příští pondělí, příští pracovní den, poslední den měsíce). Náhled přesného okamžiku: POST /automations/resolve-time.
Životní cyklus
| Stav | Význam |
|---|---|
draft | koncept, nikdy nespuštěný |
active | běží |
paused | zastavený po běhu (ručně, nebo automaticky při vysokém podílu nedoručitelných, stížností či odhlášení, nebo při chybě šablony; pausedReason) |
POST /automationszaloží koncept (verze 1); graf můžete poslat rovnou, nebo později přesPUT /automations/{id}/graph.POST /automations/{id}/activatezapne:draftnebopaused→active. Když něco chybí, vrátí 400validation/graphsparams.issues(viz níže). Zapnutí posílá e-maily skutečným lidem.POST /automations/{id}/pausezastaví; čekající kontakty zůstanou na místě a po dalším zapnutí pokračují.DELETE /automations/{id}smaže jen scénář, do kterého nikdo nevstoupil (jinak 409runs).POST /automations/{id}/copyvytvoří koncept „<název> - kopie“ (bez hesel webhooků).
Validace a problémy grafu
Problémy mají tvar {"node": "<klíč>" | null, "field": "<pole>", "code": "<kód>"} a dvě úrovně:
- Chyby (
errors): graf nejde uložit (400validation/graphsparams.issues). Kódy:invalid,unavailable(typ uzlu),duplicate,node(hrana k neexistujícímu uzlu),cycle,self_trigger(scénář by spouštěl sám sebe). - Neúplné nastavení (
incomplete): graf se uloží, ale nejde zapnout ani otestovat. Kódy:required,invalid,unavailable(událost nebo podmínka),not_found,locked(seznam napojený na e-shop),empty(šablona bez obsahu),lint(chyba kontroly obsahu šablony),unverified(neověřený odesílatel),unreachable(uzel, kam žádný spouštěč nedojde),too_short,too_long,not_whitelisted,reserved. Bez spouštěče:{"node": null, "field": "trigger", "code": "required"}.
POST /automations/validate s {shopId, graph} zkontroluje graf bez uložení:
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/automations/validate" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"shopId": "1",
"graph": {
"nodes": [
{
"id": "kosik",
"type": "trigger_event",
"config": {
"event": "cart_updated",
"shopId": "1",
"reentry": "restart"
}
},
{
"id": "pockat",
"type": "wait",
"config": {
"mode": "duration",
"value": 2,
"unit": "hours"
}
},
{
"id": "email",
"type": "send_email",
"config": {}
}
],
"edges": [
{
"source": "kosik",
"target": "pockat"
},
{
"source": "pockat",
"target": "email"
}
]
}
}
JSON{
"errors": [],
"incomplete": [
{
"node": "email",
"field": "templateId",
"code": "required"
}
]
}Detail automatizace (GET /automations/{id}) vrací v issues vše, co brání zapnutí.
Uložení grafu a verze
PUT /automations/{id}/graph s {"baseVersion", "graph"} vrátí detail s verzí + 1.
- Jiná verze na serveru = 409
conflict/versionsparams.current. - Běžící scénář (
active) se uloží jen s"confirmRunning": truea jen bez jakéhokoli problému; jinak 409conflict/confirm. Změny platí pro další krok každého kontaktu. - Odstranit nebo změnit typ uzlu, ve kterém kontakty čekají, nejde: 409
conflict/waitingsparams.nodes(nejdřív je uvolněte:POST /automations/{id}/nodes/{klíč}/release). - Změna spouštěče začne jeho plán znovu; nová hrana z odkladiště pustí čekající kontakty dál.
- Každé uložení je verze:
GET /automations/{id}/versions,GET /automations/{id}/versions/{verze}.
curl -sS -X PUT "https://www.postarna.cz/api/v1/tenants/$TENANT/automations/81/graph" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"baseVersion": 1,
"graph": {
"nodes": [],
"edges": []
}
}
JSON{
"error": {
"code": "conflict",
"message": "confirm"
}
}Testování a sledování
POST /automations/{id}/test: zkušební průchod nad dnešními daty, nic se neuloží ani neodešle. Vrátí, kolik kontaktů by vstoupilo a kolik by došlo do každého uzlu a výstupu. Volitelněgraph(neuložený graf z editoru) adays(1 až 90, okno přehrání událostí).POST /automations/{id}/traces{"contactId" | "email"}: průchod jednoho kontaktu krok za krokem s důvody (smí vstoupit, kudy půjde, kde skončí). Nic se neodešle.GET /automations/{id}/counts: živé počty po uzlech a výstupech včetně čekajících.GET /automations/{id}/runs?contactId=: historie běhů kontaktu.GET /automations/{id}/nodes/{klíč}/passes: kdo prošel uzlem.GET /automations/{id}/report?from=&to=(iformat=csv): statistiky e-mailových uzlů a volání webhooků.
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/automations/83/test" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{}
JSON{
"scope": "today",
"days": null,
"since": null,
"entered": 0,
"waiting": 0,
"left": 0,
"nodes": {
"svatek": {
"reached": 0,
"waiting": 0,
"left": 0,
"outputs": {
"next": 0
}
},
"prani": {
"reached": 0,
"waiting": 0,
"left": 0,
"outputs": {
"next": 0
}
}
},
"testedAt": "2026-10-01T08:00:00.000Z"
}Kdo vstoupí a kdy odejde e-mail
- Vstupují jen kontakty, kterým lze psát (přihlášené, bez potlačení a slabého souhlasu, v lhůtě zákaznické výjimky) z e-shopu automatizace.
- E-mail uzlu odejde jednomu kontaktu nejvýš jednou za 24 hodin (nastavení firmy) a jen se zapnutým odesíláním firmy, v denním limitu. Před odesláním se stav kontaktu kontroluje znovu; e-mail starší 48 hodin ve frontě neodejde.
- Scénář, který by spouštěl sám sebe, nejde uložit (
self_trigger); řetěz scénářů (událost jednoho spouští druhý) končí po 3 krocích. - Běh spuštěný objednávkou skončí, když se objednávka zruší, vrátí nebo smaže.
Události z vašeho systému
POST /contact-events zapíše událost existujícího kontaktu (podle contactId nebo email; nikdy kontakt nezaloží):
{"type": "custom", "name": "vip-dosazeno", "data": {...}}: vlastní událost pro spouštěčcustom(název a-z, 0-9 a-, nejvýš 50 znaků, nese-).{"type": "cart", "shopId", "items": [{code, name, quantity, price, url}], "currency", "total"}: aktuální stav košíku (prázdnéitems= košík vyprázdněn) procart_updateda podmínkucart_items_count.{"type": "visit", "shopId", "url", "visitType", "attributes"}: návštěva stránky propage_visit.
Nejvýš 60 událostí jednoho kontaktu za 10 minut (429 rate_limited). Ukázka v receptu opuštěného košíku.
Transakční automatizace (smluvní e-maily)
Pro e-maily k uzavřené smlouvě, například upomínky splatnosti faktur. Režim zapnete polem "transactional": true při POST /automations nebo PATCH /automations/{id} (stejné oprávnění jako úprava automatizací); přepnout jde jen scénář, který neběží (jinak 409 conflict / status).
- Spouštěč smí být jen vlastní událost (
trigger_eventsevent: "custom") a uzly jensend_email,wait,conditionaend. Jiný graf vrátí 400validation/transactional(při přepnutí) nebograph(při uložení) sparams.issuesa kódytransactional_node,transactional_trigger. - E-mail dostane každý existující kontakt bez ohledu na souhlas s newsletterem nebo odhlášení z něj. Tvrdý odraz, stížnost, neplatná adresa, limit měkkých odrazů a blacklist ho zastaví vždy, při vstupu i těsně před odesláním.
- E-mail nemá odkaz na odhlášení, hlavičku
List-Unsubscribeani patičku newsletteru. Šablona proto nepotřebuje{{unsubscribe}}a nesmí ho mít (ani{{gf_footer}}, odkaz na nastavení odběru nebo kupón; kód problémutransactional_content). Otevření a prokliky se měří jako obvykle. - Scénář patří e-shopu události:
shopIduPOST /contact-eventsurčuje, která automatizace se spustí (bez něj se použije hlavní e-shop kontaktu). Limit jednoho e-mailu uzlu za 24 hodin neplatí (dvě faktury jedné firmy se stejnou splatností dostanou dva e-maily); opakování hlídá váš systém. - Předmět e-mailu je prostý text bez skriptů: data události v něm čtou značky
{{metadata.event.attributes.data.<klíč>}}(jen jednoduché hodnoty), napříkladFaktura {{metadata.event.attributes.data.invoiceNumber}}. - Platební QR kód: značka
{{payment_qr}}vloží obrázek QR platby zdata.spaydudálosti (řetězec SPAYD 1.0 s účtemACC), například{% set d = metadata.event.attributes.data %}{% if d.spayd %}{{payment_qr}}{% endif %}. Obrázek je podepsaný odkaz/m/r/<token>.pngna doméně odkazů, takže ho ukáže i Gmail a Outlook; bez platného řetězce se nevloží nic. - Právní poznámka (není právní stanovisko): upomínka k vystavené faktuře není obchodní sdělení (zákon 480/2004 Sb., na Slovensku zákon 452/2021 Z. z.), právním základem je plnění smlouvy. E-mail proto nesmí obsahovat marketing (nabídky zboží, kupóny, bannery).