What FA(3) is
FA(3) is the third version of the logical structure of the Polish structured invoice (e-Faktura), published by the Ministry of Finance as an XSD. Since KSeF 2.0, every invoice sent to KSeF has to be valid FA(3) XML. In KSeF the XML is the invoice; a PDF is only a visualisation of it.
Every FA(3) document starts with the same header:
<Faktura xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/">
<Naglowek>
<KodFormularza kodSystemowy="FA (3)" wersjaSchemy="1-0E">FA</KodFormularza>
<WariantFormularza>3</WariantFormularza>
<DataWytworzeniaFa>2026-10-12T07:23:07Z</DataWytworzeniaFa>
</Naglowek>
<!-- Podmiot1 (seller), Podmiot2 (buyer), Fa (invoice data) -->
</Faktura>
Structure of an FA(3) invoice
A standard VAT invoice uses four main blocks. The table shows where each field of a Notaly POST /invoices request ends up.
| FA(3) element | Contains | From JSON field |
|---|---|---|
Naglowek | Form code, schema version, creation timestamp | Generated |
Podmiot1 | Seller: NIP, Nazwa, Adres | seller |
Podmiot2 | Buyer: NIP, Nazwa, Adres | buyer |
Fa/KodWaluty | Currency (ISO 4217) | currency |
Fa/P_1 | Issue date | issueDate |
Fa/P_2 | Invoice number | number |
Fa/P_13_x, P_14_x | Net and VAT totals per rate (23%, 8%, 5%, 0%) | Computed from items |
Fa/P_15 | Gross total | Computed |
Fa/Adnotacje | Mandatory annotations (split payment, exemptions, margin scheme…) | Generated defaults |
Fa/FaWiersz | Line items: P_7 name, P_8A unit, P_8B quantity, P_9A unit net price, P_11 net value, P_12 VAT rate | items[] |
How to validate FA(3) against the XSD
Validate locally before you send anything to KSeF. Download the official FA(3) schema from the Ministry of Finance (the main schemat.xsd imports shared type definitions, so keep all the files in one folder) and run:
xmllint --noout --schema schemat.xsd invoice.xml
# invoice.xml validates
XSD validation catches structure and type errors. KSeF also runs business checks after the XSD, so a schema-valid file can still be rejected. Notaly validates every invoice against the XSD before submitting it and returns KSeF rejections as stable error codes.
Common FA(3) validation errors
- Invalid NIP. A NIP has 10 digits and a checksum (weights 6, 5, 7, 2, 3, 4, 5, 6, 7 modulo 11). A typo fails before KSeF even sees the invoice.
- Totals that do not add up.
P_13_xandP_14_xhave to equal the sum of the lines for each VAT rate, andP_15the gross total, rounded to 2 decimals. - Wrong date or currency format. Dates are
YYYY-MM-DD, currencies ISO 4217 (PLN,EUR), countries ISO 3166 alpha-2 (PL). - Missing annotations.
Adnotacjeis mandatory even when nothing special applies: every flag (P_16,P_17,P_18,P_18A,P_23…) must be set explicitly. - Old namespace. FA(2) files use a different namespace and are not accepted as FA(3).
- Unescaped characters. Names with
&,<or quotes must be XML-escaped.
Generate FA(3) XML from JSON
With Notaly you do not write FA(3) by hand. Send the invoice as JSON and Notaly computes totals per VAT rate, fills in the header and annotations, escapes the text, validates the result and submits it to KSeF.
- Create the invoiceSend
POST /invoiceswith seller, buyer and items, as in the KSeF API example. - Download the exact XMLCall
GET /invoices/{id}/xmlto get the FA(3) document that was sent to KSeF, byte for byte. - Keep the proofWhen the invoice is
accepted, store the KSeF number and the UPO, and share the PDF with the KSeF QR code with your customer.
curl https://api.getnotaly.com/invoices/inv_8f2c…/xml \
-H "Authorization: Bearer $NOTALY_API_KEY" -o invoice.xml