GitHub

Get Status and UPO

Check online and batch session status, list session invoices, and download UPO documents.

On this page

Use this page after you have submitted invoice XML. The examples assume you already have an authenticated client named auth.

Status calls return SDK models. UPO calls return XML bytes.

Online invoice status

For online sending, send_invoice() returns a session invoice reference. Use that reference to poll the invoice result and download invoice UPO.

from pathlib import Path

from ksef2 import FormSchema

with auth.online_session(form_code=FormSchema.FA3) as session:
    submission = session.send_invoice(invoice_xml)

    invoice_status = submission.wait(timeout=120.0, poll_interval=2.0)

    # SessionInvoiceStatusResponse
    # {
    #   "ordinal_number": 1,
    #   "reference_number": "20260625-ABCD-EF1234567890",
    #   "invoice_number": "FV/42/2026",
    #   "ksef_number": "1234567890-20260625-...",
    #   "status": {
    #     "code": 200,
    #     "description": "Processed"
    #   }
    # }

    upo_xml = submission.download_upo()
    Path("upo.xml").write_bytes(upo_xml)
python

download_upo() is one request and never waits, so call submission.wait() first, as above. Called too early it raises KSeFNotReadyError with a hint to call wait().

Inside the same session block, if you already have the KSeF number, you can download invoice UPO by KSeF number instead:

ksef_number = invoice_status.ksef_number
if ksef_number is None:
    raise RuntimeError("KSeF did not assign an invoice number.")

upo_xml = session.download_invoice_upo(ksef_number=ksef_number)
python

Download UPO after restart

With a newly authenticated auth client, use stored references to download UPO from an online or batch session. You do not need an open session handle or OnlineSessionResumeState and its encryption keys.

# Load these references from your application's records.
upo_xml = auth.invoice_sessions.download_upo(
    session_reference_number,
    invoice_reference_number=invoice_reference_number,
)
_ = Path("upo.xml").write_bytes(upo_xml)

# Alternatively, select the invoice by its KSeF number.
upo_xml = auth.invoice_sessions.download_upo(
    session_reference_number,
    ksef_number=ksef_number,
)

# Or download one session UPO page using its stored UPO reference.
upo_page_xml = auth.invoice_sessions.download_upo(
    session_reference_number,
    upo_reference_number=upo_reference_number,
)
python

Pass exactly one of invoice_reference_number, ksef_number, or upo_reference_number. Each call makes one authenticated request and returns XML bytes. For an async client, await the same call.

Like submission.download_upo(), this method never waits or polls. If KSeF returns code 21165 or 21178, it raises KSeFNotReadyError. Check processing status before retrying; rejected invoices may never receive a UPO. A session UPO page becomes available after the session is closed and processed.

Online session pages

Use session pages when you need to inspect everything submitted in an online session instead of one invoice reference.

Accepted

page = session.list_invoices(page_size=100)

for invoice in page.invoices:
    print(invoice.reference_number, invoice.ksef_number)
python

Failed

page = session.list_failed_invoices(page_size=100)

for invoice in page.invoices:
    print(invoice.reference_number, invoice.status.code, invoice.status.details)
python

Batch status and UPO

For batch sending, keep the returned BatchSessionResumeState. The batch service can poll by state or by plain session reference number.

from pathlib import Path

final_status = session.wait(timeout=300.0, poll_interval=2.0)

# SessionStatusResponse
# {
#   "status": {
#     "code": 200,
#     "description": "Processed"
#   },
#   "invoice_count": 10,
#   "successful_invoice_count": 9,
#   "failed_invoice_count": 1,
#   "upo": {
#     "pages": [
#       {
#         "reference_number": "upo-page-reference",
#         "download_url_expiration_date": "2026-06-26T10:00:00Z"
#       }
#     ]
#   }
# }

session.wait(timeout=120.0)  # the session is closed; wait for KSeF to finish

for number, upo_xml in enumerate(session.download_upo(), start=1):
    Path(f"batch-upo-{number}.xml").write_bytes(upo_xml)
python

List accepted and failed batch invoices

Accepted and failed invoices are separate pages. Read both when reconciling a batch.

Accepted

page = session.list_invoices(page_size=100)

for invoice in page.invoices:
    print(invoice.invoice_file_name, invoice.ksef_number, invoice.status.description)
python

Failed

page = session.list_failed_invoices(page_size=100)

for invoice in page.invoices:
    print(invoice.invoice_file_name, invoice.status.code, invoice.status.details)
python

When a page has continuation_token, pass it to the next call:

page = session.list_invoices(page_size=100)

while page.continuation_token is not None:
    page = session.list_invoices(
        page_size=100,
        continuation_token=page.continuation_token,
    )
python

Find sessions after restart

Use auth.invoice_sessions when you need to find online or batch sessions after the original sender process has exited.

list() returns a Pager: iterate it for every session, call .pages() for page-sized lists, or .first_page() to make a single request.

One page

sessions = auth.invoice_sessions.list(
    "online",
    statuses=["in_progress", "succeeded"],
).first_page()

for item in sessions:
    print(item.reference_number, item.status.code, item.total_invoice_count)
python

All sessions

for item in auth.invoice_sessions.list("batch"):
    print(item.reference_number, item.status.description)
python
  1. Persist session references and invoice reference numbers when sending.

  2. Poll the specific invoice, online session, or batch session that matches the question you are answering.

  3. Store accepted and failed invoice details.

  4. Download UPO XML and store it with your audit records.

  5. Use auth.invoice_sessions to recover session references after process restart.

Next workflows

  • Send invoices: Submit invoice XML through online or batch sessions before polling status.
  • Status and UPO: Understand status surfaces, UPO documents, polling, and local timeouts.
  • Download invoices: Fetch processed invoice XML after KSeF assigns a number.
  • Query invoices: Find processed invoices through metadata filters and pagination.