XML Reference
FA(3) XML structure, namespace, element ordering, and KSeF validation rules.
Wersja: 1.0 | Data: 2026-03-14 | Namespace FA(3): http://crd.gov.pl/wzor/2025/06/25/13775/
Endpointy przyjmujące XML
1.1 POST /api/invoices/submit-raw-xml
Wysyłka pojedynczej faktury w formacie XML FA(3) bezpośrednio do KSeF.
| Parametr | Wartość |
|---|---|
| Auth | Bearer JWT |
| Content-Type | application/json |
| Środowisko demo | https://demo.ksefapi.com/api/invoices/submit-raw-xml |
| Środowisko prod | https://gateway.ksefapi.com/api/invoices/submit-raw-xml |
Request body:
{
"company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
"xml_content": "<?xml version='1.0' encoding='UTF-8'?><Faktura xmlns=\"http://crd.gov.pl/wzor/2025/06/25/13775/\">...</Faktura>"
}| Pole | Typ | Opis |
|---|---|---|
company_id | UUID | ID firmy (musi należeć do Twojego tenant) |
xml_content | string | Pełny XML FA(3), UTF-8. Klient odpowiada za poprawność XML |
Response (201):
{
"status": "submitted",
"invoice_id": "1d69f57c-3c5e-4928-840c-9920e787adcc",
"ksef_response": {
"referenceNumber": "20260314-EE-220FD3B000-D0580027F0-3D"
},
"xml_hash": "f5edddd131138c0cdb2876416e6ab878ffd99b21071b225462cd9a4ae7365123",
"xml_size": 1919
}Flow wewnętrzny:
Client → POST /api/invoices/submit-raw-xml
│
├─ Parse XML → wyciągnij P_2 (numer), P_1 (data), P_6 (data sprzedaży)
├─ Zapisz do DB (status: SENDING)
├─ Pobierz/utwórz sesję KSeF dla company_id
├─ Szyfruj XML: AES-256-CBC (klucz sesji z Vault)
├─ POST do KSeF: /sessions/online/{ref}/invoices
│ ├─ 200 OK → zapisz ksef_reference_number, start background polling
│ └─ 401 → unieważnij sesję, retry z nową
└─ Background: poll → SENDING → REGISTERED (lub FAILED)1.2 POST /api/invoices/submit-sync
Wysyłka faktury w formacie JSON — gateway automatycznie generuje XML FA(3).
| Parametr | Wartość |
|---|---|
| Auth | Bearer JWT |
| Content-Type | application/json |
| URL demo | https://demo.ksefapi.com/api/invoices/submit-sync |
Request body (JSON):
{
"company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
"invoice_type_code": "VAT",
"invoice_number": "FV/2026/03/001",
"invoice_date": "2026-03-14",
"sale_date": "2026-03-14",
"seller": {
"nip": "8133793363",
"name": "Bizneto Mirosław Dykiel",
"street": "Mieszka I 38",
"city": "Rzeszów",
"postal_code": "35-308",
"country": "PL"
},
"buyer": {
"nip": "8132952463",
"name": "Test Buyer Sp. z o.o.",
"street": "ul. Testowa 1",
"city": "Warszawa",
"postal_code": "00-001",
"country": "PL"
},
"items": [{
"position": 1,
"name": "Usługa integracji KSeF",
"quantity": "1",
"unit": "szt",
"unit_price": "5000.00",
"vat_rate": "23",
"net_amount": "5000.00",
"vat_amount": "1150.00",
"gross_amount": "6150.00"
}],
"summary": {
"net_total": "5000.00",
"vat_total": "1150.00",
"gross_total": "6150.00"
},
"tax_breakdowns": [{
"name": "PTU",
"category": "S",
"percent": "23",
"taxable_base": "5000.00",
"tax_amount": "1150.00"
}],
"currency": "PLN"
}Response (201):
{
"invoice_id": "698ac8e1-2355-4e08-bda1-b29054263fee",
"status": "sending",
"ksef_reference_number": "20260314-EE-21715A2000-D05678D784-5A",
"ksef_number": null,
"fingerprint": "a7bd1e6d37f5...",
"identifier": "https://ksef-demo.mf.gov.pl/client-app/invoice/...",
"qr_code": "iVBORw0KGgo...(base64 PNG)",
"xml_url": "/api/invoices/{id}/xml",
"qr_url": "/api/invoices/{id}/qr"
}1.3 POST /api/batch/queue-raw-xml
Wysyłka paczki do 100 faktur XML w jednym requeście. Faktury dzielone na chunki (100/chunk, max 3 jednocześnie).
Request body:
{
"company_id": "22919080-f3fe-4aff-8d71-f6493afc956a",
"invoices": [
{ "xml_content": "<?xml version=\"1.0\"?><Faktura ...>...</Faktura>" },
{ "xml_content": "<?xml version=\"1.0\"?><Faktura ...>...</Faktura>" },
{ "xml_content": "<?xml version=\"1.0\"?><Faktura ...>...</Faktura>" }
]
}Response (202):
{
"batch_id": "423e4567-e89b-12d3-a456-426614174003",
"status": "queued",
"total_invoices": 3,
"total_chunks": 1,
"items": [
{ "invoice_id": "aaa...", "invoice_number": "FV/2026/03/001", "status": "pending" },
{ "invoice_id": "bbb...", "invoice_number": "FV/2026/03/002", "status": "pending" },
{ "invoice_id": "ccc...", "invoice_number": "FV/2026/03/003", "status": "pending" }
]
}Powiązane endpointy batch:
| Endpoint | Opis |
|---|---|
GET /api/batch/batch/{batch_id} | Status batcha + chunk breakdown |
GET /api/batch/batch/{batch_id}/items?status=failed | Per-invoice results z filtrem |
POST /api/batch/batch/{batch_id}/retry-failed | Ponów failed faktury |
1.4 POST /api/invoices (async via Kafka)
Wysyłka JSON przez kolejkę Kafka (przetwarzanie asynchroniczne przez Worker).
Request body: identyczny jak submit-sync.
Response (202): zwraca invoice_id natychmiast, faktura przetwarzana w tle.
Endpointy odczytujące XML
| Endpoint | Metoda | Opis |
|---|---|---|
/api/invoices/{id}/xml | GET | XML FA(3) faktury z DB |
/api/invoices/{id}/qr | GET | Kod QR (PNG) z linkiem do KSeF |
/api/invoices/{id} | GET | Pełne dane faktury (JSON) |
/api/invoice-status/{id}/poll-status | POST | Poll statusu z KSeF (exponential backoff) |
/api/invoice-status/{id}/download-upo | POST | Pobierz UPO (Urzędowe Poświadczenie Odbioru) |
/api/companies/{id}/ksef/invoices/{ref}/xml | GET | Pobierz XML z KSeF po reference number |
Kody błędów
| HTTP | Przyczyna |
|---|---|
| 400 | Błąd parsowania XML / nieprawidłowe kodowanie |
| 400 | Sesja nie ma kluczy szyfrowania |
| 401 | Nieprawidłowy lub wygasły JWT |
| 403 | Brak dostępu do firmy |
| 4xx | Błąd API KSeF (przekazany z KSeF) |
| 503 | Circuit breaker KSeF otwarty (system niedostępny) |
Struktura XML FA(3) — Kompletna Referencja
4.1 Namespace i nagłówek
<?xml version="1.0" encoding="UTF-8"?>
<Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">UWAGA: Stary namespace
http://crd.gov.pl/wzor/2025/04/03/04031/powoduje odrzucenie przez KSeF. Zawsze używaj namespace z datą2025/06/25/13775/.
4.2 Sekcja Nagłówek
<Naglowek>
<KodFormularza kodSystemowy="FA (3)" wersjaSchemy="1-0E">FA</KodFormularza>
<WariantFormularza>3</WariantFormularza>
<DataWytworzeniaFa>2026-03-14T10:00:00Z</DataWytworzeniaFa>
<SystemInfo>KSeF API Gateway v1.0.0</SystemInfo> <!-- opcjonalne -->
</Naglowek>| Element | Wymagany | Opis |
|---|---|---|
KodFormularza | ✅ | Stała: FA, atrybuty: kodSystemowy="FA (3)", wersjaSchemy="1-0E" |
WariantFormularza | ✅ | Stała: 3 |
DataWytworzeniaFa | ✅ | ISO 8601: YYYY-MM-DDThh:mm:ssZ. Zakres: 2025-09-01 do 2050-01-01 |
SystemInfo | ❌ | Nazwa systemu generującego fakturę (max 256 znaków) |
4.3 Podmiot1 — Sprzedawca
<Podmiot1>
<DaneIdentyfikacyjne>
<NIP>8133793363</NIP>
<Nazwa>Bizneto Mirosław Dykiel</Nazwa>
</DaneIdentyfikacyjne>
<Adres>
<KodKraju>PL</KodKraju>
<AdresL1>Mieszka I 38</AdresL1> <!-- ulica + numer -->
<AdresL2>35-308 Rzeszów</AdresL2> <!-- kod + miasto (opcjonalne) -->
<GLN>5901234123457</GLN> <!-- Global Location Number (opcjonalne) -->
</Adres>
</Podmiot1>NIP sprzedawcy musi zgadzać się z NIP firmy zarejestrowanej w systemie (
company.nip).
4.4 Podmiot2 — Nabywca
<Podmiot2>
<DaneIdentyfikacyjne>
<NIP>8132952463</NIP>
<Nazwa>Test Buyer Sp. z o.o.</Nazwa>
</DaneIdentyfikacyjne>
<Adres>
<KodKraju>PL</KodKraju>
<AdresL1>ul. Testowa 1</AdresL1>
<AdresL2>00-001 Warszawa</AdresL2>
</Adres>
<JST>2</JST> <!-- 1=samorząd, 2=nie -->
<GV>2</GV> <!-- 1=jednostka rządowa, 2=nie -->
</Podmiot2>4.5 Sekcja Fa — Dane faktury
<Fa>
<KodWaluty>PLN</KodWaluty>
<P_1>2026-03-14</P_1> <!-- data wystawienia -->
<P_2>FV/2026/03/001</P_2> <!-- numer faktury -->
<P_6>2026-03-14</P_6> <!-- data sprzedaży/dostawy -->
<!-- Kwoty netto per stawka VAT -->
<P_13_1>5000.00</P_13_1> <!-- netto 23% -->
<P_14_1>1150.00</P_14_1> <!-- VAT 23% -->
<P_15>6150.00</P_15> <!-- brutto razem -->
<Adnotacje>
<P_16>2</P_16> <!-- metoda kasowa: 1=tak, 2=nie -->
<P_17>2</P_17> <!-- samofakturowanie: 1=tak, 2=nie -->
<P_18>2</P_18> <!-- odwrotne obciążenie: 1=tak, 2=nie -->
<P_18A>2</P_18A> <!-- mechanizm podzielonej płatności: 1=tak, 2=nie -->
<Zwolnienie><P_19N>1</P_19N></Zwolnienie> <!-- brak zwolnienia -->
<NoweSrodkiTransportu><P_22N>1</P_22N></NoweSrodkiTransportu> <!-- nie dotyczy -->
<P_23>2</P_23> <!-- faktura marża: 1=tak, 2=nie -->
<PMarzy><P_PMarzyN>1</P_PMarzyN></PMarzy> <!-- brak marży -->
</Adnotacje>
<RodzajFaktury>VAT</RodzajFaktury>
<!-- Pozycje faktury -->
<FaWiersz>
<NrWierszaFa>1</NrWierszaFa> <!-- numer wiersza -->
<P_7>Usługa integracji KSeF</P_7> <!-- nazwa towaru/usługi -->
<P_8A>szt</P_8A> <!-- jednostka miary -->
<P_8B>1</P_8B> <!-- ilość (opcjonalne) -->
<P_9A>5000.00</P_9A> <!-- cena jednostkowa netto -->
<P_11>5000.00</P_11> <!-- wartość netto -->
<P_11Vat>1150.00</P_11Vat> <!-- kwota VAT pozycji -->
<P_12>23</P_12> <!-- stawka VAT -->
</FaWiersz>
</Fa>4.6 Mapowanie stawek VAT → pola kwotowe
| Stawka | Pole netto | Pole VAT | Kategoria |
|---|---|---|---|
| 23% | P_13_1 | P_14_1 | S (Standard) |
| 8% | P_13_2 | P_14_2 | S |
| 5% | P_13_3 | P_14_3 | S |
| 0% (krajowe) | P_13_6 | — | Z (Zero) |
| zw (zwolnione) | P_13_7 | — | E (Exempt) |
| np (nie podlega) | P_13_9 | — | O/AE (Reverse charge) |
4.7 Typy faktur (RodzajFaktury)
| Kod | Opis |
|---|---|
VAT | Faktura VAT (standardowa) |
KOR | Faktura korygująca |
ZAL | Faktura zaliczkowa |
ROZ | Faktura rozliczeniowa (końcowa po zaliczce) |
UPR | Faktura uproszczona |
KOR_ZAL | Korekta do faktury zaliczkowej |
KOR_ROZ | Korekta do faktury rozliczeniowej |
4.8 Sekcja Adnotacje — wymagana (!)
UWAGA: Brak sekcji
<Adnotacje>powoduje odrzucenie faktury przez KSeF. Wszystkie pola w Adnotacjach są wymagane.
Dla standardowej faktury VAT bez szczególnych cech, użyj wartości domyślnych:
<Adnotacje>
<P_16>2</P_16> <!-- 2 = nie stosuje metody kasowej -->
<P_17>2</P_17> <!-- 2 = nie jest samofakturą -->
<P_18>2</P_18> <!-- 2 = nie jest odwrotnym obciążeniem -->
<P_18A>2</P_18A> <!-- 2 = nie wymaga split payment -->
<Zwolnienie><P_19N>1</P_19N></Zwolnienie>
<NoweSrodkiTransportu><P_22N>1</P_22N></NoweSrodkiTransportu>
<P_23>2</P_23> <!-- 2 = nie jest fakturą marżową -->
<PMarzy><P_PMarzyN>1</P_PMarzyN></PMarzy>
</Adnotacje>Częste błędy walidacji XML
| Problem | Przyczyna | Rozwiązanie |
|---|---|---|
| Odrzucenie bez wyraźnego błędu | Stary namespace | Zmień na 2025/06/25/13775/ |
Brak <Adnotacje> | Sekcja wymagana w FA(3) | Dodaj pełną sekcję z wartościami domyślnymi |
Pusty <Stopka/> | Pusty element niedozwolony | Usuń lub wypełnij treścią |
<FormaPlatnosci> błąd | Tekst zamiast kodu numerycznego | Użyj kodów: 1=gotówka, 2=przelew, 6=karta |
<DodatkowyOpis> malformed | Brak <Klucz> lub <Wartosc> | Oba elementy wymagane w parze |
| NIP sprzedawcy nie zgadza się | NIP w XML ≠ NIP firmy w systemie | Sprawdź NIP w Podmiot1 |
Statusy faktury
QUEUED → SENDING → REGISTERED (sukces)
→ FAILED (błąd)| Status | Opis | Finalne? |
|---|---|---|
queued | W kolejce Kafka, czeka na Worker | ❌ |
sending | Worker wysyła do KSeF | ❌ |
registered | Zarejestrowana w KSeF (ma ksef_number) | ✅ |
failed | Błąd przetwarzania (sprawdź error_message) | ✅ |
cancelled | Anulowana przed wysłaniem | ✅ |
Polling statusu
POST /api/invoice-status/{invoice_id}/poll-statusExponential backoff: 2s → 3s → 4.5s → ... max 60s. Automatyczny retry na 409, 429, 503.
Bulk polling (do 100 faktur jednocześnie):
POST /api/invoices/bulk-poll-status
{ "invoice_ids": ["uuid1", "uuid2", ...] }Wyniki testów (2026-03-14)
| Endpoint | Faktura | Status | KSeF Number | Czas |
|---|---|---|---|---|
submit-sync (JSON) | FV/TEST/2026/03/001 | ✅ registered | 8133793363-20260314-4B85A3000000-CE | ~18s |
submit-raw-xml (XML) | FV/RAW-XML/2026/03/001 | ✅ registered | 8133793363-20260314-4CCA28C00000-32 | ~12s |
Obie faktury zarejestrowane pomyślnie w KSeF demo, z poprawnymi QR code, fingerprint, UPO, i linkami do portalu KSeF.