Kampaně
Kampaň je jednorázová rozesílka (newsletter) jednoho e-shopu. Nic neodejde z konceptu: odeslání spustí jen schválení s potvrzeným počtem příjemců.
Stavy
| Akce | Ze stavu | Do stavu |
|---|---|---|
POST /campaigns/{id}/approve se sendAt | draft | scheduled |
POST /campaigns/{id}/approve se sendAt: null | draft | sending |
| nastal čas odeslání | scheduled | sending (nebo paused s recipient_drift, když se počet příjemců změnil o víc než 5 %) |
| automatická pauza | sending | paused (bounce_rate, complaint_rate, unsubscribe_rate, template_error) |
POST /campaigns/{id}/pause | scheduled, sending | paused (manual) |
POST /campaigns/{id}/resume | paused | sending, nebo scheduled, když ještě nezačala |
POST /campaigns/{id}/cancel | draft, scheduled, sending, paused | cancelled |
| odešel poslední e-mail | sending | completed |
Jiný přechod = 409 conflict / status. Upravovat (PATCH, obsah) jde jen koncept.
Koncept
POST /campaigns založí koncept; povinné jsou jen name a shopId, zbytek doplníte později.
senderId: ověřený odesílatel e-shopu kampaně (GET /senders).fromName,subject(do 200 znaků),preheader.audience: komu kampaň jde (viz níže).trackOpens,trackClicks(výchozítrue),utm({source, medium, campaign, term?, content?}nebonull),linkParams,headers(vlastní hlavičkyX-...).templateIdje jen informace, odkud se obsah zkopíroval. Obsah kampaně uložíte přesPUT /campaigns/{id}/content({editor, html, design, baseVersion}, u nové kampaněbaseVersion: 0).
Publikum
{"listIds": ["42"], "segmentIds": [], "excludeListIds": [], "excludeInactive": true,
"excludeEmails": [], "onlyWithPurpose": false, "purposeIds": []}listIds,segmentIds: seznamy e-shopu kampaně nebo celé firmy a segmenty e-shopu kampaně (nejvýš 100 ID v každém poli).excludeListIds,excludeEmails(nejvýš 1 000 adres): vyloučení.excludeInactive: vynechá kontakty s angažovaností E.onlyWithPurposeapurposeIds: jen kontakty s platným souhlasem pro některý z účelů.
POST /campaigns/audience spočítá příjemce a důvody vyloučení (každý kontakt má jeden důvod): not_mailable (odhlášený, nedoručitelný, stížnost, potlačený), unconfirmed, weak_consent, exception_expired, no_purpose, excluded_list, excluded_manual, inactive. Platí recipients + součet excluded = matched.
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/audience" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"shopId": "17",
"audience": {
"listIds": [
"44"
],
"segmentIds": [],
"excludeListIds": [],
"excludeInactive": true,
"excludeEmails": [],
"onlyWithPurpose": false,
"purposeIds": []
}
}
JSON{
"matched": 1,
"recipients": 1,
"excluded": {
"not_mailable": 0,
"unconfirmed": 0,
"weak_consent": 0,
"exception_expired": 0,
"no_purpose": 0,
"excluded_list": 0,
"excluded_manual": 0,
"inactive": 0
}
}Schválení (odeslání)
POST /campaigns/{id}/approve s {"sendAt", "expectedRecipients"}:
sendAt:null= odeslat hned, jinak čas 5 minut až 365 dní dopředu (ISO 8601 se zónou).expectedRecipients: počet příjemců, který jste právě spočítali a uživatel potvrdil. Když se skutečný počet liší o víc než 5 %, server vrátí 409conflict/recipientssparams.expectedaparams.actuala kampaň zůstane konceptem:
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/151/approve" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"sendAt": "2026-10-02T07:00:00.000Z",
"expectedRecipients": 250
}
JSON{
"error": {
"code": "conflict",
"message": "recipients",
"params": {
"expected": 250,
"actual": 1
}
}
}Kontroly v tomto pořadí: stav draft, subject, fromName, senderId (ověřený odesílatel téhož e-shopu), content (bez obsahu nejde odeslat), lint (chyba kontroly obsahu, params.codes), audience (aspoň jeden seznam nebo segment a aspoň jeden příjemce), sendAt, expectedRecipients.
Co musí být nastavené, aby e-maily odešly
- Ověřený odesílatel e-shopu (doména s SPF, DKIM a DMARC, Nastavení › Odesílání; přes API
/sending/...). - Zapnuté odesílání firmy:
GET /sending-modevracísendingEnabled(hlavní vypínač firmy, zapíná ho jen přihlášený člověk) asendingState(schválení ostrého odesílání platformou). Dokud je vypnuté, naplánované kampaně čekají a automatizace nikoho nepustí; testovací e-maily chodí. - Denní limity a zahřívání nové domény rozloží velké rozesílky v čase.
Statistiky
GET /campaigns/{id} vrací stats (sent, delivered, opened, clicked, bounced, complained, unsubscribed; unikátní kontakty, delivered + bounced = sent). Podrobně: GET /stats/campaigns/{id}, /activity, /conversions, /recipients (i CSV), /heatmap ve skupině Statistiky. Strojová otevření a kliky (skenery odkazů) se nepočítají.
Jazykové varianty
Kampaň může mít jazykové varianty pro kontakty s jiným jazykem (/campaigns/{id}/variants): náhled rozdělení (/variants/preview), schválení (/variants/approve), pauza, obnovení a zrušení celé skupiny. API klíčem jdou volat; AI asistent přes MCP skupinu variant neschválí (posílá ji jen člověk v aplikaci).