A lightweight, framework-agnostic Python client for the Polish National e-Invoicing System (Krajowy System e-Faktur - KSeF) API 2.0.
This library is designed to be simple, synchronous (ideal for frameworks like Django or Flask), and relies on requests for HTTP communication and cryptography for RSA token encryption required by the authentication process.
- Full implementation of the KSeF API 2.0 endpoints (Auth, Sessions, Invoices, Certificates, Permissions, Batch, Limits).
- Built-in automatic handling of the complex token authentication flow (Challenge -> RSA Encryption -> Init -> Wait -> Redeem).
- Automatic KSeF error parsing into readable Python exceptions (
Error,AuthError,TimeoutError). - Clean, Pythonic syntax with proper type hinting and Context Manager support.
Install the package and its dependencies using pip:
pip install ksef(Note: If installing from source, you can run pip install -e . in the directory containing pyproject.toml)
Here are some common examples of how to use the client using Python best practices (context managers and specific exceptions).
To connect to KSeF, you need your NIP (Tax Identification Number) and an Authorisation Token generated in the KSeF portal. It is recommended to use the client as a Context Manager (with block) to ensure the underlying HTTP session is correctly closed.
from ksef import Client
from ksef.exceptions import AuthError, Error
# By default, test=True connects to the test environment (api-test.ksef.mf.gov.pl)
with Client(test=True) as client:
try:
print("Logging into KSeF...")
client.login(nip='1111111111', token='YOUR_KSEF_AUTHORISATION_TOKEN')
print(f"Login successful! Active Token: {client.token}")
# You can now safely make other KSeF calls...
status = client.session_status()
print(f"Session reference: {status.get('referenceNumber') if status else 'None'}")
except AuthError as e:
print(f"Authentication failed: {e}")
except Error as e:
print(f"KSeF API Error: {e}")You no longer need to extract tokens manually; the client automatically uses its authenticated token for the required Session-Token header.
from ksef import Client
from ksef.exceptions import Error
invoice_payload = {
"invoiceHash": {
"hashSHA": {
"algorithm": "SHA-256",
"encoding": "Base64",
"value": "base64_encoded_sha256_hash_of_xml"
},
"fileSize": 1024
},
"invoicePayload": {
"type": "plain",
"invoiceBody": "base64_encoded_xml_invoice_content"
}
}
with Client(test=True, nip='1111111111', ksef_token='YOUR_TOKEN') as client:
try:
client.login() # Authenticates using credentials from initialization
response = client.invoices.send_online(invoice_data=invoice_payload)
print("Invoice sent successfully!")
print(f"Reference Number: {response.get('referenceNumber')}")
except Error as e:
print(f"Failed to send invoice: {e}")You can search for invoices within a specific date range:
search_criteria = {
"queryCriteria": {
"subjectType": "subject1",
"type": "incremental",
"acquisitionTimestampThresholdFrom": "2023-10-01T00:00:00Z",
"acquisitionTimestampThresholdTo": "2023-10-31T23:59:59Z"
}
}
with Client(test=True) as client:
client.login(nip='1111111111', token='YOUR_TOKEN')
response = client.invoices.query_metadata(
filters=search_criteria,
params={"PageSize": 10, "PageOffset": 0}
)
print(f"Found {len(response.get('items', []))} invoices in the current page.")It's good practice to terminate your session when you're done, even when using the context manager.
with Client(test=True) as client:
client.login(nip='1111111111', token='YOUR_TOKEN')
# ... perform operations ...
print("Terminating KSeF session...")
client.sessions.terminate_current()The client is split into modular managers mimicking the KSeF domain logic:
client.auth- Authentication flowsclient.sessions- Session managementclient.invoices- Invoice sending, querying, and downloadingclient.certificates- Certificate operationsclient.permissions- Permission managementclient.batch- Batch operationsclient.limits- API limit inquiries