API Reference
Complete API reference for the ksef-client-ts library — a TypeScript client for the Polish National e-Invoice System (KSeF) API v2.
Table of Contents
- KSeFClient
- AuthService
- ActiveSessionsService
- OnlineSessionService
- BatchSessionService
- SessionStatusService
- InvoiceDownloadService
- PermissionsService
- TokenService
- CertificateApiService
- LighthouseService
- LimitsService
- PeppolService
- TestDataService
- CryptographyService
- VerificationLinkService
- SignatureService (static)
- CertificateService (static)
- QrCodeService (static)
- Builders
- XML Serialization
- Error Types
- Validation
- Workflows
- KSeF Feature Constants
- Configuration
KSeFClient
Main entry point. Creates all services and wires shared dependencies.
constructor(options?: KSeFClientOptions)Properties
| Property | Type | Description |
|---|---|---|
auth | AuthService | Authentication and authorization |
activeSessions | ActiveSessionsService | List and revoke active sessions |
onlineSession | OnlineSessionService | Open/close online sessions, send invoices |
batchSession | BatchSessionService | Open/close batch sessions, upload parts |
sessionStatus | SessionStatusService | Session status, invoices, UPO retrieval |
invoices | InvoiceDownloadService | Download invoices, query metadata, export |
permissions | PermissionsService | Grant, revoke, and query permissions |
tokens | TokenService | Generate, query, and revoke KSeF tokens |
certificates | CertificateApiService | Certificate enrollment and management |
lighthouse | LighthouseService | KSeF system status and messages |
limits | LimitsService | Session, subject, and rate limits |
peppol | PeppolService | Query PEPPOL providers |
testData | TestDataService | Test environment data management |
crypto | CryptographyService | Encryption, hashing, CSR generation |
qr | VerificationLinkService | Invoice and certificate verification URLs |
options | ResolvedOptions | Resolved configuration |
authManager | AuthManager | Token store with automatic 401 refresh |
Methods
loginWithToken(token: string, nip: string): Promise<void>High-level login: challenge → crypto init → encrypt token → submit → redeem → store tokens in authManager.
loginWithCertificate(certPem: string, keyPem: string, nip: string): Promise<void>High-level login: challenge → build AuthTokenRequest XML → XAdES sign → submit → redeem → store tokens. SignatureService is dynamically imported.
logout(): Promise<void>Clear access and refresh tokens from authManager.
AuthService
Accessed via client.auth.
getChallenge(): Promise<AuthChallengeResponse>Request an authorization challenge from the KSeF API.
submitXadesAuthRequest(signedXml: string, verifyCertificateChain?: boolean): Promise<AuthenticationInitResponse>Submit a signed XAdES XML for authentication. Sends XML as application/octet-stream.
submitKsefTokenAuthRequest(payload: AuthKsefTokenRequest): Promise<AuthenticationInitResponse>Authenticate using an encrypted KSeF token.
getAuthStatus(referenceNumber: string, authToken: string): Promise<AuthenticationOperationStatusResponse>Poll the authorization status by reference number.
getAccessToken(authToken: string): Promise<AuthenticationTokensResponse>Redeem the auth token for a session access token.
refreshAccessToken(refreshToken: string): Promise<AuthenticationTokenRefreshResponse>Refresh an expired access token using a refresh token.
ActiveSessionsService
Accessed via client.activeSessions.
getActiveSessions(pageSize?: number, continuationToken?: string): Promise<AuthenticationListResponse>List all active sessions for the current subject.
revokeCurrentSession(): Promise<void>Revoke the caller's current session.
revokeSession(sessionRef: string): Promise<void>Revoke a specific session by its reference number.
OnlineSessionService
Accessed via client.onlineSession.
openSession(request: OpenOnlineSessionRequest, upoVersion?: string): Promise<OpenOnlineSessionResponse>Open a new online (interactive) session.
sendInvoice(sessionRef: string, request: SendInvoiceRequest): Promise<SendInvoiceResponse>Send an invoice within an open online session.
closeSession(sessionRef: string): Promise<void>Close an online session.
BatchSessionService
Accessed via client.batchSession.
openSession(request: OpenBatchSessionRequest, upoVersion?: string): Promise<OpenBatchSessionResponse>Open a new batch session and receive part upload URLs.
sendParts(openResponse: OpenBatchSessionResponse, parts: BatchPartSendingInfo[]): Promise<void>Upload batch parts to the pre-signed URLs from the open response.
closeSession(batchRef: string): Promise<void>Close a batch session.
SessionStatusService
Accessed via client.sessionStatus.
getSessions(type: SessionType, pageSize?: number, continuationToken?: string, filter?: SessionsFilter): Promise<SessionsQueryResponse>List sessions by type with optional filtering.
getSessionStatus(sessionRef: string): Promise<SessionStatusResponse>Get the status of a specific session.
getSessionInvoices(sessionRef: string, pageSize?: number, continuationToken?: string): Promise<SessionInvoicesResponse>List invoices processed within a session.
getSessionInvoice(sessionRef: string, invoiceRef: string): Promise<SessionInvoiceStatusResponse>Get details of a specific invoice within a session.
getSessionFailedInvoices(sessionRef: string, pageSize?: number, continuationToken?: string): Promise<SessionInvoicesResponse>List invoices that failed processing within a session.
getInvoiceUpoByKsefNumber(sessionRef: string, ksefNumber: string): Promise<UpoResult>Download UPO (official receipt) for an invoice by its KSeF number. Returns { upo: string, hash?: string }.
getInvoiceUpoByReference(sessionRef: string, invoiceRef: string): Promise<UpoResult>Download UPO for an invoice by its reference number. Returns { upo: string, hash?: string }.
getSessionUpo(sessionRef: string, upoRef: string): Promise<UpoResult>Download a session-level UPO by reference. Returns { upo: string, hash?: string }.
InvoiceDownloadService
Accessed via client.invoices.
getInvoice(ksefNumber: string): Promise<string>Download an invoice XML by its KSeF number.
queryInvoiceMetadata(filters: InvoiceQueryFilters, pageOffset?: number, pageSize?: number, sortOrder?: SortOrder): Promise<PagedInvoiceResponse>Query invoice metadata with filters and pagination.
exportInvoices(request: InvoiceExportRequest): Promise<OperationResponse>Start an asynchronous invoice export job.
getInvoiceExportStatus(ref: string): Promise<InvoiceExportStatusResponse>Check the status of an invoice export operation.
PermissionsService
Accessed via client.permissions.
Grant Methods
grantPersonPermissions(request: GrantPermissionsPersonRequest): Promise<OperationResponse>Grant permissions to a person (by PESEL, NIP, or other identifier).
grantEntityPermissions(request: GrantPermissionsEntityRequest): Promise<OperationResponse>Grant permissions to a legal entity (by NIP).
grantAuthorizationPermissions(request: GrantPermissionsAuthorizationRequest): Promise<OperationResponse>Grant authorization-level permissions.
grantIndirectPermissions(request: GrantPermissionsIndirectRequest): Promise<OperationResponse>Grant indirect permissions.
grantSubunitPermissions(request: GrantPermissionsSubunitRequest): Promise<OperationResponse>Grant permissions to a subunit.
grantEuEntityAdminPermissions(request: GrantPermissionsEuEntityAdminRequest): Promise<OperationResponse>Grant permissions to an EU entity.
grantEuEntityRepresentativePermissions(request: GrantPermissionsEuEntityRepresentativeRequest): Promise<OperationResponse>Grant permissions to an EU entity representative.
Revoke Methods
revokeCommonGrant(grantId: string): Promise<OperationResponse>Revoke a common (person/entity/subunit) permission grant by ID.
revokeAuthorizationGrant(grantId: string): Promise<OperationResponse>Revoke an authorization permission grant by ID.
Query Methods
queryPersonalGrants and queryEntitiesGrants accept an optional contextIdentifier in the request body that narrows results to a NIP or a VAT-group subunit. contextIdentifier.type is 'Nip' | 'InternalId'; InternalId values must be 10-16 characters (otherwise the call throws KSeFValidationError client-side before the request is sent).
queryPersonalGrants(
options?: QueryPersonalGrantsRequest,
pageOffset?: number,
pageSize?: number,
): Promise<PagedPermissionsResponse<PersonalPermission>>Query the caller's own permissions. Supports contextIdentifier filtering.
queryPersonsGrants(options: QueryPersonsGrantsRequest, pageOffset?: number, pageSize?: number): Promise<PagedPermissionsResponse<PersonPermission>>Query permissions granted to persons.
querySubunitsGrants(options?: QuerySubunitsGrantsRequest): Promise<PagedPermissionsResponse<SubunitPermission>>Query permissions granted to subunits.
queryEntitiesRoles(options?: QueryEntitiesRolesRequest): Promise<PagedRolesResponse<EntityRole>>Query roles assigned to entities.
queryEntitiesGrants(options?: QueryEntitiesGrantsRequest, pageOffset?: number, pageSize?: number): Promise<PagedPermissionsResponse<EntityPermissionItem>>Query permissions granted to entities. Supports contextIdentifier filtering (NIP or 10-16-char VAT-group subunit InternalId).
querySubordinateEntitiesRoles(options?: QuerySubordinateEntitiesRolesRequest): Promise<PagedRolesResponse<SubordinateEntityRole>>Query roles assigned to subordinate entities.
queryAuthorizationsGrants(options: QueryAuthorizationsGrantsRequest, pageOffset?: number, pageSize?: number): Promise<PagedAuthorizationsResponse<EntityAuthorizationGrant>>Query authorization-level grants.
queryEuEntitiesGrants(options?: QueryEuEntitiesGrantsRequest): Promise<PagedPermissionsResponse<EuEntityPermission>>Query permissions granted to EU entities.
Status Methods
getOperationStatus(ref: string): Promise<PermissionsOperationStatusResponse>Check the status of a permissions operation by reference.
getAttachmentStatus(): Promise<PermissionsAttachmentAllowedResponse>Check whether attachment permissions are enabled for the current context.
TokenService
Accessed via client.tokens.
generateToken(request: KsefTokenRequest): Promise<KsefTokenResponse>Generate a new KSeF authentication token.
queryTokens(options?: QueryKsefTokensOptions): Promise<QueryKsefTokensResponse>List all tokens for the current subject.
getToken(ref: string): Promise<AuthenticationKsefToken>Get a specific token by reference.
revokeToken(ref: string): Promise<void>Revoke a token by reference.
CertificateApiService
Accessed via client.certificates.
getLimits(): Promise<CertificateLimitResponse>Get certificate enrollment limits.
getEnrollmentData(): Promise<CertificateEnrollmentsInfoResponse>Get certificate enrollment configuration data.
enroll(request: SendCertificateEnrollmentRequest): Promise<CertificateEnrollmentResponse>Submit a certificate enrollment request (CSR).
getEnrollmentStatus(ref: string): Promise<CertificateEnrollmentStatusResponse>Check the status of a certificate enrollment by reference.
retrieve(request: CertificateListRequest): Promise<CertificateListResponse>Retrieve certificates matching the given criteria.
revoke(serialNumber: string, request: CertificateRevokeRequest): Promise<void>Revoke a certificate by serial number.
query(request: CertificateMetadataListRequest): Promise<CertificateMetadataListResponse>Query certificate metadata.
LighthouseService
Accessed via client.lighthouse. Uses raw fetch() against the lighthouse URL (not RestClient).
getStatus(): Promise<KsefStatusResponse>Get the current KSeF system status.
getMessages(): Promise<LighthouseMessage[]>Get system status messages.
LimitsService
Accessed via client.limits.
getContextLimits(): Promise<SessionLimitsInCurrentContextResponse>Get session limits for the current context.
getSubjectLimits(): Promise<CertificatesLimitInCurrentSubjectResponse>Get certificate limits for the current subject.
getRateLimits(): Promise<EffectiveApiRateLimits>Get the effective API rate limits.
PeppolService
Accessed via client.peppol.
queryProviders(pageOffset?: number, pageSize?: number): Promise<QueryPeppolProvidersResponse>Query registered PEPPOL providers.
TestDataService
Accessed via client.testData. Available only in the TEST environment.
Subject Management
createSubject(request: SubjectCreateRequest): Promise<void>Create a test subject (NIP entity).
removeSubject(request: SubjectRemoveRequest): Promise<void>Remove a test subject.
Person Management
createPerson(request: PersonCreateRequest): Promise<void>Create a test person (PESEL identity).
removePerson(request: PersonRemoveRequest): Promise<void>Remove a test person.
Permissions
grantPermissions(request: TestDataPermissionsGrantRequest): Promise<void>Grant test permissions directly (bypasses normal flow).
revokePermissions(request: TestDataPermissionsRevokeRequest): Promise<void>Revoke test permissions directly.
Attachment Permissions
enableAttachment(request: AttachmentPermissionGrantRequest): Promise<void>Enable attachment permissions for a test subject.
disableAttachment(request: AttachmentPermissionRevokeRequest): Promise<void>Disable attachment permissions for a test subject.
Session Limits
changeSessionLimits(request: SetSessionLimitsRequest): Promise<void>Override session limits in the current context.
restoreDefaultSessionLimits(): Promise<void>Restore default session limits.
Certificate Limits
changeCertificatesLimit(request: SetSubjectLimitsRequest): Promise<void>Override subject limits (enrollment/certificate) for the current subject.
restoreDefaultCertificatesLimit(): Promise<void>Restore default certificate limits.
Rate Limits
setRateLimits(request: SetRateLimitsRequest): Promise<void>Set custom API rate limits.
restoreDefaultRateLimits(): Promise<void>Restore default API rate limits.
setProductionRateLimits(): Promise<void>Set production-level rate limits in the test environment.
Context Blocking
blockContext(request: BlockContextAuthenticationRequest): Promise<void>Block a context (simulate maintenance or ban).
unblockContext(request: UnblockContextAuthenticationRequest): Promise<void>Unblock a previously blocked context.
CryptographyService
Accessed via client.crypto. Requires explicit initialization before use.
init(): Promise<void>Initialize the service by fetching and caching KSeF public certificates. Must be called before any encryption method.
AES-256-CBC
encryptAES256(content: Uint8Array, key: Uint8Array, iv: Uint8Array): Uint8ArrayEncrypt data with AES-256-CBC (PKCS7 padding).
decryptAES256(content: Uint8Array, key: Uint8Array, iv: Uint8Array): Uint8ArrayDecrypt AES-256-CBC encrypted data.
Key Wrapping
getEncryptionData(): Promise<EncryptionData>Generate a random AES-256 key + IV and wrap the key with the KSeF SymmetricKeyEncryption RSA public key (RSA-OAEP SHA-256). Uses Web Crypto under the hood for cross-runtime portability (Node, Deno, edge runtimes). Async since 0.8.0.
Token Encryption
encryptKsefToken(token: string, challengeTimestamp: string): Promise<Uint8Array>Encrypt a KSeF token for session authorization. Auto-selects RSA-OAEP (via Web Crypto) or ECDH+AES-256-GCM based on the certificate key type. Async since 0.8.0.
File Metadata
getFileMetadata(file: Uint8Array): FileMetadataCompute SHA-256 hash (base64) and byte length of a file.
CSR Generation
generateCsrRsa(fields: X500NameFields): Promise<CsrResult>Generate an RSA-2048 CSR (PKCS#10 DER) and private key PEM.
generateCsrEcdsa(fields: X500NameFields): Promise<CsrResult>Generate an ECDSA P-256 CSR (PKCS#10 DER) and private key PEM.
Key Parsing
parsePrivateKey(pem: string): crypto.KeyObjectParse a PEM-encoded private key into a Node.js KeyObject.
VerificationLinkService
Accessed via client.qr.
buildInvoiceVerificationUrl(nip: string, issueDate: Date | string, invoiceHashBase64: string): stringBuild an invoice verification URL (Code I). Format: {baseQrUrl}/invoice/{NIP}/{DD-MM-YYYY}/{hash_base64url}.
buildCertificateVerificationUrl(contextType: string, contextId: string, sellerNip: string, certSerial: string, invoiceHashBase64: string, privateKeyPem: string, privateKeyPassword?: string): stringBuild a certificate verification URL (Code II) with a cryptographic signature. Uses RSA-PSS (SHA-256, salt=32) for RSA keys or ECDSA (SHA-256, IEEE P1363) for EC keys. Pass privateKeyPassword to decrypt a password-protected PEM.
SignatureService (static)
Imported directly: import { SignatureService } from 'ksef-client-ts'.
static sign(xml: string, certPem: string, privateKeyPem: string): stringSign an XML document with an XAdES-B enveloped signature. Supports both RSA and ECDSA keys. Returns the complete signed XML document.
CertificateService (static)
Imported directly: import { CertificateService } from 'ksef-client-ts'.
static getSha256Fingerprint(certPem: string): stringCompute the SHA-256 fingerprint of a PEM certificate. Returns uppercase hex string.
static generatePersonalCertificate(givenName: string, surname: string, serialNumber: string, commonName: string, method?: CryptoEncryptionMethod): Promise<SelfSignedCertificateResult>Generate a self-signed personal certificate (for individual authentication). Default method is 'RSA'.
static generateCompanySeal(orgName: string, orgIdentifier: string, commonName: string, method?: CryptoEncryptionMethod): Promise<SelfSignedCertificateResult>Generate a self-signed company seal certificate (for entity authentication). Default method is 'RSA'.
CryptoEncryptionMethod is 'RSA' | 'ECDSA'.
SelfSignedCertificateResult contains certificatePem, privateKeyPem, and fingerprint.
QrCodeService (static)
Imported directly: import { QrCodeService } from 'ksef-client-ts'.
static generateQrCode(url: string, options?: QrCodeOptions): Promise<Buffer>Generate a QR code as a PNG buffer.
static generateQrCodeBase64(url: string, options?: QrCodeOptions): Promise<string>Generate a QR code as a base64-encoded PNG string.
static generateQrCodeSvg(url: string, options?: QrCodeOptions): Promise<string>Generate a QR code as an SVG string.
static generateQrCodeSvgWithLabel(url: string, label: string, options?: QrCodeOptions): Promise<string>Generate a QR code as an SVG string with a text label below.
static generateResult(url: string, options?: QrCodeOptions): Promise<QrCodeResult>Generate a QrCodeResult containing both the URL and its base64-encoded QR code.
QrCodeOptions
| Field | Type | Default |
|---|---|---|
width | number | 300 |
margin | number | 2 |
errorCorrectionLevel | string | 'M' |
Builders
AuthTokenRequestBuilder
Builds an AuthTokenRequest for XAdES-based authentication.
new AuthTokenRequestBuilder()
.withChallenge(challenge: string)
.withContextNip(nip: string) // or:
.withContextInternalId(id: string) // or:
.withContextNipVatUe(value: string) // or:
.withContextPeppolId(id: string)
.withSubjectType(type: SubjectIdentifierType)
.withAuthorizationPolicy(policy: AuthorizationPolicy) // optional
.build(): AuthTokenRequestAuthKsefTokenRequestBuilder
Builds an AuthKsefTokenRequest for token-based authentication.
new AuthKsefTokenRequestBuilder()
.withChallenge(challenge: string)
.withContextNip(nip: string) // or:
.withContextInternalId(id: string) // or:
.withContextNipVatUe(value: string) // or:
.withContextPeppolId(id: string)
.withEncryptedToken(token: string)
.withAuthorizationPolicy(policy: AuthorizationPolicy) // optional
.build(): AuthKsefTokenRequestInvoiceQueryFilterBuilder
Builds InvoiceQueryFilters for invoice metadata queries.
new InvoiceQueryFilterBuilder()
.withSubjectType(type: InvoiceSubjectType) // required
.withDateRange(from: string, to: string) // required
.withKsefNumber(ksefNumber: string) // optional
.withInvoiceNumber(invoiceNumber: string) // optional
.withAmountRange(from: number, to: number) // optional
.withSellerNip(nip: string) // optional
.withBuyerIdentifier(identifier: string) // optional
.withCurrencyCodes(codes: string[]) // optional
.withInvoiceFilterInvoicingMode(mode: InvoiceFilterInvoicingMode) // optional
.withSelfInvoicing(value: boolean) // optional
.withFormType(type: FormType) // optional
.withInvoiceTypes(types: InvoiceType[]) // optional
.withHasAttachment(value: boolean) // optional
.build(): InvoiceQueryFiltersPersonPermissionGrantBuilder
Builds a GrantPermissionsPersonRequest.
new PersonPermissionGrantBuilder()
.withSubjectIdentifier(type: PermissionSubjectIdentifierType, value: string)
.addPermission(permission: PersonPermissionType) // repeatable
.withPermissions(permissions: PersonPermissionType[]) // or set all at once
.build(): GrantPermissionsPersonRequestEntityPermissionGrantBuilder
Builds a GrantPermissionsEntityRequest.
new EntityPermissionGrantBuilder()
.withNip(nip: string)
.addPermission(type: EntityPermissionItemType, canDelegate?: boolean) // repeatable
.withPermissions(permissions: EntityPermission[]) // or set all
.withDescription(description: string)
.withSubjectDetails(details: EntityDetails)
.build(): GrantPermissionsEntityRequestAuthorizationPermissionGrantBuilder
Builds a GrantPermissionsAuthorizationRequest.
new AuthorizationPermissionGrantBuilder()
.withPermission(permission: EntityAuthorizationPermissionType)
.build(): GrantPermissionsAuthorizationRequestXML Serialization
Invoice XML builders in src/xml/, exported from the package root. Build FA2, FA3, PEF, or PEF_KOR XML from typed TypeScript objects with correct element ordering (including the FA3 per-VAT-rate P_13 / P_14 / P_14W interleave) and automatic namespace injection. See XML Serialization for the full guide.
serializeInvoiceXml(
input: string | Buffer | XmlDocument | FakturaInput | PefUblDocumentInput,
options?: SerializeInvoiceOptions,
): BufferPolymorphic entry point. Buffer inputs are returned byte-for-byte (as the same reference — callers must not mutate); string inputs are UTF-8 BOM-stripped and wrapped; XmlDocument arrays are rebuilt via the engine; typed inputs dispatch to the right builder. Throws KSeFValidationError naming the first missing top-level key if the input does not match any known shape.
buildFakturaXml(faktura: FakturaInput, options?: BuildFakturaOptions): stringFA2/FA3 builder. Normalizes Naglowek.KodFormularza (typed FormCode → attribute-shaped children), orders children via ORDER_MAP + natural P_* sort, and injects xmlns + xmlns:etd on <Faktura>. Default schema is FA3.
buildPefXml(input: PefUblDocumentInput, options?: BuildPefOptions): stringPEF / PEF_KOR UBL 2.1 builder. Detects the schema from the root key (Invoice → PEF, CreditNote → PEF_KOR). Injects the UBL namespace set on the root. Throws KSeFValidationError when options.schema contradicts the detected root.
buildRawXmlString(document: XmlObject, options?: { pretty?: boolean }): stringLow-level escape hatch for pre-shaped XmlObject inputs (e.g. produced by parseXml). Returns a string — wrap with Buffer.from(xml, 'utf8') for byte-ready output.
parseXml(xml: string): XmlDocument
buildXml(document: XmlDocument): string
stripBom(text: string): string
ORDER_MAP: Record<string, string[]>
comparePKey(a: string, b: string): number
orderXmlObject(obj: XmlObject, contextKey?: string): XmlObjectLower-level primitives re-exported for advanced use. ORDER_MAP keys each XSD parent to its expected child order; comparePKey is a natural-sort comparator over P_* ordinals; orderXmlObject recursively reorders an XmlObject tree.
BuildFakturaOptions
| Field | Type | Default | Description |
|---|---|---|---|
schema | 'FA2' | 'FA3' | 'FA3' | Target schema (also switches default namespaces) |
fakturaNamespace | string | per-schema constant | Override the xmlns attribute on <Faktura> |
etdNamespace | string | per-schema constant | Override the xmlns:etd attribute on <Faktura> |
pretty | boolean | false | Emit indented output |
BuildPefOptions
| Field | Type | Default | Description |
|---|---|---|---|
schema | 'PEF' | 'PEF_KOR' | inferred from root | Must match the detected root or KSeFValidationError is thrown |
pretty | boolean | false | Emit indented output |
SerializeInvoiceOptions
Union of the above — schema accepts any of 'FA2' \| 'FA3' \| 'PEF' \| 'PEF_KOR', but the value must be compatible with the dispatched builder.
Constants
| Constant | Type | Description |
|---|---|---|
FAKTURA_NAMESPACE | Record<FakturaSchema, string> | xmlns defaults for FA2 and FA3 |
ETD_NAMESPACE | Record<FakturaSchema, string> | xmlns:etd defaults for FA2 and FA3 |
PEF_NAMESPACE | Record<PefSchema, string> | UBL Invoice-2 / CreditNote-2 namespaces |
Type guards
isFakturaInput(input: unknown): input is FakturaInput
isPefUblDocumentInput(input: unknown): input is PefUblDocumentInput
isFormCodeShape(value: unknown): value is FormCode
toKodFormularza(formCode: FormCode): XmlObjectError Types
KSeFError
Base error class for all KSeF-related errors. Extends Error.
class KSeFError extends Error {
constructor(message: string)
}All other error classes extend KSeFError, so you can catch all library errors with a single instanceof KSeFError check.
KSeFApiError
Extends KSeFError. Thrown on non-2xx responses from the KSeF API.
| Field | Type | Description |
|---|---|---|
message | string | Human-readable error description |
statusCode | number | HTTP status code |
errorResponse | ApiErrorResponse? | Parsed error body from the API |
static fromResponse(statusCode: number, body?: ApiErrorResponse): KSeFApiErrorKSeFRateLimitError
Extends KSeFApiError. Thrown on HTTP 429 responses (too many requests). statusCode is a 429 literal.
| Field | Type | Description |
|---|---|---|
retryAfterSeconds | number? | Seconds to wait (from Retry-After header) |
retryAfterDate | Date? | Absolute retry time (if header was a date) |
recommendedDelay | number | Seconds to wait (falls back to 60 if unknown) |
problem | TooManyRequestsProblemDetails? | RFC 7807 body (KSeF API v2.4.0+): detail, traceId, instance, timestamp |
static fromRetryAfterHeader(
statusCode: number,
retryAfterHeader?: string | null,
body?: ApiErrorResponse,
problem?: TooManyRequestsProblemDetails,
): KSeFRateLimitErrorKSeFBadRequestError
Extends KSeFApiError. Thrown on HTTP 400 responses when the body matches BadRequestProblemDetails (KSeF API v2.4.0+). When the server returns a legacy 400 body, the client falls back to generic KSeFApiError with statusCode === 400.
| Field | Type | Description |
|---|---|---|
statusCode | 400 | Always 400 |
detail | string? | Human-readable summary of what failed |
instance | string? | The endpoint path that was called |
errors | BadRequestErrorDetail[] | Structured list of validation failures |
traceId | string? | Trace ID for debugging |
timestamp | string? | UTC timestamp recorded by the server |
interface BadRequestErrorDetail {
code: number;
description: string;
details: string[];
}KSeFUnauthorizedError
Extends KSeFApiError. Thrown on HTTP 401 responses when the body matches UnauthorizedProblemDetails.
| Field | Type | Description |
|---|---|---|
statusCode | 401 | Always 401 |
detail | string | Error detail from the API |
traceId | string? | Trace ID for debugging |
instance | string? | Request instance identifier |
timestamp | string? | UTC timestamp recorded by the server (KSeF API v2.4.0+) |
KSeFForbiddenError
Extends KSeFApiError. Thrown on HTTP 403 responses when the body matches ForbiddenProblemDetails.
| Field | Type | Description |
|---|---|---|
statusCode | 403 | Always 403 |
detail | string | Error detail from the API |
reasonCode | ForbiddenReasonCode | One of: missing-permissions, ip-not-allowed, insufficient-resource-access, auth-method-not-allowed, security-service-blocked, context-type-not-allowed |
instance | string? | Request instance identifier |
security | ForbiddenSecurityInfo & Record<string, unknown>? | Typed requiredAnyOfPermissions / presentPermissions lists plus any forward-compat fields |
traceId | string? | Trace ID for debugging |
timestamp | string? | UTC timestamp recorded by the server (KSeF API v2.4.0+) |
interface ForbiddenSecurityInfo {
requiredAnyOfPermissions?: string[];
presentPermissions?: string[];
}KSeFGoneError
Extends KSeFApiError. Thrown on HTTP 410 responses when an async operation status has aged out of the KSeF retention window (KSeF API v2.4.0+). Retention is 7 days for authentication and export operations and 30 days for certificate and permission enrollments.
| Field | Type | Description |
|---|---|---|
statusCode | 410 | Always 410 |
detail | string | Server detail, or default retention-expired message if absent |
instance | string? | Request instance identifier |
traceId | string? | Trace ID for debugging |
timestamp | string? | UTC timestamp recorded by the server |
ApiErrorResponse
interface ApiErrorResponse {
exception?: {
serviceCtx?: string;
serviceCode?: string;
serviceName?: string;
timestamp?: string;
referenceNumber?: string;
exceptionDetailList?: ExceptionDetails[];
};
}
interface ExceptionDetails {
exceptionCode: number;
exceptionDescription: string;
details?: string[];
}KSeFAuthStatusError
Extends KSeFError. Thrown when an authentication operation fails or times out.
| Field | Type | Description |
|---|---|---|
referenceNumber | string? | Auth operation reference number |
statusDescription | string? | Status description from the API |
constructor(message: string, referenceNumber?: string, statusDescription?: string)KSeFSessionExpiredError
Extends KSeFError. Thrown when a stored session has expired.
constructor(message?: string) // default: 'KSeF session has expired'KSeFValidationError
Extends KSeFError. Thrown when client-side validation fails (e.g., invalid NIP, missing required fields).
| Field | Type | Description |
|---|---|---|
details | ValidationDetail[] | List of validation issues |
constructor(message: string, details?: ValidationDetail[])
static fromField(field: string, message: string): KSeFValidationError
static fromMessages(messages: string[]): KSeFValidationErrorinterface ValidationDetail {
field?: string;
message: string;
}Error Hierarchy
Error
└── KSeFError // base class for all library errors
├── KSeFApiError // any non-2xx HTTP response
│ ├── KSeFBadRequestError // HTTP 400 (RFC 7807)
│ ├── KSeFUnauthorizedError // HTTP 401 (RFC 7807)
│ ├── KSeFForbiddenError // HTTP 403 (RFC 7807)
│ ├── KSeFGoneError // HTTP 410 (RFC 7807, retention expired)
│ ├── KSeFRateLimitError // HTTP 429 (RFC 7807)
│ └── KSeFBatchTimeoutError // KSeF exception code 21208
├── KSeFAuthStatusError // auth operation failed/timed out
├── KSeFSessionExpiredError // stored session expired
└── KSeFValidationError // client-side validation failedAll server-returned HTTP errors extend KSeFApiError, so a single instanceof KSeFApiError check covers every response-side failure. RestClient.ensureSuccess dispatches errors in order: 429 → 401 → 403 → 410 → 400 → (exceptionCode 21208 → KSeFBatchTimeoutError) → generic KSeFApiError.
KSeFApiProblem
Discriminated union of every RFC 7807 error class, keyed by statusCode literal.
type KSeFApiProblem =
| KSeFBadRequestError // statusCode: 400
| KSeFUnauthorizedError // statusCode: 401
| KSeFForbiddenError // statusCode: 403
| KSeFGoneError // statusCode: 410
| KSeFRateLimitError; // statusCode: 429Use with assertNever for exhaustive compile-time dispatch:
import { assertNever, type KSeFApiProblem } from 'ksef-client-ts';
function describe(err: KSeFApiProblem): string {
switch (err.statusCode) {
case 400: return `Validation: ${err.errors.length} error(s)`;
case 401: return 'Authenticate and retry';
case 403: return `Forbidden: ${err.reasonCode}`;
case 410: return 'Operation status expired';
case 429: return `Rate limited, retry in ${err.recommendedDelay}s`;
default: return assertNever(err);
}
}assertNever
function assertNever(value: never): neverThrows Error('Unexpected value: ...') at runtime. Its primary purpose is compile-time: adding a new variant to KSeFApiProblem causes assertNever to fail type-checking at every dispatch site until handled.
Validation
Regex Patterns
All patterns are exported as RegExp constants.
| Pattern | Description |
|---|---|
Nip | Polish NIP (10-digit tax ID) |
VatUe | EU VAT number (all member states) |
NipVatUe | Combined NIP-VatUE format |
InternalId | KSeF internal identifier (NIP-XXXXX) |
PeppolId | PEPPOL participant ID |
ReferenceNumber | KSeF operation reference number |
KsefNumber | KSeF invoice number |
KsefNumberV35 | KSeF invoice number (v3.5 format) |
KsefNumberV36 | KSeF invoice number (v3.6 format) |
CertificateName | Valid certificate name (alphanumeric + Polish) |
Pesel | Polish PESEL (11-digit personal ID) |
CertificateFingerprint | SHA-256 fingerprint (64 hex chars uppercase) |
Base64String | Standard base64 string |
Ip4Address | IPv4 address |
Ip4Range | IPv4 range (addr-addr) |
Ip4Mask | IPv4 CIDR mask (addr/prefix) |
Sha256Base64 | SHA-256 hash encoded as base64 (44 chars) |
Validator Functions
Each returns boolean. Functions marked with CRC-8 verify the checksum in addition to regex format.
isValidNip(value: string): boolean // regex + weighted checksum (mod 11)
isValidPesel(value: string): boolean // regex + weighted checksum (mod 10)
isValidKsefNumber(value: string): boolean // regex + CRC-8 (handles 35 and 36-char formats)
isValidKsefNumberV35(value: string): boolean // regex + CRC-8 (35-char canonical format)
isValidKsefNumberV36(value: string): boolean // regex + CRC-8 (36-char format with middle hyphen)
isValidVatUe(value: string): boolean
isValidNipVatUe(value: string): boolean
isValidInternalId(value: string): boolean
isValidPeppolId(value: string): boolean
isValidReferenceNumber(value: string): boolean
isValidCertificateName(value: string): boolean
isValidCertificateFingerprint(value: string): boolean
isValidBase64(value: string): boolean
isValidIp4Address(value: string): boolean
isValidSha256Base64(value: string): booleanKSeF Number CRC-8 Validation
KSeF invoice numbers are exactly 35 characters: 32 data chars + separator + 2-char CRC-8 checksum (uppercase hex). The CRC-8 uses polynomial 0x07 with init value 0x00, matching the official specification.
5265877635-20250826-0100001AF629-AF
| | | |
NIP(10) Date(8) TechHex(12) CRC-8(2)isValidKsefNumber() accepts both 35-char (HHHHHHHHHHHH) and 36-char (HHHHHH-HHHHHH) formats, normalizing internally before CRC verification.
Constraints
| Constant | Value |
|---|---|
REQUIRED_CHALLENGE_LENGTH | 36 |
CERTIFICATE_NAME_MIN_LENGTH | 5 |
CERTIFICATE_NAME_MAX_LENGTH | 100 |
SUBUNIT_NAME_MIN_LENGTH | 5 |
SUBUNIT_NAME_MAX_LENGTH | 256 |
PERMISSION_DESCRIPTION_MIN_LENGTH | 5 |
PERMISSION_DESCRIPTION_MAX_LENGTH | 256 |
Configuration
KSeFClientOptions
All fields are optional. Defaults to the TEST environment.
interface KSeFClientOptions {
environment?: EnvironmentName; // 'TEST' | 'DEMO' | 'PROD'
baseUrl?: string; // Override API base URL
baseQrUrl?: string; // Override QR verification base URL
lighthouseUrl?: string; // Override lighthouse status URL
apiVersion?: string; // Default: 'v2'
timeout?: number; // Default: 30000 (ms)
customHeaders?: Record<string, string>; // Extra headers for all requests
authManager?: AuthManager; // Custom AuthManager (default: DefaultAuthManager)
transport?: TransportFn; // Custom fetch implementation
retry?: Partial<RetryPolicy>; // Retry policy overrides
rateLimit?: { globalRps?: number; endpointLimits?: ... } | null; // null disables
presignedUrlHosts?: string[]; // Additional allowed hosts for presigned URLs
errorFormat?: 'problem-details' | 'legacy'; // Default: 'problem-details' (RFC 7807)
}ResolvedOptions
The fully resolved configuration used internally.
interface ResolvedOptions {
baseUrl: string;
baseQrUrl: string;
lighthouseUrl: string;
apiVersion: string;
timeout: number;
customHeaders: Record<string, string>;
environmentName?: EnvironmentName;
errorFormat: 'problem-details' | 'legacy';
}Environment
Pre-configured environments with API, QR, and lighthouse URLs.
| Name | API URL | QR URL |
|---|---|---|
TEST | https://api-test.ksef.mf.gov.pl | https://qr-test.ksef.mf.gov.pl |
DEMO | https://api-demo.ksef.mf.gov.pl | https://qr-demo.ksef.mf.gov.pl |
PROD | https://api.ksef.mf.gov.pl | https://qr.ksef.mf.gov.pl |
Workflows
High-level orchestration functions that combine multiple service calls into common multi-step operations. All functions are exported from the package root.
Authentication Workflows
import { authenticateWithToken, authenticateWithCertificate, authenticateWithPkcs12 } from 'ksef-client-ts';
// Token auth: challenge → encrypt → submit → poll → redeem tokens
const result = await authenticateWithToken(client, {
token: 'your-ksef-token',
nip: '1234567890',
});
// result: { accessToken, refreshToken, accessTokenExpiry, refreshTokenExpiry }
// Certificate auth: challenge → XAdES sign → submit → poll → redeem tokens
const result = await authenticateWithCertificate(client, {
certPem: '-----BEGIN CERTIFICATE-----...',
keyPem: '-----BEGIN PRIVATE KEY-----...',
nip: '1234567890',
});
// PKCS#12 auth: load P12 → delegate to certificate auth
const result = await authenticateWithPkcs12(client, {
p12Buffer: fs.readFileSync('cert.p12'),
password: 'secret',
nip: '1234567890',
});Online Session Workflows
import { openOnlineSession, openSendAndClose } from 'ksef-client-ts';
// Open a session and get a handle for sending invoices
const handle = await openOnlineSession(client, { formCode, encryption });
await handle.sendInvoice(invoiceRequest);
await handle.close();
const upo = await handle.waitForUpo();
// Or do it all in one call: open → send → close → poll UPO
const upo = await openSendAndClose(client, {
formCode, encryption, invoices: [invoice1, invoice2],
});Batch Session Workflow
import { uploadBatch } from 'ksef-client-ts';
const result = await uploadBatch(client, {
formCode, encryption, parts: [{ partContent, partSize, partHash }],
});
// result: { sessionReference, upo }Invoice Export Workflows
import { exportInvoices, exportAndDownload } from 'ksef-client-ts';
// Initiate export and poll until ready
const result = await exportInvoices(client, { queryFilters });
// result: { parts: [{ ordinal, url, size, hash, expiration }] }
// Or export + download + decrypt in one call
const result = await exportAndDownload(client, { queryFilters, cipherKey, cipherIv });
// result: { parts: [...], decryptedParts: [Uint8Array, ...] }Polling Utility
import { pollUntil } from 'ksef-client-ts';
// Generic polling with configurable interval and max attempts
const result = await pollUntil(
() => client.sessionStatus.getSessionStatus(ref),
(status) => status.processingCode === 200,
{ intervalMs: 2000, maxAttempts: 30 },
);Workflow Types
| Type | Description |
|---|---|
PollOptions | intervalMs, maxAttempts, onProgress callback |
OnlineSessionHandle | Session ref + sendInvoice(), close(), waitForUpo() methods |
UpoInfo | Pages with reference numbers, download URLs, invoice counts |
BatchUploadResult | Session reference + UPO info |
ExportResult | Export parts array (ordinal, URL, size, hash, expiration) |
ExportDownloadResult | Extends ExportResult with decryptedParts: Uint8Array[] |
AuthResult | Access/refresh tokens with expiry timestamps |
KSeF Feature Constants
Constants for the X-KSeF-Feature header, used to negotiate UPO format version and XAdES compliance.
import { KSEF_FEATURE_HEADER, UpoVersion, ENFORCE_XADES_COMPLIANCE } from 'ksef-client-ts';| Constant | Value | Description |
|---|---|---|
KSEF_FEATURE_HEADER | 'X-KSeF-Feature' | HTTP header name for feature negotiation |
UpoVersion.V4_2 | 'upo-v4-2' | UPO format v4-2 (default before 2026-01-05) |
UpoVersion.V4_3 | 'upo-v4-3' | UPO format v4-3 (adds InvoicingMode field) |
ENFORCE_XADES_COMPLIANCE | 'enforce-xades-compliance' | Strict XAdES validation in auth requests |
Session open methods (onlineSession.openSession(), batchSession.openSession()) and auth.submitXadesAuthRequest() accept an optional upoVersion parameter to set this header.