Skip to main content

UBL JSON to KSeF FA(3) Mapping Reference

This document describes how UBL JSON invoice payloads are mapped to the Polish KSeF FA(3) e-invoice format.

Invoice Header

Fa = Faktura = invoice

KodWaluty = Currency code

RodzajFaktury = Invoice type

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.P_2document > invoice > invoiceNumber
JSONPath$.document.invoice.invoiceNumber
YesInvoice number
Fa.P_1document > invoice > issueDate
JSONPath$.document.invoice.issueDate
YesInvoice issue date. Formatted as date (Y-m-d)
Fa.KodWalutydocument > invoice > documentCurrencyCode
JSONPath$.document.invoice.documentCurrencyCode
YesCurrency code
Fa.RodzajFakturydocument > documentType
JSONPath$.document.documentType
YesInvoice type. Storecove has no separate credit note.
Map:
invoiceVAT
credit_noteKOR
STRICT
Fa.RodzajFakturyNoKORThe document references the invoice it correctsInvoice type. Storecove has no separate credit note

Correction Invoice

KOR = Faktura Korygujaca = correction invoice

DaneFaKorygowanej = Data of the corrected invoice

NrFaKorygowanej = Number of the corrected invoice

DataWystFaKorygowanej = Issue date of the corrected invoice

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.DaneFaKorygowanejdocument > invoice > references[?(@.documentType == 'billing')]
JSONPath$.document.invoice.references[?(@.documentType == 'billing')]
NoThe document references the invoice it correctsThe invoice each "billing" reference corrects.. Grouped by rowIndex

Fa.DaneFaKorygowanej

DaneFaKorygowanej = Data of the corrected invoice

FA(3) FieldUBL JSONReq.DefaultConditionDescription
DataWystFaKorygowanej$.issueDateYesIssue date of the corrected invoice. Formatted as date (Y-m-d)
NrFaKorygowanej$.documentIdYesNumber of the corrected invoice
NrKSeFNo1The reference carries a KSeF identifier instead of a seller numberFlag indicating the corrected invoice was in KSeF
NrKSeFFaKorygowanej$.documentIdNoThe reference carries a KSeF identifier instead of a seller numberKSeF identifier of the corrected invoice
NrKSeFNNo1NOT: The reference carries a KSeF identifier instead of a seller numberFlag indicating the corrected invoice was NOT in KSeF

Seller

Podmiot1 = Subject/entity 1 (seller)

DaneIdentyfikacyjne = Identification data

NIP = Polish tax ID

Nazwa = Name

Adres = Address

KodKraju = Country code

AdresL1 = Address line 1

AdresL2 = Address line 2

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Podmiot1.DaneIdentyfikacyjne.NIPdocument > invoice > accountingSupplierParty > publicIdentifiers[?search(@.scheme, 'VAT')] > id
JSONPath$.document.invoice.accountingSupplierParty.publicIdentifiers[?search(@.scheme, 'VAT')].id
NoSeller tax identification number (10 digits, PL prefix stripped). Extracted via regex /^(?:[A-Z]{2})?([0-9]+)$/
Podmiot1.DaneIdentyfikacyjne.Nazwadocument > invoice > accountingSupplierParty > party > companyName
JSONPath$.document.invoice.accountingSupplierParty.party.companyName
NoSeller name
Podmiot1.Adres.KodKrajudocument > invoice > accountingSupplierParty > party > address > country
JSONPath$.document.invoice.accountingSupplierParty.party.address.country
NoSeller country code
Podmiot1.Adres.AdresL1document > invoice > accountingSupplierParty > party > address > street1
JSONPath$.document.invoice.accountingSupplierParty.party.address.street1
NoSeller street address
Podmiot1.Adres.AdresL2document > invoice > accountingSupplierParty > party > address > zip
JSONPath$.document.invoice.accountingSupplierParty.party.address.zip
NoSeller postal code and city. Computed: trim(source ~ ' ' ~ jsonpath(row, '$.document.invoice.accountingSupplierParty.party.address.city'))

Buyer

Podmiot2 = Subject/entity 2 (buyer)

JST = Local government unit flag

GV = VAT group flag

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Podmiot2.DaneIdentyfikacyjne.Nazwadocument > invoice > accountingCustomerParty > party > companyName
JSONPath$.document.invoice.accountingCustomerParty.party.companyName
YesBuyer name
Podmiot2.DaneIdentyfikacyjne.NIPdocument > invoice > accountingCustomerParty > publicIdentifiers[?search(@.scheme, 'VAT|IVA')] > id
JSONPath$.document.invoice.accountingCustomerParty.publicIdentifiers[?search(@.scheme, 'VAT|IVA')].id
YesBuyer is Polish or country not specifiedBuyer tax ID (Polish buyer, PL prefix stripped). Extracted via regex /^(?:[A-Z]{2})?([0-9]+)$/
Podmiot2.DaneIdentyfikacyjne.KodUEdocument > invoice > accountingCustomerParty > party > address > country
JSONPath$.document.invoice.accountingCustomerParty.party.address.country
YesBuyer is established in another EU member stateVAT country prefix of an EU buyer.
Map:
GREL
Podmiot2.DaneIdentyfikacyjne.NrVatUEdocument > invoice > accountingCustomerParty > publicIdentifiers[?search(@.scheme, 'VAT|IVA')] > id
JSONPath$.document.invoice.accountingCustomerParty.publicIdentifiers[?search(@.scheme, 'VAT|IVA')].id
YesBuyer is established in another EU member stateEU VAT identifier with the optional country prefix stripped. Extracted via regex /^(?:[A-Z]{2})?([A-Za-z0-9]+)$/
Podmiot2.DaneIdentyfikacyjne.KodKrajudocument > invoice > accountingCustomerParty > party > address > country
JSONPath$.document.invoice.accountingCustomerParty.party.address.country
YesBuyer outside the EU, identified by KodKraju and NrIDTax ID country of a buyer outside the EU
Podmiot2.DaneIdentyfikacyjne.NrIDdocument > invoice > accountingCustomerParty > publicIdentifiers[?search(@.scheme, 'VAT|IVA')] > id
JSONPath$.document.invoice.accountingCustomerParty.publicIdentifiers[?search(@.scheme, 'VAT|IVA')].id
YesBuyer outside the EU, identified by KodKraju and NrIDOther tax identifier, kept as the sender supplied it
Podmiot2.Adres.KodKrajudocument > invoice > accountingCustomerParty > party > address > country
JSONPath$.document.invoice.accountingCustomerParty.party.address.country
NoBuyer country code
Podmiot2.Adres.AdresL1document > invoice > accountingCustomerParty > party > address > street1
JSONPath$.document.invoice.accountingCustomerParty.party.address.street1
NoBuyer street address
Podmiot2.Adres.AdresL2document > invoice > accountingCustomerParty > party > address > zip
JSONPath$.document.invoice.accountingCustomerParty.party.address.zip
NoBuyer postal code and city. Computed: trim(source ~ ' ' ~ jsonpath(row, '$.document.invoice.accountingCustomerParty.party.address.city'))
Podmiot2.jSTNo2Local government unit flag (always "no")
Podmiot2.gVNo2VAT group flag (always "no")

Tax Totals

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.P_13_1document > invoice > taxSubtotals[?(@.percentage == 23)] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 23)].taxableAmount
NoNet amount at 23% VAT rate
Fa.P_14_1document > invoice > taxSubtotals[?(@.percentage == 23)] > taxAmount
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 23)].taxAmount
NoTax amount at 23% VAT rate
Fa.P_13_2document > invoice > taxSubtotals[?(@.percentage == 8)] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 8)].taxableAmount
NoNet amount at 8% VAT rate
Fa.P_14_2document > invoice > taxSubtotals[?(@.percentage == 8)] > taxAmount
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 8)].taxAmount
NoTax amount at 8% VAT rate
Fa.P_13_3document > invoice > taxSubtotals[?(@.percentage == 5)] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 5)].taxableAmount
NoNet amount at 5% VAT rate
Fa.P_14_3document > invoice > taxSubtotals[?(@.percentage == 5)] > taxAmount
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 5)].taxAmount
NoTax amount at 5% VAT rate
Fa.P_13_6_2document > invoice > taxSubtotals[?(@.category == 'intra_community')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'intra_community')].taxableAmount
NoNet amount of intra-community supplies (0% WDT).
Fa.P_13_6_1document > invoice > taxSubtotals[?(@.category == 'zero_rated')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'zero_rated')].taxableAmount
NoNet amount at the domestic 0% rate (0 KR)
Fa.P_13_6_3document > invoice > taxSubtotals[?(@.category == 'export')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'export')].taxableAmount
NoNet amount of exports (0 EX)
Fa.P_13_7document > invoice > taxSubtotals[?(@.category == 'exempt')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'exempt')].taxableAmount
NoNet amount of VAT-exempt sales
Fa.P_13_8document > invoice > taxSubtotals[?(@.category == 'outside_scope')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'outside_scope')].taxableAmount
NoOut-of-scope supply reported as "np I"Net amount of supplies outside Poland, other than the
Fa.P_13_9document > invoice > taxSubtotals[?(@.category == 'outside_scope')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'outside_scope')].taxableAmount
NoOut-of-scope supply reported as "np II" (article 100(1)(4) services)Net amount of article 100(1)(4) services
Fa.P_13_10document > invoice > taxSubtotals[?(@.category == 'reverse_charge')] > taxableAmount
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'reverse_charge')].taxableAmount
NoNet amount under the domestic reverse charge procedure.
Fa.P_14_1Wdocument > invoice > taxSubtotals[?(@.percentage == 23)] > taxAmountPLN
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 23)].taxAmountPLN
Nojsonpath(row, '$.document.invoice.documentCurrencyCode') != 'PLN'
Fa.P_14_2Wdocument > invoice > taxSubtotals[?(@.percentage == 8)] > taxAmountPLN
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 8)].taxAmountPLN
Nojsonpath(row, '$.document.invoice.documentCurrencyCode') != 'PLN'
Fa.P_14_3Wdocument > invoice > taxSubtotals[?(@.percentage == 5)] > taxAmountPLN
JSONPath$.document.invoice.taxSubtotals[?(@.percentage == 5)].taxAmountPLN
Nojsonpath(row, '$.document.invoice.documentCurrencyCode') != 'PLN'

Total Amount

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.P_15document > invoice > amountIncludingVat
JSONPath$.document.invoice.amountIncludingVat
YesTotal payable amount

Annotations

Adnotacje = Annotations

Zwolnienie = VAT exemption

NoweSrodkiTransportu = New means of transport

PMarzy = Margin scheme (procedura marzy)

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.Adnotacje.P_16No2Self-billing annotation (always "no")
Fa.Adnotacje.P_17No2Self-billing invoice (always "no")
Fa.Adnotacje.P_18No1!empty(jsonpath(row, "$.document.invoice.taxSubtotals[?(@.category == 'reverse_charge')]"))
Buyer is Polish or country not specified
Reverse charge annotation. Only the domestic procedure is
Fa.Adnotacje.P_18ANo-Explicit split payment; omitted means not applicable.. Computed: row['_crawler'].find('$.document.invoice.SplitPayment') === [] ? '2' : (jsonpath(row, '$.document.invoice.SplitPayment') === 1 ? '1' : 'unsupported').
Map:
11
22
STRICT
Fa.Adnotacje.Zwolnienie.P_19No1The invoice carries VAT-exempt linesVAT exemption present. Article 106e(1)(19) of the Polish VAT act
Fa.Adnotacje.Zwolnienie.P_19Adocument > invoice > taxSubtotals[?(@.category == 'exempt')] > taxExemptionReason
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'exempt')].taxExemptionReason
YeshasExemptSale() and !isDirectiveExemption() and !isOtherExemption()Exemption under the Polish VAT act
Fa.Adnotacje.Zwolnienie.P_19Bdocument > invoice > taxSubtotals[?(@.category == 'exempt')] > taxExemptionReason
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'exempt')].taxExemptionReason
YeshasExemptSale() and isDirectiveExemption()Exemption under directive 2006/112/EC
Fa.Adnotacje.Zwolnienie.P_19Cdocument > invoice > taxSubtotals[?(@.category == 'exempt')] > taxExemptionReason
JSONPath$.document.invoice.taxSubtotals[?(@.category == 'exempt')].taxExemptionReason
YeshasExemptSale() and isOtherExemption()Exemption under another legal basis
Fa.Adnotacje.Zwolnienie.P_19NNo1NOT: The invoice carries VAT-exempt linesNo VAT exemption
Fa.Adnotacje.NoweSrodkiTransportu.P_22NNo1New means of transport not applicable
Fa.Adnotacje.P_23No2Simplified triangular transaction (always "no")
Fa.Adnotacje.PMarzy.P_PMarzyNNo1Margin scheme not applied

Delivery notes and additional notes

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.WZNo-Computed: row['_crawler'].find("$.document.invoice..references[?(@.documentType == 'despatch_advice')].documentId"). Transform: unique

Transaction conditions

WarunkiTransakcji = Transaction conditions

Umowy = Contracts

Zamowienia = Orders

NrPartiiTowaru = Goods batch numbers

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.WarunkiTransakcji.Umowydocument > invoice > references[?(@.documentType == 'contract')]
JSONPath$.document.invoice.references[?(@.documentType == 'contract')]
No!empty(jsonpath(row, "$.document.invoice.references[?(@.documentType == 'contract')]"))Contract the invoice relates to. Grouped by $.documentId
Fa.WarunkiTransakcji.Zamowieniadocument > invoice > references[?(@.documentType == 'purchase_order')]
JSONPath$.document.invoice..references[?(@.documentType == 'purchase_order')]
No!empty(jsonpath(row, "$.document.invoice..references[?(@.documentType == 'purchase_order')]"))Purchase orders the invoice refers to. Grouped by $.documentId
Fa.WarunkiTransakcji.NrPartiiTowaruNo-!empty(jsonpath(row, "$.document.invoice..references[?(@.documentType == 'line_document_reference')]"))Batch numbers, sent per line as line_document_reference. Computed: row['_crawler'].find("$.document.invoice..references[?(@.documentType == 'line_document_reference')].documentId"). Transform: unique
Fa.DodatkowyOpisdocument > invoice > notes[*]
JSONPath$.document.invoice.notes[*]
No!empty(jsonpath(row, '$.document.invoice.notes'))Grouped by rowIndex
Fa.DodatkowyOpis[legacyNote].KluczNoNoteempty(jsonpath(row, '$.document.invoice.notes')) and !empty(jsonpath(row, '$.document.invoice.note'))
Fa.DodatkowyOpis[legacyNote].Wartoscdocument > invoice > note
JSONPath$.document.invoice.note
Noempty(jsonpath(row, '$.document.invoice.notes'))

Fa.WarunkiTransakcji.Umowy

Umowy = Contracts

FA(3) FieldUBL JSONReq.DefaultConditionDescription
NrUmowy$.documentIdYes
DataUmowy$.issueDateNoFormatted as date (Y-m-d)

Fa.WarunkiTransakcji.Zamowienia

Zamowienia = Orders

FA(3) FieldUBL JSONReq.DefaultConditionDescription
NrZamowienia$.documentIdYes
DataZamowienia$.issueDateNoFormatted as date (Y-m-d)

Fa.DodatkowyOpis

FA(3) FieldUBL JSONReq.DefaultConditionDescription
KluczNoNote
Wartosc$Yes

Payment

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.Platnosc.TerminPlatnosci[0].Termindocument > invoice > dueDate
JSONPath$.document.invoice.dueDate
NoFormatted as date (Y-m-d)
Fa.Platnosc.RachunekBankowydocument > invoice > paymentMeansArray[?(@.code == 'credit_transfer' || @.code == 'sepa_credit_transfer')]
JSONPath$.document.invoice.paymentMeansArray[?(@.code == 'credit_transfer' || @.code == 'sepa_credit_transfer')]
No!empty(jsonpath(row, "$.document.invoice.paymentMeansArray[?(@.code == 'credit_transfer' || @.code == 'sepa_credit_transfer')]"))Grouped by rowIndex
Fa.Platnosc.RachunekBankowy[0].NrRBdocument > invoice > paymentMeansIban
JSONPath$.document.invoice.paymentMeansIban
No!hasPaymentMeans()
Fa.Platnosc.RachunekBankowy[0].SWIFTdocument > invoice > paymentMeansBic
JSONPath$.document.invoice.paymentMeansBic
No!hasPaymentMeans() and !empty(jsonpath(row, '$.document.invoice.paymentMeansIban'))
Fa.Platnosc.FormaPlatnosciNo-knownPaymentMethod()Computed: empty(jsonpath(row, '$.document.invoice.paymentMeansArray')) ? jsonpath(row, '$.document.invoice.paymentMeansCode') : jsonpath(row, '$.document.invoice.paymentMeansArray[0].code').
Map:
cash1
card2
bank_card2
credit_card2
bank_cheque4
cashiers_cheque4
credit_transfer6
sepa_credit_transfer6
STRICT
Fa.Platnosc.PlatnoscInnaNo1!knownPaymentMethod() and (hasPaymentMeans() or !empty(jsonpath(row, '$.document.invoice.paymentMeansCode')))
Fa.Platnosc.OpisPlatnosciNo-!knownPaymentMethod() and (hasPaymentMeans() or !empty(jsonpath(row, '$.document.invoice.paymentMeansCode')))Computed: empty(jsonpath(row, '$.document.invoice.paymentMeansArray')) ? [jsonpath(row, '$.document.invoice.paymentMeansCode')] : row['_crawler'].find('$.document.invoice.paymentMeansArray[*].code'). Transform: arrayReduce
Fa.Platnosc.ZaplaconoNo-!empty(jsonpath(row, '$.document.invoice.prepaidAmount')) or hasDatedPayment()Computed: (!empty(jsonpath(row, '$.document.invoice.prepaidAmount')) or (!empty(jsonpath(row, '$.document.invoice.prepaidPayments')) and row['_crawler'].find('$.document.invoice.prepaidAmount') !== [])) ? 'prepaidAmount has no payment date; supply one prepaidPayments item with amount and date instead' : (!empty(jsonpath(row, '$.document.invoice.prepaidPayments[1]')) ? 'only one prepaidPayments item is supported' : (jsonpath(row, '$.document.invoice.prepaidPayments[0].amount') > 0 and jsonpath(row, '$.document.invoice.prepaidPayments[0].amount') <= jsonpath(row, '$.document.invoice.amountIncludingVat') ? (jsonpath(row, '$.document.invoice.prepaidPayments[0].amount') == jsonpath(row, '$.document.invoice.amountIncludingVat') ? '1' : 'partial') : 'prepaidPayments amount must be positive and not exceed the invoice total')).
Map:
11
partial → ``
STRICT
Fa.Platnosc.DataZaplatydocument > invoice > prepaidPayments[0] > date
JSONPath$.document.invoice.prepaidPayments[0].date
YeshasDatedPayment() and paidInFull()Formatted as date (Y-m-d). Computed: source.format('Y-m-d') == jsonpath(row, '$.document.invoice.prepaidPayments[0].date') and source.format('Y-m-d') <= jsonpath(row, '$.document.invoice.issueDate') ? source.format('Y-m-d') : 'invalid prepaidPayments date: must be a real date on or before issueDate'. Formatted as date (Y-m-d)
Fa.Platnosc.ZnacznikZaplatyCzesciowejNo1hasDatedPayment() and !paidInFull()
Fa.Platnosc.ZaplataCzesciowa[0].KwotaZaplatyCzesciowejdocument > invoice > prepaidPayments[0] > amount
JSONPath$.document.invoice.prepaidPayments[0].amount
NohasDatedPayment() and !paidInFull()
Fa.Platnosc.ZaplataCzesciowa[0].DataZaplatyCzesciowejdocument > invoice > prepaidPayments[0] > date
JSONPath$.document.invoice.prepaidPayments[0].date
YeshasDatedPayment() and !paidInFull()Formatted as date (Y-m-d). Computed: source.format('Y-m-d') == jsonpath(row, '$.document.invoice.prepaidPayments[0].date') and source.format('Y-m-d') <= jsonpath(row, '$.document.invoice.issueDate') ? source.format('Y-m-d') : 'invalid prepaidPayments date: must be a real date on or before issueDate'. Formatted as date (Y-m-d)

Fa.Platnosc.RachunekBankowy

FA(3) FieldUBL JSONReq.DefaultConditionDescription
NrRB$.accountYes
SWIFT$.branche_codeNojsonpath(row, '$.branche_code') matches '/^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$/'
OpisRachunku$.holderNo

Invoice Lines

FaWiersz = Faktura wiersz = invoice line

NrWierszaFa = Invoice line number

P_7 = Item name

P_8B = Quantity

P_9A = Unit net price

P_11 = Line net amount

P_12 = VAT rate

FA(3) FieldUBL JSONReq.DefaultConditionDescription
Fa.FaWierszdocument > invoice > invoiceLines[*]
JSONPath$.document.invoice.invoiceLines[*]
NoInvoice lines. Grouped by rowIndex

Fa.FaWiersz

FaWiersz = Faktura wiersz = invoice line

FA(3) FieldUBL JSONReq.DefaultConditionDescription
NrWierszaFa_indexNoInvoice line number
P_7$.nameNoItem name
Indeksreferences[?(@.documentType == 'line_sellers_item_identification')] > documentId
JSONPath$.references[?(@.documentType == 'line_sellers_item_identification')].documentId
NoSeller's item code
P_8B$.quantityNoQuantity
P_9A$.itemPriceNoUnit net price
P_11$.amountExcludingVatNoLine net amount
P_12tax > percentage
JSONPath$.tax.percentage
NoSupply outside the scope of Polish VAT. Which of the two
KursWalutyNo-!empty(row['_root'].find('$.document.invoice.accountingCurrencyExchangeRate')) and row['_root'].find('$.document.invoice.documentCurrencyCode')[0] != 'PLN'Exchange rate supplied by the sender, never derived. Computed: row['_root'].find('$.document.invoice.accountingCurrencyExchangeRate')[0]