In KSeF, sending an invoice is the start of processing, not the final outcome. The API first accepts encrypted invoice data into a session. KSeF then validates and processes that invoice asynchronously.
The SDK reflects that model: sending returns a processing handle first. A KSeF number, metadata visibility, invoice download, and UPO come later.
FA(3) XML
-> online or batch session
-> invoice reference number
-> KSeF processing
-> KSeF number
-> metadata, download, UPO
-> failed invoice statusThe stages
-
Prepare valid invoice XML.
The SDK can send bytes from a file or bytes generated by the FA(3) builder.
-
Submit the XML through an online or batch session.
Online sessions send one invoice at a time. Batch sessions upload a prepared ZIP package and expose per-invoice results after package processing.
-
Store the returned references.
The invoice reference number is the first durable handle for a submitted invoice. The session reference tells KSeF where that invoice was submitted.
-
Poll the session or invoice status.
A successful HTTP response does not mean the invoice has a KSeF number yet.
-
Use the final identifiers for retrieval and audit.
After successful processing, the KSeF number becomes the stable identifier for direct download, reconciliation, metadata lookup, and many support workflows.
Send is not acceptance
send_invoice() encrypts the XML and submits it into an open online session. It
returns an invoice reference_number.
send_invoice() returns an InvoiceSubmission handle. Its wait() polls the
invoice status until KSeF assigns a ksef_number, reaches a failed terminal
status, or the local timeout expires.
submission = session.send_invoice(xml_bytes)
print(submission.reference_number)
status = session.get_invoice_status(
invoice_reference_number=sent.reference_number,
)
print(status.status.code, status.ksef_number)Identifiers to keep straight
| Identifier | Where it appears | What it is for |
|---|---|---|
| Local invoice number | Inside the invoice XML and local system. | Business correlation before and after KSeF processing. |
| Session reference number | Opening an online or batch session. | Finding the remote sending workflow. |
| Invoice reference number | Response from sending, and session invoice status. | Polling one invoice and downloading invoice UPO by reference. |
| Invoice hash | Session invoice status and batch preparation. | Correlating batch results with local source documents. |
| KSeF number | Successful invoice status and metadata. | Stable KSeF identifier for download, reconciliation, and support. |
| UPO reference | Session status when collective UPO is available. | Downloading a UPO page for the session or batch. |
For batch sending, the invoice reference number may not be visible until KSeF
processes the uploaded package. Keep the prepared batch metadata so the
invoice_hash and invoice_file_name can connect KSeF results back to local
files.
Metadata and download are later surfaces
Session status tells you what happened to a submission. Metadata and invoice download are retrieval surfaces used after KSeF has processed and materialized the invoice.
Use the surfaces for different jobs:
| Surface | Best question |
|---|---|
| Session invoice status | Did this submitted invoice get a KSeF number or fail? |
| Metadata query | Which processed invoices match these filters, roles, and dates? |
| Direct invoice download | Give me the XML for this known KSeF number. |
| Export package | Give me a larger filtered set of invoice XML files. |
| UPO | Give me official confirmation for the accepted invoice or session. |
invoice_xml = auth.invoices.download(status.ksef_number)
print(len(invoice_xml))Dates are not interchangeable
KSeF metadata exposes several dates. Choose the date based on the workflow, not on the label that looks convenient.
| Date | Meaning |
|---|---|
issue_date | Date declared on the invoice document. |
invoicing_date | Date KSeF received the invoice for processing. |
acquisition_date | Date the invoice became available to a party in KSeF. |
permanent_storage_date | Date used by durable storage and incremental export workflows. |
For incremental synchronization, prefer the Permanent Storage model described in the querying/export pages. It is designed to avoid missing invoices while KSeF processing is asynchronous.
Related pages
- Build FA(3) invoices: Generate valid invoice XML programmatically before sending.
- Send invoices: Submit invoices through online or batch workflows.
- Get status and UPO: Poll session and invoice status, then retrieve UPO documents.
- Querying and exports: Understand metadata queries, export packages, and incremental retrieval.
- Download invoices: Download invoice XML directly or through export packages.
