E-commerce

Invoicing and KSeF Compliance for Online Stores

Invoicing is the part of a shop where a plausible guess is worse than no answer at all. The pipeline issues what is clearly issuable, files what the law says must be filed, and hands everything else to a human with the reason attached.

Guessing is the one thing invoicing must not do

Most shop automation can afford to be approximately right and correct itself later. Invoicing cannot. A document with the wrong buyer, the wrong total or the wrong tax treatment is not a bug report, it is a correction, an accountant's time and a conversation with a customer.

So the pipeline is built around a simple division. Orders that are unambiguously invoiceable get an invoice. Orders that are unambiguously not invoiceable are skipped with the reason recorded. Everything in between is parked for a person, and parking something is treated as a normal outcome rather than a failure.

Five gates handle the clear negatives: already invoiced, dated before the configured start date, wrong currency, canceled, and not fully paid. None of them raises an error, because none of them is an error.

KSeF, and the two dates worth writing down

KSeF, the Krajowy System e-Faktur, is Poland's national e-invoicing system. From April 2026 an invoice issued to a buyer identified by a NIP has to be filed there. Penalties for failing to file begin in January 2027.

That is the whole regulatory shape, and it explains the default filing mode. A buyer with a NIP is filed, a consumer is not, which is precisely what the law asks for and nothing more. A mode that never files also exists, but it belongs to development and testing rather than to a live shop.

Every invoice carries its filing decision and the reason for it. When somebody asks in eighteen months why a specific document went to KSeF or did not, the answer is stored next to the document instead of being inferred from the code.

Working out whether the buyer is a business

The B2B decision is the pivot of the whole system, and it comes down to whether a valid NIP is present. Customers do not cooperate with this. They put the tax number in the company name field, in a note, in whichever box was nearest to their cursor.

So the extractor looks in order at the order metadata, then the billing address metadata, then a NIP parsed out of the billing address company field, and it accepts the common metadata key spellings along the way. What it does not do is trust what it finds: the checksum is validated, and a number that is not a valid Polish NIP leaves the order as a consumer sale.

A foreign VAT id is handled as its own case rather than being pushed through the NIP path. It looks similar enough to be dangerous, and treating it as a NIP would file a document that should not have been filed.

The invoices that were issued outside the shop

Every store that has been trading for a while has invoices raised by hand, in a hurry, for an order that needed a document before the software was ready. Reconciliation exists for those.

Only inFakt is consulted, and no legacy system is read. Three hard gates decide whether a document belongs to an order. The invoice date has to sit within a tolerance of the order's Warsaw calendar day, seven days by default and thirty-one at the most. The buyer has to match exactly: a normalized NIP for a B2B order, and an exact email or an exact normalized full name for a consumer one. And the gross total has to match as an integer, grosz for grosz, with no tolerance whatsoever.

Line names are never used as a signal, because product descriptions get edited on invoices and a fuzzy name match is how two different orders end up sharing a document. Matches are graded high or medium confidence, reads are always a dry run, and even a write remains a dry run until it is explicitly told to apply.

What adoption does is record a document that already exists. No invoice is created, nothing is filed to KSeF, and no issued event is emitted, so nothing downstream reacts as though a new invoice had just appeared.

What it does not do, said out loud

Corrective invoices are not automated. A canceled or refunded order that already has an invoice goes to review, and a person issues the correction in inFakt. This is a limitation and we would rather write it on the page than let it surprise you during a return, because a correction is a legal document about another legal document and the cost of getting one wrong is not symmetrical with the effort saved.

The other thing worth knowing is how it behaves before you have decided anything. With no API key configured it does nothing. Invoicing starts paused even once it is configured. There is a separate environment kill switch on top of both. Shipping inert is deliberate: the failure mode of an invoicing system that starts working the moment it is installed is a batch of documents nobody meant to issue.

It is one of the plugins we develop in the open, documented at medusa-infakt, so the rules above can be read rather than taken on trust.

What you get

Invoices issued from paid orders

An inFakt invoice raised for an order automatically, triggered on payment capture by default or on order placement if that suits your process better.

B2B filing to KSeF, consumers left alone

The default filing mode sends an invoice to KSeF when the buyer is identified by a NIP and leaves a consumer sale unfiled, which is exactly the line the regulation draws.

A NIP check that is a real check

The tax code is looked for in order through order metadata, billing address metadata and the billing address company field, and it only makes an order B2B if the checksum actually validates.

Skips with reasons instead of failures

Already invoiced, dated before your start date, wrong currency, canceled, not fully paid. Each of these skips the order and records why, so nothing sits in an error queue pretending to be broken.

Retries that give up in a useful way

Backoff starting at five minutes and doubling per attempt, capped at six hours. After eight attempts the row is marked as needing review rather than retried forever.

Reconciliation for invoices issued elsewhere

Documents raised by hand in inFakt are matched back to their orders through date, buyer identity and an exact gross total, and adopted as records rather than reissued.

How we work

  1. 01

    Agree what counts as invoiceable

    Which currencies, from which date, at which point in the order lifecycle, and what happens to the awkward cases. These are business answers rather than technical ones and they decide most of the configuration.

  2. 02

    Connect inFakt with nothing switched on

    With no API key the plugin does nothing at all, and invoicing starts paused even once it is configured. The first useful run is a read, not a write.

  3. 03

    Reconcile the history first

    Existing invoices are matched to their orders as a dry run, and stay a dry run until someone explicitly asks to apply the result. Adoption records a document that already exists: nothing is created and nothing is filed.

  4. 04

    Unpause issuing, then unpause filing

    Issuing and KSeF filing are separate decisions. Running issuing first, with filing in its development mode, gives you real invoices to inspect before anything becomes a legal submission.

  5. 05

    Work the review queue

    Everything the pipeline refuses to decide ends up in one place with a reason. That queue is the deliverable as much as the invoices are, because it is where the cases that need a person are visible instead of silent.

Tools and technology

Where a solid open-source tool exists, we choose it over a closed one. No lock-in to a single vendor, and costs you can actually predict.

  • Medusa v2
  • inFakt
  • KSeF
  • TypeScript
  • Node.js
  • PostgreSQL
  • Redis
  • Next.js
  • medusa-infakt
  • medusa-admin-kit

Frequently asked questions

More services in this category

Read testimonials from companies that trusted us

They're always a few steps ahead.

Mikołaj

CEO & Founder, GBS®

View on Clutch
GBS® logo

Delivered well ahead of the deadline.

Yasniel

CEO, IMEGA Sp z o.o.

View on Clutch

ZanReal's individual approach is impressive.

Adam

Executive, w-studio.pl

View on Clutch

Knowledge and business intuition make them a valuable partner.

Magda

Designer, DIGITALUNI

View on Clutch

Quick solutions that reduced costs by 99%.

Andrei Kapytau

Team Lead, busel.uk

View on Clutch

+20% deliverability for our email campaigns.

Joan Calabria

Sales Director, 36NORTH

View on Clutch
36NORTH logo

Latest

Technical guides, security insights, and what we've learned building with AI.

Still issuing shop invoices by hand?

Message us

Tell us how orders become invoices today, including the manual ones. We will look at what can be issued automatically, what has to be filed to KSeF, and what should stay a human decision.

Zanek

Can't keep up with changes in AI world?

Let us do the heavy lifting. Every week we distill the most important AI developments into a focused 5-minute briefing - so you stay ahead without the noise.

Find out more
Weekly AIonline