Přeskočit na obsah
API dokumentace

Recept: odeslání kampaně

Cíl: připravit newsletter pro seznam odběratelů, zkontrolovat obsah a příjemce, poslat test a naplánovat odeslání.

Potřebujete: klíč s rolí marketing_manager, ověřeného odesílatele, testovací adresu firmy (v aplikaci Testovací adresy v nastavení odesílání; přes API PUT /test-recipients s rolí správce účtu).

1. Příjemci

Pro ukázku kontakt se souhlasem a seznam:

Požadavek: POST /api/v1/tenants/{tenant}/contacts
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/contacts" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "email": "petr.svoboda@example.cz",
  "shopId": "17",
  "purposeId": "9",
  "consentConfirmed": true,
  "firstName": "Petr",
  "vocativeFirstName": "Petře"
}
JSON
Odpověď: 201 Created
{
  "id": "1206",
  "email": "petr.svoboda@example.cz",
  "firstName": "Petr",
  "lastName": "",
  "status": "subscribed",
  "engagement": "N",
  "excluded": false,
  "shopId": "17",
  "suppressionReason": null,
  "blacklisted": false,
  "blacklistedAt": null,
  "state": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "phone": "",
  "mobile": "",
  "titleBefore": "",
  "titleAfter": "",
  "salutation": "",
  "salutationFormal": "",
  "vocativeFirstName": "Petře",
  "vocativeLastName": "",
  "gender": null,
  "language": "cs",
  "company": "",
  "companyId": "",
  "street": "",
  "city": "",
  "postalCode": "",
  "note": "",
  "affiliateId": "",
  "country": null,
  "birthday": null,
  "nameDay": null,
  "source": "manual",
  "consentBasis": "imported",
  "statusAt": "2026-10-01T08:00:00.000Z",
  "consentAt": "2026-10-01T08:00:00.000Z",
  "consentWeak": false,
  "softBounces": 0,
  "lastSentAt": null,
  "lastOpenAt": null,
  "lastClickAt": null,
  "suppressedAt": null,
  "engagementAt": null,
  "suppressionNote": null,
  "customFields": {},
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "stats90d": {
    "received": 0,
    "opened": 0,
    "clicked": 0,
    "bestHour": null
  },
  "lists": [],
  "recentActivities": [
    {
      "id": "consent-7",
      "type": "status_change",
      "at": "2026-10-01T08:00:00.000Z",
      "title": "purpose_assigned"
    }
  ],
  "orders": [],
  "orderTotals": [],
  "editedFields": [],
  "sources": []
}
Požadavek: POST /api/v1/tenants/{tenant}/lists
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/lists" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "name": "Newsletter",
  "publicName": "Novinky e-shopu",
  "shopId": "17",
  "notifyOnUnsubscribe": false,
  "notifyOnAdd": false,
  "note": ""
}
JSON
Odpověď: 201 Created
{
  "id": "44",
  "name": "Newsletter",
  "publicName": "Novinky e-shopu",
  "shopId": "17",
  "systemKind": null,
  "locked": false,
  "manualMembers": true,
  "tags": [],
  "counts": {
    "total": 0,
    "byBucket": {
      "active": 0,
      "unconfirmed": 0,
      "unsubscribed": 0,
      "bounced": 0,
      "complained": 0,
      "blacklisted": 0
    }
  },
  "createdAt": "2026-10-01T08:00:00.000Z",
  "notifyOnUnsubscribe": false,
  "notifyOnAdd": false,
  "note": ""
}
Požadavek: POST /api/v1/tenants/{tenant}/lists/44/members
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/lists/44/members" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "contactIds": [
    "1206"
  ]
}
JSON
Odpověď: 200 OK
{
  "added": 1,
  "alreadyMember": 0,
  "skipped": 0
}

2. Odesílatel

Požadavek: GET /api/v1/tenants/{tenant}/senders
curl -sS -X GET "https://www.postarna.cz/api/v1/tenants/$TENANT/senders" \
  -H "Authorization: Bearer $POSTARNA_API_KEY"
Odpověď: 200 OK
{
  "items": [
    {
      "id": "17",
      "shopId": "17",
      "name": "Example.cz",
      "email": "info@example.cz",
      "replyTo": "",
      "verified": true,
      "isDefault": true
    },
    {
      "id": "18",
      "shopId": "18",
      "name": "Example.sk",
      "email": "info@example.sk",
      "replyTo": "",
      "verified": true,
      "isDefault": true
    }
  ]
}

Odesílat smí jen ověřená adresa (verified: true) e-shopu kampaně.

3. Koncept kampaně

Požadavek: POST /api/v1/tenants/{tenant}/campaigns
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "name": "Říjnový newsletter",
  "shopId": "17",
  "senderId": "17",
  "fromName": "Example.cz",
  "subject": "Podzimní novinky",
  "preheader": "Nová káva a tipy na přípravu",
  "audience": {
    "listIds": [
      "44"
    ],
    "segmentIds": [],
    "excludeListIds": [],
    "excludeInactive": true,
    "excludeEmails": [],
    "onlyWithPurpose": false,
    "purposeIds": []
  }
}
JSON
Odpověď: 201 Created
{
  "id": "151",
  "name": "Říjnový newsletter",
  "shopId": "17",
  "subject": "Podzimní novinky",
  "status": "draft",
  "recipients": null,
  "scheduledAt": null,
  "startedAt": null,
  "completedAt": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "stats": null,
  "variantGroupId": null,
  "variantLabel": "",
  "variantPosition": 0,
  "tags": [],
  "preheader": "Nová káva a tipy na přípravu",
  "senderId": "17",
  "fromName": "Example.cz",
  "fromEmail": "info@example.cz",
  "replyTo": "",
  "templateId": null,
  "hasContent": false,
  "audience": {
    "listIds": [
      "44"
    ],
    "segmentIds": [],
    "excludeListIds": [],
    "excludeInactive": true,
    "excludeEmails": [],
    "onlyWithPurpose": false,
    "purposeIds": []
  },
  "pausedReason": null,
  "approvedAt": null,
  "trackOpens": true,
  "trackClicks": true,
  "utm": null,
  "headers": [],
  "timing": "later",
  "plannedAt": null,
  "linkParams": [],
  "preferTime": false,
  "replyToOptions": [
    "info@example.cz"
  ]
}

4. Obsah

baseVersion: 0 u kampaně, která obsah ještě nemá. Obsah musí mít odkaz na odhlášení ({{unsubscribe}}), jinak Poštárna doplní standardní patičku.

Požadavek: PUT /api/v1/tenants/{tenant}/campaigns/151/content
curl -sS -X PUT "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/151/content" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "editor": "html",
  "design": null,
  "baseVersion": 0,
  "html": "<!doctype html><html><body><p>Dobrý den, {{df_salution|default('vážený zákazníku', true)}},</p><p>na e-shopu máme novou podzimní kávu.</p><p><a href=\"https://www.example.cz/novinky\">Prohlédnout novinky</a></p><p style=\"font-size:12px\">{{cl_company}}, {{cl_address}}. <a href=\"{{unsubscribe}}\">Odhlásit odběr</a></p></body></html>"
}
JSON
Odpověď: 200 OK
{
  "editor": "html",
  "html": "<!doctype html><html><body><p>Dobrý den, {{df_salution|default('vážený zákazníku', true)}},</p><p>na e-shopu máme novou podzimní kávu.</p><p><a href=\"https://www.example.cz/novinky\">Prohlédnout novinky</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"
}

Kontrola obsahu (tady s neznámou značkou a bez odhlášení):

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": {}
    }
  ]
}

5. Počet příjemců

Požadavek: POST /api/v1/tenants/{tenant}/campaigns/audience
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
Odpověď: 200 OK
{
  "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
  }
}

6. Testovací e-mail

Jen na testovací adresy firmy (GET /test-recipients), nejvýš 10 za 24 hodin:

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"
}

7. Schválení

Když počet nesedí (liší se o víc než 5 %), kampaň zůstane konceptem:

Požadavek: POST /api/v1/tenants/{tenant}/campaigns/151/approve
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
Odpověď: 409 Conflict
{
  "error": {
    "code": "conflict",
    "message": "recipients",
    "params": {
      "expected": 250,
      "actual": 1
    }
  }
}

Se správným počtem a časem odeslání (sendAt 5 minut až 365 dní dopředu, null = hned):

Požadavek: POST /api/v1/tenants/{tenant}/campaigns/151/approve
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": 1
}
JSON
Odpověď: 200 OK
{
  "id": "151",
  "name": "Říjnový newsletter",
  "shopId": "17",
  "subject": "Podzimní novinky",
  "status": "scheduled",
  "recipients": 1,
  "scheduledAt": "2026-10-02T07:00:00.000Z",
  "startedAt": null,
  "completedAt": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "stats": null,
  "variantGroupId": null,
  "variantLabel": "",
  "variantPosition": 0,
  "tags": [],
  "preheader": "Nová káva a tipy na přípravu",
  "senderId": "17",
  "fromName": "Example.cz",
  "fromEmail": "info@example.cz",
  "replyTo": "",
  "templateId": null,
  "hasContent": true,
  "audience": {
    "listIds": [
      "44"
    ],
    "segmentIds": [],
    "excludeListIds": [],
    "excludeInactive": true,
    "excludeEmails": [],
    "onlyWithPurpose": false,
    "purposeIds": []
  },
  "pausedReason": null,
  "approvedAt": "2026-10-01T08:00:00.000Z",
  "trackOpens": true,
  "trackClicks": true,
  "utm": null,
  "headers": [],
  "timing": "later",
  "plannedAt": null,
  "linkParams": [],
  "preferTime": false,
  "replyToOptions": [
    "info@example.cz"
  ]
}
Požadavek: GET /api/v1/tenants/{tenant}/campaigns/151
curl -sS -X GET "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/151" \
  -H "Authorization: Bearer $POSTARNA_API_KEY"
Odpověď: 200 OK
{
  "id": "151",
  "name": "Říjnový newsletter",
  "shopId": "17",
  "subject": "Podzimní novinky",
  "status": "scheduled",
  "recipients": 1,
  "scheduledAt": "2026-10-02T07:00:00.000Z",
  "startedAt": null,
  "completedAt": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "stats": null,
  "variantGroupId": null,
  "variantLabel": "",
  "variantPosition": 0,
  "tags": [],
  "preheader": "Nová káva a tipy na přípravu",
  "senderId": "17",
  "fromName": "Example.cz",
  "fromEmail": "info@example.cz",
  "replyTo": "",
  "templateId": null,
  "hasContent": true,
  "audience": {
    "listIds": [
      "44"
    ],
    "segmentIds": [],
    "excludeListIds": [],
    "excludeInactive": true,
    "excludeEmails": [],
    "onlyWithPurpose": false,
    "purposeIds": []
  },
  "pausedReason": null,
  "approvedAt": "2026-10-01T08:00:00.000Z",
  "trackOpens": true,
  "trackClicks": true,
  "utm": null,
  "headers": [],
  "timing": "later",
  "plannedAt": null,
  "linkParams": [],
  "preferTime": false,
  "replyToOptions": [
    "info@example.cz"
  ]
}

8. Pauza a zrušení

Naplánovanou nebo odesílanou kampaň zastaví POST /campaigns/{id}/pause, znovu ji pustí /resume, úplně zruší /cancel:

Požadavek: POST /api/v1/tenants/{tenant}/campaigns/151/cancel
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/151/cancel" \
  -H "Authorization: Bearer $POSTARNA_API_KEY"
Odpověď: 200 OK
{
  "id": "151",
  "name": "Říjnový newsletter",
  "shopId": "17",
  "subject": "Podzimní novinky",
  "status": "cancelled",
  "recipients": 1,
  "scheduledAt": "2026-10-02T07:00:00.000Z",
  "startedAt": null,
  "completedAt": null,
  "createdAt": "2026-10-01T08:00:00.000Z",
  "updatedAt": "2026-10-01T08:00:00.000Z",
  "stats": null,
  "variantGroupId": null,
  "variantLabel": "",
  "variantPosition": 0,
  "tags": [],
  "preheader": "Nová káva a tipy na přípravu",
  "senderId": "17",
  "fromName": "Example.cz",
  "fromEmail": "info@example.cz",
  "replyTo": "",
  "templateId": null,
  "hasContent": true,
  "audience": {
    "listIds": [
      "44"
    ],
    "segmentIds": [],
    "excludeListIds": [],
    "excludeInactive": true,
    "excludeEmails": [],
    "onlyWithPurpose": false,
    "purposeIds": []
  },
  "pausedReason": null,
  "approvedAt": "2026-10-01T08:00:00.000Z",
  "trackOpens": true,
  "trackClicks": true,
  "utm": null,
  "headers": [],
  "timing": "later",
  "plannedAt": null,
  "linkParams": [],
  "preferTime": false,
  "replyToOptions": [
    "info@example.cz"
  ]
}

Statistiky po odeslání

GET /campaigns/{id} (stats), GET /stats/campaigns/{id}, /recipients?format=csv, /conversions. Viz Kampaně.