Solidna integracja z KSeF: dlaczego większość wdrożeń zawodzi i jak zrobić to porządnie
KSeF to nie zwykłe wywołanie HTTP. To asynchroniczny, limitowany system państwowy, który potrafi nie działać. Jak zbudować integrację, która nie zgubi ani jednej faktury.
Od 1 lutego 2026 KSeF jest obowiązkowy dla dużych podatników VAT, od 1 kwietnia 2026 dla pozostałych. Rok 2026 to okres przejściowy — kary wchodzą w życie dopiero od 1 stycznia 2027. To właśnie ten termin ujawni różnicę między integracją, która „jakoś działa", a taką, która wytrzyma próbę czasu i kontrolę skarbową.
Większość wdrożeń KSeF, które widzimy, ma tę samą wadę: są fire-and-forget. Aplikacja wysyła fakturę w żądaniu HTTP i liczy na to, że się udało. Dopóki system państwowy odpowiada sprawnie, wszystko wygląda dobrze. Problem pojawia się pierwszego dnia, gdy KSeF zwróci błąd, timeout lub limit zapytań — i faktura po cichu znika. Nikt się o tym nie dowiaduje, dopóki nie przyjdzie kontrola.
Dlaczego KSeF jest trudniejszy, niż wygląda
KSeF nie jest zwykłym REST API. Ma cztery właściwości, które razem tworzą pułapkę:
- Jest asynchroniczny. Wysłanie faktury i otrzymanie potwierdzenia (UPO) to dwa odrębne momenty. Pomiędzy nimi musisz gdzieś przechowywać stan.
- Ma limity wywołań. Przy wysyłce wsadowej szybko natkniesz się na ograniczenia przepustowości. Bez kolejki i kontroli tempa blokujesz całą fakturację.
- Bywa niedostępny. Systemy państwowe mają awarie i okna serwisowe. Twoja fakturacja nie może z tego powodu padać.
- Ma własny model sesji. Sesje wygasają, tokeny tracą ważność, a zewnętrzne SDK dokładają do tego własne osobliwości.
Gdy system ma dwie lub więcej z tych cech, nie chodzi już o proste wywołanie API. Masz do czynienia z długotrwałym, stanowym workflowem — a to wymaga zupełnie innej architektury niż „wywołaj API w kontrolerze".
Jak to budujemy: durable, nie fire-and-forget
Kluczowa zasada: każde wywołanie KSeF to trwała, idempotentna, utrwalona jednostka pracy. Nigdy fire-and-forget, nigdy wewnątrz żądania HTTP. Oto filary, na których to stoi.
1. Idempotentne wysyłanie
Każda faktura otrzymuje deterministyczny klucz idempotencji. Gdy wysyłka zostanie ponowiona — a zostanie, przez mechanizm retry, restart procesu lub race condition — system rozpoznaje, że już to obsługiwał, i nie tworzy duplikatu w systemie państwowym. Bez idempotencji każdy retry to ryzyko duplikatu.
2. Retry z exponential backoff
Przejściowe błędy i timeouty to norma, nie wyjątek. Zamiast ręcznie pisanej pętli retry (którą zawsze ktoś implementuje błędnie) używamy mechanizmu z exponential backoff — sprawdzonego w boju rozwiązania, które ponawia próby z rosnącymi odstępami i nie zalewa API, gdy to już ma problemy.
3. Rate limiting jako stan współdzielony
Limity KSeF musisz respektować nawet wtedy, gdy działasz na wielu instancjach aplikacji. Licznik in-memory w jednym procesie nie wystarczy — potrzebujesz współdzielonego token bucket (typowo przez Redis), żeby instancje nie „kradły" sobie nawzajem kwoty.
4. Job reconciliacji
To element, który niemal każdy pomija — a jest najważniejszy. Cykliczny job zadaje pytanie: „czy rzeczywistość zgadza się z naszymi danymi?" Czy każda faktura ma potwierdzenie? Czy coś nie utkwiło w stanie pending? Czy nie ma sierot? Bez reconciliacji nie monitorujesz — tylko masz nadzieję.
5. Polling statusu i UPO
Wysłanie faktury to dopiero początek. Śledzimy status aż do UPO (Urzędowe Poświadczenie Odbioru) — oficjalnego potwierdzenia, że urząd przyjął fakturę. Dopiero UPO jest dowodem. Dopóki go nie masz, faktura nie jest gotowa.
6. Audit log i alerting
Każde przejście stanu generuje strukturyzowany event. Alerty uruchamiają się na błędach terminalnych i stanach zawieszonych — zanim staną się problemem podczas kontroli. Ciche LogWarning bez alertu to odłożony dług.
7. Anti-corruption layer
Opakowujemy SDK KSeF własną warstwą, żeby jego osobliwości — obce ciągi błędów, kody numeryczne, TTL sesji — nie przeciekały do twojej logiki biznesowej. Gdy SDK się zmienia, zmieniasz jedno miejsce, a nie cały kod.
Checklist: czy twoja integracja z KSeF jest solidna?
Przejdź przez to uczciwie:
- Czy wysyłanie faktury przeżyje restart aplikacji w połowie procesu?
- Co się stanie, gdy KSeF zwróci 500 lub timeout — czy znajdziesz tę fakturę?
- Czy masz dowód (UPO) dla każdej wysłanej faktury, czy tylko zakładasz, że przeszła?
- Czy istnieje job, który codziennie weryfikuje, że nic nie utknęło?
- Czy dostaniesz alert, gdy coś się zawiesi, czy dowiesz się o tym od księgowej?
Jeśli na którekolwiek pytanie odpowiedź brzmi „nie", masz integrację fire-and-forget. W okresie przejściowym to ujdzie. Od stycznia 2027 — już nie.
Zweryfikowane produkcyjnie
To nie są teorie ze slajdów. Dla TrafinOil podłączyliśmy fakturację do KSeF i podczas forensic recovery odtworzyliśmy 15 141 brakujących dokumentów, które poprzedni pipeline fire-and-forget po cichu utracił. Nocny dataloader skróciliśmy z 20 godzin do 30 minut. Retry, reconciliacja i monitoring działają na produkcji i pilnują, żeby się to nie powtórzyło.
Więcej o naszej usłudze integracji z KSeF.
Termin KSeF się zbliża. Jeśli masz to zrobić, zrób to tak, żeby nie padło w styczniu 2027. Napisz do nas — powiemy ci dokładnie, w którym miejscu twoja integracja jest narażona.