@naprawksef/sdk
v1.0.0
Published
Official TypeScript / Node.js SDK for the NaprawKSeF API (KSeF XML validation, FA(3) correction builder, webhooks). Zero runtime dependencies; works in Node ≥18, Bun, Deno and edge runtimes.
Downloads
146
Maintainers
Readme
@naprawksef/sdk
Official TypeScript / Node.js SDK for the NaprawKSeF API.
- Full coverage of
/api/v1: validate, correction analyze, scenarios, webhooks, me, health - Typed request/response models (mirrors OpenAPI 3.1)
- Built-in retries (429, 5xx, network), respects
Retry-After - Automatic
Idempotency-Keygeneration for POST requests - Webhook signature verification helper (constant-time HMAC-SHA256)
- Zero runtime dependencies — only Node 18+ built-ins
- Works in Node, Bun, Deno, Cloudflare Workers, Vercel Edge
Installation
npm install @naprawksef/sdk
# or
pnpm add @naprawksef/sdk
# or
yarn add @naprawksef/sdkRequires Node.js 18 or newer.
Quick start
import { NaprawKsef } from "@naprawksef/sdk";
import { readFileSync } from "node:fs";
const client = new NaprawKsef({
apiKey: process.env.NAPRAW_KSEF_API_KEY!, // nk_live_... or nk_test_...
appName: "trawers-erp/7.4.2", // optional, attached to User-Agent
});
// 1. Who am I? (rate-limit + scope check)
const me = await client.me.retrieve();
console.log(me.organization.name, me.key.scopes);
// 2. Validate a KSeF XML
const xml = readFileSync("invoice.xml", "utf8");
const result = await client.validate.run({ xml, filename: "invoice.xml" });
if (!result.valid) {
for (const issue of result.issues) {
console.error(`[${issue.severity}] ${issue.code} → ${issue.message}`);
}
}
// 3. Analyse for FA(3) correction scenarios
const analysis = await client.correction.analyze({ xml });
console.log(analysis.suggestions); // top 5 scenarios with confidenceAPI keys
API keys come in two environments:
| Prefix | Environment | Quota | History |
|-------------|-------------|-------|---------|
| nk_live_* | production | counts against your plan | persisted in dashboard |
| nk_test_* | sandbox | bypassed | not persisted |
Both are 44 characters long (nk_<env>_<4 hex prefix><32 hex secret>).
The SDK rejects malformed keys at construction time.
Idempotency
Every POST that mutates state accepts an Idempotency-Key header (8–200 chars).
The SDK auto-generates a UUID when you don't supply one — pass your own to
guarantee replay safety from your own retry loop:
await client.validate.run(
{ xml, idempotencyKey: `invoice-${invoiceId}-v3` },
);Replays return the original response for 24 hours. Conflicting bodies under
the same key yield a NaprawKsefIdempotencyConflictError.
Errors
All API errors are subclasses of NaprawKsefError and carry the original
status, code, requestId and headers:
import {
NaprawKsefAuthError,
NaprawKsefRateLimitError,
NaprawKsefValidationError,
} from "@naprawksef/sdk";
try {
await client.validate.run({ xml });
} catch (e) {
if (e instanceof NaprawKsefRateLimitError) {
console.log("Wait", e.retryAfterSeconds, "seconds");
} else if (e instanceof NaprawKsefAuthError) {
console.log("Key rotated?", e.message);
} else if (e instanceof NaprawKsefValidationError) {
console.log("Bad input:", e.details);
} else {
throw e;
}
}Retries
The SDK retries 429, 408, 425, 500, 502, 503, 504, and network
errors up to maxRetries times (default 3) with decorrelated jitter
(±20 %). Retry-After is honoured on 429/503.
Disable retries entirely with maxRetries: 0.
Webhooks
Verify incoming events with the standalone helper (no client needed):
import { verifyWebhookSignature } from "@naprawksef/sdk/webhooks";
// Next.js App Router example
export async function POST(req: Request) {
const rawBody = await req.text();
const header = req.headers.get("x-nk-signature");
const result = verifyWebhookSignature({
secret: process.env.NAPRAW_KSEF_WEBHOOK_SECRET!,
rawBody,
header,
});
if (!result.ok) {
return new Response(`Invalid signature: ${result.reason}`, { status: 401 });
}
const event = JSON.parse(rawBody);
// … handle event.type ("validation.completed", etc.)
return new Response("ok");
}Express raw body example:
import express from "express";
import { verifyWebhookSignature } from "@naprawksef/sdk/webhooks";
app.post("/webhooks/napraw-ksef",
express.raw({ type: "application/json" }),
(req, res) => {
const result = verifyWebhookSignature({
secret: process.env.NAPRAW_KSEF_WEBHOOK_SECRET!,
rawBody: req.body.toString("utf8"),
header: req.header("x-nk-signature"),
});
if (!result.ok) return res.status(401).send(result.reason);
// …
res.send("ok");
},
);Observability
const client = new NaprawKsef({
apiKey: process.env.NAPRAW_KSEF_API_KEY!,
hooks: {
onResponse: ({ method, url, status, durationMs, requestId }) => {
log.info({ method, url, status, durationMs, requestId }, "nk.api");
},
onRetry: ({ url, attempt, delayMs, reason }) => {
log.warn({ url, attempt, delayMs, reason }, "nk.api.retry");
},
},
});Custom fetch (testing, edge runtimes)
const client = new NaprawKsef({
apiKey,
fetchImpl: customFetch,
});License
MIT. See LICENSE.
