← Back to blog

Robust KSeF Integration: Why Most Implementations Fail and How to Do It Right

KSeF is not just an HTTP call. It is an async, rate-limited government system that goes down. Here is how to build an integration that never loses an invoice.

Since 1 February 2026, KSeF (Krajowy System e-Faktur) has been mandatory for large VAT payers in Poland; since 1 April 2026 for all other VAT payers. 2026 is a grace period — penalties only kick in from 1 January 2027. That deadline is exactly where the difference between an integration that "sort of works" and one that holds up under pressure becomes visible.

Most KSeF integrations we encounter share the same flaw: they are fire-and-forget. The app sends an invoice in an HTTP request and hopes for the best. While the government system is up and fast, everything looks fine. The problem surfaces the first day KSeF responds with an error, a timeout, or a rate-limit — and the invoice silently disappears. No one finds out until an audit.

Why KSeF Is Harder Than It Looks

KSeF is not a standard REST API. It has four properties that together form a trap:

  • It is asynchronous. Sending an invoice and receiving its acknowledgement (UPO) are two separate moments in time. You have to persist state in between.
  • It is rate-limited. Batch sending will hit quotas. Without a queue and throttling, your entire invoicing pipeline stalls.
  • It goes down. State systems have outages and maintenance windows. Your invoicing must not go down with it.
  • It has its own session model. Sessions expire, tokens expire, and third-party SDKs add their own quirks on top.

When a system has two or more of these properties, you are no longer dealing with a simple API call. You are dealing with a long-running stateful workflow — and that requires a fundamentally different architecture than "call the API in a controller".

How We Build It: Durable, Not Fire-and-Forget

The core principle: every KSeF call is a durable, idempotent, persisted unit of work. Never fire-and-forget, never inside an HTTP request. These are the pillars it rests on.

1. Idempotent Submission

Every invoice gets a deterministic idempotency key. When a submission is retried — and it will be retried, due to retry logic, restarts, or race conditions — the system recognises it has already handled this and does not create a duplicate in the government system. Without idempotence, every retry is a duplicates risk.

2. Retry with Exponential Backoff

Transient errors and timeouts are the norm, not the exception. Instead of a hand-rolled retry loop (which someone always implements incorrectly), we use exponential backoff — a battle-tested mechanism that retries with increasing intervals and does not flood an already-struggling API.

3. Rate Limiting as Shared State

KSeF quotas must be respected even when you are running multiple instances. An in-memory counter in a single process is not enough — you need a shared token bucket (typically via Redis) so instances do not compete for the same quota.

4. Reconciliation Job

This is the piece almost everyone skips — and it is the most important one. A periodic job asks: "does reality match our records?" Does every invoice have a confirmation? Is anything stuck in a pending state? Are there orphans? Without reconciliation you are not monitoring — you are hoping.

5. Status Polling and UPO

Submission is just the beginning. We track status all the way through to UPO (Urzędowe Poświadczenie Odbioru) — the official acknowledgement that the government has accepted the invoice. UPO is the proof. Until you have it, the invoice is not done.

6. Audit Log and Alerting

Every state transition generates a structured event. Alerts fire on terminal failures and stuck states — before they become an audit problem. A silent LogWarning without an alert is just deferred debt.

7. Anti-Corruption Layer

We wrap the KSeF SDK in our own layer so its quirks — foreign error strings, numeric codes, session TTL — do not leak into your business logic. When the SDK changes, you change one place, not the entire codebase.

Checklist: Is Your KSeF Integration Robust?

Go through this honestly:

  • Does invoice submission survive an application restart mid-process?
  • What happens when KSeF returns a 500 or timeout — can you trace that invoice?
  • Do you have proof (UPO) for every submitted invoice, or do you just assume it went through?
  • Is there a job that verifies daily that nothing is stuck?
  • Do you get an alert when something seizes up, or do you find out from your accountant?

If any answer is "no", you have a fire-and-forget integration. It will survive the grace period. After January 2027, it will not.

Proven in Production

This is not slide-deck theory. For TrafinOil we connected billing to KSeF and during forensic recovery retrieved 15,141 missing documents that a previous fire-and-forget pipeline had silently lost. The nightly dataloader was cut from 20 hours to 30 minutes. Retry, reconciliation, and monitoring are running in production, ensuring it does not happen again.

Learn more about our KSeF integration service.

The KSeF deadline is approaching. If you are going to do this, do it so it does not fail in January 2027. Get in touch — we will tell you exactly where your integration is vulnerable.

Facing a similar problem? Get in touch.

Book a consultation