Integracja z KSeF API 2.0 w Laravelu — uwierzytelnianie, wysyłka faktur i UPO od strony kodu
Jak wygląda integracja własnego systemu z Krajowym Systemem e-Faktur w wersji 2.0: środowiska, uwierzytelnianie tokenem i certyfikatem, szyfrowanie faktury, sesja interaktywna i wsadowa, pobieranie faktur zakupowych i tryby offline — z perspektywy aplikacji w Laravelu.
KSeF jest obowiązkowy dla większości firm od 2026 roku. Programy do fakturowania mają integrację gotową, ale firmy, które wystawiają faktury z własnego systemu — CRM-u, platformy sprzedażowej, systemu rozliczeń — muszą ją zbudować same. W tym tekście opisujemy, jak wygląda API KSeF 2.0 od strony kodu i jak podchodzimy do takiej integracji w Laravelu. Stan na koniec września 2026.
Terminy i najświeższe zmiany
Według Ministerstwa Finansów:
- od 1 lutego 2026 — wszyscy podatnicy odbierają faktury przez KSeF, a firmy ze sprzedażą powyżej 200 mln zł (z VAT) w 2024 roku także je wystawiają,
- od 1 kwietnia 2026 — wystawianie w KSeF obowiązuje pozostałych przedsiębiorców,
- od 1 stycznia 2027 — także najmniejsze firmy, ze sprzedażą do 10 tys. zł brutto miesięcznie.
We wrześniu 2026 pojawiły się dwie zapowiedzi, które wpływają na integracje: MF zapowiedziało, że uwierzytelnianie tokenem KSeF zostanie zachowane bezterminowo (pierwotnie tokeny miały działać tylko do końca 2026 roku), a okres bez kar za błędy ma zostać wydłużony do końca 2027. Obie zmiany w chwili pisania nie są jeszcze wprowadzone do przepisów — zanim oprzesz na nich architekturę, sprawdź aktualny stan.
Dokumentacja i środowiska
Oficjalna dokumentacja techniczna jest w repozytorium CIRFMF/ksef-api (razem ze specyfikacją OpenAPI i changelogiem). MF udostępnia trzy środowiska:
- TEST —
https://api-test.ksef.mf.gov.pl/v2, do rozwoju, z codzienną przerwą serwisową; nie wolno tam wysyłać prawdziwych danych, - DEMO —
https://api-demo.ksef.mf.gov.pl/v2, konfiguracja jak na produkcji, do testów przed startem, - PROD —
https://api.ksef.mf.gov.pl/v2.
MF publikuje referencyjne klienty w C# i Javie. Oficjalnego klienta PHP nie ma — najpopularniejszą biblioteką społeczności jest n1ebieski/ksef-php-client.
Uwierzytelnianie
Każda sesja zaczyna się od uwierzytelnienia w kontekście firmy (NIP):
POST /auth/challengezwraca wyzwanie ważne 10 minut.- Wyzwanie potwierdzasz na jeden z dwóch sposobów:
- podpisem XAdES dokumentu XML z wyzwaniem (
POST /auth/xades-signature) — podpisem kwalifikowanym, pieczęcią kwalifikowaną albo certyfikatem KSeF, który KSeF wystawia sam na podstawie CSR, - tokenem KSeF — szyfrujesz ciąg
token|znacznik czasukluczem publicznym MF (RSA-OAEP, SHA-256) i wysyłasz naPOST /auth/ksef-token.
- podpisem XAdES dokumentu XML z wyzwaniem (
- Status sprawdzasz przez
GET /auth/{referenceNumber}. POST /auth/token/redeemwymienia wynik na access token (JWT, ważny kilkanaście minut) i refresh token (do 7 dni), aPOST /auth/token/refreshodświeża access token.
W aplikacji przechowujemy token albo klucz prywatny certyfikatu jako sekret poza repozytorium, a access token w cache z czasem życia nieco krótszym niż exp z JWT. Tokeny KSeF mają przypisany zestaw uprawnień (np. tylko odczyt albo tylko wystawianie) — dla integracji warto założyć osobny token z minimalnymi uprawnieniami.
Szyfrowanie faktury
Faktury nie wysyła się otwartym tekstem. Dla każdej sesji generujesz losowy klucz AES-256 i wektor IV, szyfrujesz fakturę algorytmem AES-256-CBC z dopełnieniem PKCS#7, a sam klucz — kluczem publicznym MF algorytmem RSA-OAEP z SHA-256.
$key = random_bytes(32);
$iv = random_bytes(16);
$encryptedInvoice = openssl_encrypt($xml, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);Pułapka w PHP: openssl_public_encrypt() z OPENSSL_PKCS1_OAEP_PADDING używa SHA-1, a KSeF wymaga OAEP z SHA-256. Do szyfrowania klucza trzeba więc użyć biblioteki, która pozwala wybrać funkcję skrótu, np. phpseclib, albo gotowego klienta, który robi to za nas.
Wysyłka: sesja interaktywna i wsadowa
Sesja interaktywna
Dla bieżącego wystawiania pojedynczych faktur:
POST /sessions/online— otwarcie sesji z kodem formularza FA (3), zaszyfrowanym kluczem AES i IV; sesja trwa do 12 godzin.POST /sessions/online/{ref}/invoices— wysyłka faktury: skróty SHA-256 i rozmiary faktury przed i po zaszyfrowaniu oraz zaszyfrowana treść w Base64. Weryfikacja odbywa się asynchronicznie.POST /sessions/online/{ref}/close— zamknięcie sesji i wygenerowanie zbiorczego UPO.
Sesja wsadowa
Dla dużych wolumenów faktury pakuje się w ZIP, dzieli na części do 100 MB (przed szyfrowaniem), szyfruje każdą część i wysyła na adresy zwrócone przy otwarciu sesji (POST /sessions/batch).
Numer KSeF i UPO
Po przetworzeniu faktura dostaje numer KSeF, a do każdej można pobrać UPO — urzędowe poświadczenie odbioru. Stan sesji i faktur sprawdza się przez GET /sessions/{ref}/invoices, a faktury odrzucone przez GET /sessions/{ref}/invoices/failed. Numer KSeF i UPO zapisujemy przy fakturze w bazie — to one są dowodem, że faktura trafiła do systemu.
Pobieranie faktur zakupowych
Faktury od dostawców pobiera się, odpytując metadane jako nabywca (POST /invoices/query/metadata) albo zlecając asynchroniczny eksport paczki (POST /invoices/exports). Do regularnej synchronizacji dokumentacja zaleca pobieranie przyrostowe po dacie trwałego zapisu i sensowną częstotliwość — eksporty mają limity (rzędu kilkudziesięciu na godzinę) i zalecany odstęp między nimi.
Limity i obsługa błędów
API ma limity liczby żądań na kontekst i adres IP; po przekroczeniu zwraca HTTP 429 z nagłówkiem Retry-After. W Laravelu wysyłkę i pobieranie robimy w kolejkach:
- każda faktura to osobne zadanie z ponawianiem i opóźnieniem zgodnym z
Retry-After, - chwilowa niedostępność KSeF nie blokuje użytkowników — faktury czekają w kolejce,
- każde wywołanie API jest logowane z numerem referencyjnym, co ułatwia wyjaśnianie spornych przypadków z księgowością,
- faktury odrzucone trafiają na listę do obsłużenia przez człowieka z powiadomieniem.
Tryby offline i kody QR
Przepisy przewidują wystawianie faktur poza KSeF i dosłanie ich później: w trybie offline24 (do następnego dnia roboczego), przy niedostępności systemu i w trybie awaryjnym. Przy wysyłce oznacza się to polem offlineMode. Wizualizacja faktury ma kod QR prowadzący do weryfikacji w KSeF, a faktury offline dodatkowo drugi kod QR podpisany certyfikatem KSeF typu Offline. Szczegóły są w dokumentacji w repozytorium MF.
Jak to budujemy
Integrację piszemy jako moduł istniejącej aplikacji albo osobną usługę z własnym API, z którą rozmawia dowolny system. Całość najpierw przechodzi testy na środowisku TEST, potem na DEMO z konfiguracją produkcyjną, a dopiero potem przełączamy ją na produkcję. Więcej o zakresie takiego wdrożenia na stronie integracji KSeF z systemem firmy.
Podsumowanie
- Dokumentacja: repozytorium CIRFMF/ksef-api, środowiska TEST, DEMO i PROD.
- Uwierzytelnianie: wyzwanie, potem podpis XAdES albo token KSeF, na końcu access i refresh token.
- Szyfrowanie: AES-256-CBC dla faktury i RSA-OAEP z SHA-256 dla klucza — uważaj na domyślne SHA-1 w PHP.
- Wysyłka: sesja interaktywna dla bieżących faktur, wsadowa dla dużych wolumenów; numer KSeF i UPO zapisuj przy fakturze.
- Architektura: kolejki, ponawianie zgodne z limitami, logowanie i obsługa odrzuconych faktur.
- Zmiany: śledź zapowiedzi MF dotyczące tokenów i kar — we wrześniu 2026 nie były jeszcze w przepisach.
Potrzebujesz integracji KSeF w systemie, który fakturuje sam? Napisz do nas — zaczniemy od przeglądu tego, jak faktury powstają dziś.