KSeF integration
The KSeF module stores the connection settings for the National e-Invoice System and can queue an invoice for background submission. No invoice can be submitted today, to any environment. The API client is written against KSeF 1.0, an API the Ministry of Finance has switched off, so the requests fail at the network layer before any authentication or validation happens. This page describes what the plugin actually does today, and what still works.
What is KSeF
Section titled “What is KSeF”The National e-Invoice System (KSeF) is a platform by the Ministry of Finance for issuing, storing and receiving structured invoices in XML format. Polish sellers file invoices there instead of exchanging PDF documents.
KSeF 2.0 has been the only system since 1 February 2026, and it is mandatory.
Why submission does not work
Section titled “Why submission does not work”The plugin’s KSeF client knows exactly two hosts, https://ksef-test.mf.gov.pl/api and https://ksef.mf.gov.pl/api, and one session endpoint, /online/Session/InitSigned. That is the shape of KSeF 1.0.
Both of those environments are gone:
- the KSeF 1.0 test environment was disabled on 1 September 2025
- KSeF 1.0 production stopped on 1 February 2026 and was permanently switched off, together with the old Certificate and Authorisation Module
- since 1 February 2026, KSeF 2.0 is the only system
So there is no setting, no token and no environment value that makes a submission succeed. Production is unreachable, and so is the sandbox.
KSeF 2.0 is not a change of address. It is a different API:
- different base,
https://api-test.ksef.mf.gov.pl/v2for test andhttps://api.ksef.mf.gov.pl/v2for production - different authentication.
POST /auth/challenge, thenPOST /auth/ksef-tokencarrying the KSeF token encrypted together with the challenge timestamp, thenPOST /auth/token/redeemto obtain an access token. There is no equivalent ofInitSigned - different submission. Open a session with
POST /sessions/onlinesupplying an AES-256 key encrypted with the Ministry’s public key, then post the already encrypted invoice to/sessions/online/{referenceNumber}/invoiceswith SHA-256 hashes of both the plain and the encrypted document
A rewrite of the module against KSeF 2.0 is planned. We are not giving it a date.
What this version does
Section titled “What this version does”| Capability | State |
|---|---|
| KSeF connection settings and credential storage | Available |
| KSeF readiness flagging on orders (FREE plugin) | Available |
| PEPPOL / UBL (XML) invoice download | Available |
| JPK_FA report | Available |
| Submitting an invoice to KSeF, test or production | Not possible, the target API no longer exists |
| A button, bulk action or scheduled job that submits | Not in this version |
| Statuses and KSeF reference numbers returned by the Ministry | Not possible, for the same reason |
| Downloading the FA(2) XML from the admin | Not in this version |
POST /wp-json/polski-pro/v1/invoices/{id}/ksef still exists, requires the manage_woocommerce capability and queues the invoice for background submission through Action Scheduler. Nothing in wp-admin calls it, and the queued job cannot complete, so calling it only produces a failed job and a retry.
Treat this module as a place where the credentials will live once the rewrite ships, not as a filing channel.
Configuration
Section titled “Configuration”There is no rendered settings screen for the KSeF fields. They live in the polski_pro_ksef option and are written through the PRO settings REST route, the same way the shipping credentials are:
PUT /wp-json/polski-pro/v1/settingsContent-Type: application/jsonX-WP-Nonce: {wp_rest nonce}
{ "ksef": { "enabled": true, "environment": "test", "api_token": "..." }}The route requires the manage_woocommerce capability. The saved payload replaces the whole polski_pro_ksef option, so send every key you want to keep in the same request.
Connection settings
Section titled “Connection settings”| Key | Description |
|---|---|
enabled | Marks the module as active. It does not make filing possible. |
environment | Stored as test or production, and read by the API client to choose between the two KSeF 1.0 hosts. Both are retired, so neither value produces a working request. |
api_token | Authorization token, stored only. No working code path sends it anywhere. |
auto_send | Stored, but read by nothing. Turning it on submits nothing. |
The issuer VAT ID (NIP) is not part of this option. It comes from the seller data in the Invoices settings and is used on the invoices the plugin already produces.
About the API token
Section titled “About the API token”There is no useful token to store right now. A KSeF 1.0 token authenticates against a system that no longer answers, and a KSeF 2.0 token is encrypted and exchanged through the /auth/* flow above, which this version does not implement. Leave api_token empty until the rewrite ships.
One deadline is worth planning around: tokens stop being an accepted authentication method on 31 December 2026. From 1 January 2027 a KSeF certificate is the only way in, so a token you obtain now has a limited life regardless of this plugin.
KSeF readiness in the FREE plugin
Section titled “KSeF readiness in the FREE plugin”The FREE Polski plugin has a separate KSeF readiness module under Polski > Modules. It never contacts KSeF, which is exactly why it is unaffected by any of the above. It tells you which orders will need a structured invoice.
With the module enabled:
- every order that goes through checkout is checked for a buyer NIP, and the
_polski_ksef_requiredorder meta is set toyesorno - a KSeF column appears in the orders list, with a badge on flagged orders
- the order screen shows a KSeF line under the billing address, reading the
_polski_ksef_statusmeta, which stays atpendingunless your own code writes to it
The single setting, Automatically detect based on NIP, controls the detection described above.
Extension points
Section titled “Extension points”polski/ksef/is_required filters the detection result before it is stored.
add_filter('polski/ksef/is_required', function (bool $required, WC_Order $order): bool { // Never flag orders below 100 PLN. if ($order->get_total() < 100) { return false; }
return $required;}, 10, 2);polski/ksef/invoice_ready fires with the WC_Order right after an order has been flagged as requiring KSeF invoicing. It is the hook to use if you file through your own accounting system or a dedicated KSeF client in the meantime, which is what you have to do today.
Getting invoice data out today
Section titled “Getting invoice data out today”Neither of these touches the KSeF API, so neither is affected:
- the PEPPOL / UBL (XML) meta box on the order screen downloads a single invoice as an EN 16931 / PEPPOL UBL file
- the JPK_FA report admin page builds a JPK_FA(3) XML for all invoices issued in a chosen date range
Neither is a KSeF filing, and neither satisfies the KSeF obligation. Both cover the common case of moving invoice data into accounting software or a tax filing tool. See Accounting exports.