Skip to content

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

  1. KSeFClient
  2. AuthService
  3. ActiveSessionsService
  4. OnlineSessionService
  5. BatchSessionService
  6. SessionStatusService
  7. InvoiceDownloadService
  8. PermissionsService
  9. TokenService
  10. CertificateApiService
  11. LighthouseService
  12. LimitsService
  13. PeppolService
  14. TestDataService
  15. CryptographyService
  16. VerificationLinkService
  17. SignatureService (static)
  18. CertificateService (static)
  19. QrCodeService (static)
  20. Builders
  21. XML Serialization
  22. Error Types
  23. Validation
  24. Workflows
  25. KSeF Feature Constants
  26. Configuration

KSeFClient

Main entry point. Creates all services and wires shared dependencies.

ts
constructor(options?: KSeFClientOptions)

Properties

PropertyTypeDescription
authAuthServiceAuthentication and authorization
activeSessionsActiveSessionsServiceList and revoke active sessions
onlineSessionOnlineSessionServiceOpen/close online sessions, send invoices
batchSessionBatchSessionServiceOpen/close batch sessions, upload parts
sessionStatusSessionStatusServiceSession status, invoices, UPO retrieval
invoicesInvoiceDownloadServiceDownload invoices, query metadata, export
permissionsPermissionsServiceGrant, revoke, and query permissions
tokensTokenServiceGenerate, query, and revoke KSeF tokens
certificatesCertificateApiServiceCertificate enrollment and management
lighthouseLighthouseServiceKSeF system status and messages
limitsLimitsServiceSession, subject, and rate limits
peppolPeppolServiceQuery PEPPOL providers
testDataTestDataServiceTest environment data management
cryptoCryptographyServiceEncryption, hashing, CSR generation
qrVerificationLinkServiceInvoice and certificate verification URLs
optionsResolvedOptionsResolved configuration
authManagerAuthManagerToken store with automatic 401 refresh

Methods

ts
loginWithToken(token: string, nip: string): Promise<void>

High-level login: challenge → crypto init → encrypt token → submit → redeem → store tokens in authManager.

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

ts
logout(): Promise<void>

Clear access and refresh tokens from authManager.


AuthService

Accessed via client.auth.

ts
getChallenge(): Promise<AuthChallengeResponse>

Request an authorization challenge from the KSeF API.

ts
submitXadesAuthRequest(signedXml: string, verifyCertificateChain?: boolean): Promise<AuthenticationInitResponse>

Submit a signed XAdES XML for authentication. Sends XML as application/octet-stream.

ts
submitKsefTokenAuthRequest(payload: AuthKsefTokenRequest): Promise<AuthenticationInitResponse>

Authenticate using an encrypted KSeF token.

ts
getAuthStatus(referenceNumber: string, authToken: string): Promise<AuthenticationOperationStatusResponse>

Poll the authorization status by reference number.

ts
getAccessToken(authToken: string): Promise<AuthenticationTokensResponse>

Redeem the auth token for a session access token.

ts
refreshAccessToken(refreshToken: string): Promise<AuthenticationTokenRefreshResponse>

Refresh an expired access token using a refresh token.


ActiveSessionsService

Accessed via client.activeSessions.

ts
getActiveSessions(pageSize?: number, continuationToken?: string): Promise<AuthenticationListResponse>

List all active sessions for the current subject.

ts
revokeCurrentSession(): Promise<void>

Revoke the caller's current session.

ts
revokeSession(sessionRef: string): Promise<void>

Revoke a specific session by its reference number.


OnlineSessionService

Accessed via client.onlineSession.

ts
openSession(request: OpenOnlineSessionRequest, upoVersion?: string): Promise<OpenOnlineSessionResponse>

Open a new online (interactive) session.

ts
sendInvoice(sessionRef: string, request: SendInvoiceRequest): Promise<SendInvoiceResponse>

Send an invoice within an open online session.

ts
closeSession(sessionRef: string): Promise<void>

Close an online session.


BatchSessionService

Accessed via client.batchSession.

ts
openSession(request: OpenBatchSessionRequest, upoVersion?: string): Promise<OpenBatchSessionResponse>

Open a new batch session and receive part upload URLs.

ts
sendParts(openResponse: OpenBatchSessionResponse, parts: BatchPartSendingInfo[]): Promise<void>

Upload batch parts to the pre-signed URLs from the open response.

ts
closeSession(batchRef: string): Promise<void>

Close a batch session.


SessionStatusService

Accessed via client.sessionStatus.

ts
getSessions(type: SessionType, pageSize?: number, continuationToken?: string, filter?: SessionsFilter): Promise<SessionsQueryResponse>

List sessions by type with optional filtering.

ts
getSessionStatus(sessionRef: string): Promise<SessionStatusResponse>

Get the status of a specific session.

ts
getSessionInvoices(sessionRef: string, pageSize?: number, continuationToken?: string): Promise<SessionInvoicesResponse>

List invoices processed within a session.

ts
getSessionInvoice(sessionRef: string, invoiceRef: string): Promise<SessionInvoiceStatusResponse>

Get details of a specific invoice within a session.

ts
getSessionFailedInvoices(sessionRef: string, pageSize?: number, continuationToken?: string): Promise<SessionInvoicesResponse>

List invoices that failed processing within a session.

ts
getInvoiceUpoByKsefNumber(sessionRef: string, ksefNumber: string): Promise<UpoResult>

Download UPO (official receipt) for an invoice by its KSeF number. Returns { upo: string, hash?: string }.

ts
getInvoiceUpoByReference(sessionRef: string, invoiceRef: string): Promise<UpoResult>

Download UPO for an invoice by its reference number. Returns { upo: string, hash?: string }.

ts
getSessionUpo(sessionRef: string, upoRef: string): Promise<UpoResult>

Download a session-level UPO by reference. Returns { upo: string, hash?: string }.


InvoiceDownloadService

Accessed via client.invoices.

ts
getInvoice(ksefNumber: string): Promise<string>

Download an invoice XML by its KSeF number.

ts
queryInvoiceMetadata(filters: InvoiceQueryFilters, pageOffset?: number, pageSize?: number, sortOrder?: SortOrder): Promise<PagedInvoiceResponse>

Query invoice metadata with filters and pagination.

ts
exportInvoices(request: InvoiceExportRequest): Promise<OperationResponse>

Start an asynchronous invoice export job.

ts
getInvoiceExportStatus(ref: string): Promise<InvoiceExportStatusResponse>

Check the status of an invoice export operation.


PermissionsService

Accessed via client.permissions.

Grant Methods

ts
grantPersonPermissions(request: GrantPermissionsPersonRequest): Promise<OperationResponse>

Grant permissions to a person (by PESEL, NIP, or other identifier).

ts
grantEntityPermissions(request: GrantPermissionsEntityRequest): Promise<OperationResponse>

Grant permissions to a legal entity (by NIP).

ts
grantAuthorizationPermissions(request: GrantPermissionsAuthorizationRequest): Promise<OperationResponse>

Grant authorization-level permissions.

ts
grantIndirectPermissions(request: GrantPermissionsIndirectRequest): Promise<OperationResponse>

Grant indirect permissions.

ts
grantSubunitPermissions(request: GrantPermissionsSubunitRequest): Promise<OperationResponse>

Grant permissions to a subunit.

ts
grantEuEntityAdminPermissions(request: GrantPermissionsEuEntityAdminRequest): Promise<OperationResponse>

Grant permissions to an EU entity.

ts
grantEuEntityRepresentativePermissions(request: GrantPermissionsEuEntityRepresentativeRequest): Promise<OperationResponse>

Grant permissions to an EU entity representative.

Revoke Methods

ts
revokeCommonGrant(grantId: string): Promise<OperationResponse>

Revoke a common (person/entity/subunit) permission grant by ID.

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

ts
queryPersonalGrants(
  options?: QueryPersonalGrantsRequest,
  pageOffset?: number,
  pageSize?: number,
): Promise<PagedPermissionsResponse<PersonalPermission>>

Query the caller's own permissions. Supports contextIdentifier filtering.

ts
queryPersonsGrants(options: QueryPersonsGrantsRequest, pageOffset?: number, pageSize?: number): Promise<PagedPermissionsResponse<PersonPermission>>

Query permissions granted to persons.

ts
querySubunitsGrants(options?: QuerySubunitsGrantsRequest): Promise<PagedPermissionsResponse<SubunitPermission>>

Query permissions granted to subunits.

ts
queryEntitiesRoles(options?: QueryEntitiesRolesRequest): Promise<PagedRolesResponse<EntityRole>>

Query roles assigned to entities.

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

ts
querySubordinateEntitiesRoles(options?: QuerySubordinateEntitiesRolesRequest): Promise<PagedRolesResponse<SubordinateEntityRole>>

Query roles assigned to subordinate entities.

ts
queryAuthorizationsGrants(options: QueryAuthorizationsGrantsRequest, pageOffset?: number, pageSize?: number): Promise<PagedAuthorizationsResponse<EntityAuthorizationGrant>>

Query authorization-level grants.

ts
queryEuEntitiesGrants(options?: QueryEuEntitiesGrantsRequest): Promise<PagedPermissionsResponse<EuEntityPermission>>

Query permissions granted to EU entities.

Status Methods

ts
getOperationStatus(ref: string): Promise<PermissionsOperationStatusResponse>

Check the status of a permissions operation by reference.

ts
getAttachmentStatus(): Promise<PermissionsAttachmentAllowedResponse>

Check whether attachment permissions are enabled for the current context.


TokenService

Accessed via client.tokens.

ts
generateToken(request: KsefTokenRequest): Promise<KsefTokenResponse>

Generate a new KSeF authentication token.

ts
queryTokens(options?: QueryKsefTokensOptions): Promise<QueryKsefTokensResponse>

List all tokens for the current subject.

ts
getToken(ref: string): Promise<AuthenticationKsefToken>

Get a specific token by reference.

ts
revokeToken(ref: string): Promise<void>

Revoke a token by reference.


CertificateApiService

Accessed via client.certificates.

ts
getLimits(): Promise<CertificateLimitResponse>

Get certificate enrollment limits.

ts
getEnrollmentData(): Promise<CertificateEnrollmentsInfoResponse>

Get certificate enrollment configuration data.

ts
enroll(request: SendCertificateEnrollmentRequest): Promise<CertificateEnrollmentResponse>

Submit a certificate enrollment request (CSR).

ts
getEnrollmentStatus(ref: string): Promise<CertificateEnrollmentStatusResponse>

Check the status of a certificate enrollment by reference.

ts
retrieve(request: CertificateListRequest): Promise<CertificateListResponse>

Retrieve certificates matching the given criteria.

ts
revoke(serialNumber: string, request: CertificateRevokeRequest): Promise<void>

Revoke a certificate by serial number.

ts
query(request: CertificateMetadataListRequest): Promise<CertificateMetadataListResponse>

Query certificate metadata.


LighthouseService

Accessed via client.lighthouse. Uses raw fetch() against the lighthouse URL (not RestClient).

ts
getStatus(): Promise<KsefStatusResponse>

Get the current KSeF system status.

ts
getMessages(): Promise<LighthouseMessage[]>

Get system status messages.


LimitsService

Accessed via client.limits.

ts
getContextLimits(): Promise<SessionLimitsInCurrentContextResponse>

Get session limits for the current context.

ts
getSubjectLimits(): Promise<CertificatesLimitInCurrentSubjectResponse>

Get certificate limits for the current subject.

ts
getRateLimits(): Promise<EffectiveApiRateLimits>

Get the effective API rate limits.


PeppolService

Accessed via client.peppol.

ts
queryProviders(pageOffset?: number, pageSize?: number): Promise<QueryPeppolProvidersResponse>

Query registered PEPPOL providers.


TestDataService

Accessed via client.testData. Available only in the TEST environment.

Subject Management

ts
createSubject(request: SubjectCreateRequest): Promise<void>

Create a test subject (NIP entity).

ts
removeSubject(request: SubjectRemoveRequest): Promise<void>

Remove a test subject.

Person Management

ts
createPerson(request: PersonCreateRequest): Promise<void>

Create a test person (PESEL identity).

ts
removePerson(request: PersonRemoveRequest): Promise<void>

Remove a test person.

Permissions

ts
grantPermissions(request: TestDataPermissionsGrantRequest): Promise<void>

Grant test permissions directly (bypasses normal flow).

ts
revokePermissions(request: TestDataPermissionsRevokeRequest): Promise<void>

Revoke test permissions directly.

Attachment Permissions

ts
enableAttachment(request: AttachmentPermissionGrantRequest): Promise<void>

Enable attachment permissions for a test subject.

ts
disableAttachment(request: AttachmentPermissionRevokeRequest): Promise<void>

Disable attachment permissions for a test subject.

Session Limits

ts
changeSessionLimits(request: SetSessionLimitsRequest): Promise<void>

Override session limits in the current context.

ts
restoreDefaultSessionLimits(): Promise<void>

Restore default session limits.

Certificate Limits

ts
changeCertificatesLimit(request: SetSubjectLimitsRequest): Promise<void>

Override subject limits (enrollment/certificate) for the current subject.

ts
restoreDefaultCertificatesLimit(): Promise<void>

Restore default certificate limits.

Rate Limits

ts
setRateLimits(request: SetRateLimitsRequest): Promise<void>

Set custom API rate limits.

ts
restoreDefaultRateLimits(): Promise<void>

Restore default API rate limits.

ts
setProductionRateLimits(): Promise<void>

Set production-level rate limits in the test environment.

Context Blocking

ts
blockContext(request: BlockContextAuthenticationRequest): Promise<void>

Block a context (simulate maintenance or ban).

ts
unblockContext(request: UnblockContextAuthenticationRequest): Promise<void>

Unblock a previously blocked context.


CryptographyService

Accessed via client.crypto. Requires explicit initialization before use.

ts
init(): Promise<void>

Initialize the service by fetching and caching KSeF public certificates. Must be called before any encryption method.

AES-256-CBC

ts
encryptAES256(content: Uint8Array, key: Uint8Array, iv: Uint8Array): Uint8Array

Encrypt data with AES-256-CBC (PKCS7 padding).

ts
decryptAES256(content: Uint8Array, key: Uint8Array, iv: Uint8Array): Uint8Array

Decrypt AES-256-CBC encrypted data.

Key Wrapping

ts
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

ts
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

ts
getFileMetadata(file: Uint8Array): FileMetadata

Compute SHA-256 hash (base64) and byte length of a file.

CSR Generation

ts
generateCsrRsa(fields: X500NameFields): Promise<CsrResult>

Generate an RSA-2048 CSR (PKCS#10 DER) and private key PEM.

ts
generateCsrEcdsa(fields: X500NameFields): Promise<CsrResult>

Generate an ECDSA P-256 CSR (PKCS#10 DER) and private key PEM.

Key Parsing

ts
parsePrivateKey(pem: string): crypto.KeyObject

Parse a PEM-encoded private key into a Node.js KeyObject.


VerificationLinkService

Accessed via client.qr.

ts
buildInvoiceVerificationUrl(nip: string, issueDate: Date | string, invoiceHashBase64: string): string

Build an invoice verification URL (Code I). Format: {baseQrUrl}/invoice/{NIP}/{DD-MM-YYYY}/{hash_base64url}.

ts
buildCertificateVerificationUrl(contextType: string, contextId: string, sellerNip: string, certSerial: string, invoiceHashBase64: string, privateKeyPem: string, privateKeyPassword?: string): string

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

ts
static sign(xml: string, certPem: string, privateKeyPem: string): string

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

ts
static getSha256Fingerprint(certPem: string): string

Compute the SHA-256 fingerprint of a PEM certificate. Returns uppercase hex string.

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

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

ts
static generateQrCode(url: string, options?: QrCodeOptions): Promise<Buffer>

Generate a QR code as a PNG buffer.

ts
static generateQrCodeBase64(url: string, options?: QrCodeOptions): Promise<string>

Generate a QR code as a base64-encoded PNG string.

ts
static generateQrCodeSvg(url: string, options?: QrCodeOptions): Promise<string>

Generate a QR code as an SVG string.

ts
static generateQrCodeSvgWithLabel(url: string, label: string, options?: QrCodeOptions): Promise<string>

Generate a QR code as an SVG string with a text label below.

ts
static generateResult(url: string, options?: QrCodeOptions): Promise<QrCodeResult>

Generate a QrCodeResult containing both the URL and its base64-encoded QR code.

QrCodeOptions

FieldTypeDefault
widthnumber300
marginnumber2
errorCorrectionLevelstring'M'

Builders

AuthTokenRequestBuilder

Builds an AuthTokenRequest for XAdES-based authentication.

ts
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(): AuthTokenRequest

AuthKsefTokenRequestBuilder

Builds an AuthKsefTokenRequest for token-based authentication.

ts
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(): AuthKsefTokenRequest

InvoiceQueryFilterBuilder

Builds InvoiceQueryFilters for invoice metadata queries.

ts
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(): InvoiceQueryFilters

PersonPermissionGrantBuilder

Builds a GrantPermissionsPersonRequest.

ts
new PersonPermissionGrantBuilder()
  .withSubjectIdentifier(type: PermissionSubjectIdentifierType, value: string)
  .addPermission(permission: PersonPermissionType)        // repeatable
  .withPermissions(permissions: PersonPermissionType[])   // or set all at once
  .build(): GrantPermissionsPersonRequest

EntityPermissionGrantBuilder

Builds a GrantPermissionsEntityRequest.

ts
new EntityPermissionGrantBuilder()
  .withNip(nip: string)
  .addPermission(type: EntityPermissionItemType, canDelegate?: boolean) // repeatable
  .withPermissions(permissions: EntityPermission[])                     // or set all
  .withDescription(description: string)
  .withSubjectDetails(details: EntityDetails)
  .build(): GrantPermissionsEntityRequest

AuthorizationPermissionGrantBuilder

Builds a GrantPermissionsAuthorizationRequest.

ts
new AuthorizationPermissionGrantBuilder()
  .withPermission(permission: EntityAuthorizationPermissionType)
  .build(): GrantPermissionsAuthorizationRequest

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

ts
serializeInvoiceXml(
  input: string | Buffer | XmlDocument | FakturaInput | PefUblDocumentInput,
  options?: SerializeInvoiceOptions,
): Buffer

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

ts
buildFakturaXml(faktura: FakturaInput, options?: BuildFakturaOptions): string

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

ts
buildPefXml(input: PefUblDocumentInput, options?: BuildPefOptions): string

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

ts
buildRawXmlString(document: XmlObject, options?: { pretty?: boolean }): string

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

ts
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): XmlObject

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

FieldTypeDefaultDescription
schema'FA2' | 'FA3''FA3'Target schema (also switches default namespaces)
fakturaNamespacestringper-schema constantOverride the xmlns attribute on <Faktura>
etdNamespacestringper-schema constantOverride the xmlns:etd attribute on <Faktura>
prettybooleanfalseEmit indented output

BuildPefOptions

FieldTypeDefaultDescription
schema'PEF' | 'PEF_KOR'inferred from rootMust match the detected root or KSeFValidationError is thrown
prettybooleanfalseEmit 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

ConstantTypeDescription
FAKTURA_NAMESPACERecord<FakturaSchema, string>xmlns defaults for FA2 and FA3
ETD_NAMESPACERecord<FakturaSchema, string>xmlns:etd defaults for FA2 and FA3
PEF_NAMESPACERecord<PefSchema, string>UBL Invoice-2 / CreditNote-2 namespaces

Type guards

ts
isFakturaInput(input: unknown): input is FakturaInput
isPefUblDocumentInput(input: unknown): input is PefUblDocumentInput
isFormCodeShape(value: unknown): value is FormCode
toKodFormularza(formCode: FormCode): XmlObject

Error Types

KSeFError

Base error class for all KSeF-related errors. Extends Error.

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

FieldTypeDescription
messagestringHuman-readable error description
statusCodenumberHTTP status code
errorResponseApiErrorResponse?Parsed error body from the API
ts
static fromResponse(statusCode: number, body?: ApiErrorResponse): KSeFApiError

KSeFRateLimitError

Extends KSeFApiError. Thrown on HTTP 429 responses (too many requests). statusCode is a 429 literal.

FieldTypeDescription
retryAfterSecondsnumber?Seconds to wait (from Retry-After header)
retryAfterDateDate?Absolute retry time (if header was a date)
recommendedDelaynumberSeconds to wait (falls back to 60 if unknown)
problemTooManyRequestsProblemDetails?RFC 7807 body (KSeF API v2.4.0+): detail, traceId, instance, timestamp
ts
static fromRetryAfterHeader(
  statusCode: number,
  retryAfterHeader?: string | null,
  body?: ApiErrorResponse,
  problem?: TooManyRequestsProblemDetails,
): KSeFRateLimitError

KSeFBadRequestError

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.

FieldTypeDescription
statusCode400Always 400
detailstring?Human-readable summary of what failed
instancestring?The endpoint path that was called
errorsBadRequestErrorDetail[]Structured list of validation failures
traceIdstring?Trace ID for debugging
timestampstring?UTC timestamp recorded by the server
ts
interface BadRequestErrorDetail {
  code: number;
  description: string;
  details: string[];
}

KSeFUnauthorizedError

Extends KSeFApiError. Thrown on HTTP 401 responses when the body matches UnauthorizedProblemDetails.

FieldTypeDescription
statusCode401Always 401
detailstringError detail from the API
traceIdstring?Trace ID for debugging
instancestring?Request instance identifier
timestampstring?UTC timestamp recorded by the server (KSeF API v2.4.0+)

KSeFForbiddenError

Extends KSeFApiError. Thrown on HTTP 403 responses when the body matches ForbiddenProblemDetails.

FieldTypeDescription
statusCode403Always 403
detailstringError detail from the API
reasonCodeForbiddenReasonCodeOne of: missing-permissions, ip-not-allowed, insufficient-resource-access, auth-method-not-allowed, security-service-blocked, context-type-not-allowed
instancestring?Request instance identifier
securityForbiddenSecurityInfo & Record<string, unknown>?Typed requiredAnyOfPermissions / presentPermissions lists plus any forward-compat fields
traceIdstring?Trace ID for debugging
timestampstring?UTC timestamp recorded by the server (KSeF API v2.4.0+)
ts
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.

FieldTypeDescription
statusCode410Always 410
detailstringServer detail, or default retention-expired message if absent
instancestring?Request instance identifier
traceIdstring?Trace ID for debugging
timestampstring?UTC timestamp recorded by the server

ApiErrorResponse

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

FieldTypeDescription
referenceNumberstring?Auth operation reference number
statusDescriptionstring?Status description from the API
ts
constructor(message: string, referenceNumber?: string, statusDescription?: string)

KSeFSessionExpiredError

Extends KSeFError. Thrown when a stored session has expired.

ts
constructor(message?: string)  // default: 'KSeF session has expired'

KSeFValidationError

Extends KSeFError. Thrown when client-side validation fails (e.g., invalid NIP, missing required fields).

FieldTypeDescription
detailsValidationDetail[]List of validation issues
ts
constructor(message: string, details?: ValidationDetail[])

static fromField(field: string, message: string): KSeFValidationError
static fromMessages(messages: string[]): KSeFValidationError
ts
interface 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 failed

All 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 21208KSeFBatchTimeoutError) → generic KSeFApiError.

KSeFApiProblem

Discriminated union of every RFC 7807 error class, keyed by statusCode literal.

ts
type KSeFApiProblem =
  | KSeFBadRequestError    // statusCode: 400
  | KSeFUnauthorizedError  // statusCode: 401
  | KSeFForbiddenError     // statusCode: 403
  | KSeFGoneError          // statusCode: 410
  | KSeFRateLimitError;    // statusCode: 429

Use with assertNever for exhaustive compile-time dispatch:

ts
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

ts
function assertNever(value: never): never

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

PatternDescription
NipPolish NIP (10-digit tax ID)
VatUeEU VAT number (all member states)
NipVatUeCombined NIP-VatUE format
InternalIdKSeF internal identifier (NIP-XXXXX)
PeppolIdPEPPOL participant ID
ReferenceNumberKSeF operation reference number
KsefNumberKSeF invoice number
KsefNumberV35KSeF invoice number (v3.5 format)
KsefNumberV36KSeF invoice number (v3.6 format)
CertificateNameValid certificate name (alphanumeric + Polish)
PeselPolish PESEL (11-digit personal ID)
CertificateFingerprintSHA-256 fingerprint (64 hex chars uppercase)
Base64StringStandard base64 string
Ip4AddressIPv4 address
Ip4RangeIPv4 range (addr-addr)
Ip4MaskIPv4 CIDR mask (addr/prefix)
Sha256Base64SHA-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.

ts
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): boolean

KSeF 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

ConstantValue
REQUIRED_CHALLENGE_LENGTH36
CERTIFICATE_NAME_MIN_LENGTH5
CERTIFICATE_NAME_MAX_LENGTH100
SUBUNIT_NAME_MIN_LENGTH5
SUBUNIT_NAME_MAX_LENGTH256
PERMISSION_DESCRIPTION_MIN_LENGTH5
PERMISSION_DESCRIPTION_MAX_LENGTH256

Configuration

KSeFClientOptions

All fields are optional. Defaults to the TEST environment.

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

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

NameAPI URLQR URL
TESThttps://api-test.ksef.mf.gov.plhttps://qr-test.ksef.mf.gov.pl
DEMOhttps://api-demo.ksef.mf.gov.plhttps://qr-demo.ksef.mf.gov.pl
PRODhttps://api.ksef.mf.gov.plhttps://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

ts
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

ts
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

ts
import { uploadBatch } from 'ksef-client-ts';

const result = await uploadBatch(client, {
  formCode, encryption, parts: [{ partContent, partSize, partHash }],
});
// result: { sessionReference, upo }

Invoice Export Workflows

ts
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

ts
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

TypeDescription
PollOptionsintervalMs, maxAttempts, onProgress callback
OnlineSessionHandleSession ref + sendInvoice(), close(), waitForUpo() methods
UpoInfoPages with reference numbers, download URLs, invoice counts
BatchUploadResultSession reference + UPO info
ExportResultExport parts array (ordinal, URL, size, hash, expiration)
ExportDownloadResultExtends ExportResult with decryptedParts: Uint8Array[]
AuthResultAccess/refresh tokens with expiry timestamps

KSeF Feature Constants

Constants for the X-KSeF-Feature header, used to negotiate UPO format version and XAdES compliance.

ts
import { KSEF_FEATURE_HEADER, UpoVersion, ENFORCE_XADES_COMPLIANCE } from 'ksef-client-ts';
ConstantValueDescription
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.

Released under the MIT License.