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. CollectiveIdentifiersService
  14. PeppolService
  15. TestDataService
  16. CryptographyService
  17. VerificationLinkService
  18. SignatureService (static)
  19. CertificateService (static)
  20. QrCodeService (static)
  21. Builders
  22. XML Serialization
  23. Error Types
  24. Validation
  25. Workflows
  26. KSeF Feature Constants
  27. 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
collectiveIdentifiersCollectiveIdentifiersServiceGroup invoices under a collective identifier
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, features?: string | readonly string[]): Promise<OpenOnlineSessionResponse>

Open a new online (interactive) session. features sets the X-KSeF-Feature header (see KSeF Feature Constants).

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, features?: string | readonly string[]): Promise<OpenBatchSessionResponse>

Open a new batch session and receive part upload URLs. features sets the X-KSeF-Feature header (see KSeF Feature Constants).

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

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

QueryPersonalPermissionsResponse extends PagedPermissionsResponse<PersonalPermission> with ownerPermissions?: OwnerPermissionScope[] | null (KSeF API v2.9.0). When the caller is the owner of the context, permissions is empty and the owner's rights are listed in ownerPermissions instead. A session opened with a KSeF token gets ownerPermissions: [], since a token carries no owner rights. Servers older than 2.9.0 omit the field or send null, so treat a missing value as an empty list.

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, per group and time window. A window equal to RATE_LIMIT_UNLIMITED (-1) has no limit — check for it before treating a value as a request count. The global group is the per-IP limit, announced in KSeF API v2.8.0 as not yet enforced; since v2.9.0 TEST reports a finite perSecond (75), so treat its windows like any other group's.


CollectiveIdentifiersService ​

Accessed via client.collectiveIdentifiers. Requires one of the InvoiceRead, InvoiceWrite, or CollectiveIdentifierManage permissions. See Collective Identifiers for the identifier format and disclosure rules.

ts
generate(request: GenerateCollectiveIdentifierRequest): Promise<GenerateCollectiveIdentifierResponse>

Generate a collective identifier for invoices issued by the same seller. The list must hold at least 2 invoices and at most 5000 — the highest any context can allow — and KSeFValidationError is thrown outside those bounds. The limit actually in force defaults to 500 and is raised through the session limits for the context, so KSeF may still reject a list this method accepts.

ts
query(request: CollectiveIdentifiersQueryRequest, pageSize?: number, continuationToken?: string): Promise<CollectiveIdentifiersQueryResponse>

List collective identifiers in the current context. The date range spans at most 100 days.

ts
getByKsefNumber(ksefNumber: string, pageSize?: number, continuationToken?: string): Promise<CollectiveIdentifiersByKsefNumberQueryResponse>

List the collective identifiers a given KSeF invoice belongs to.

ts
queryInvoices(request: CollectiveIdentifierInvoicesQueryRequest, pageSize?: number, continuationToken?: string): Promise<CollectiveIdentifierInvoicesQueryResponse>

List the invoices inside up to 10 collective identifiers at once. Each returned invoice carries the identifier it belongs to. Payment fields are omitted and detailsHidden is true when the caller may not see them.


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.

Certificate Update ​

ts
updateCertificate(serialNumber: string, request: TestDataUpdateCertificateRequest): Promise<void>

Update an existing KSeF certificate expiry for the authenticated subject. TEST environment only; validTo must not be later than the current expiry.

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;     // absent when KSeF reports only the code
  details?: string[] | null;
}

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
        │     ├── KSeFUnknownPublicKeyError   // HTTP 400, KSeF code 21470
        │     └── KSeFSessionUnavailableError // HTTP 400, KSeF code 21184 (open a new session)
        ├── KSeFAuthStatusError         // auth operation failed/timed out
        ├── KSeFSessionExpiredError     // stored session expired
        ├── KSeFSessionFailedError      // online/batch session ended in a failed status
        ├── KSeFInvoiceRejectedError    // waitForInvoice: KSeF rejected the invoice (e.g. 440 duplicate)
        ├── KSeFCircuitOpenError        // opt-in circuit breaker is open
        ├── KSeFValidationError         // client-side validation failed
        ├── KSeFXsdValidationError      // XSD schema validation failed
        ├── KSeFMetadataPaginationError // metadata paging cannot advance
        └── KSeFPaginationError         // continuation-token paging repeats a token or hits maxPages

All server-returned HTTP errors extend KSeFApiError, so a single instanceof KSeFApiError check covers every response-side failure. RestClient.ensureSuccess dispatches errors in order: 400 (KSeF code 21184 → KSeFSessionUnavailableError, 21470 → KSeFUnknownPublicKeyError, otherwise KSeFBadRequestError) → 429 → 401 → 403 → 410 → (exceptionCode 21208 → KSeFBatchTimeoutError) → 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 });
const invoiceRef = await handle.sendInvoice(invoiceRequest);
const { ksefNumber } = await handle.waitForInvoice(invoiceRef); // throws KSeFInvoiceRejectedError if rejected
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(), waitForInvoice(), 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 switch on optional KSeF behaviour: the UPO format version, invoice identifier validation and XAdES compliance.

ts
import { KSEF_FEATURE_HEADER, KSeFFeature, 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)
KSeFFeature.SubjectIdentifierValidation'subject-identifier-validation'Validate the NIP numbers and internal identifiers of the parties on each invoice (TEST only, KSeF API v2.8.0)
ENFORCE_XADES_COMPLIANCE'enforce-xades-compliance'Strict XAdES validation in auth requests

Session open methods (onlineSession.openSession(), batchSession.openSession()) take the feature as their optional second argument, a single value or an array; the workflows (openOnlineSession(), openSendAndClose(), uploadBatch(), uploadBatchStream() and their *Parsed variants) take it as the features option. The older upoVersion option is deprecated; it still works and counts as one of the features. auth.submitXadesAuthRequest() sends ENFORCE_XADES_COMPLIANCE when its enforceXadesCompliance argument is true.

KSeF applies only one feature per session: a comma-separated list, or the header repeated, is accepted but none of the listed features takes effect. The client therefore throws KSeFValidationError before opening the session when it is given more than one distinct value. Strings are split on commas and trimmed first, so 'upo-v4-3, subject-identifier-validation' counts as two values, while repeats and empty entries are dropped ('a,a' and 'a, ' both send a).

ts
const handle = await openOnlineSession(client, {
  features: KSeFFeature.SubjectIdentifierValidation,
});
// An invoice with an invalid buyer NIP now ends with status 450
// ("Błąd weryfikacji semantyki dokumentu faktury") instead of being accepted.

Released under the MIT License.