KSeF + n8n: jak wpiąć e-faktury do automatyzacji (konfiguracja krok po kroku)
Damian GębalaAutorKSeF wpięty w n8n to w praktyce kilka węzłów HTTP Request i jeden węzeł Code do szyfrowania. Ministerstwo Finansów udostępnia do tego gotowe API w wersji v2, więc nie piszesz własnego klienta, tylko konfigurujesz żądania. Poniżej pełna ścieżka: od uzyskania tokenu, przez wysłanie faktury, po odbiór UPO.
Nie ma gotowego węzła KSeF dla n8n. Ministerstwo udostępnia klienty referencyjne tylko dla C# i Javy, więc integrację buduje się na HTTP Request - i to naprawdę jest niewiele pracy, o ile wykroczysz poza środowisko testowe dopiero wtedy, gdy cały przepłyg działa.
Co dokładnie musisz wysłać do KSeF
KSeF to Krajowy System e-Faktur, czyli miejsce, w którym faktura przestaje być plikiem, a staje się wpisem w systemie podatkowym. Od 1 lutego 2026 r. obowiązuje struktura logiczna FA(3), a od 1 kwietnia 2026 r. system jest obowiązkowy dla pozostałych przedsiębiorców.
Technicznie faktura to plik XML zgodny ze strukturą FA(3), opublikowaną na ePUAP. System go nie zapisze, jeśli któreś wymagane pole będzie puste - zamiast tego zwraca błąd walidacji. NIP sprzedawcy jest obowiązkowy: bez niego faktura nie zostanie przyjęta w ogóle.
Tu ważna rzecz o samym API: dokument leci do systemu zaszyfrowany. Nie wysyłasz czystego XML-a. Wysyłasz zaszyfrowaną treść wraz z zaszyfrowanym hashem i rozmiarem, a system to odszyfrowuje u siebie. Dlatego w n8n nie wystarczy sam węzeł HTTP Request - potrzebujesz jeszcze szyfrowania, czyli węzła Code.
Trzy środowiska, zacznij od testowego
API ma adres bazowy https://api.ksef.mf.gov.pl/v2 dla produkcji. Wersja w dokumentacji to OpenAPI 3.0.4, a sama dokumentacja API KSeF 2.0 została opublikowana 30 czerwca 2025 r.
Oprócz produkcji istnieją dwa środowiska przedprodukcyjne. Testowe jest dostępne pod ksef-test.mf.gov.pl, a dokumentację w wersji testowej znajdziesz pod adresem api-test.ksef.mf.gov.pl/docs/v2. Środowisko demonstracyjne siedzi pod api-demo.ksef.mf.gov.pl. Na środowisku integracyjnym obowiązuje zasada, że dane mają być zanonimizowane, a demo i produkcja pracują już na rzeczywistych danych uwierzytelniających zgodnych z rejestrem właścicieli firm.
Konfiguruję to w n8n przez zmienne środowiskowe, nie na sztywno. Jeden parametr w kodzie workflow, nie jedna litera zmieniona w dwóch miejscach:
KSEF_BASE_URL=https://api-test.ksef.mf.gov.pl/v2
KSEF_CONTEXT_TYPE=Nip
KSEF_CONTEXT_VALUE=0000000000
KSEF_TOKEN=
Przełączenie na produkcję to potem zmiana pierwszej linii. Nic więcej.
Zmienne środowiskowe obsługuje w n8n każdy przepływ. Jeśli dopiero zaczynasz pracę z tym narzędziem, pierwsza automatyzacja w n8n krok po kroku prowadzi Cię od węzła do węzła, bez skrótów.
Krok 1: uwierzytelnienie, czyli zdobycie tokenu
Cała reszta API chroni się jednym mechanizmem: nagłówkiem z tokenem w formacie Bearer. W n8n konfigurujesz to jako Credentials typu Generic, w sekcji Header Auth - nazwa nagłówka Authorization, wartość Bearer plus wygenerowany token. Dokumentacja n8n podaje, że do integracji nieobsługiwanych gotowym węzłem używa się właśnie generic credentials z ręcznie ustawioną metodą autoryzacji.
Sama autoryzacja ma trzy ścieżki startowe, a dla wtyczki i dla skryptu w firmie właściwa jest ta druga:
POST /auth/challenge- generuje jednorazowy challenge wymagany w kolejnym kroku uwierzytelniania.POST /auth/ksef-token- właściwa ścieżka dla integracji programowej.POST /auth/xades-signature- podpis elektroniczny XAdES, czyli wariant dla ludzi, nie dla automatyzacji.
W ścieżce programowej bierzesz challenge, dokładasz do niego token KSeF i znacznik czasu w taki sposób, żeby wyszła para token|timestamp, a całość szyfrujesz kluczem publicznym Ministerstwa Finansów. Algorytm to RSA-OAEP z SHA-256 jako funkcją skrótu, a znacznik czasu podajesz jako liczbę milisekund od 1 stycznia 1970 roku. W zapytaniu idą wtedy trzy pola: challenge, contextIdentifier i encryptedToken. Kontekst wskazuje, w czyim imieniu działasz - numer NIP albo Twój wewnętrzny identyfikator podmiotu.
To jest jedyny fragment, w którym potrzebujesz kryptografii poza n8n. Reszta to zwykłe wywołania HTTP.
Krok 2: wymiana na parę tokenów
Po uwierzytelnieniu status operacji sprawdzasz przez GET /auth/{referenceNumber}, a wynik odbierasz w POST /auth/token/redeem. Dostajesz parę access token i refresh token, a kluczowe jest jedno zdanie z dokumentacji: tokeny można pobrać tylko raz.
Ten zapis oznacza konkrety w automatyzacji. Jeśli workflow przerwie się między redeemem a zapisem tokena, trzeba zaczynać od nowa. Dlatego zapisuję token w Credentials n8n zaraz po otrzymaniu, a nie na końcu przepływu.
Odświeżenie idzie osobnym wywołaniem POST /auth/token/refresh. Warto wiedzieć, że publiczna specyfikacja nie podaje wprost, ile godzin ważny jest access token - są za to pola refreshTokenValidUntil i lastTokenRefreshDate w odpowiedzi. Licz z odpowiedzi, nie z domysłów. Unieważnienie sesji przez DELETE /auth/sessions/current nie zabija od razu aktywnych access tokenów: działają do czasu minięcia terminu ważności, unieważniony zostaje refresh token.
Krok 3: otwarcie sesji online
Faktur w KSeF nie wysyła się pojedynczo. Najpierw otwierasz sesję, w niej wysyłasz dokumenty, a na końcu ją zamykasz. W wariancie online, przeznaczonym dla pojedynczych faktur, są trzy wywołania:
POST /sessions/online- otwarcie sesji, podajesz schemat wysyłanych faktur i informacje o kluczu szyfrowania.POST /sessions/online/{referenceNumber}/invoices- zaszyfrowana faktura wraz z metadanymi, od tej chwili system ją przetwarza.POST /sessions/online/{referenceNumber}/close- zamknięcie sesji i wygenerowanie zbiorczego UPO.
Ciało żądania otwierającego wymaga dwóch pól: schematu faktury oraz parametrów szyfrowania. Sama faktura idzie jako pięć pól obowiązkowych: zaszyfrowana treść, zaszyfrowany hash, zaszyfrowany rozmiar, a do tego niezaszyfrowany hash i rozmiar, po których system sprawdza integralność.
W węźle HTTP Request wybierasz metodę POST, w JSON ustawiasz pola, a w zakładce z opcjami włączasz zwracanie nagłówków i kodu odpowiedzi. Bez tej ostatniej opcji węzeł zwraca wyłącznie treść odpowiedzi, a przy błędzie KSeF zostajesz bez informacji, o co chodziło.
Jeśli faktur jest dużo, użyj wariantu wsadowego: POST /sessions/batch i POST /sessions/batch/{referenceNumber}/close. Przy czym w body sesji wsadowej dochodzi pole z plikiem paczki, więc nie jest to zamiana jednego słowa w adresie.
Krok 4: potwierdzenie, że faktura naprawdę weszła
Najczęstszy błąd przy wdrożeniach KSeF to uznanie wysłania za sukces. Wysłanie to dopiero początek. Stan fakty sprawdzisz w trzech miejscach:
GET /sessions/{referenceNumber}/invoices/failed- lista faktur niepoprawnie przetworzonych, z powodem odrzucenia.GET /sessions/{referenceNumber}/invoices- lista faktur w sesji wraz ze statusami.GET /invoices/ksef/{ksefNumber}- pojedyncza faktura po numerze KSeF, wymaga uprawnienia InvoiceRead.
UPO, czyli potwierdzenie odbioru, pobierasz osobnymi ścieżkami - zbiorcze dla sesji albo pojedyncze dla faktury. UPO to numer, który wstawiasz do swojego systemu, bo dopiero on łączy Twoją fakturę z systemem podatkowym. Bez zapisanego numeru KSeF i UPO nie masz dowodu, że faktura gdzieś poszła.
Skoro KSeF nie wystawia webhooka z numerem nadanej faktury, w n8n zostaje Ci cykliczne odpytywanie. W praktyce ustawiam węzeł Schedule Trigger z interwałem dopasowanym do Twojego wolumenu i za każdym razem sprawdzam listę faktur w sesji.
Druga strona KSeF: odbieranie faktur zakupowych
Wystawianie to połowa pracy. Druga połowa to dostarczanie faktur od dostawców do Twojego systemu, a to robi się eksportem, nie pojedynczymi odczytami. POST /invoices/exports uruchamia asynchroniczne wyszukiwanie faktur i przygotowuje z nich zaszyfrowaną paczkę, a GET /invoices/exports/{referenceNumber} służy do odbierania statusu tej paczki.
Tu obowiązują limity, o których trzeba wiedzieć przed projektem. W zalogowanym kontekście można uruchomić maksymalnie 10 równoczesnych eksportów. Jedna paczka to 10 tysięcy faktur albo 1 GB danych skompresowanych, a system dzieli ją na części po 50 MB, każdą szyfrowaną algorytmem AES-256-CBC z dopełnieniem PKCS#7. Do samego wyszukiwania służy POST /invoices/query/metadata, który zwraca metadane faktur pasujących do filtrów, z limitem 10 tys. rekordów na zestaw filtrów.
W n8n wygląda to jako wyzwalacz cykliczny, wywołanie eksportu i gałąź, która czeka na status. Efekt biznesowy jest prosty: faktury od dostawców trafiają do Twojego arkusza lub systemu bez klikania, a nie musisz osobno ściągać każdej z ewidencji. Warto przy tym pamiętać, że w KSeF faktura jest archiwizowana przez 10 lat, a zwrot VAT ma szansę przyjść w 40 dni zamiast 60.
Gdy fakturuje za Ciebie ktoś inny
Część integracji nie wystawia faktur własnych, tylko w imieniu klienta, na przykład automatyzacja w sklepie, która generuje dokument po płatności. Do tego KSeF ma osobny mechanizm uprawnień, oparty na kilkunastu endpointach /permissions, między innymi do nadawania uprawnień podmiotom, osobom i podmiotom pośrednim.
Uprawnienia są granularne, co w tym przypadku jest zaletą: InvoiceRead daje dostęp do odczytu faktur, InvoiceWrite do ich wystawiania, a CredentialsRead i CredentialsManage do zarządzania tokenami. Nie da się nadać uprawnienia do odczytu, nie dając przy okazji możliwości wystawiania faktur, a to dokładnie ta granica, którą chcesz mieć, gdy integrację pisze osoba z zewnątrz. Osobno działa GET /permissions/attachments/status, które mówi, czy dany kontekst w ogóle może wystawiać faktury z załącznikiem.
Alternatywą dla tokenów są certyfikaty KSeF. Certyfikat typu 1 jest jedną z metod uwierzytelnienia w systemie i pasuje do integracji, w których nie chcesz trzymać sekretu w zmiennej środowiskowej. Wniosek składasz przez POST /certificates/enrollments, a status wniosku sprawdzasz pod GET /certificates/enrollments/{referenceNumber}, przy czym jest dostępny przez 30 dni. Limity odczytasz z GET /certificates/limits. Obsługa certyfikatów działa tylko w API KSeF 2.0, w wersji 1.0 jej nie było.
Błędy, limity i retry
KSeF zwraca błędy w formacie Problem Details, ale tylko jeśli wyślesz nagłówek X-Error-Format: problem-details. Wtedy odpowiedź wraca jako application/problem+json i zawiera konkretny powód odrzucenia, zamiast ogólnego komunikatu o błędzie.
Limity, które musisz znać przed produkcją:
- 10 żądań na sekundę, 30 na minutę i 120 na godzinę w grupie zapytań ogólnych.
- 10 tysięcy rekordów na zestaw filtrów w zapytaniu o metadane. Po przekroczeniu limitu odpowiedź dostaje znacznik
isTruncated= true i trzeba zawęzić zakres dat oraz wyzerowaćpageOffset. - Maksymalnie 10 równoczesnych eksportów w zalogowanym kontekście.
- Paczka faktur dzielona na części po 50 MB, każda szyfrowana algorytmem AES-256-CBC z dopełnieniem PKCS#7. Eksport to 10 tysięcy faktur albo 1 GB danych skompresowanych.
Po stronie n8n dwa węzły robią tu robotę za Ciebie. W opcjach HTTP Request włączasz batching, gdzie podajesz liczbę elementów na paczkę i interwał między nimi w milisekundach. Do limitów przepływu sięga węzeł Handle rate limits, który przy 429 potrafi rozłożyć żądania w czasie zamiast wypychać je w kółko. W ustawieniach node'a ustawiasz też timeout w milisekundach, bo bez niego żądanie do KSeF wisi tak długo, jak mu system na to pozwoli.
Dodatkowo ustawiam w workflow ścieżkę błędu: gdy kod odpowiedzi nie jest 2xx, węzeł HTTP Request zatrzymuje przepływ, a osobna gałąź zapisuje treść błędu i numer sesji, żeby dało się to odtworzyć bez zgadywania.
Terminy, których nie da się obejść konfiguracją
Część wdrożenia KSeF to terminologia, nie kod. Warto mieć ją w głowie, bo to ona decyduje, kiedy automatyzacja musi być gotowa:
- 1 lutego 2026 r. - KSeF 2.0 dla podmiotów, które w 2024 r. miały sprzedaż powyżej 200 mln zł z VAT. Od tej samej daty obowiązuje struktura FA(3).
- 1 kwietnia 2026 r. - obowiązek dla pozostałych przedsiębiorców, z wyjątkiem najmniejszych firm, których łączna sprzedaż fakturowana nie przekracza 10 tys. zł miesięcznie.
- Do 31 grudnia 2026 r. - te najmniejsze firmy nadal mogą wystawiać faktury poza KSeF, o ile suma sprzedaży z VAT na takich fakturach w danym miesiącu nie przekroczy 10 tys. zł.
- 1 stycznia 2027 r. - KSeF obowiązkowy dla wszystkich, w tym dla wcześniej zwolnionych. Kary za błędy w KSeF zostały odroczone do tej samej daty.
W praktyce system daje też dwa tryby przepisowe. Tryb offline24 wymaga przesłania faktur do systemu najpóźniej następnego dnia roboczego, a tryb awaryjny daje siedem dni roboczych od zakończenia awarii KSeF. Warto je zapisać w konfiguracji, bo to one decydują, jak agresywny musi być retry w n8n.
Jedna rzecz, o której mniej się mówi: tokeny wygenerowane w KSeF 1.0 nie są kompatybilne z 2.0, a generowanie tokenów zostało udostępnione 1 lutego 2026 r. Jeśli przenosisz integrację ze starego API, to nie jest kwestia podmiany adresu.
Kiedy nie warto tego budować samemu
Nie dla każdej firmy własna integracja ma sens. Jeśli wystawiasz kilkaset faktur miesięcznie i masz gotowy system, który ma już integrację z KSeF, wdrożenie własnego przepływu to szkoda kilku dni pracy i jednego dodatkego kodu, który musisz utrzymywać przy każdej zmianie API. KSeF 2.0 wchodzi w etapy i API będzie się zmieniać.
Własne wpięcie ma sens wtedy, gdy faktury powstają w miejscu, do którego gotowa wtyczka nie sięga - na przykład przy zamówieniu z nietypowego sklepu albo w procesie, który sam sobie generujesz. Wtedy parametryzacja w n8n, sesje online i walidacja przed wysyłką robią swoją robotę. Tak zrobiłem integrację, w której faktura powstaje dopiero po zakończeniu płatności, i w której walidacja schematu działa przed wysłaniem, a nie po odrzuceniu.
Jeśli dopiero rozważasz automatyzację, zacznij od prostszego: siedmiu procesów, które warto zautomatyzować w pierwszej kolejności albo od integracji sklepu z księgowością. KSeF dokłada się potem, jako jeden przepływ w istniejącym procesie.
Zanim w to wejdziesz, zmapuj procesy w firmie i sprawdź, czy fakturowanie naprawdę jest wąskim gardłem, a nie etap, który zakłada zespół.
Jeśli zaczynasz dopiero teraz, sensowna kolejność wygląda tak: najpierw zrób to na środowisku testowym, potem cały przepłyg na jednej fakturze produkcyjnej, i dopiero na końcu włącz automatyczne wysyłanie dla całego wolumenu. Odwrotna kolejność kosztuje więcej niż cała reszta wdrożenia.
Co sprawdzić przed włączeniem produkcji
- Token zapisany w Credentials, nie w kodzie przepływu, i odświeżany przed wygaśnięciem.
- Sesja otwierana i zamykana w jednym przebiegu, z wywołaniem close także przy błędzie.
- Sprawdzenie listy failed faktur po każdej sesji, nie tylko na koniec dnia.
- Numer KSeF i UPO zapisane w Twoim systemie, a nie tylko w logu n8n.
- Batching włączony, żeby zmieścić się w limicie 10 żądań na sekundę.
- Retry na 429, a nie na wszystkie błędy naraz.
KSeF + n8n to połączenie, które działa, bo API jest udokumentowane i stabilne, a n8n daje Ci węzły HTTP, szyfrowanie, harmonogram i obsługę błędów w jednym miejscu. Nie ma w tym żadnej magii, jest za to sporo roboty, którą da się zrobić raz i zapomnieć. Napisz do mnie, jeśli chcesz to przejść ze swoim procesem fakturotwórczym - odpowiadam zwykle tego samego dnia.