# KSeF e-invoicing (Agent Skill)

> 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.

Page: https://timerise.ai/skills/ksef

Agent Skill `ksef`: https://github.com/timerise-ai/ksef. Category: Payments & compliance. Runs on Next.js; backend: Postgres (Neon/Supabase) on Vercel.

Latest release: v1.2.6 (2026-09-29).

Install: npx skills add timerise-ai/ksef. Timerise builds it on a brief; the price comes from the brief.

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.

Build KSeF API 2.0 integrations (Krajowy System e-Faktur, Poland's national e-invoicing system) in a Next.js App Router app on Vercel. Use when: (1) sending, receiving, querying or syncing structured invoices (faktura ustrukturyzowana, FA(3) XML) through api.ksef.mf.gov.pl, (2) implementing KSeF auth: challenge, KSeF token, accessToken and refreshToken, the one-time XAdES bootstrap, (3) encrypting invoices, fetching UPO receipts, generating KOD I and KOD II QR codes, running interactive or batch sessions, offline modes, KSeF certificates, tokens or permissions, (4) debugging a rejected invoice or a rate limit, (5) the user mentions: KSeF, e-faktura, Polish e-invoicing, UPO, FA(3), NIP, sesja wsadowa, ksef.mf.gov.pl, AES-256-CBC, RSA-OAEP, publicKeyId, status 430, 440 duplicate, error 21470, 429 Retry-After. Carries TypeScript on node:crypto and fetch where the official SDKs are C# and Java only, with the details the official clients and the live OpenAPI settle: raw ciphertext with the IV carried once, the seller NIP bound to the authenticating context, a 440 duplicate resolved to its UPO, every rejection stored with its description. Next.js App Router on Vercel; the seam is the database state the cron routes resume from, so any Postgres-like store fits. Not other countries' e-invoicing, not KSeF 1.0, and not tax advice.

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](CHANGELOG.md) rather than a `references/provenance.md`: each release says what it fixed, added or changed and how it was verified.

What it builds:
- Token auth
- Invoice encryption
- Interactive and batch sending
- UPO receipts
- Purchase-invoice sync
- QR codes

When to use:
- 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.

When not to use:
- Other countries' e-invoicing systems (ViDA, PEPPOL-only flows outside KSeF, Italian SdI).
- Polish tax or legal advice: this skill covers the API, not interpretations of the VAT Act.
- KSeF 1.0 (the SessionToken/InitSigned XML API): this skill covers API 2.0 only.

Non-negotiables:
- 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.
- 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.
- 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.
- 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).
- 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.
- 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.

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

Requirements:
- 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`

Booking features we build with it:
- Invoices and e-invoicing: /features/invoicing

What to tell your agent:
- 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.
- Pull our purchase invoices from KSeF into Postgres every night.
- The KSeF test environment returns status 430 for every invoice we send. Find the cause.

Agent eval results (newest per agent and prompt):
- Gemini CLI (gemini-3.8-flash) on v1.2.6, 2026-09-29: pass (Postgres)
- Claude Code (claude-opus-5-5) on v1.2.6, 2026-09-29: pass (Postgres)

Recent releases:
- v1.2.6 (2026-09-29): 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.
- v1.2.5 (2026-09-21): Wording release. The skill content is unchanged from 1.2.4.
- v1.2.4 (2026-09-02): Wording release. Templates and technical content are unchanged from 1.2.3.
