FinchContext
Run with

Convert an Invoice into KSeF FA(2) XML

Skill: Convert a source invoice (PDF, CSV, or JSON) into upload-ready KSeF FA(2) XML

Region: Poland (Polska) Category: KSeF — Krajowy System e-Faktur Does: Reads a source invoice — a PDF, a CSV/JSON export, or pasted text — extracts the invoice data, and emits a valid FA(2) XML document ready to send to KSeF. Schema version: FA(2), wersjaSchemy="1-0E"

This is a conversion task: input = an existing invoice, output = FA(2) XML. The schema tables further down are the mapping target. Always validate the emitted XML against the official FA(2) XSD before sending; field codes and the VAT-summary suffix mapping change between revisions — confirm against the current Ministerstwo Finansów publication.


Conversion procedure

Follow these steps in order. Steps 1–2 get the data out of the source; steps 3–6 build and check the XML.

  1. Read the source.
    • PDF → extract the text layer (e.g. pdftotext -layout invoice.pdf -). If the PDF is a scan with no text layer, OCR it first, then treat the result as text. Read tables column-by-column so line items stay aligned.
    • CSV / JSON → parse directly.
    • Pasted text → work from it as-is.
  2. Extract these fields from the source (see the Source → FA(2) map below for where each one lands): seller NIP/name/address, buyer NIP/name/address, invoice number, issue date, sale date (if shown), currency, every line item (description, unit, quantity, net unit price, VAT rate), payment method, due date. If a required field is missing or ambiguous in the source, stop and ask rather than guessing.
  3. Normalize the extracted values:
    • NIP → digits only (strip spaces, dashes, the PL prefix).
    • Dates → ISO YYYY-MM-DD.
    • Amounts → number with exactly 2 decimals (parse Polish formatting: 1 234,561234.56).
    • Map each line's VAT rate to a P_12 code (see table); map the payment method to a FormaPlatnosci code.
  4. Compute the line nets, per-rate VAT totals, and the gross total (see Calculation rules). Do the maths yourself — never copy a total blindly from the PDF; recompute and flag any mismatch with the source.
  5. Emit the XML in the structure shown under Document structure, using the worked example as the template. Set DataWytworzeniaFa to the current timestamp.
  6. Validate against the FA(2) XSD and run the checklist at the bottom before handing back / sending.

Source → FA(2) field map

From the source invoice → FA(2) element
Seller tax ID Podmiot1/DaneIdentyfikacyjne/NIP
Seller name Podmiot1/DaneIdentyfikacyjne/Nazwa
Seller street / postcode+city Podmiot1/Adres/AdresL1 / AdresL2
Buyer tax ID / name / address Podmiot2/… (same shape, Rola=Nabywca)
Invoice number Fa/P_2
Issue date Fa/P_1
Sale/delivery date (if different) Fa/P_1M
Currency Fa/KodWaluty
Line description FaWiersz/P_7
Line unit / quantity / net unit price FaWiersz/P_8A / P_8B / P_9A
Line VAT rate FaWiersz/P_12 (code)
(computed) line net FaWiersz/P_11
(computed) per-rate net / VAT Fa/P_13_x / P_14_x
(computed) gross total Fa/P_15
Payment method / due date Platnosc/FormaPlatnosci / TerminPlatnosci

Worked example (end-to-end)

Input — text extracted from a PDF invoice

FAKTURA VAT  nr FV/001/2024
Data wystawienia: 15.01.2024

Sprzedawca: Acme Sp. z o.o., NIP 123-456-78-90
            ul. Programistyczna 42, 00-001 Warszawa
Nabywca:    Client Sp. z o.o., NIP 098-765-43-21
            ul. Biznesowa 7, 30-001 Kraków

Lp  Nazwa                    J.m.  Ilość  Cena netto   VAT   Wartość netto
1   Usługi programistyczne   godz   40    250,00 zł    23%   10 000,00 zł

Razem netto: 10 000,00 zł   VAT 23%: 2 300,00 zł   Do zapłaty: 12 300,00 zł
Forma płatności: przelew      Termin: 29.01.2024

After extraction + normalization (intermediate)

{
  "seller": {"nip": "1234567890", "name": "Acme Sp. z o.o.",
             "addrL1": "ul. Programistyczna 42", "addrL2": "00-001 Warszawa"},
  "buyer":  {"nip": "0987654321", "name": "Client Sp. z o.o.",
             "addrL1": "ul. Biznesowa 7", "addrL2": "30-001 Kraków"},
  "number": "FV/001/2024", "issueDate": "2024-01-15", "currency": "PLN",
  "lines": [{"desc": "Usługi programistyczne", "unit": "godz",
             "qty": "40.00", "netUnit": "250.00", "vat": "23"}],
  "payment": {"method": "6", "due": "2024-01-29"}
}

Output — FA(2) XML to upload

<?xml version='1.0' encoding='UTF-8'?>
<Faktura xmlns="http://crd.gov.pl/wzor/2023/06/29/12648/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://crd.gov.pl/wzor/2023/06/29/12648/ fa_2-1-0e.xsd">
  <Naglowek>
    <KodFormularza kodSystemowy="FA (2)" wersjaSchemy="1-0E">FA</KodFormularza>
    <WariantFormularza>2</WariantFormularza>
    <DataWytworzeniaFa>2024-01-15T10:30:00</DataWytworzeniaFa>
    <SystemInfo>Example</SystemInfo>
  </Naglowek>
  <Podmiot1>
    <DaneIdentyfikacyjne><NIP>1234567890</NIP><Nazwa>Acme Sp. z o.o.</Nazwa></DaneIdentyfikacyjne>
    <Adres><KodKraju>PL</KodKraju><AdresL1>ul. Programistyczna 42</AdresL1><AdresL2>00-001 Warszawa</AdresL2></Adres>
    <Rola>Sprzedawca</Rola>
  </Podmiot1>
  <Podmiot2>
    <DaneIdentyfikacyjne><NIP>0987654321</NIP><Nazwa>Client Sp. z o.o.</Nazwa></DaneIdentyfikacyjne>
    <Adres><KodKraju>PL</KodKraju><AdresL1>ul. Biznesowa 7</AdresL1><AdresL2>30-001 Kraków</AdresL2></Adres>
    <Rola>Nabywca</Rola>
  </Podmiot2>
  <Fa>
    <KodWaluty>PLN</KodWaluty>
    <P_1>2024-01-15</P_1>
    <P_2>FV/001/2024</P_2>
    <RodzajFaktury>VAT</RodzajFaktury>
    <FaWiersz>
      <NrWierszaFa>1</NrWierszaFa>
      <UU_ID>1</UU_ID>
      <P_7>Usługi programistyczne</P_7>
      <P_8A>godz</P_8A>
      <P_8B>40.00</P_8B>
      <P_9A>250.00</P_9A>
      <P_11>10000.00</P_11>
      <P_12>23</P_12>
    </FaWiersz>
    <P_13_1>10000.00</P_13_1>
    <P_14_1>2300.00</P_14_1>
    <P_15>12300.00</P_15>
    <Adnotacje>
      <P_16>2</P_16><P_17>2</P_17><P_18>2</P_18><P_18A>2</P_18A>
      <P_19>2</P_19><P_22>2</P_22><P_23>2</P_23><P_PMarzy>2</P_PMarzy>
    </Adnotacje>
    <Platnosc>
      <FormaPlatnosci>6</FormaPlatnosci>
      <TerminPlatnosci>2024-01-29</TerminPlatnosci>
    </Platnosc>
  </Fa>
</Faktura>

Note how the normalization happened: 123-456-78-901234567890; 15.01.20242024-01-15; 10 000,00 zł10000.00; przelew6; 23%P_12=23. The Do zapłaty line from the PDF (12 300,00) was recomputed as P_15 and only then trusted.


Document structure

Faktura
├── Naglowek          (header)
├── Podmiot1          (seller)
├── Podmiot2          (buyer)
└── Fa                (invoice body)
    ├── FaWiersz ...  (one per line item)
    ├── P_13_x / P_14_x   (VAT totals per rate)
    ├── P_15          (gross total payable)
    ├── Adnotacje     (mandatory markers — `1` applies / `2` does not; set all `2` for an ordinary VAT invoice)
    └── Platnosc      (payment)

Header is fixed: KodFormularza=FA (kodSystemowy="FA (2)", wersjaSchemy="1-0E"), WariantFormularza=2, DataWytworzeniaFa = generation timestamp, SystemInfo = issuing system name. Parties carry digits-only NIP, Nazwa, and Adres (KodKraju, AdresL1, AdresL2). The mandatory Adnotacje markers are P_16, P_17, P_18, P_18A, P_19, P_22, P_23, P_PMarzy.


Code tables

VAT rate (P_12) and VAT-summary suffix (P_13_x net / P_14_x VAT)

P_12 Meaning Summary suffix
23 23% standard _1
8 8% reduced _2
5 5% reduced _3
0 0% _4
oo reverse charge _5
zw exempt _6
np not subject to VAT _7

Invoice type (RodzajFaktury): VAT standard · KOR correcting · ZAL advance · ROZ settlement

Payment method (FormaPlatnosci): 1 cash · 3 card · 5 offset · 6 transfer


Calculation rules


Validation checklist


Last updated: 2026-05-26 — verify all field codes, schema version, and VAT-summary suffix mapping against the current Ministerstwo Finansów FA(2) XSD.