KSeF e-invoicing

Poland's mandatory e-invoicing over KSeF API 2.0, built into a Next.js app on Vercel: token auth, invoice encryption, sending, receipts and QR codes.

Released
September 29, 2026
npx skills add timerise-ai/ksef
Current release
v1.2.6
Reference docs
9
Non-negotiables
6
License
MIT

What problem does KSeF e-invoicing solve?

From February 2026 Polish businesses stop sending domestic invoices as PDFs. They file them with KSeF, the Ministry of Finance's national e-invoicing system. An invoice counts only once KSeF accepts it and issues a receipt, the UPO.

If your booking, rental or subscription system issues invoices, this becomes part of your software. Every invoice has to be encrypted, sent to the ministry's API, checked for acceptance and stored with its KSeF number and receipt. Purchase invoices come back the same way.

Three things make this harder than a normal API. There is no official TypeScript library, only C# and Java. KSeF never calls your system back, so everything is submit and poll. And nothing in the API checks that the invoice belongs to your company. A mistake files a binding tax document under the wrong taxpayer.

This skill gives a coding agent the rules and the code to build that integration into a Next.js app on Vercel, the way we build it, with those three problems handled by design.

What does the skill build?

An agent with this skill builds one module for a Next.js App Router app, on your stack. For KSeF e-invoicing that module consists of:

  • 1. Token auth
  • 2. Invoice encryption
  • 3. Interactive and batch sending
  • 4. UPO receipts
  • 5. Purchase-invoice sync
  • 6. QR codes

What it needs from you

  • A Next.js App Router app on Vercel, since the patterns assume serverless functions, Vercel Cron, and a database (Neon/Supabase Postgres or equivalent)
  • A KSeF token for the target environment; the one-time bootstrap on TEST and production is documented in references/errors-limits-and-testing.md
  • Env vars KSEF_BASE_URL, KSEF_KSEF_TOKEN, KSEF_CONTEXT_NIP to get started, plus KSEF_CREDENTIALS_ENCRYPTION_KEY and CRON_SECRET once credentials live in the database and crons run, all of them documented in references/architecture-and-vercel.md

Where do the rules come from?

This skill is written by the engineer who has shipped this integration, a KSeF invoicing module in a Next.js app on Vercel, starting from the Ministry of Finance's own API 2.0 specification and corrected against the official C# and Java clients, the live OpenAPI and what integrating it taught us. The references hold four properties: the seller NIP is compared to the authenticating context before every send, the raw ciphertext is uploaded with the IV carried once in the session metadata, a 440 duplicate resolves to its UPO in the session that accepted it, and every rejection is stored with its description and details, not only its code. The examples in assets/examples/ type-check under --strict. This skill keeps its audit record in CHANGELOG.md rather than a references/provenance.md: each release says what it fixed, added or changed and how it was verified.

Each entry is a rule that changed because the integration taught something the specification did not.

  1. Release 1.1.0, 2026-07-21

    Corrections and hardening driven by a field report from a production integration, verified against the official C#/Java clients and the live OpenAPI spec (API 2.7.0).

    • Invoice encryption (send-blocking) the skill prepended the IV to the ciphertext, following a sentence in the MF docs that both official clients contradict. KSeF then decrypted 16 bytes too many and returned status 430 blaming the invoice size, a false trail. encryptDocument() now returns raw ciphertext; decryptDocument() takes the IV as an argument.
    • Export packages parts are a binary split, so they must be concatenated before unzipping (the old loop only worked for single-part packages), and the export's IV must be persisted alongside its key to decrypt them at all.
    • Duplicates (440) status.extensions is a string-keyed object, not a list of key/value pairs; and a duplicate's UPO lives in the original session, reachable via /sessions/{originalRef}/invoices/ksef/{ksefNumber}/upo.
  2. Release 1.0.1, 2026-07-15

    Correctness fixes found by re-verifying against the live OpenAPI spec.

    • KSeF number validator CRC-8 was computed over 33 characters (including the separating hyphen) instead of the specified 32, so isValidKsefNumber rejected every valid KSeF number, including the official docs' own example.
    • Error code extraction ksefCode read exceptionDetailList at the body root; it is nested under exception. The getter always returned undefined, making the error-21470 stale-key refresh-and-retry path unreachable. It now also reads the RFC 9457 errors[].code shape, and no longer mistakes a 429 rate-limit body's HTTP status for a KSeF code.
    • An over-length challenge example, a checksum-invalid KSeF number example, and the claim that /permissions/attachments/status reports system availability (it reports attachment consent)
    • CSR key length (RSA 2048 exactly, not a minimum) and Owner rights (excludes VatUeManage)
Read the full record in CHANGELOG.md ›

What are the 6 rules the module never breaks?

Every module built from this skill holds these, whoever builds it. The same list is in the skill's README and SKILL.md, so the agent reads it before it writes a line.

  1. Upload raw ciphertext and never prepend the IV.

    It is transmitted once in encryption.initializationVector; the MF docs say otherwise, every official client contradicts them, and KSeF reports a prefixed IV as status 430 on the invoice size. assets/examples/crypto.ts is the reference implementation.

  2. The seller NIP must equal the authenticating context NIP.

    Verify before every send, and never fall back to a shared env-var token in a multi-tenant app; either mistake files invoices under the wrong taxpayer. The check in sending-interactive.md runs before the session opens.

  3. No XAdES in the runtime path.

    Authenticate out-of-band once, mint a KSeF token, and authenticate with pure node:crypto from then on. assets/examples/auth-ksef-token.ts runs that flow with no XML library.

  4. No webhooks: submit, then poll.

    State lives in your database between cron invocations, and KSeF is synced into it rather than called on a user's click, which keeps the app inside tight hourly rate limits (such as 20 metadata queries an hour, per context and IP).

  5. Everything is server-only.

    Tokens, session AES keys and invoice XML never reach a client component; credentials are encrypted at rest and never logged, echoed or embedded in code. lib/ksef/ sits behind import 'server-only', so the build fails if a client component imports it.

  6. Persist status.description and status.details, not just the code.

    The code names the category; only the text names the fault: 430 alone spans schema, hash, size and encoding faults.

When should you use it, and when not?

Use it for

  • Building or debugging a KSeF integration in a Next.js, Node.js or Vercel codebase: issuing sales invoices, ingesting purchase invoices, UPO handling, QR codes, offline modes, credentials.
  • Questions about KSeF API 2.0 mechanics: auth flows, sessions, encryption, rate limits, the test environment.

Not for

  • Other countries' e-invoicing systems, such as ViDA, PEPPOL-only flows outside KSeF, Italian SdIInsteadThat system's own API and documentation
  • Polish tax or legal adviceInsteadA tax advisor; this skill covers the API, not interpretations of the VAT Act
  • KSeF 1.0 (the SessionToken/InitSigned XML API)InsteadThe Ministry's 1.0 documentation; this skill covers API 2.0 only

How do I install it?

One command. The skills.sh CLI installs the skill into every skills-compatible agent it finds.

$ npx skills add timerise-ai/ksef

Claude Code

Invoke with /ksef

Codex CLI

Invoke with $ksef

Gemini CLI

Invoke with /skills

Name the agents instead with -a, for example npx skills add timerise-ai/ksef -a claude-code -a codex. Or clone the repository into your agent's skills folder. Nothing in it is agent-specific.

What is inside the repository (17 entries)
  • SKILL.mdEntry point: when to use and when not to, the architecture and environments, eight critical facts, six hard rules, the quick start, and the reference directory
  • README.mdThis file: the human-facing front door
  • CHANGELOG.mdEvery release, newest first, and the record of what each one fixed, added or changed and why, which is this skill's provenance
  • CLAUDE.mdWhat this repository is and its editing conventions, for an agent editing the skill itself
  • LICENSEMIT
  • references/architecture-and-vercel.mdStart here for greenfield: system model, env vars, Postgres DDL, cron polling, multi-tenancy, Vercel function limits, go-live checklist
  • references/crypto-and-client.mdThe node:crypto primitives for AES-256-CBC, RSA-OAEP key wrapping and hashes, and the typed fetch client
  • references/auth.mdChallenge flow, KSeF-token auth, access/refresh token lifecycle, the bootstrap-once XAdES step
  • references/sending-interactive.mdOnline sessions, invoice status codes, description/details/extensions, duplicates, UPO, pre-send NIP validation
  • references/sending-batch.mdSesja wsadowa (batch session): the ZIP/tar.gz pipeline, part splitting, part uploads
  • references/receiving-and-sync.mdMetadata queries, export packages, high-water-mark incremental sync
  • references/qr-codes-and-offline.mdKOD I / KOD II, verification links, offline24 and awaryjny modes, technical corrections
  • references/certificates-tokens-permissions.mdKSeF tokens, CSR enrollment, certificate types, the permissions model
  • references/errors-limits-and-testing.mdRate limits, error codes, troubleshooting, and the TEST-environment bootstrap
  • assets/examples/*.tsSix runnable scripts mirroring the reference code (npx tsx <script>): crypto.ts, ksef-client.ts, auth-ksef-token.ts, send-invoice-online.ts, poll-session-status.ts, qr-codes.ts
  • evals/The prompts an operator types after installing (prompts.md) and one file per agent eval: the skill installed into an empty Next.js app, one prompt, no help, then type-checked, built and tested
  • .github/workflows/agent-eval.ymlRuns the agent evals on every published release through the index's reusable workflow; the same in every skill

Recent releases

  1. v1.2.6September 29, 2026

    Documentation-only release. The skill's technical content, its endpoints, code and facts, is unchanged from 1.2.5; SKILL.md, the README, CLAUDE.md and the references are brought to the index's STANDARD.md.

  2. v1.2.5September 21, 2026

    Wording release. The skill content is unchanged from 1.2.4.

  3. v1.2.4September 2, 2026

    Wording release. Templates and technical content are unchanged from 1.2.3.

What do I tell my agent?

Say what you need in your own words; the skill supplies the how. These are starting points, and the ones we tested say how it went.

  1. Send our sales invoices to KSeF API 2.0 from this Next.js app on Vercel: authenticate with a KSeF token, encrypt and send each invoice, and store the UPO and the QR code.

  2. Pull our purchase invoices from KSeF into Postgres every night.

    Postgres
  3. The KSeF test environment returns status 430 for every invoice we send. Find the cause.

How does it do in each agent?

We install the skill into an empty Next.js app, give the agent one of the prompts above and no further help, then type-check, build and run the tests it left behind. Nothing is fixed by hand before the checks, and a failing run is published like a passing one. The procedure and every result are public, and the first prompt runs again before each release.

  • Gemini CLI0.61.0

    gemini-3.8-flash

    Built, checks pass
    Send our sales invoices to KSeF API 2.0 from this Next.js app on Vercel: authenticate with a KSeF token, encrypt and send each invoice, and store the UPO and the QR code.
    Typecheck: passBuild: passTests: pass
    Time
    11 min
    Changed
    32 files, +4,675 lines
    Stack
    Postgres
    Skill
    v1.2.6
    Run
    Sep 29, 2026

    Result file ›Agent log ›

  • Claude Code2.1.284

    claude-opus-5-5

    Built, checks pass
    Send our sales invoices to KSeF API 2.0 from this Next.js app on Vercel: authenticate with a KSeF token, encrypt and send each invoice, and store the UPO and the QR code.
    Typecheck: passBuild: passTests: pass
    Time
    7 min
    Changed
    31 files, +2,808 lines
    Stack
    Postgres
    Skill
    v1.2.6
    Run
    Sep 29, 2026

    Result file ›Agent log ›

Not run yet in Codex CLI.

How long does it take, and what does it cost?

We quote this module per project. The price depends on what it has to connect to. The path to a number is short and free:

  1. Step 1

    Brief

    Tell us what the module must connect to. Takes minutes, in a chat.

  2. Step 2

    Prototype in 48 hours

    A clickable prototype of your system and a quote, at no cost.

  3. Step 3

    Build and handoff

    One project price. Source code, documentation and IP are yours.

Two ways to get KSeF e-invoicing

Build it yourself

Install the skill. Your own agent builds the module.

  • MIT licensed, no strings
  • Runs in Claude Code, Codex CLI and Gemini CLI
  • The same rules our engineers build by
$ npx skills add timerise-ai/ksef

Build it with Timerise

Send a brief. We build KSeF e-invoicing into a system you own.

  • Clickable prototype and a quote within 48 hours, free
  • One project price, no subscription, no commission
  • Source code, documentation and IP handed over
3 years of support included.

Generated from the skill's own files at commit 18068ba. Every rule above links to where the repository says it. All skills