Skip to content

Peppol BIS to KSeF FA(3)

This page describes how xTool maps Peppol BIS Billing 3.0 (UBL Invoice or Credit Note) to KSeF FA(3).

The conversion is one-way: Peppol → KSeF. The reverse path (KSeF → Peppol) exists separately and is not covered here.

Peppol BIS XML  →  xTool invoice model  →  KSeF FA(3) XML
Role Format code
Source invoice peppol_bis_billing.invoice.3_0.xml_ubl
Source credit note peppol_bis_billing.credit_note.3_0.xml_ubl
Target ksef_fa.invoice.3_0.xml

xTool first reads Peppol into the internal invoice model, then builds FA(3). The result is validated against the official FA(3) XSD.

To connect the organisation to KSeF before sending, see Connect to KSeF. To convert a file automatically, see Validate and convert and SFTP (+fa3 in the file name).


Invoices (type 380)

A Peppol commercial invoice (InvoiceTypeCode = 380) becomes a standard KSeF document with RodzajFaktury = VAT. Amounts are copied as they are — the sign is not changed.

Peppol BIS KSeF FA(3) Notes
Invoice number (BT-1) P_2 Unchanged
Issue date (BT-2) P_1 Unchanged
Tax point date (BT-7) / delivery date P_6 Delivery date if present, otherwise tax point date
Invoice period P_6_OD / P_6_DO Start and end
Currency (BT-5) KodWaluty e.g. PLN, EUR
Seller (BG-4) Podmiot1 NIP, name, address, contacts
Buyer (BG-7) Podmiot2 NIP / EU VAT / other ID
Delivery party (BG-13) Podmiot3 Role = 2 (Odbiorca)
Lines (BG-25) FaWiersz One FA(3) line per Peppol line
Tax breakdown P_13_x / P_14_x Taxable base and VAT per rate
Amount due (BT-115) P_15 Payable amount including VAT
Payment (BG-16) Platnosc Method, account, due date
Notes (BT-22) Stopka Joined note text
Purchase order (BT-13) WarunkiTransakcji Order number
Delivery address (BG-13) WarunkiTransakcji/Transport Ship-to address
Despatch advice (BT-16) WZ If present

Credit notes (type 381)

KSeF has no separate “negative invoice” type. A Peppol credit note (381) is either a correcting invoice (KOR) or a standard invoice (VAT) with negative net amounts.

KOR or VAT

The choice depends on a preceding invoice reference (BG-3):

Condition KSeF type Logic
Credit note has a real original invoice number KOR + DaneFaKorygowanej Correction with a link to the original
Credit note has no original invoice number VAT with negative net amounts KOR is not allowed without a required reference

Placeholder references are treated as missing: N/A, NA, -, none, null, or an empty string. That avoids a KOR document with no real original number.

DaneFaKorygowanej (corrected invoice)

For KOR only:

FA(3) field Source Description
DataWystFaKorygowanej Issue date of the preceding invoice Falls back to the credit note’s own issue date
NrFaKorygowanej Preceding invoice number Original invoice number
NrKSeFN Always 1 Original invoice was issued outside KSeF

NrKSeFN = 1 is always used for incoming Peppol credit notes: xTool does not have a KSeF number for the original, because it was issued via Peppol.

For the VAT fallback, DaneFaKorygowanej is omitted. PrzyczynaKorekty and TypKorekty are cleared — they are not valid on VAT.

Sign of amounts

KSeF expects a correction to be filled as the delta after the correction. For a reducing credit note the net delta is negative. xTool applies -abs() to line net, unit price, line discount, and document totals (including payable):

FA3_amount = -abs(Peppol_amount)
Sign in the Peppol credit note Result for net / price / payable
Positive (usual Peppol convention) Negative
Already negative (non-standard sender) Negative — not inverted again
Zero (e.g. a 0% line) Zero

Unconditional × -1 would turn an already-negative amount positive. -abs() prevents that.

This sign is applied to:

  • Lines (FaWiersz): P_11 (net), P_9A (unit price), P_10 (line discount, if present)
  • Header (Fa): P_13_x (taxable bases from lines), P_15 (payable)

VAT amounts are not inverted the same way. Document-level Peppol tax subtotals (TaxSubtotal) are copied into P_14_x as they are. Line P_11_VAT is then reconciled to that header VAT. With the usual Peppol convention (positive tax subtotals), P_14_x and the reconciled P_11_VAT stay positive, while net and payable are negative.

If a Peppol line has a negative quantity, xTool takes the absolute quantity and puts the sign on the unit price. KSeF expects a positive quantity and a negative price on credit notes.

Correction reason

Peppol BIS has no dedicated correction-reason or correction-type field in the xTool model. For KOR, xTool always sets PrzyczynaKorekty to Korekta faktury (required by the FA(3) schema). TypKorekty is not set.


Parties (Podmiot)

Podmiot1 (seller)

Field Source Notes
NIP Seller VAT ID or tax ID If missing, derived from Peppol endpoint scheme 9945
Name Seller name "-" if empty
Address Seller address Street, city, postcode, country
Contacts Email and phone If present
GLN Endpoint ID (scheme 0088) If present

Seller NIP is required. If xTool cannot resolve a 10-digit Polish NIP, conversion fails.

Podmiot2 (buyer)

Buyer identification is chosen in this order:

  1. Polish NIP (buyer VAT ID starts with PL, or a 10-digit tax ID)
  2. EU VAT (country code + number, for non-PL VAT IDs)
  3. Tax ID (country + number)
  4. Other party ID (country + number)
  5. Endpoint ID (scheme 9945 → PL NIP; other EU VAT schemes → EU VAT; remaining schemes → ID)
  6. Brak ID = 1 if nothing is found

Podmiot3 (delivery recipient)

Created when delivery data includes an address. Role = 2 (Odbiorca).


VAT rates

Peppol rate / code KSeF P_12 Header buckets
23% 23 P_13_1 / P_14_1 (standard)
22% 22 P_13_1 / P_14_1 (standard)
8% 8 P_13_2 / P_14_2 (reduced 1)
7% 7 P_13_2 / P_14_2 (reduced 1)
5% 5 P_13_3 / P_14_3 (reduced 2; FA(3) documents this bucket as currently 5%)
4% 4 Line P_12 only — not summed into header P_13_x / P_14_x
3% 3 Line P_12 only — not summed into header P_13_x / P_14_x
0%, code E / ZW zw P_13_7 (exempt)
0%, code AE / OO oo P_13_10 (reverse charge)
0%, any other code (including S, G, K, O) 0 KR P_13_6_1 (zero domestic)

An unsupported percent (for example 19%) fails conversion with an explicit error. A 0% line with a code other than E / ZW / AE / OO does not fail: it is written as 0 KR. Intra-community (K) and export (G) codes are not mapped to 0 WDT or 0 EX.

Line VAT (P_11_VAT) is always calculated as net × rate (skipped for codes E, AE, O). Header VAT (P_14_x) prefers document-level tax subtotals when those exist. If the sum of line VAT differs from the header breakdown, the residual is applied to the last line in that rate bucket.


Lines (FaWiersz)

Each Peppol line becomes one FaWiersz (or ZamowienieWiersz for advance invoices ZAL / KOR_ZAL):

FA(3) field Peppol source Description
P_6A Line period End date, otherwise start date
P_7 Item name Description if name is empty
P_8A Unit of measure UN/ECE code (e.g. C62); can be overridden by property unit_of_measure
P_8B Quantity Absolute value when the Peppol quantity was negative
P_9A Unit price Net; negative on credit notes
P_10 Line discount If present; negative on credit notes
P_11 Line net Negative on credit notes
P_11_VAT Line VAT Net × rate; then reconciled to header P_14_x (see VAT rates)
P_12 VAT rate code See the table above
PKWiU Classification Scheme PKWIU / PKWIUZ
CN CN code Scheme CN
PKOB PKOB Scheme PKOB
GTIN Standard item ID If present
Indeks Seller item ID If present

Payment (Platnosc)

The payment block is created when payment details or a due date are present.

FA(3) field Source Description
FormaPlatnosci Payment means code / name 6 if the code is 30, 31, 42 or 58, or the name contains transfer/SEPA/bank. 15 and 7 are matched on the name only (cash, card, voucher, cheque/check, credit, mobile/phone). Otherwise the field is omitted. Other UNECE codes (for example 10 cash, 48 card) are not mapped by code.
RachunekBankowy IBAN / account number + BIC Payee account
TerminPlatnosci Due date (BT-9) Date by which the invoice should be paid
Zaplacono Paid vs payable 1 if paid amount ≥ payable amount
DataZaplaty Due date Set when Zaplacono = 1

Currency and exchange rate

If the invoice is not in PLN:

  1. KodWaluty is set to the invoice currency.
  2. If an exchange rate is present, xTool fills KursWalutyZ and VAT amounts in PLN (P_14_1W, P_14_2W, P_14_3W).
  3. If there is no rate, a warning is logged and the PLN conversion fields stay empty (allowed by the XSD).

Extra descriptions (DodatkowyOpis)

Source Key Level
Sales order reference (BT-14) sales_order_reference Header
Other line properties Property name Line (with line number)

If a line property is named unit_of_measure, its value is written to P_8A and is not added as DodatkowyOpis.


Annotations (Adnotacje)

Filled with schema-safe defaults:

Field Default Override
P_16 2 (no)
P_17 2 (no) 1 for types 389 / 527
P_18 2 (no)
P_18A 2 (no)
Zwolnienie P_19N = 1 (no exemption) P_19 = 1, P_19A = <text> when an exemption reason is present (BT-6)
NoweSrodkiTransportu P_22_N = 1 (no)
P_23 2 (no)
PMarzy P_PMarzy_N = 1 (no)

Document notes (BT-22) are joined and written to Stopka/Informacje.


XSD validation

The converted XML is validated against FA(3). Checks include:

  • Element order in sequences
  • Required fields
  • Choices (for example NrKSeF / NrKSeFFaKorygowanej or NrKSeFN in DaneFaKorygowanej)
  • Data types (TKwotowy, TWybor1, TStawkaPodatku, TFormaPlatnosci)
  • String lengths

Validation errors stop the conversion with a detailed message.


Current limitations

Limitation Description
Document-level discounts/charges Not mapped to KSeF (a warning is logged)
Advance invoices (ZAL) ZamowienieWiersz structure exists; full advance logic is not implemented
4% / 3% header totals Written to line P_12; not accumulated in P_13_x / P_14_x
WDT / export 0% Peppol codes K / G become 0 KR, not 0 WDT / 0 EX
Credit-note header VAT P_14_x follows Peppol TaxSubtotal (not -abs()); line P_11_VAT is reconciled to it
VAT margin scheme Not supported (P_23 = 2)
New means of transport Not supported (P_22_N = 1)
Factoring Not supported (RachunekBankowyFaktora empty)
Authorised representative Not supported (PodmiotUpowazniony empty)

Invoice vs credit note

Aspect Invoice (380) Credit note (381) with reference Credit note (381) without reference
RodzajFaktury VAT KOR VAT
DaneFaKorygowanej No Yes (NrKSeFN = 1) No
PrzyczynaKorekty No Yes (always Korekta faktury) No
TypKorekty No No No
Sign of net / payable Unchanged Negative (-abs) Negative (-abs)
Sign of VAT (P_14_x) Unchanged As in Peppol TaxSubtotal As in Peppol TaxSubtotal
Lines FaWiersz FaWiersz FaWiersz
XSD validation Full Full Full

Next steps