Skip to content

For developers

KSeF integration: how the KRONENWERK KSeF 2.0 module works

Last reviewed NOT YET READY

KRONENWERK contains a KSeF 2.0 module that authenticates with a taxpayer's KSeF token, opens an online session, submits FA(3) invoices encrypted under the Ministry's key, polls for the KSeF number, retrieves the UPO and reads incoming invoices. The module is built and tested against the Ministry's environments, but it has not been used against the production KSeF, and KRONENWERK does not currently sell subscriptions to Polish companies until that is proven. For transmission the status is NOT YET READY. Your integration would use the ordinary API around it — customers, drafts, webhooks — and nothing KSeF-specific is exposed on the API.

What KSeF is, in one paragraph

KSeF (Krajowy System e-Faktur) is Poland's central clearance system: a structured invoice in the FA(3) schema is submitted to the Ministry of Finance's system, which validates it, assigns a KSeF number and returns an official receipt (UPO, urzędowe poświadczenie odbioru). Until that number exists the file is not legally an invoice. This makes Poland different from Germany, where a compliant file sent by any route discharges the obligation, and from Belgium, where the route is the Peppol network. Background is on KSeF explained; the schema on FA(3); the hub at e-invoicing in Poland.

What the KRONENWERK KSeF 2.0 module does

The module implements the KSeF API 2.0 as published in the Ministry's OpenAPI specification (paths and field names copied from there, not remembered). It works per taxpayer: every call is made in the context of one NIP with that taxpayer's KSeF token, and access tokens are cached per NIP and refreshed before they expire.

StepKSeF API 2.0 calls usedWhat the module does
Ministry keysGET /security/public-key-certificatesLoads the current public certificates and picks the one marked for KsefTokenEncryption and the one for SymmetricKeyEncryption; cached for twelve hours
Authentication with a KSeF tokenPOST /auth/challenge, POST /auth/ksef-token, GET /auth/{referenceNumber}, POST /auth/token/redeem, POST /auth/token/refreshFetches a challenge, encrypts the taxpayer's KSeF token with the Ministry key, polls the authentication status, redeems the access and refresh tokens (JWT) and refreshes them later
SessionPOST /sessions/onlineOpens an online (interactive) session with a fresh AES key encrypted under the Ministry's key
SubmissionPOST /sessions/online/{ref}/invoices, GET /sessions/{ref}/invoices/{invoiceRef}Submits the FA(3) XML encrypted with the session key, then polls the invoice status until KSeF assigns a number or rejects the document
Close and UPOPOST /sessions/online/{ref}/close, download from upoDownloadUrlCloses the session and downloads the UPO from the address the status names; the KSeF number and UPO are stored with the invoice as the proof
Duplicate protectionStatus 440, POST /invoices/query/metadataNever resends without reconciling: KSeF reports a duplicate with the original number, and a metadata search finds an already-accepted invoice
ReceivingPOST /invoices/query/metadata, GET /invoices/ksef/{ksefNumber}Lists invoices issued to the taxpayer and downloads each by its KSeF number, to be read into bills

Two of the Ministry's authentication methods exist; the module uses the KSeF token method, in which a JSON document carrying a previously obtained system token is sent rather than an XML request signed with XAdES. The token belongs to the company and is issued to it inside KSeF; KRONENWERK stores it sealed and uses it only to authenticate. The Ministry documents both methods and notes that self-signed certificates are accepted only in the test environment.

Why it is environment-dependent and not yet ready

The Ministry publishes three environments, and the module is configured against exactly one of them at a time:

EnvironmentHostLegal effectFormats accepted
TEST (release candidate)api-test.ksef.mf.gov.plNone; shared between integrators, use random NIPsFA(2), FA(3), FA_PEF(3), FA_KOR_PEF(3)
DEMO (pre-production)api-demo.ksef.mf.gov.plNone; mirrors production configuration and ownership dataFA(3), FA_PEF(3), FA_KOR_PEF(3)
PRODUCTIONapi.ksef.mf.gov.plFull legal effectFA(3), FA_PEF(3), FA_KOR_PEF(3)

KRONENWERK's module has been exercised against the Ministry's non-production environments. It has not been used against the production KSeF, where a submission is a legal act that another party's tax position depends on. Until a real submission with a real UPO has been made and verified, KRONENWERK marks transmission NOT YET READY and does not sell subscriptions to Polish companies. This is a statement about proof, not about code coverage: the difference between "the client passes its tests" and "the Ministry accepted our invoice" is the one that matters, and it is the one still outstanding.

FA(3) generation itself — producing the XML from a draft's facts and validating it against the schema — is SUPPORTED WITH LIMITATIONS: the document is produced, but a FA(3) file without a KSeF number is not an invoice, so its usefulness is bounded by the transmission status above.

How a developer would use the API around it

Nothing on the KRONENWERK API is KSeF-specific. If the Polish route becomes available, an integration looks exactly like one for any other country: the KSeF work is inside issuance and transmission, both of which stay in the product.

  1. Create the Polish customer with POST /customers, including country: "PL" and the buyer's NIP in vatId. FA(3) identifies the buyer by NIP, and a customer without one cannot be invoiced through KSeF.
  2. Start the draft with POST /invoices/drafts and an Idempotency-Key.
  3. A person completes and issues the draft in the product. The Polish module renders FA(3) XML and validates it; the number is spent and invoice.issued is queued.
  4. The person transmits the issued invoice from the product. The module authenticates with the company's KSeF token stored in Settings → Delivery, opens a session, submits, polls, closes, and stores the KSeF number and UPO. An unknown outcome blocks resending until a reconciliation query has asked KSeF whether it already holds the document.
  5. Your endpoint receives invoice.issued, later invoice.paid or invoice.cancelled. The KSeF number, the UPO and the transmission state are shown in the product and are not on the API today.

What the company must configure, when the route is available: legal entity master data with its NIP (derived from the tax number), the KSeF token entered in Settings → Delivery — KRONENWERK validates it immediately by making an authenticated call with the very token it just stored, and refuses to keep a token that does not work — and, for your integration, an API key with customers:write, customers:read, invoices:write, invoices:read and companies:read plus a webhook endpoint. The general API mechanics are on the accounting API page and invoice API page.

KSeF API 2.0 basics, with sources

If you are evaluating a direct integration instead, the Ministry's material is the primary source and this is where to start.

  • Integrator guide: the Ministry's guide (dated 5 May 2026 in the current revision) covers authentication, permissions, KSeF certificates, offline modes, QR codes, interactive and batch sessions, invoice retrieval, incremental retrieval, KSeF token management, encryption keys, limits and test data, with examples in C# and Java from its open-source reference clients. github.com/CIRFMF/ksef-docs.
  • OpenAPI: each environment serves its own specification under /docs/v2; the test one is at api-test.ksef.mf.gov.pl/docs/v2. Errors are RFC 7807 problem documents with detail and an errors[] list.
  • Authentication: obtain a challenge (valid ten minutes), then either send an XML AuthTokenRequest signed with XAdES using a qualified certificate or a KSeF certificate, or send a JSON document with a KSeF token; poll the status; redeem a JWT access token and a refresh token. The authenticating party must hold at least one active permission for the chosen context (a NIP, an internal identifier or an EU VAT composite identifier). uwierzytelnianie.md.
  • Sessions: an interactive session takes invoices one at a time and returns a status per invoice; closing the session triggers generation of a collective UPO. A batch session is documented separately for bulk submission. Public keys for encrypting the session key and the KSeF token are published by the Ministry and rotate.
  • Environments and maintenance: TEST and DEMO must never receive production invoices or real party data; the Ministry schedules maintenance on the test environments from 16:00 to 18:00 and publishes API-affecting changes in its changelog. srodowiska.md.

The KSeF guide for developers goes deeper into the schema and the session model.

How KRONENWERK handles this

NOT YET READY for transmission. The KSeF 2.0 module — token authentication, session, FA(3) submission, UPO retrieval and receiving — is built and environment-dependent, and it has not been used against the production KSeF. KRONENWERK currently does not sell subscriptions to Polish companies until that is proven, and nothing on this page should be read as implying government or production acceptance. FA(3) generation is SUPPORTED WITH LIMITATIONS. The API exposes no KSeF-specific endpoint, event or field; when the route is proven, integrations will use the same customer, draft and webhook calls as everywhere else. The Poland country page is at Poland; the product's e-invoicing scope is on e-invoicing.

Frequently asked questions

Can I use KRONENWERK to submit invoices to KSeF today?

No. The module exists and has been tested against the Ministry's non-production environments, but it has not been used against production KSeF, and KRONENWERK does not currently sell to Polish companies.

Does the API expose the KSeF number or the UPO?

No. Neither GET /invoices nor any webhook carries KSeF-specific fields today. They are shown in the product on the invoice.

Which authentication method does the module use?

The KSeF token method: the company's token, encrypted with the Ministry's published public key, is exchanged for JWT access and refresh tokens. XAdES-signed authentication is documented by the Ministry but not used by the module.

What happens if a submission times out?

The product refuses to resend until a reconciliation query has asked KSeF whether the document is already there. KSeF also reports duplicates with the original number (status 440).

Where is the authoritative API documentation?

The Ministry's integrator guide on GitHub (CIRFMF/ksef-docs) and the OpenAPI specification served by each environment under /docs/v2.

Sources

  1. KRONENWERK developer documentation read on
  2. Ministry of Finance (Poland) — KSeF 2.0 guide for integrators read on
  3. Ministry of Finance (Poland) — KSeF API 2.0 environments read on
  4. Ministry of Finance (Poland) — KSeF API 2.0 authentication read on
  5. Ministry of Finance (Poland) — KSeF 2.0 implementation stages read on
  6. KSeF API 2.0 OpenAPI specification (test environment) read on

Start integrating

Read the quickstart Reference

Read next