Skip to content

artpods56/ksef2

Repository files navigation

KSeF Toolkit

Python SDK and Tools for Poland's KSeF (Krajowy System e-Faktur) v2.0 API.

API Coverage Python Version Integration Tests
beartype pre-commit Ruff License: MIT

Installation

pip install ksef2

Or with uv:

uv add ksef2

Requires Python 3.12+.

Features

  • Type-Safe — Full type annotations with Pydantic models, excellent IDE support and autocomplete
  • Pythonic API — Context managers for sessions, clean interfaces, intuitive method chaining
  • Both Auth Methods — XAdES (certificate-based) and token authentication supported
  • Automatic Encryption — Invoice encryption/decryption handled transparently (AES-CBC, RSA-OAEP)
  • Session Resume — Serialize session state and resume later, perfect for worker processes and long-running exports
  • Test Environment Support — Self-signed certificates, test data setup with automatic cleanup via temporal() context manager

Quick Start

from datetime import datetime, timezone
from ksef2 import Client, Environment, FormSchema
from ksef2.core.xades import generate_test_certificate
from ksef2.domain.models import (
    InvoiceQueryFilters, InvoiceSubjectType, InvoiceQueryDateRange, DateType,
)

NIP = "5261040828"
client = Client(Environment.TEST)

# Authenticate (XAdES — TEST environment)
cert, key = generate_test_certificate(NIP)
auth = client.auth.authenticate_xades(nip=NIP, cert=cert, private_key=key)

with client.sessions.open_online(
    access_token=auth.access_token,
    form_code=FormSchema.FA3,
) as session:

    # Send an invoice
    result = session.send_invoice(open("invoice.xml", "rb").read())
    print(result.reference_number)

    # Check processing status
    status = session.get_invoice_status(result.reference_number)

    # Export invoices matching a query
    export = session.schedule_invoices_export(
        filters=InvoiceQueryFilters(
            subject_type=InvoiceSubjectType.SUBJECT1,
            date_range=InvoiceQueryDateRange(
                date_type=DateType.ISSUE,
                from_=datetime(2026, 1, 1, tzinfo=timezone.utc),
                to=datetime.now(tz=timezone.utc),
            ),
        ),
    )

    # Download the exported package
    export_result = session.get_export_status(export.reference_number)
    if package := export_result.package:
        for path in session.fetch_package(package=package, target_directory="downloads"):
            print(f"Downloaded: {path}")

Full runnable version: send_query_export_download.py — more examples in scripts/examples.

XAdES on DEMO / PRODUCTION (MCU certificate)

The TEST environment accepts self-signed certificates generated by the SDK. DEMO and PRODUCTION require a certificate issued by MCU — use the provided helpers to load it:

from ksef2 import Client, Environment
from ksef2.core.xades import load_certificate_from_pem, load_private_key_from_pem

cert = load_certificate_from_pem("cert.pem")  # downloaded from MCU
key  = load_private_key_from_pem("key.pem")

auth = Client(Environment.DEMO).auth.authenticate_xades(
    nip=NIP, cert=cert, private_key=key, verify_chain=False,
)

If your certificate is a .p12 archive: load_certificate_and_key_from_p12("cert.p12", password=b"...")

Token Authentication

For production, or when you have a pre-generated KSeF token:

from ksef2 import Client

client = Client()  # uses production environment by default

auth = client.auth.authenticate_token(ksef_token="your-ksef-token", nip=NIP)
print(auth.access_token)

Authenticated Operations

After authentication, you get an AuthenticatedClient with access to various services — no need to open an invoice session for these operations:

auth = client.auth.authenticate_xades(nip=NIP, cert=cert, private_key=key)

# Manage KSeF authorization tokens
token = auth.tokens.generate(
    permissions=[TokenPermission.INVOICE_READ, TokenPermission.INVOICE_WRITE],
    description="API integration token",
)
print(f"Generated token: {token.token}")

# Query and modify API limits (TEST environment)
limits = auth.limits.get_context_limits()
print(f"Max invoices per session: {limits.online_session.max_invoices}")

# Manage permissions
auth.permissions.grant_person(
    subject_identifier=IdentifierType.PESEL,
    subject_value="12345678901",
    permissions=[PermissionType.INVOICE_READ],
    description="Read access for accountant",
    first_name="Jan", last_name="Kowalski",
)

# List and terminate authentication sessions
sessions = auth.sessions.list()
auth.sessions.terminate_current()

# Manage KSeF certificates
certs = auth.certificates.query(status=CertificateStatus.ACTIVE)

Development

just sync          # Install all dependencies (including dev)
just test          # Run unit tests
just regenerate-models  # Regenerate OpenAPI models

Other commands

just integration   # Run integration tests (requires KSEF credentials in .env)
just coverage       # Calculate API coverage (updates coverage.json)
just fetch-spec     # Fetch latest OpenAPI spec from KSeF

API Coverage

The SDK covers 77 of 77 KSeF API endpoints (100%). See feature docs for details:

  • Authentication — XAdES, token auth, session management
  • Invoices — send, download, query, export
  • Sessions — online/batch sessions, resume support
  • Tokens — generate and manage KSeF authorization tokens
  • Permissions — grant/query permissions for persons and entities
  • Certificates — enroll, query, revoke KSeF certificates
  • Limits — query and modify API rate limits
  • Test Data — create test subjects, manage test environment

License

MIT

About

Python SDK and Tools for Poland's KSeF (Krajowy System e-Faktur) v2.0 API.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •