# Integracje (webhook i JSONL)

KSeFka może powiadamiać zewnętrzne systemy gdy z synchronizacji KSeF wpadnie nowa faktura otrzymana. Do dyspozycji są dwa kanały, które mogą działać jednocześnie:

- **Webhook HTTP** — POST z payloadem JSON na wskazany URL (np. n8n, Make, Zapier, własny endpoint).
- **Event log (JSONL)** — dopisywanie kolejnych zdarzeń do pliku tekstowego, jedno zdarzenie w jednej linii.

> [!TIP]
> Integracje są funkcją [KSeFka PRO](https://ksefka.com/docs/licencja-pro). Bez aktywnej licencji pola w ustawieniach są wyłączone, a zdarzenia nie są wysyłane.

## Kiedy wysyłane jest zdarzenie

Zdarzenie "invoice:received-from-sync" jest emitowane **wyłącznie** dla faktur, które:

- Są **nowe** w lokalnej bazie KSeFki (nie aktualizacje istniejących wpisów ani duplikaty).
- Mają kierunek **otrzymana** (faktura od kontrahenta, pobrana przez synchronizację z KSeF).

Faktury wystawione przez Ciebie, ręcznie wprowadzone, edytowane oraz zaktualizowane statusy **nie** wywołują tego zdarzenia — zgodnie z zasadą "immutable from birth" (faktura otrzymana z KSeF jest niezmienna od momentu pobrania, więc nadaje się jako trigger).

## Format payloadu

Oba kanały wysyłają identyczny obiekt JSON:

```
{
  "invoice_id": 1234,
  "ksef_reference_number": "1234567890-20260209-SE-ABCDEF-12",
  "sync_timestamp": "2026-05-05T10:23:14.512Z",
  "xml_content": "<Faktura xmlns=\"...\">...</Faktura>"
}
```

| Pole | Typ | Opis |
| --- | --- | --- |
| `invoice_id` | liczba | Lokalne ID faktury w bazie KSeFki (przydatne do późniejszego dopytania CLI/MCP). |
| `ksef_reference_number` | tekst | Numer referencyjny KSeF, np. `1234567890-20260209-SE-ABCDEF-12`. |
| `sync_timestamp` | tekst (RFC 3339, UTC) | Moment zapisania faktury lokalnie. Sortuj po tym polu, jeśli potrzebujesz kolejności. |
| `xml_content` | tekst | Pełny XML faktury w formacie FA(3) — można go przekazać dalej do parsowania albo zarchiwizować. |

## Webhook HTTP

KSeFka wysyła pojedyncze żądanie `POST` na wskazany URL z nagłówkami:

- `Content-Type: application/json`
- `User-Agent: KSeFka/<wersja>`
- `X-KSeFka-Event-Type: invoice:received-from-sync`

Timeout wynosi **10 sekund**. Sukces to dowolny kod `2xx`; każdy inny status traktowany jest jako porażka i trafia do logów aplikacji (bez ponawiania — zdarzenie wykonuje się _fire-and-forget_).

### Konfiguracja

1. Otwórz **Ustawienia → Integracje**.
2. W polu **Webhook nowej faktury** wpisz URL endpointu (np. `https://n8n.example.com/webhook/...`).
3. Kliknij **Wyślij testowy event** — KSeFka wyśle syntetyczne zdarzenie z numerem `TEST-WEBHOOK-PING` i krótkim XML `<TestEvent>`, żebyś mógł zweryfikować odbiór bez czekania na prawdziwą fakturę.
4. Kliknij **Zapisz**.

Aby wyłączyć kanał — wyczyść pole URL i zapisz.

### Bezpieczeństwo

> [!WARNING]
> Payload zawiera dane fiskalne (XML faktury otrzymanej). Dla endpointów spoza sieci lokalnej używaj wyłącznie **HTTPS**.

KSeFka nie podpisuje payloadu HMAC. Jeśli odbiorca jest publiczny, dodaj sekret w samym URL (np. `https://n8n.example.com/webhook/abc123secret`) albo umieść endpoint za reverse-proxy z autoryzacją.

### Przykład: n8n

1. W n8n stwórz workflow z nodem **Webhook** (metoda `POST`, ścieżka dowolna).
2. Skopiuj **Production URL** i wklej go do **Ustawienia → Integracje → Webhook** w KSeFce.
3. W KSeFce kliknij **Wyślij testowy event** — w n8n zobaczysz pierwszy execution z payloadem.
4. Doklej dalsze nody (Slack, e-mail, baza danych) korzystając z pól `$json.invoice_id`, `$json.ksef_reference_number` itd.

## Event log (JSONL)

Format **JSONL** (zwany też NDJSON) to plik tekstowy, w którym każda linia jest osobnym, kompletnym obiektem JSON zakończonym znakiem `\n`. Idealny gdy nie chcesz utrzymywać serwera HTTP — wystarczy konsument typu `tail -f`, n8n _Read Binary File_ z `chokidar`, `fswatch` albo zwykły skrypt w cronie.

### Konfiguracja

1. Otwórz **Ustawienia → Integracje → Event log (plik JSONL)**.
2. Kliknij **Wybierz...** i wskaż plik (np. `~/Documents/ksefka-events.jsonl`). Plik zostanie utworzony automatycznie, ale **katalog musi istnieć**.
3. Zaznacz **Włącz zapis do pliku**.
4. Kliknij **Zapisz**.

Aktualny rozmiar pliku jest wyświetlany pod konfiguracją i odświeża się automatycznie co 5 sekund — szybki sygnał, że nowe zdarzenia rzeczywiście trafiają na dysk.

Przycisk **Wyczyść plik** obcina plik do zera bajtów (zachowuje sam plik i jego ścieżkę). Przydatne po testach lub gdy konsument przeczytał wszystko, co miał przeczytać.

### Format pliku

Każda linia to ten sam payload co w webhooku, zserializowany do JSON bez wcięć i zakończony pojedynczym `\n` (LF, również w Windows). XML faktury jest zapisany w polu `xml_content` jako string z escape'owanymi znakami nowej linii (`\\n`) — dzięki temu plik pozostaje **jedna linia = jedno zdarzenie** i każde narzędzie liniowe (`wc -l`, `head`, `jq -c`) działa poprawnie.

```
# przeczytaj na żywo
tail -F ~/Documents/ksefka-events.jsonl

# policz zdarzenia
wc -l ~/Documents/ksefka-events.jsonl

# wyłuskaj numery KSeF z ostatnich 10 zdarzeń
tail -n 10 ~/Documents/ksefka-events.jsonl | jq -r '.ksef_reference_number'

# zarchiwizuj XML każdej faktury osobno
jq -r '.ksef_reference_number + ".xml\t" + .xml_content' \
  ~/Documents/ksefka-events.jsonl
```

### Rotacja

KSeFka otwiera plik tylko na czas zapisu jednej linii (open → append → flush → close), więc bezpiecznie współpracuje z zewnętrzną rotacją (logrotate, ręczne `mv` + utworzenie nowego pliku). Aplikacja sama nie rotuje — duże logi przycinaj **Wyczyść plik** albo skryptem.

## Oba kanały jednocześnie

Webhook i event log są niezależne — możesz włączyć jeden, drugi albo oba. Każde zdarzenie jest kierowane do każdego skonfigurowanego kanału. Awaria jednego kanału (np. timeout webhooka) nie blokuje drugiego, a sama synchronizacja KSeF działa dalej w tle.

## Diagnostyka

### Pola w ustawieniach są wyłączone

Brakuje aktywnej licencji PRO. Sprawdź [Licencja PRO](https://ksefka.com/docs/licencja-pro).

### Webhook nie wysyła zdarzeń

- Najpierw kliknij **Wyślij testowy event** — to izoluje problem od synchronizacji.
- Sprawdź, czy URL zaczyna się od `http://` lub `https://` (przycisk testu jest aktywny tylko dla poprawnego URL).
- Błędy z odpowiedzi serwera (kody non-2xx, timeout, błąd DNS) lądują w logach aplikacji z dopiskiem `integrations: webhook POST...`.
- Pamiętaj, że webhook wysyłany jest tylko dla **nowych otrzymanych** faktur — edycja istniejącej albo ponowny sync tej samej faktury (deduplikacja) nie wywoła zdarzenia.

### Plik JSONL nie rośnie

- Sprawdź, czy **Włącz zapis do pliku** jest zaznaczone i czy konfiguracja została zapisana.
- Upewnij się, że **katalog** wskazany w ścieżce istnieje — aplikacja nie tworzy katalogów automatycznie i zwróci błąd "parent directory does not exist" w logach.
- Sprawdź uprawnienia zapisu do pliku (na macOS aplikacja może potrzebować zgody na dostęp do _Documents_ / _Desktop_ przy pierwszym zapisie).

## Powiązane

- [Synchronizacja KSeF](https://ksefka.com/docs/synchronizacja-ksef) — kiedy KSeFka pobiera nowe faktury otrzymane.
- [Licencja PRO](https://ksefka.com/docs/licencja-pro) — jak aktywować funkcje premium.
- [Integracja z AI](https://ksefka.com/docs/integracja-ai) — kanał równoległy, oparty o protokół MCP.
