Authentication turns a root Client into an authenticated client. Use the root
client to choose the KSeF environment, then choose exactly one authentication
method for the context you are operating as.
Environment variables
These names are used by examples in this documentation and by ksef2-cli
profiles:
| Variable | Purpose |
|---|---|
KSEF2_ENV | test, demo, or production for SDK examples. |
KSEF2_NIP | Taxpayer/context NIP used during authentication. |
KSEF2_TOKEN | KSeF token for token authentication. |
KSEF2_PROFILE | CLI profile name selected by ksef2-cli and SDK profile auth. |
KSEF2_CONFIG | Optional path to the CLI profile config file. |
KSEF2_KEY_PASSWORD | Optional encrypted PEM private-key password. |
KSEF2_P12_PASSWORD | Optional PKCS#12/PFX archive password. |
export KSEF2_ENV=test
export KSEF2_NIP=5261040828
export KSEF2_TOKEN=replace-with-a-real-ksef-tokenThe SDK reads KSEF2_PROFILE and KSEF2_CONFIG when you use
client.authentication.with_profile(). For direct token or certificate auth,
keep the boundary explicit in your application:
import os
from ksef2 import Environment
environment_name = os.environ.get("KSEF2_ENV", "test").upper()
environment = Environment[environment_name]The method snippets below assume client is an open root client for the target
environment. In scripts, prefer a context manager such as
with Client(Environment.TEST) as client:.
Choose an authentication method
With a KSeF token
Use a KSeF token when your application already has a valid token for the context. Token auth works in TEST, DEMO, and PRODUCTION.
import os
auth = client.authentication.with_token(
ksef_token=os.environ["KSEF2_TOKEN"],
nip=os.environ["KSEF2_NIP"],
context_type="nip",
)With the TEST certificate
Use the SDK-generated TEST certificate for local development. This method is
only available with Environment.TEST.
import os
auth = client.authentication.with_test_certificate(
nip=os.environ["KSEF2_NIP"],
)With PEM XAdES
Use PEM certificate and private-key files when your certificate material is stored separately.
import os
from ksef2.xades import load_certificate_from_pem, load_private_key_from_pem
password = os.environ.get("KSEF2_KEY_PASSWORD")
cert = load_certificate_from_pem("company.pem")
private_key = load_private_key_from_pem(
"company.key",
password=password.encode() if password else None,
)
auth = client.authentication.with_xades(
nip=os.environ["KSEF2_NIP"],
cert=cert,
private_key=private_key,
)With PKCS#12
Use a PKCS#12/PFX archive when the certificate and private key are stored in one file.
import os
from ksef2.xades import load_certificate_and_key_from_p12
password = os.environ.get("KSEF2_P12_PASSWORD")
cert, private_key = load_certificate_and_key_from_p12(
"company.p12",
password=password.encode() if password else None,
)
auth = client.authentication.with_xades(
nip=os.environ["KSEF2_NIP"],
cert=cert,
private_key=private_key,
)CLI-compatible profiles
ksef2-cli and the SDK share the same local profile file. A profile stores
non-secret defaults such as environment, NIP, auth method, certificate paths,
polling settings, and the name of the environment variable that contains a
secret. It does not store token values or certificate passwords.
ksef2 profile create test-company \
--env test \
--nip 5261040828 \
--test-cert
ksef2 profile create prod-token \
--env production \
--nip "$KSEF2_NIP" \
--token-env KSEF2_TOKENSelect the active profile for future CLI commands:
ksef2 profile use prod-token
ksef2 --json profile currentOr select a profile for one shell or one command:
export KSEF2_PROFILE=prod-token
ksef2 --json auth login
ksef2 --profile test-company --json auth loginProfile selection order is the same in the CLI and SDK:
- Explicit profile name.
KSEF2_PROFILE.active_profilein the local config file.
Use KSEF2_CONFIG or config_path="..." when the profile file is not at the
default ~/.config/ksef2/config.toml location. Existing
~/.config/ksef2-cli/config.toml files are still read as a legacy fallback.
Use an existing profile from SDK code:
from ksef2 import Client, Environment
with Client(Environment.PRODUCTION) as client:
auth = client.authentication.with_profile()
# To select a named profile explicitly instead:
# auth = client.authentication.with_profile("prod-token")The root client environment must match the selected profile environment.
Create or update the same profile file from SDK code:
from ksef2 import Environment
from ksef2.profiles import Profile, ProfileStore, TokenProfileAuth
store = ProfileStore.default()
store.save(
"prod-token",
Profile(
environment=Environment.PRODUCTION,
nip="5261040828",
auth=TokenProfileAuth(token_env="KSEF2_TOKEN"),
),
activate=True,
overwrite=True,
)Async clients use the same profile file and selection order:
from ksef2 import AsyncClient, Environment
async with AsyncClient(Environment.PRODUCTION) as client:
auth = await client.authentication.with_profile("prod-token")See also:
- Use profiles: Create profiles with ksef2-cli, authenticate with with_profile(), and manage profiles through ProfileStore.
- CLI authentication: Use the same token, TEST certificate, PEM XAdES, PKCS#12, and profile flows from ksef2-cli.
Recommended flow
-
Put secrets into environment variables.
Use
KSEF2_TOKEN,KSEF2_KEY_PASSWORD, orKSEF2_P12_PASSWORD. -
Keep non-secret defaults in one place.
Use application config for fully custom setups, or
ksef2-cliprofiles when the same environment is also operated from the command line. -
Create the root client for the selected environment.
Use
Client(Environment.TEST),Client(Environment.DEMO), orClient(Environment.PRODUCTION). -
Authenticate once, then pass the authenticated client into workflows.
The authenticated client owns access tokens and exposes workflow branches.
Errors
Catch SDK-classified failures with KSeFException. Catch httpx.HTTPError
separately for transport failures before KSeF returns a response.
import httpx
from ksef2 import Client, Environment, KSeFException
try:
with Client(Environment.TEST) as client:
auth = client.authentication.with_test_certificate(nip="5261040828")
except KSeFException as exc:
print(exc)
except httpx.HTTPError as exc:
print(f"Transport failed: {exc}")Next workflows
- Send invoices: Open online or batch sessions after authentication.
- Query invoices: Fetch invoice metadata with filters and pagination.
- Download invoices: Download processed invoices or encrypted export packages.
