← Blog
API6 min czytania

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):

  1. POST /auth/challenge zwraca wyzwanie ważne 10 minut.
  2. 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 czasu kluczem publicznym MF (RSA-OAEP, SHA-256) i wysyłasz na POST /auth/ksef-token.
  3. Status sprawdzasz przez GET /auth/{referenceNumber}.
  4. POST /auth/token/redeem wymienia wynik na access token (JWT, ważny kilkanaście minut) i refresh token (do 7 dni), a POST /auth/token/refresh odś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:

  1. POST /sessions/online — otwarcie sesji z kodem formularza FA (3), zaszyfrowanym kluczem AES i IV; sesja trwa do 12 godzin.
  2. 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.
  3. 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ś.