← BlogBlog

Poland's KSeF e-invoicing is live. Here is the invoice pipeline your Polish entity needs.

KSeF, Poland's mandatory e-invoicing system, has been live since February 2026 for the largest companies and since April for nearly everyone else with a Polish entity. If your finance team still files it under "the accountant's problem", the pipeline that feeds your ERP is about to break in ways no "KSeF is coming" explainer will help you fix.

What KSeF e-invoicing actually changes for a Polish finance team

Start with the flow that dies. For years the shape was the same on both sides. An invoice arrives as a PDF in someone's inbox, a person reads it, and either keys it into the ERP or lets an OCR tool guess at the fields. Accounts payable eyeballs it against a purchase order, an accountant codes it to a GL account, and it gets posted. Outbound, the ERP renders a PDF and emails it, and everyone hopes the client received it.

Under KSeF, the PDF stops being the invoice. An outbound invoice is now structured XML built to the FA(3) schema, sent to KSeF over its API. KSeF validates the document and either rejects it or accepts it and stamps a numer KSeF on it. That number, not an email, is your proof the invoice legally exists. Receiving is mandatory too: from 1 February 2026 every company has to be able to take invoices in through KSeF, so your Polish suppliers' invoices now arrive as FA(3) XML you pull from the system, not as attachments you can skim.

Here is the part the explainers skip. KSeF is a transport and registry layer, not an accounting engine. It hands you a clean, schema-valid XML and a number. It does not match that invoice to your purchase order, and it does not code it or post it. All of that reconciliation work is still yours, it just now starts from structured data instead of a scanned page. So the eyeballing-a-PDF step disappears for Polish counterparties, and the coding and matching work does not. Teams that assumed KSeF equals automation discover the automation they actually need sits on both sides of KSeF, and they still have to build it.

The flow before and after you automate around KSeF
StepManual flow (dying)Automated pipeline
Inbound receiptSupplier PDF lands in an inboxFA(3) XML pulled from KSeF on a schedule
Data captureOCR or manual keying, part guessworkParse structured XML, fields already typed
MatchingA clerk compares PO and delivery by eyeRules match the clean cases, AI proposes the rest
GL coding (dekretacja)Accountant codes each line by handModel suggests coding, human clears the exceptions
Outbound issueERP emails a PDF and hopesXML validated, submitted, numer KSeF captured
Proof of delivery"Did they get the email?"Acceptance in KSeF is the receipt

The target pipeline, one stage at a time

Think of it as two pipelines that meet at KSeF, with one human gate in the middle. Outbound first, because that is where a mistake becomes a legal problem fastest.

Your billing system produces invoice data. A mapping step turns that data into FA(3) XML, and this is deterministic code, because every field has exactly one place in the schema and you want to get the mapping right once rather than approximately every time. Then you validate the XML locally against the FA(3) XSD, at your own border, before you ever call KSeF. Only then do you submit. KSeF answers with acceptance and a number, or a rejection and an error, and your code stores the number against the ERP document or routes the error to a person.

The local validation gate is worth dwelling on, because a pipeline that only finds out its output is broken when KSeF rejects it is a pipeline that fails at month-end under load. In a Figma-to-code system we built in a different domain, the cheap structural check was never enough on its own; the gate that actually held was a validation loop that re-rendered the output and compared it to the source, and it caught misalignment in about 15% of frames that structurally valid code had hidden. The same instinct applies here. Check your work before you hand it over, not after.

Inbound runs the other way. A scheduled job polls KSeF for new invoices, parses each FA(3) XML into your own canonical record, and deduplicates so the same document does not enter twice. Rules match it to a purchase order and a goods receipt. Then comes dekretacja: assigning the GL account and cost center, and deciding the VAT treatment. Everything that matches cleanly and codes confidently flows straight to posting. Everything else stops at the gate.

That gate is the load-bearing decision in the whole design. You are not choosing between fully manual and fully automated. You are choosing a threshold. Invoices that match cleanly and code within tolerance post themselves; the exceptions queue for a person, each one carrying the reason it stopped. Get the threshold right and a human touches the handful of invoices that genuinely need judgement, instead of re-checking the hundreds that don't.

Where AI earns its keep, and where plain code wins

This split is where most KSeF automation goes wrong, in one of two directions. One team points a language model at the whole thing because "AI", and lets it generate XML that is mostly valid, which is another way of saying sometimes invalid. Another team hand-codes the fuzzy classification work that a model would do better, and drowns in rules. The honest answer is that KSeF automation is mostly deterministic code with a few well-chosen places where a model earns its seat. That honest split, not a blanket "AI does invoices now", is the difference between a pipeline you can trust at month-end and one you babysit.

Use plain, deterministic code for anything with one correct answer and a schema behind it. Building and parsing FA(3) XML is exactly that: a fixed structure where "mostly right" is a bug, not a feature. XSD validation is pass or fail. Deduplicating on the numer KSeF, submitting with idempotency, retrying with backoff when KSeF is slow, looking up a VAT rate: none of these want a model's judgement, they want a function that behaves the same way every time. A language model in any of these spots adds cost and latency, plus a failure mode you did not have before.

Bring in a model where the answer is a judgement call and you have history to learn from. Dekretacja is the clearest case: mapping a free-text line item to the right account and cost center is fuzzy classification, and because FA(3) is structured, the model classifies clean fields instead of OCR mush, which makes it both easier and more reliable. Matching messy invoice lines to purchase orders when SKUs were renamed or a delivery was partial is another spot where a model proposes what a rules engine can't. So is flagging anomalies, a supplier billing in a currency they never use or an amount ten times their usual, where the model surfaces it and a person decides.

One more place earns a model honestly: the invoices that never enter KSeF at all. A foreign supplier with no fixed establishment in Poland is exempt, so they keep sending you PDFs, and OCR plus LLM extraction still does real work there. The rule of thumb holds across all of it. Use deterministic code where there is a schema and one right answer. Bring in a model where the answer is a judgement call, and keep a person behind the model whenever that judgement carries money or law.

The honest split: which tool for which job
TaskRight toolWhy
Build and parse FA(3) XMLDeterministic codeFixed schema; "mostly valid" is a bug
Validate against the XSDDeterministic codePass or fail has one answer
Deduplicate invoicesDeterministic codeKey on the numer KSeF
Submit and retry to KSeFDeterministic codeIdempotency and backoff, not judgement
GL coding (dekretacja)AI proposes, human approvesFuzzy classification with history to learn from
Match messy lines to POsRules first, AI on the restRules clear the clean cases, the model the odd ones
Flag anomaliesAI surfaces, human decidesA pattern too irregular to enumerate as rules

The failure modes you design for on day one

A demo handles the happy path. Production is the edge cases, and with KSeF the edge cases carry legal weight, so you design for them from the start rather than patching them in after the first bad month-end.

Schema rejections come first. KSeF rejects malformed XML, and a rejected outbound invoice that nobody notices is an unissued invoice, a compliance gap and a cash-flow hole at once. Validate locally so most rejections never happen, and when KSeF still says no, raise it to a person with the exact error attached. Silent failure is the one outcome you cannot allow here.

Duplicates come next. The same invoice can reach your system more than once: a re-poll, a resubmission, an offline invoice that arrives twice once connectivity returns. You dedupe on the numer KSeF and treat submission as idempotent. This is the exactly-once problem, and it is the same shape we solved in a real-time feed pipeline where one posting could arrive on overlapping windows and still had to be delivered exactly once. Retry-with-backoff on transient KSeF errors lives in the same layer.

Then the awkward invoices. Corrections (faktura korygująca), multi-currency documents, exempt foreign suppliers who still send PDFs, invoices carrying an attachment now that FA(3) added a node for one: each is a branch you enumerate before go-live, because these are the ones that stall a batch at the worst time. Offline mode has its own clock. The tryb offline24 lets you issue without a live connection, but you have until the next business day to send the document to KSeF, and a longer window applies only during an announced KSeF outage. That deadline is something you monitor, not something you hope holds.

The failure that bites quietly is mapping drift. Your ERP changes a field, your FA(3) mapping keeps producing XML that is valid but semantically wrong, and it sails through the schema check to fail an audit months later. Valid-but-wrong is more dangerous than malformed, because malformed gets rejected and wrong gets accepted. The defense is a round-trip check on meaning, not just structure: build the XML, parse it straight back into a record, and diff that against what you meant to send, before KSeF sees it and long before your accountant does.

A readiness check you can run this week

You can pressure-test your own setup without hiring anyone. Walk these seven questions and be honest about which ones you can answer with a system rather than a person's memory.

Run these against your own setup
CheckYou are ready when
FA(3) mappingEvery ERP invoice field has a schema slot, verified against the XSD
Local validationBad XML is rejected at your border, before you call KSeF
Inbound pollingA scheduled job pulls new invoices and dedupes on the numer KSeF
Human gateExceptions queue to a named person with the reason attached
Offline24 clockOffline invoices are tracked against the next-business-day deadline
Edge casesCorrections, multi-currency and exempt foreign suppliers each have a branch
Rejection handlingA rejected invoice raises an alert and never disappears

If you can answer all seven with a system, you are in good shape and mostly need monitoring. If three or four are still "a person remembers to check", that is your build list, in priority order. And the current deadlines, thresholds and schema versions are the one thing worth re-reading at the source before you commit code, because KSeF has moved its dates more than once: the official schedule on podatki.gov.pl is the reference. If you would rather have someone map that build list against your ERP and stack with you, that is the kind of thing we do in a free audit.

FAQ

Does KSeF replace our accounting or ERP software?

No. KSeF is a transport and registry layer: it validates a structured invoice, stores it, and returns a numer KSeF. Matching to a PO, coding to a GL account, and posting all still happen in your systems. If anything, KSeF makes the case for automating those steps stronger, because your inputs are now clean structured data instead of PDFs.

We are a foreign company with a Polish entity. Does KSeF apply to us?

It turns on whether you have a fixed establishment in Poland that takes part in the transaction. With no seat and no participating fixed establishment here, you generally issue outside KSeF. But your Polish suppliers issue to you through KSeF regardless, so your inbound side is affected either way. The exact test lives on podatki.gov.pl, and it is worth reading with your tax advisor rather than guessing.

Can we let AI post invoices to GL accounts automatically?

Let it propose, not silently post. A model can code the confident majority and route low-confidence lines to a person, with every decision logged. Auto-posting the uncertain ones removes the human exactly where the judgement, and the audit exposure, is highest.

What happens if KSeF rejects an invoice?

It is not legally issued until KSeF accepts it. So validate locally first to catch most problems before they reach KSeF, alert a person on any rejection, and never let a rejected invoice fail silently. An unnoticed rejection is an invoice you never issued.

Changelog
  • 12 July 2026Published.
Free process audit

See what this would look like in your operations.

Get in touch

30 minutes · we map your 3 best automation opportunities · no obligation