KSeF

How to check KSeF invoice status and retrieve the UPO

How to check an invoice's KSeF status and retrieve the UPO: the submit response, polling GET /invoices/{id} and the signed status webhooks.

Published 2 min readBy Tomek

Overview

When you create an invoice, the POST /invoices response returns submitted with a KSeF reference number, and the final decision — accepted or rejected — arrives later. You can verify it by polling GET /invoices/{id}, which re-checks KSeF while the invoice is still submitted, or by listening for the signed status webhook. The UPO and the KSeF number arrive together with the accepted status.

The statuses

An invoice moves through a small set of states. draft means the FA(3) XML was generated but not sent (for example, KSeF was unavailable). submitted means it reached KSeF and is being processed. accepted means KSeF accepted it and the KSeF number and UPO are set. rejected means KSeF refused it and the error field holds a stable code such as ksef_rejected:<code>.

Verify by polling

GET /invoices/{id} returns the same invoice object you got on creation. While the invoice is submitted, this call also checks KSeF and records the decision, so polling it is a valid alternative to webhooks if you do not want to run a webhook endpoint. Poll a sensible interval — KSeF decides asynchronously, so a single immediate check will often still show submitted.

Verify by webhook

If you register an HTTPS endpoint, Notaly pushes the result to you. invoice.accepted carries the KSeF number, the UPO and an absolute pdfUrl; invoice.rejected carries the error code; invoice.error means the invoice could not be processed. Every delivery is signed with HMAC and retried with backoff, and deliveries are at-least-once, so deduplicate on X-Webhook-Id.

In the dashboard

The Notaly dashboard shows your invoice list with each invoice's status, and lets you open the XML, the PDF and, for accepted invoices, the UPO. That is the fastest way to check a single document by hand.

FAQ

How do I know the final result after submitting? Poll GET /invoices/{id} (it re-checks KSeF while submitted) or listen for the signed invoice.accepted / invoice.rejected webhook.

When do I get the UPO? With the accepted status — the webhook payload and the invoice object both carry the UPO and the KSeF number.

Disclaimer

Notaly is not a tax, accounting or legal advisor. This article is general information, not tax advice, and may be outdated. You are responsible for your own VAT compliance; confirm with a qualified accountant where required.

Sources

Source: www.podatki.gov.pl

Frequently asked questions

How do I know the final result after submitting?

Poll GET /invoices/{id} (it re-checks KSeF while submitted) or listen for the signed invoice.accepted / invoice.rejected webhook.

When do I get the UPO?

With the accepted status — the webhook payload and the invoice object both carry the UPO and the KSeF number.

What if KSeF is unavailable when I submit?

The invoice is stored as draft with error ksef_unavailable; no data is lost, and you can retry later.

Issue your first KSeF test invoice today

Create a sandbox account: API key in seconds, 3 free test invoices on KSeF TEST, no credit card.