Przykład integracji z API KSeF krok po kroku – od danych faktury do numeru KSeF i UPO
W poprzednim artykule opisaliśmy, jak wygląda integracja z API KSeF od strony architektury — ten wpis jest jego praktycznym uzupełnieniem. Zamiast ogólnego omówienia procesu, przechodzimy przez konkretny, działający przykład: od pojedynczej transakcji sprzedaży, przez przygotowanie danych, po odebranie numeru KSeF i UPO. Całość na przykładzie API KSeFService — środowisko TEST, gotowy kod PHP, realistyczne dane wejściowe.
Scenariusz
Załóżmy prosty, ale realistyczny przypadek: firma sprzedała usługę konsultingową kontrahentowi firmowemu. Mamy dane transakcji w naszym systemie (np. w tabeli zamówień) i chcemy automatycznie wystawić z nich fakturę w KSeF. To dokładnie ten sam scenariusz, który powtarza się przy każdej integracji sklepu, ERP czy systemu fakturującego — zmieniają się tylko źródła danych.
Krok 1 — dane wejściowe
Zanim cokolwiek wyślemy, musimy mieć komplet danych po stronie naszego systemu:
$order = [
'seller' => [
'nip' => '1234567890',
'name' => 'Moja Firma Sp. z o.o.',
'address' => 'ul. Testowa 1, 00-001 Warszawa',
],
'buyer' => [
'nip' => '9876543210',
'name' => 'Kontrahent Sp. z o.o.',
'address' => 'ul. Przykładowa 5, 00-002 Warszawa',
],
'items' => [
[
'name' => 'Usługa konsultingowa',
'quantity' => 1,
'net_price' => 2000.00,
'vat_rate' => 23,
],
],
'payment_method' => 'przelew',
'issue_date' => date('Y-m-d'),
];
To dane, jakie realnie miałbyś np. w tabeli zamówień sklepu albo w rekordzie faktury z systemu księgowego — nic w tym momencie nie jest jeszcze związane z formatem KSeF.
Krok 2 — dane dostępowe do API
Do wysyłki potrzebujemy danych logowania do konta KSeFService oraz wskazania środowiska. Na etapie developmentu i testów zawsze używamy środowiska TEST — nigdy produkcyjnego:
$clientId = 'TWOJ_CLIENT_ID';
$login = 'twoj_login';
$password = 'twoje_haslo';
$apiEnv = 'TEST'; // TEST | DEMO | PROD
Krok 3 — przygotowanie faktury FA(3)
Zamiast ręcznie budować cały XML zgodny ze schematem FA(3) (co wymaga dokładnej znajomości struktury i kolejności elementów), korzystamy z endpointu, który przyjmuje dane w prostszym, ustrukturyzowanym formacie i sam generuje poprawny dokument:
$payload = [
'clientId' => $clientId,
'login' => $login,
'password' => $password,
'api_env' => $apiEnv,
'seller' => $order['seller'],
'buyer' => $order['buyer'],
'items' => $order['items'],
'payment_method' => $order['payment_method'],
'issue_date' => $order['issue_date'],
];
$ch = curl_init('https://ksefservice.pl/api/v1/invoices/fa3');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$ch = null;
$result = json_decode($response, true);
$xmlContent = $result['data']['xml'] ?? null;
Na tym etapie otrzymujemy gotowy dokument XML zgodny ze schematem FA(3) — możemy go zwalidować, zapisać do archiwum lub od razu przekazać do wysyłki.
Krok 4 — wysyłka do KSeF
Dokument trafia do endpointu odpowiedzialnego za komunikację z Krajowym Systemem e-Faktur:
$tmpFile = tempnam(sys_get_temp_dir(), 'fa3_') . '.xml';
file_put_contents($tmpFile, $xmlContent);
$file = new CURLFile($tmpFile, 'application/xml', 'invoice_FA3.xml');
$postFields = [
'clientId' => $clientId,
'login' => $login,
'password' => $password,
'api_env' => $apiEnv,
'file' => $file,
];
$ch = curl_init('https://ksefservice.pl/api/v1/invoices/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postFields,
CURLOPT_RETURNTRANSFER => true,
]);
$sendResponse = curl_exec($ch);
$ch = null;
unlink($tmpFile);
Krok 5 — odczyt odpowiedzi
Odpowiedź zawiera informację o statusie przetworzenia oraz, przy powodzeniu, numer KSeF:
{
"success": true,
"stage": "ksef_ok",
"data": {
"ksefNumber": "5771876968-20251209-0100805B192F-B3",
"sessionReference": "20251209-SO-178C9DF000-9498D48B5B-BB"
}
}
W kodzie odczytujemy i zapisujemy te wartości w naszym systemie źródłowym — to one są dowodem, że faktura trafiła do KSeF, i to je trzeba przypisać do rekordu zamówienia czy faktury w bazie danych:
$sendResult = json_decode($sendResponse, true);
if ($sendResult['success'] ?? false) {
$ksefNumber = $sendResult['data']['ksefNumber'];
$sessionRef = $sendResult['data']['sessionReference'];
// zapis $ksefNumber i $sessionRef w tabeli zamówień/faktur
} else {
// obsługa błędu — zapisanie treści odpowiedzi do logu
}
Krok 6 — pobranie UPO
Numer KSeF potwierdza nadanie identyfikatora, ale to Urzędowe Poświadczenie Odbioru (UPO) jest formalnym dowodem doręczenia faktury do systemu. Pobieramy je osobnym żądaniem, na podstawie numeru referencyjnego sesji:
$upoPayload = [
'clientId' => $clientId,
'login' => $login,
'password' => $password,
'api_env' => $apiEnv,
'sessionReference' => $sessionRef,
'ksefNumber' => $ksefNumber,
];
$ch = curl_init('https://ksefservice.pl/api/v1/invoices/upo');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($upoPayload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
]);
$upoResponse = curl_exec($ch);
$ch = null;
// zapis UPO (XML) do archiwum, powiązany z numerem KSeF
Pobrane UPO warto zarchiwizować razem z oryginalnym dokumentem faktury — to ono, a nie sam fakt wysłania żądania, jest dowodem zgodności z obowiązkiem prawnym.
Cały proces w skrócie
- Zbierz dane transakcji w swoim systemie (zamówienie, faktura, dokument sprzedaży).
- Wygeneruj dokument FA(3) na podstawie tych danych.
- Wyślij dokument do KSeF.
- Odczytaj numer KSeF ze odpowiedzi i zapisz go w swoim systemie.
- Pobierz UPO i zarchiwizuj je razem z fakturą.
Każdy z tych kroków, mimo że tutaj pokazany osobno dla przejrzystości, w produkcyjnej integracji zwykle łączy się w jeden spójny proces uruchamiany automatycznie po zdarzeniu biznesowym (np. zmianie statusu zamówienia na „opłacone").
Co dalej po tym przykładzie
- Dodaj obsługę błędów — sprawdzaj pole
successi loguj pełną treść odpowiedzi przy niepowodzeniu. - Zaimplementuj retry dla błędów przejściowych (5xx), zanim uznasz wysyłkę za nieudaną.
- Przetestuj cały proces na środowisku
TEST, zanim przełączyszapi_envnaPROD. - Jeśli integrujesz się z konkretną platformą (sklep, ERP), sprawdź gotowe przykłady dla PHP, Node.js, .NET, Java, React i Angular.
Podsumowanie
Powyższy przykład pokazuje pełny cykl integracji z API KSeF na konkretnych, działających danych — od transakcji w Twoim systemie, przez wygenerowanie faktury FA(3), po numer KSeF i UPO. To ten sam schemat, który powtarza się w każdej integracji, niezależnie od tego, czy źródłem danych jest sklep internetowy, ERP czy własny system fakturujący.
Chcesz przetestować ten przykład na własnym koncie? Skontaktuj się z nami, żeby uzyskać dostęp do środowiska TEST, lub sprawdź pełną dokumentację API z przykładami.