Sending Invoices to KSeF
KSeF Pro generates FA(2) XML documents from your PrestaShop orders, signs them with XAdES-BES digital signatures, and submits them to the KSeF API through a managed session lifecycle. This page covers the full pipeline from order trigger to archived KSeF-ID.
FA(2) XML Structure Overview
Every invoice submitted to KSeF must conform to the FA(2) logical structure defined by the Ministry of Finance (schema version 2.0 mandatory from April 2026). KSeF Pro generates this XML automatically from order data.
Key FA(2) Blocks and Data Sources
| FA(2) Block | Element | Source in PrestaShop |
|---|---|---|
| <Naglowek> | <KodFormularza> | Fixed: FA, version 2 |
| | <DataWystawienia> | Order confirmation date |
| | <RodzajFaktury> | VAT (standard) or KOR (correction) |
| | <NumerFaktury> | KSeF Pro sequential number or PrestaShop order reference |
| <Podmiot1> (seller) | <NIP> | Seller NIP from KSeF Pro configuration |
| | <NazwaPodmiotu> | Company name from KSeF Pro Seller Data |
| | <Adres> | Seller address from KSeF Pro Seller Data |
| <Podmiot2> (buyer) | <NIP> | Customer NIP from order (B2B) or BRAK (B2C) |
| | <NazwaPodmiotu> | Customer billing company name or full name |
| | <Adres> | Customer billing address |
| <Fa> | <P_1> | Invoice date |
| | <P_15> | Total gross amount (PLN) |
| | <P_13_1> | Net amount at 23% VAT rate |
| | <P_14_1> | VAT amount at 23% rate |
| | <RodzajTransakcji> | krajowa (domestic) or UE (intra-EU) |
| <FaWiersz> | Per-product rows | Order line items โ one row per SKU |
| | <P_7> | Product name |
| | <P_8A> | Unit of measure (default: szt.) |
| | <P_8B> | Quantity |
| | <P_9A> | Unit net price |
| | <P_12> | VAT rate code (23, 8, 5, 0, ZW, NP) |
Shipping Line Treatment
Shipping is included as a separate <FaWiersz> row using:
<P_7>: Shipping method name from the order<P_12>: VAT rate mapped from your shipping tax rule<P_8A>:usล.(services unit)
If your shipping is VAT-exempt or zero-rated, configure the shipping tax rule mapping accordingly in Invoice Settings โ Tax Rate Mapping.
XML Preview
Before going live, review the XML output for a real order:
- Go to KSeF Pro โ Audit Log
- Find any
PENDINGorACCEPTEDrecord - Click the XML icon to view the signed FA(2) document
- Verify seller NIP, buyer data, line items, VAT rates, and total amounts

XAdES-BES Digital Signature
Before submission, every FA(2) XML document is signed with an XAdES-BES enveloped signature. KSeF requires this to confirm the document has not been tampered with in transit.
Signing Process
- The FA(2) XML is canonicalized (whitespace normalized, elements sorted per C14N spec)
- A SHA-256 digest is computed over the canonical XML
- The digest is signed using HMAC-SHA256 with the KSeF token as the key
- The resulting
<ds:Signature>block is embedded in the FA(2) XML - The entire signed document is Base64-encoded for API transport
No Qualified Certificate Required
You do not need a separate qualified electronic certificate (kwalifikowany podpis elektroniczny) for invoice-level signing. The KSeF portal token is sufficient for XAdES-BES. Qualified signatures are only required for token issuance at the KSeF portal โ not for individual invoice submissions.
Signing Failure Diagnosis
If signing fails (audit log error 10100), the most common causes are:
| Cause | Diagnosis | Fix |
|---|---|---|
| OpenSSL extension missing | php -m \| grep openssl โ not listed | Enable OpenSSL in PHP config |
| Token has trailing whitespace | Copy token again from password manager | Re-paste token, save, verify |
| OpenSSL 3.2+ deprecation | var/logs/ksefpl.log shows digest algorithm warning | Update to KSeF Pro 1.3.2+ |
Session Lifecycle
KSeF submissions happen within sessions โ bounded API contexts. Each session has a lifecycle that must be completed for invoices to receive KSeF-IDs.
Stage 1: Open Session
POST /api/online/Session/InitSigned
โ Body: signed InitialisationSigned XML
โ Response: {
"sessionToken": "SESSION_TOKEN",
"referenceNumber": "SESSION_REF_123"
}
KSeF Pro opens a session automatically when the first invoice trigger fires. The referenceNumber is stored in the audit log โ use it to cross-reference submissions in the KSeF portal if needed.
Stage 2: Submit Invoice(s)
POST /api/online/Session/Invoice/Send
โ Body: {
"invoiceHash": {
"hashSHA": { "algorithm": "SHA-256", "encoding": "Base64", "value": "HASH" },
"fileSize": 12345
},
"invoicePayload": {
"type": "plain",
"invoiceBody": "BASE64_ENCODED_FA2_XML"
}
}
โ Response: { "elementReferenceNumber": "ELEM_REF_456" }
Each invoice receives an elementReferenceNumber โ a temporary reference within the session. KSeF Pro stores this in the audit record alongside the order until the UPO is downloaded and the permanent KSeF-ID is assigned.
Multiple invoices can be queued in a single session (up to 100 per session, MF-imposed limit). For stores processing fewer than 100 invoices per batch, all invoices go into one session.
Stage 3: Close Session
POST /api/online/Session/CloseSigned
โ Response: { "processingCode": 200 }
Closing the session signals to KSeF that no more invoices will be submitted in this batch. The MF servers then begin asynchronous processing: validating every FA(2) document, assigning KSeF-IDs, and generating the UPO.
Sessions must be explicitly closed to receive KSeF-IDs. A session that is opened but never closed (e.g., the server process is killed) expires after 30 minutes without generating UPOs for any submitted invoices.
Stage 4: Poll for UPO
GET /api/common/Status/{referenceNumber}
โ Response when ready: {
"processingCode": 200,
"upo": "BASE64_ENCODED_UPO_XML",
"invoiceStatusList": [
{ "invoiceReferenceNumber": "ELEM_REF_456", "ksefReferenceNumber": "KSEF_ID_789" }
]
}
UPO processing is asynchronous. KSeF Pro polls the status endpoint at a configurable interval (default: every 30 seconds) until processingCode: 200. Processing typically completes within 1โ3 minutes during normal MF server load.
When the UPO is ready:
- The UPO XML is downloaded and stored at
modules/ksefpl/upo/{order-reference}-{timestamp}.xml - The KSeF-ID for each invoice is written to the PrestaShop order record
- The audit log record status changes from
SUBMITTEDtoACCEPTED
Terminate Session (Error Recovery)
POST /api/online/Session/Terminate
If an unrecoverable error occurs before closing (e.g., the FA(2) XML for one invoice in the batch has a validation error that blocks the entire session), you can terminate the session to discard all submitted invoices. None receive KSeF-IDs.
After termination, fix the underlying issue (see Troubleshooting) and re-trigger submission from the audit log.

UPO Content and Legal Standing
The UPO (Urzฤdowe Poลwiadczenie Odbioru โ Official Proof of Receipt) is a signed XML document containing:
| UPO Field | Description | |---|---| | KSeF-ID | Permanent government-assigned invoice identifier | | Submission timestamp | When the FA(2) XML was received by KSeF | | Processing timestamp | When the invoice was validated and accepted | | Ministry of Finance seal | Cryptographic seal confirming authenticity | | FA(2) XML hash | SHA-256 hash of the original submitted document | | NIP | Your seller NIP |
The UPO is the legal proof that your invoice was submitted to and accepted by the Polish tax authority. It must be retained for the duration of your tax records โ currently 5 years under Polish law (ustawa o rachunkowoลci). KSeF Pro does not auto-purge UPOs.
Batch Submission
For high-volume stores or when catching up after downtime (e.g., KSeF portal maintenance):
- Go to KSeF Pro โ Audit Log
- Filter by status:
PENDINGorFAILED - Select records using the checkbox column
- Click "Submit selected to KSeF"
KSeF Pro batches up to 100 invoices per session. If you select more than 100 orders, the module opens sequential sessions automatically โ it does not prompt for confirmation between sessions.

Batch Rate Limits
The KSeF API does not publish explicit rate limits, but the Ministry of Finance recommends no more than 1 session open at a time per NIP. KSeF Pro enforces this โ it does not open parallel sessions. If two processes attempt to open a session simultaneously (e.g., a cron job and a manual batch), the second is queued until the first session closes.
Correction Invoices (Faktura Korygujฤ ca)
When a correction is needed (price change, return, address error on a previously submitted invoice):
- KSeF Pro generates an FA(2) XML with
<RodzajFaktury>KOR</RodzajFaktury> - The
<DaneFaKorygowanej>block references the original KSeF-ID - The correction is submitted as a new session โ it receives its own KSeF-ID
- Both the original and the correction appear in your KSeF ledger
Corrections are triggered from the KSeF Pro panel on the order detail page โ click "Issue correction" and select the correction type (full reversal or partial).