Preskočiť na obsah
API dokumentácia

Recept: import kontaktov z CSV

Cieľ: nahrať kontakty z CSV súboru so súhlasom, ktorý máte doložený, a overiť výsledok.

Potrebujete: kľúč s modulom contacts na úrovni full.

1. Nahranie súboru

Dve možnosti:

  • multipart/form-data s poľom file (súbor do 64 MB a 300 000 riadkov, kódovanie UTF-8, UTF-16 alebo windows-1250 sa pozná samo) a voliteľne delimiter, quote, hasHeader, encoding.
  • JSON {"text": "...", "delimiter", "quote", "hasHeader"} s obsahom do 5 MB.
Požiadavka: POST /api/v1/tenants/{tenant}/imports/files
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/imports/files" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "text": "email;jmeno;prijmeni;mesto\nmarie.dvorakova@example.cz;Marie;Dvořáková;Praha\ntomas.cerny@example.cz;Tomáš;Černý;Ostrava\nchybna-adresa;Jan;Bez;Plzeň\n",
  "delimiter": ";",
  "quote": "\"",
  "hasHeader": true
}
JSON
Odpoveď: 201 Created
{
  "fileId": "71",
  "fileName": "vlozeny-text.csv",
  "size": 155,
  "delimiter": ";",
  "quote": "\"",
  "hasHeader": true,
  "encoding": "utf-8",
  "columns": [
    "email",
    "jmeno",
    "prijmeni",
    "mesto"
  ],
  "rowCount": 3,
  "sample": [
    [
      "marie.dvorakova@example.cz",
      "Marie",
      "Dvořáková",
      "Praha"
    ],
    [
      "tomas.cerny@example.cz",
      "Tomáš",
      "Černý",
      "Ostrava"
    ],
    [
      "chybna-adresa",
      "Jan",
      "Bez",
      "Plzeň"
    ]
  ],
  "suggestedKind": "csv",
  "suggestedMapping": [
    "email",
    "firstName",
    "lastName",
    "city"
  ]
}

Odpoveď má fileId, rozpoznané stĺpce, ukázku riadkov a suggestedMapping (návrh, ktoré pole je v ktorom stĺpci). Súbor sa drží 24 hodín.

2. Náhľad

mapping má jednu položku na stĺpec súboru, v poradí: názov poľa, alebo null (stĺpec preskočiť). Práve jeden stĺpec musí byť email. Polia: email, firstName, lastName, fullName, titleBefore, titleAfter, phone, mobile, company, companyId, street, city, postalCode, country, language, gender, birthday, note, newsletterConsent, newsletterConsentAt, registeredAt a vlastné pole.

Požiadavka: POST /api/v1/tenants/{tenant}/imports/preview
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/imports/preview" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "fileId": "71",
  "mapping": [
    "email",
    "firstName",
    "lastName",
    "city"
  ],
  "mode": "upsert",
  "shopId": "9",
  "listIds": []
}
JSON
Odpoveď: 200 OK
{
  "counts": {
    "rows": 3,
    "create": 2,
    "update": 0,
    "skipSuppressed": 0,
    "skipMissing": 0,
    "invalid": 1,
    "duplicate": 0,
    "unsubscribe": 0,
    "remove": 0,
    "blacklist": 0
  },
  "rows": [
    {
      "row": 2,
      "email": "marie.dvorakova@example.cz",
      "action": "create",
      "error": null,
      "field": null,
      "values": {
        "email": "marie.dvorakova@example.cz",
        "firstName": "Marie",
        "lastName": "Dvořáková",
        "city": "Praha"
      },
      "consent": true
    },
    {
      "row": 3,
      "email": "tomas.cerny@example.cz",
      "action": "create",
      "error": null,
      "field": null,
      "values": {
        "email": "tomas.cerny@example.cz",
        "firstName": "Tomáš",
        "lastName": "Černý",
        "city": "Ostrava"
      },
      "consent": true
    },
    {
      "row": 4,
      "email": "chybna-adresa",
      "action": "invalid",
      "error": "email_invalid",
      "field": "email",
      "values": {
        "email": "chybna-adresa",
        "firstName": "Jan",
        "lastName": "Bez",
        "city": "Plzeň"
      },
      "consent": null
    }
  ],
  "report": {
    "consent": {
      "optIn": 2,
      "none": 0,
      "keptUnsubscribed": 0
    },
    "merge": {
      "existing": 0,
      "fromSources": {},
      "fieldsUpdated": 0,
      "fieldsKeptEdited": 0
    },
    "dropped": {}
  }
}

counts hovorí, koľko riadkov sa založí, aktualizuje, preskočí (potlačené adresy, chyby) a prečo; rows ukazuje prvé riadky s ich výsledkom.

3. Spustenie

  • mode: upsert (založiť aj aktualizovať), update_only, alebo hromadné odhlásenie unsubscribe, odobratie remove, blacklist blacklist.
  • purposeId a consentConfirmed: true: potvrdzujete, že ku všetkým kontaktom máte doložený súhlas s týmto účelom (pri unsubscribe, remove a blacklist súhlas potrebný nie je).
  • listIds: ručné zoznamy, do ktorých kontakty pribudnú.
  • runAutomations: východiskovo false = import nespustí žiadnu automatizáciu (ani „nový kontakt“ či „pridanie do zoznamu“). Zapnite len vedome.
  • kind: csv, alebo exporty Shoptetu shoptet_customers a shoptet_newsletter.
Požiadavka: POST /api/v1/tenants/{tenant}/imports
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/imports" \
  -H "Authorization: Bearer $POSTARNA_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- <<'JSON'
{
  "name": "Kontakty z veletrhu",
  "source": "csv",
  "fileId": "71",
  "mapping": [
    "email",
    "firstName",
    "lastName",
    "city"
  ],
  "mode": "upsert",
  "shopId": "9",
  "listIds": [],
  "purposeId": "5",
  "consentConfirmed": true
}
JSON
Odpoveď: 201 Created
{
  "id": "61",
  "name": "Kontakty z veletrhu",
  "status": "finished",
  "kind": "csv",
  "fileName": "vlozeny-text.csv",
  "shopId": "9",
  "mode": "upsert",
  "listIds": [],
  "createdAt": "2026-10-01T08:00:00.000Z",
  "startedAt": "2026-10-01T08:00:00.000Z",
  "finishedAt": "2026-10-01T08:00:00.000Z",
  "progress": {
    "processed": 3,
    "total": 3
  },
  "counts": {
    "rows": 3,
    "create": 2,
    "remove": 0,
    "update": 0,
    "invalid": 1,
    "blacklist": 0,
    "duplicate": 0,
    "skipMissing": 0,
    "unsubscribe": 0,
    "skipSuppressed": 0
  },
  "source": "csv",
  "purposeId": "5",
  "addedToLists": 0,
  "errors": [
    {
      "row": 4,
      "error": "email_invalid",
      "field": "email"
    }
  ],
  "runAutomations": false,
  "options": {},
  "report": {
    "consent": {
      "none": 0,
      "optIn": 2,
      "keptUnsubscribed": 0
    },
    "merge": {
      "existing": 0,
      "fromSources": {},
      "fieldsUpdated": 0,
      "fieldsKeptEdited": 0
    },
    "dropped": {}
  }
}

Do 1 000 riadkov prebehne import hneď (status: "finished"); väčší ide do radu (queued, running s priebehom progress) a dokončí ho worker.

4. Výsledok

Požiadavka: GET /api/v1/tenants/{tenant}/imports/61
curl -sS -X GET "https://www.postarna.cz/api/v1/tenants/$TENANT/imports/61" \
  -H "Authorization: Bearer $POSTARNA_API_KEY"
Odpoveď: 200 OK
{
  "id": "61",
  "name": "Kontakty z veletrhu",
  "status": "finished",
  "kind": "csv",
  "fileName": "vlozeny-text.csv",
  "shopId": "9",
  "mode": "upsert",
  "listIds": [],
  "createdAt": "2026-10-01T08:00:00.000Z",
  "startedAt": "2026-10-01T08:00:00.000Z",
  "finishedAt": "2026-10-01T08:00:00.000Z",
  "progress": {
    "processed": 3,
    "total": 3
  },
  "counts": {
    "rows": 3,
    "create": 2,
    "remove": 0,
    "update": 0,
    "invalid": 1,
    "blacklist": 0,
    "duplicate": 0,
    "skipMissing": 0,
    "unsubscribe": 0,
    "skipSuppressed": 0
  },
  "source": "csv",
  "purposeId": "5",
  "addedToLists": 0,
  "errors": [
    {
      "row": 4,
      "error": "email_invalid",
      "field": "email"
    }
  ],
  "runAutomations": false,
  "options": {},
  "report": {
    "consent": {
      "none": 0,
      "optIn": 2,
      "keptUnsubscribed": 0
    },
    "merge": {
      "existing": 0,
      "fromSources": {},
      "fieldsUpdated": 0,
      "fieldsKeptEdited": 0
    },
    "dropped": {}
  }
}

errors uvádza riadky, ktoré neprešli (tu neplatná adresa na riadku 4).

Pravidlá, na ktoré pozor

  • Potlačená adresa (odhlásená, nedoručiteľná, sťažnosť) sa importom nikdy znovu neprihlási.
  • Polia, ktoré v aplikácii upravil človek, import neprepíše.
  • Adresa vymazaná na žiadosť (GDPR) sa importom znovu nezaloží.
  • Import zákazníkov bez súhlasu (shoptet_customers bez stĺpca súhlasu) založí kontakty customer, ktorým sa nepíše.