[Intum Pomoc V1](https://intum.intum.pl/kb/intum-kb-v1.md) / [CRM](https://intum.intum.pl/kb/intum-kb-v1/crm.md)

# [Automatyczna synchronizacja danych klientów pomiędzy własną aplikacją a Intum CRM](https://intum.intum.pl/kb/intum-kb-v1/crm/automatyczna-synchronizacja-danych-klientow.md) | [API](#api)

Jeśli dane o klientach żyją w Twoim systemie (ERP, sklepie, własnej aplikacji), nie musisz ich przepisywać do Intum ręcznie ani wgrywać plików. Aplikacja "CRM - import i synchronizacja klientów" daje stały kanał: Twój system wysyła dane, a Intum na bieżąco tworzy i aktualizuje klientów w CRM. Dzięki temu np. dział marketingu może wysyłać kampanie do grup klientów wybranych po aktualnych danych - planie, saldzie, statusie - bez czekania na ręczne importy.

## Krok 1. Zainstaluj aplikację

Wejdź w Ustawienia konta - Aplikacje i dodatki, znajdź "CRM - import i synchronizacja klientów" i kliknij Zainstaluj. Po instalacji panel aplikacji znajdziesz pod adresem /a/crm-data-ingest (link pojawi się też w ustawieniach CRM).

Tak wygląda panel aplikacji:

![Panel aplikacji CRM - import i synchronizacja klientów](08dcaf2b6416-crm_ingest_panel.png)

## Krok 2. Załóż pola własne

Zastanów się, jakie informacje o kliencie chcesz widzieć w CRM poza standardowymi (nazwa, NIP, adres, email). Może to być np. plan abonamentowy, saldo, data ostatniej płatności, status współpracy. Każdą taką informację załóż jako pole własne klienta w module Automatyzacja - Pola własne (panel aplikacji ma bezpośredni link).

To ważne: przy imporcie zapisywane są tylko wartości pól, które wcześniej zdefiniujesz. Nieznane pola są pomijane, a ich liczba widoczna w statystykach - łatwo więc wyłapiesz literówkę w nazwie pola.

## Krok 3. Utwórz token dla swojego systemu

W panelu aplikacji kliknij "Utwórz token tylko do importu". Powstanie klucz dostępu ograniczony wyłącznie do wysyłania danych - Twój system nie będzie mógł nim zrobić niczego innego w Intum, więc można go bezpiecznie przekazać np. zewnętrznej firmie utrzymującej Twój ERP. Token jest pokazywany tylko raz - skopiuj go od razu.

## Krok 4. Skopiuj gotowy przykład i podłącz swój system

Panel aplikacji generuje gotowy do użycia przykład zapytania (curl) na podstawie Twoich pól własnych - z adresem, tokenem i przykładowymi wartościami. Przekaż go osobie technicznej odpowiedzialnej za Twój system. W przykładzie jest jedno miejsce do świadomej decyzji: nazwa źródła (source_code), np. "moj_erp" albo "sklep". Ta nazwa wiąże identyfikatory klientów z Twojego systemu z klientami w CRM, więc raz wybranej nie zmieniaj.

Dane można wysyłać pojedynczo (przy każdej zmianie klienta) albo paczkami do 5000 rekordów - przy pierwszym zasileniu całej bazy używaj paczek.

## Przykład: co wysyła Twój system

Poniżej przykładowe zapytanie dla konta "twojafirma" z dwoma polami własnymi: "plan" i "saldo" (najpierw załóż je w polach własnych klienta). Adres i token znajdziesz w panelu aplikacji.

```
POST https://twojafirma.intum.com/automation/import_batches.json
Authorization: Bearer TWOJ_TOKEN
Content-Type: application/json
```

```json
{
  "kind": "crm_clients",
  "source_code": "moj_erp",
  "batch_id": "2026-08-21-0001",
  "clients": [
    {
      "external_id": "123",
      "name": "Firma Przykładowa Sp. z o.o.",
      "email": "kontakt@firma.pl",
      "tax_no": "5551112233",
      "fields": {
        "plan": "premium",
        "saldo": 199.99
      }
    },
    {
      "external_id": "124",
      "name": "Jan Kowalski",
      "email": "jan@kowalski.pl",
      "fields": {
        "plan": "podstawowy",
        "saldo": 0
      }
    }
  ]
}
```

Pole "batch_id" to identyfikator paczki nadawany przez Twój system (np. numer kolejny albo data z licznikiem). Chroni przed podwójnym przetworzeniem: gdy po błędzie połączenia wyślesz tę samą paczkę ponownie, Intum rozpozna ją po batch_id i pominie duplikat - przy błędach zawsze bezpiecznie jest ponowić wysyłkę.

W odpowiedzi dostaniesz potwierdzenie przyjęcia (202) - dane pojawią się w CRM po chwili, gdy bufor zostanie przetworzony.

### Skąd Intum wie, że to ten sam klient

Przy każdej kolejnej wysyłce trzeba jakoś rozpoznać, że przysłana firma to ta sama, która już jest w CRM. Służą do tego dwa pola i warto wiedzieć, czym się różnią:

- **"external_id"** to numer klienta, który chcesz widzieć w Intum. Trafia do kolumny "Identyfikator zewnętrzny" na karcie klienta, można po nim filtrować i szukać, a w obrębie konta jest niepowtarzalny. To numer, którym posługują się ludzie w firmie, gdy mówią "klient 4471"
- **"id"** to identyfikator z Twojego systemu, używany wyłącznie do rozpoznawania rekordów. Działa zawsze w parze z nazwą źródła (source_code) - ten sam numer z dwóch różnych systemów to dwa osobne powiązania i nic się nie miesza. Nie pokazuje się na karcie klienta

Wystarczy podać jedno z nich. Jeśli masz jeden system i jeden numer klienta, użyj samego "external_id" - wtedy pełni obie role naraz, tak jak w przykładzie powyżej. Takie numery są też po prostu lepiej widoczne: możesz je oglądać na karcie klienta i wyświetlić jako kolumnę na liście, co ułatwia porównywanie danych między systemami. Gdy podasz oba pola, o rozpoznaniu rekordu decyduje "id", a "external_id" zapisuje się na kliencie jak zwykłe pole.

Rozdzielenie przydaje się w dwóch sytuacjach. Pierwsza: gdy dane płyną do Intum z kilku systemów (np. ERP i sklep) i każdy ma własne oznaczenia tej samej firmy. Wtedy każdy system wysyła swoje "id", a "external_id" zostaje na ten jeden numer obowiązujący w całej firmie. Druga: gdy identyfikator w Twoim systemie jest techniczny i nie chcesz go pokazywać handlowcom.

```json
{
  "kind": "crm_clients",
  "source_code": "moj_erp",
  "clients": [
    {
      "id": "500",
      "external_id": "4471",
      "name": "Firma Przykładowa Sp. z o.o."
    }
  ]
}
```

Powiązanie jest zawsze jeden do jednego: jeden klient CRM ma jeden "id" w danym źródle i odwrotnie. Próba podpięcia drugiego numeru do tego samego klienta (albo tego samego numeru do drugiego klienta) kończy się czytelnym błędem w statystykach - to sygnał duplikatu w danych źródłowych. Tak samo "external_id" zajęty już przez innego klienta odrzuci rekord zamiast po cichu nadpisać dane.

W osobach kontaktowych oba pola działają tak samo: "id" rozpoznaje osobę, a "external_id" jest jej numerem widocznym na karcie kontaktu. Jedna różnica: numer firmy jest niepowtarzalny w obrębie konta, a numer osoby nie musi być, więc przy osobach nic nie zablokuje powtórzenia tej samej wartości.

A co z rekordami bez żadnego identyfikatora albo z identyfikatorem, którego Intum jeszcze nie zna? Wtedy dopasowaniem rządzą pola łączące - opisane w sekcji "Jak synchronizacja łączy rekordy" poniżej.

## Osoby kontaktowe przy kliencie

Do każdej firmy możesz dołączyć listę osób. Wtedy w CRM powstaną kontakty powiązane z tą firmą, a każde powiązanie może mieć rolę osoby w tej konkretnej firmie: właściciel, księgowość, administrator, użytkownik albo podgląd.

```json
{
  "kind": "crm_clients",
  "source_code": "moj_erp",
  "batch_id": "2026-08-27-0002",
  "clients": [
    {
      "external_id": "123",
      "name": "Firma Przykładowa Sp. z o.o.",
      "email": "kontakt@firma.pl",
      "contacts_complete": true,
      "contacts": [
        {
          "external_id": "u-9",
          "email": "jan@firma.pl",
          "first_name": "Jan",
          "last_name": "Kowalski",
          "role": "owner"
        },
        {
          "external_id": "u-12",
          "email": "anna@biuro-ksiegowe.pl",
          "first_name": "Anna",
          "last_name": "Nowak",
          "role": "accountant"
        }
      ]
    }
  ]
}
```

Osoby rozpoznajemy tak samo jak firmy: przez "id" (identyfikator z Twojego systemu, niewidoczny w CRM) albo "external_id" (numer osoby zapisywany na jej karcie kontaktu). Wystarczy jedno z nich, a jeśli podasz tylko "external_id", pełni obie role - jak w przykładzie powyżej.

Gdy nie podasz "id" ani "external_id" dla którejś osoby, zostanie ona pominięta i pokazana w statystykach jako odrzucona, a pozostałe osoby tej firmy zapiszą się normalnie.

Osoba to zawsze jeden kontakt w CRM, niezależnie od tego, dla ilu firm pracuje. Jeśli Anna prowadzi księgowość czterem Twoim klientom, przyśle ją każdy z nich, a w CRM powstanie jeden kontakt z czterema powiązaniami i czterema rolami. Dzięki temu cała historia rozmów z Anną jest w jednym miejscu, a kampania marketingowa wyśle do niej jedną wiadomość, nie cztery.

Pierwsza firma, przy której osoba się pojawi, staje się jej firmą główną. Kolejne wysyłki tego nie zmieniają, bo o tym, która firma jest główna, decyduje osoba pracująca w CRM.

### Opcja "to wszystkie osoby tej firmy"

Ustawienie `"contacts_complete": true` mówi, że przysłana lista to pełny skład osobowy firmy. Jeśli ktoś z niej zniknie przy następnej wysyłce, jego powiązanie z tą firmą zostanie zakończone. Sam kontakt nie zniknie z CRM i zachowa powiązania z pozostałymi firmami oraz całą historię.

To wygodne, gdy Twój system i tak wie, kto ma dostęp do konta: nie musisz wysyłać osobnych informacji o odebraniu dostępu, wystarczy że osoba przestanie występować na liście.

Jeśli tej opcji nie podasz (albo ustawisz ją na `false`), lista jest traktowana jako uzupełnienie. Nic nie zostanie odłączone, więc możesz bezpiecznie wysłać jedną zmienioną osobę:

```json
{
  "kind": "crm_clients",
  "source_code": "moj_erp",
  "batch_id": "2026-08-27-0003",
  "clients": [
    {
      "external_id": "123",
      "contacts": [
        { "external_id": "u-9", "email": "jan@firma.pl", "phone": "+48 600 100 200" }
      ]
    }
  ]
}
```

Zwróć uwagę, że firma ma tu tylko swój identyfikator, bez nazwy i pozostałych danych. Pole nieobecne w wysyłce nigdy nie nadpisuje tego, co jest w CRM, więc poprawienie numeru telefonu jednej osoby nie wymaga wysyłania całej reszty.

Powiązań osób dodanych ręcznie w CRM import nie usuwa nigdy, także przy pełnej liście. Praca zrobiona ręcznie jest bezpieczna.

## Co się dzieje po wysłaniu

Dane trafiają najpierw do bufora (dostajesz natychmiastowe potwierdzenie), a Intum przetwarza je w tle:

- klient rozpoznany po identyfikatorze jest aktualizowany
- klient, którego identyfikatora jeszcze nie znamy, jest najpierw dopasowywany do istniejących po polach łączących (domyślnie po adresie e-mail; szczegóły w następnej sekcji)
- klient, do którego nic nie pasuje, zostanie utworzony automatycznie
- ponowne wysłanie tej samej paczki jest bezpieczne - duplikat zostanie rozpoznany i pominięty

W panelu aplikacji ustawisz też, czy import ma nadpisywać wypełnione pola, czy tylko uzupełniać puste.

## Jak synchronizacja łączy rekordy (pola łączące)

Podstawą rozpoznawania rekordów są identyfikatory ("id" lub "external_id") - klient i osoba raz połączone z Twoim systemem są przy kolejnych wysyłkach rozpoznawane właśnie po nich. Zdarza się jednak, że identyfikatora jeszcze nie ma: klient został wcześniej dodany ręcznie, przyszedł z innego źródła albo import w ogóle nie przysyła identyfikatorów. Wtedy do gry wchodzą pola łączące.

To ważne zwłaszcza wtedy, gdy masz już wypełnioną bazę CRM - klientów dodawanych ręcznie przez lata, z e-mailami, telefonami czy NIP-ami. Uruchamiana synchronizacja dokleja się wtedy po polach łączących do właściwych, istniejących klientów (i dopisuje im identyfikatory), zamiast tworzyć całą bazę od nowa jako duplikaty.

Listę pól łączących ustawiasz w konfiguracji synchronizacji (opcja "Pola łączące" w panelu aplikacji i na regule importu). Do wyboru są:

| Pole | Co porównujemy | Łączy |
|---|---|---|
| email | adres e-mail (znormalizowany) | klientów i osoby |
| phone | numer telefonu (znormalizowany) | klientów i osoby |
| tax_no | NIP (znormalizowany) | tylko klientów |
| register_number | numer rejestrowy | tylko klientów |
| name | nazwa | tylko klientów |

E-mail i telefon przed porównaniem są normalizowane, więc "+48 601-602-603" i "601602603" to dla synchronizacji ta sama wartość - telefon porównujemy po części krajowej. Prefiks międzynarodowy działa przy tym jak dodatkowy warunek: numer wysłany z jawnym prefiksem (np. "+48691112233") dopasuje się tylko do rekordu, którego prefiks telefonu jest pusty albo wskazuje ten sam kraj ("+48" i "48" to to samo). Numer w formacie krajowym ("691112233") dostaje kraj domniemany: z pola "country" wysyłanego rekordu, a bez niego z ustawień konta (pole "Kraj" w Ustawieniach konta; np. konto polskie - "+48"). Ten sam numer krajowy przy rekordzie z prefiksem "+49" nie zostanie więc połączony. NIP porównujemy po samych literach i cyfrach: "777-000-11-22" w CRM i "7770001122" z importu łączą się bez problemu, ale prefiks kraju wpisany w wartość (np. "PL7770001122") to już inna wartość niż "7770001122".

Puste pole "Pola łączące" wyłącza łączenie: rekord bez rozpoznanego identyfikatora nie jest wtedy dopasowywany po żadnym polu - od razu powstaje nowy klient. Aplikacja synchronizacji ustawia na starcie wartość "email".

Literówka na liście (np. "emial") zatrzyma zapis konfiguracji z czytelnym błędem - cicha pomyłka wyłączyłaby łączenie i import tworzyłby duplikaty.

### Kolejność ma znaczenie

Pola sprawdzamy po kolei, w podanej kolejności - pierwsze pole, które znajdzie jednoznaczne dopasowanie, kończy szukanie. "email, phone" może więc dać inny wynik niż "phone, email": ustaw jako pierwsze to pole, które w Twoich danych najlepiej identyfikuje firmę.

### Jak działa łączenie

Gdy importowany rekord ma identyfikator, którego nie znamy jeszcze w CRM (albo nie ma go wcale), synchronizacja idzie po polach łączących i szuka klienta z dokładnie tą wartością. Połączenie następuje tylko przy jednoznacznym dopasowaniu - muszą być spełnione wszystkie warunki:

- w CRM istnieje dokładnie jeden klient z tą wartością pola,
- dla e-maila i telefonu: osób kontaktowych z tą wartością jest w całym CRM najwyżej jedna, a jeśli jest, to musi należeć do tego właśnie klienta,
- pozostałe pola łączące z listy też się zgadzają - każde z nich jest po obu stronach puste albo identyczne. Jeśli np. łączysz po "tax_no, email", a klient znaleziony po NIP-ie ma inny e-mail niż rekord z importu, dopasowanie odpada.

Jeśli wszystko się zgadza, importowany rekord podłącza się do znalezionego klienta i - gdy import niesie identyfikator - identyfikator zapisuje się na kliencie. Od tej pory kolejne wysyłki rozpoznają go już po identyfikatorze i pola łączące nie są do niczego potrzebne.

Uwaga: zgodność pól łączących obowiązuje tylko przy dopasowaniu po polach łączących. Rekord rozpoznany po identyfikatorze aktualizuje klienta niezależnie od tego, czy pola łączące się zgadzają - identyfikator rozstrzyga tożsamość, a zmiana e-maila czy telefonu w Twoim systemie po prostu zapisuje się w CRM.

### Gdy dopasowanie jest niejednoznaczne

Każda niejednoznaczność oznacza brak dopasowania: gdy dwóch klientów ma tę samą wartość albo e-mail pojawia się przy osobie z innej firmy, synchronizacja nie zgaduje. Co się wtedy dzieje, zależy od tego, czy rekord ma identyfikator:

- rekord z "id" lub "external_id" - powstaje nowy klient (lepszy duplikat do ręcznego scalenia niż dane dopisane do niewłaściwej firmy); kolejne wysyłki rozpoznają go już po identyfikatorze, więc duplikat się nie mnoży,
- rekord bez identyfikatorów - jest odrzucany z czytelnym błędem w statystykach. Taki rekord rozpoznaje się przy kolejnych wysyłkach wyłącznie po polach łączących, więc utworzenie klienta oznaczałoby nowy duplikat przy każdym przebiegu. Dodaj identyfikator do rekordu albo scal duplikaty w CRM.

### Ślad połączenia: pole "merge_sync"

Dopasowanie po polach łączących to zawsze decyzja na podstawie danych, nie identyfikatora - dlatego zostawia ślad. Jeśli podczas takiego połączenia import zastąpił niepuste wartości, poprzednie wartości zapisują się w polu "merge_sync" rekordu - możesz więc zawsze sprawdzić, że rekord został połączony po polach łączących i co dokładnie zostało nadpisane. Ślad niesie też datę połączenia i nazwę źródła, które je wykonało. Na karcie klienta widać go w boksie "Zastąpione przy łączeniu".

Zwykła aktualizacja rekordu rozpoznanego po identyfikatorze tego śladu nie zostawia.

### Osoby też łączą się po polach łączących

Po dopasowaniu firmy te same zasady stosujemy do osób z wysyłki - działają tu pola łączące mające odpowiednik na kontakcie (email, phone). Osoba, której identyfikatora nie znamy, podłącza się do kontaktu tej firmy o tej samej wartości pola - pod warunkiem, że wśród kontaktów firmy jest dokładnie jeden taki kontakt, a pozostałe pola łączące osoby też się zgadzają. Identyfikator z wysyłki dopisuje się wtedy do dopasowanego kontaktu zamiast tworzyć duplikat osoby.

### Czego synchronizacja nigdy nie zrobi

- Nie przepnie cudzego identyfikatora. Jeśli znaleziony po polu łączącym klient lub kontakt ma już przypisany inny identyfikator zewnętrzny, dopasowanie odpada - rekord z importu nie przejmie firmy ani osoby połączonej z innym rekordem.
- Nie połączy przy niejednoznaczności - dwa rekordy o tej samej wartości pola łączącego w CRM zawsze blokują łączenie po tej wartości.
- Nie połączy przy rozjeździe pozostałych pól z listy.

### Typowy scenariusz: najpierw prosty import, potem pełna synchronizacja

Pola łączące pozwalają rozłożyć wdrożenie na etapy:

1. Wysyłasz uproszczone dane bez identyfikatorów (wystarczą nazwy i e-maile) - w CRM powstają klienci z kontaktami.
2. Ponowny import tych samych danych nie tworzy duplikatów - rekordy łączą się po polach łączących.
3. Gdy uruchomisz docelową synchronizację z identyfikatorami, rekordy dopasują się po polach łączących, a identyfikatory dopiszą się do istniejących klientów i kontaktów - dalsze wysyłki działają już w pełni automatycznie po identyfikatorach.

## Monitorowanie

Panel pokazuje listę źródeł z datą ostatniej wrzutki i liczbą paczek czekających w buforze, ostatnie paczki oraz statystyki przetwarzania: ilu klientów utworzono, zaktualizowano, powiązano, ile było błędów i jakie nieznane pola się pojawiły. Gdy wysyłasz też osoby kontaktowe, w statystykach widać ile kontaktów utworzono i zaktualizowano, ile powiązań z firmami powstało i ile zostało zakończonych.

## Co dalej: kampanie do grup klientów

Gdy dane płyną, pola własne klientów są dostępne w zaawansowanym filtrze CRM i w listach odbiorców Marketing Automation typu "filtr". Możesz np. utworzyć listę "klienci z planem premium i saldem powyżej zera" - lista odświeża się automatycznie przed każdą wysyłką kampanii.

---

## API

### Ogólne API

# Intum API

Dokumentacja API platformy [Intum](https://intum.pl) - system operacyjny firmy.

## Host

Host jest zawsze taki sam jak adres konta: `xxxx.intum.com` lub `xxx.intum.pl` (w zależności od ustawień konta)

## Autoryzacja

Wszystkie requesty API wymagają `api_token`:
- header: `Authorization: Bearer TOKEN`

Token możesz wygenerować w **Ustawienia Konta** → **Tokeny API**

## CRM Data Ingest - API

Bufor importów danych klientów. Autoryzacja: `Authorization: Bearer TOKEN` z uprawnieniem `automation_import` (token można ograniczyć wyłącznie do tego uprawnienia). Throttle: 2000 requestów/min per konto - operacje masowe wysyłaj batchami.

### Wysyłka

```
POST /automation/import_batches.json
```

```json
{
  "kind": "crm_clients",
  "source_code": "moj_system",
  "batch_id": "unikalny-id-batcha",
  "clients": [
    {
      "external_id": "123",
      "name": "Firma Przykładowa",
      "email": "kontakt@firma.pl",
      "tax_no": "5551112233",
      "fields": { "plan": "premium", "saldo": 199.99 }
    }
  ]
}
```

| Pole | Wymagane | Opis |
|------|----------|------|
| `kind` | nie | obecnie tylko `crm_clients` (default) |
| `source_code` | tak | stała nazwa źródła `[a-z][a-z0-9_]*` - przestrzeń identyfikatorów `id`; nie zmieniać po starcie |
| `batch_id` | nie | klucz idempotencji retry (duplikat -> `"duplicate": true`); bez niego hash treści |
| `clients[].id` | tak* | id klienta w systemie źródłowym - klucz tożsamości w przestrzeni `source_code` (tabela powiązań external_ids), nie pokazuje się w CRM |
| `clients[].external_id` | tak* | globalny identyfikator zapisywany w kolumnie `external_id` klienta CRM (unikalna w obrębie konta, widoczna w filtrach i eksportach). Bez `id` pełni rolę klucza tożsamości - rozpoznanie po kolumnie, bez wpisu w external_ids |
| `clients[].fields` | nie | pola własne (JSONB `fields`) - zapisywane także klucze bez definicji `Automation::CustomField` (opcja `save_unknown_fields`, domyślnie włączona; po wyłączeniu nieznane klucze są pomijane i zliczane w statystykach). Definicja pola nie powstaje automatycznie |

\* przynajmniej jedno z `id` / `external_id`. Rekord bez obu przejdzie z samym `email` - jest wtedy rozpoznawany wyłącznie po polach łączących (patrz niżej).

Limity: 5000 klientów na request i 20 000 pozycji łącznie (klienci razem z osobami). Odpowiedź: `202 Accepted` + `{ status, accepted, batch_id, duplicate }`. Przetwarzanie asynchroniczne w tle. Wysyłaj pełny aktualny stan klienta, nie delty - rekordy w batchu są deduplikowane po kluczu tożsamości, ostatni stan wygrywa. Pole nieobecne w payloadzie nie nadpisuje wartości w CRM.

Pola stałe klienta: `name, shortcut, first_name, last_name, company, email, phone, mobile_phone, www, tax_no, register_number, external_id, street, post_code, city, province, country, note, description, kind, paid_to`.

### Osoby przy kliencie

Rekord klienta może zawierać listę `contacts`. Każda osoba wymaga `id` albo `external_id` (znaczenie jak przy kliencie; kolumna `external_id` kontaktu nie jest unikalna).

| Pole | Opis |
|------|------|
| `contacts[].role` | rola w TEJ firmie: `owner`, `admin`, `accountant`, `user`, `viewer` (inna wartość zapisze się bez zmian) |
| `contacts[].fields` | pola własne kontaktu - jak przy kliencie |
| `clients[].contacts_complete` | `true` = lista to pełny stan, brak osoby kończy jej powiązanie z firmą. Bez flagi payload jest przyrostowy i nic nie odłącza |

Pola stałe osoby: `name, first_name, last_name, email, phone, mobile_phone, external_id, position, note, description`.

Osoba to jeden kontakt niezależnie od liczby firm - rozpoznana po `id` w przestrzeni `source_code` (albo po polach łączących) dostaje kolejne powiązania z rolami, nie duplikaty. Powiązania dopisane ręcznie w CRM nie są usuwane przez `contacts_complete`; gdy choć jedna osoba z listy zostanie odrzucona, flaga nie odłącza nikogo w tym przebiegu.

### Pola łączące i merge

Rekord, którego klucza tożsamości nie ma jeszcze w CRM, jest najpierw dopasowywany do istniejących po polach łączących z opcji `linking_fields` reguły (np. `"email, phone"`; dostępne: `email`, `phone`, `tax_no`, `register_number`, `name` - dwa pierwsze działają też dla osób). Pola sprawdzane są po kolei, łączy tylko jednoznaczne dopasowanie (dokładnie jeden kandydat, pozostałe pola z listy zgodne albo puste po którejś ze stron). E-mail i telefon porównywane po znormalizowanej postaci (telefon po części krajowej, prefiks międzynarodowy jako dodatkowy warunek; numer krajowy dostaje kraj z pola `country` rekordu albo z ustawień konta), NIP po samych znakach alfanumerycznych. Pusta opcja wyłącza łączenie; aplikacja ustawia na starcie `email`.

Merge po polach łączących, który zastąpił niepuste wartości, zapisuje poprzednie wartości w polu `merge_sync` rekordu (plus meta `_merged_at` i `_source_code`). Rekord rozpoznany po kluczu tożsamości aktualizuje się bez sprawdzania pól łączących i bez śladu merge_sync. Niejednoznaczne dopasowanie: rekord z `id`/`external_id` tworzy nowego klienta, rekord bez identyfikatorów jest odrzucany z błędem w statystykach.

Konfiguracja (opcje `linking_fields`, `save_unknown_fields`, `batch_size`) mieszka na akcji `crm_client_sync` reguły automatyzacji zakładanej przez aplikację - edycja w panelu aplikacji albo przez `PATCH /automation/rules/:id.json`.

### Podgląd

```
GET /automation/import_batches.json?processed=false&source_code=...   # batche w buforze
GET /automation/import_batches/:id.json                               # pojedynczy batch
GET /automation/import_batches/stats.json                             # endpoint_url, źródła, statystyki, ostatnie odrzuty (recent_failed)
```

---

## Powiązane

- [Scalanie zdublowanych kontaktów po adresie e-mail](https://intum.intum.pl/kb/intum-kb-v1/crm/scalanie-zdublowanych-kontaktow-po-adresie-e-mail.md)
- [Import klientów z Fakturowni](https://intum.intum.pl/kb/intum-kb-v1/crm/import-klientow-z-fakturowni.md)
- [Klienci](https://intum.intum.pl/kb/intum-kb-v1/crm/klienci.md)
