GitHub

Authenticate

Configure ksef2 credentials with environment variables, KSeF tokens, XAdES certificates, or CLI-compatible profiles.

On this page

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:

VariablePurpose
KSEF2_ENVtest, demo, or production for SDK examples.
KSEF2_NIPTaxpayer/context NIP used during authentication.
KSEF2_TOKENKSeF token for token authentication.
KSEF2_PROFILECLI profile name selected by ksef2-cli and SDK profile auth.
KSEF2_CONFIGOptional path to the CLI profile config file.
KSEF2_KEY_PASSWORDOptional encrypted PEM private-key password.
KSEF2_P12_PASSWORDOptional PKCS#12/PFX archive password.
export KSEF2_ENV=test
export KSEF2_NIP=5261040828
export KSEF2_TOKEN=replace-with-a-real-ksef-token
bash

The 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]
python

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",
)
python

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"],
)
python

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,
)
python

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,
)
python

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_TOKEN
bash

Select the active profile for future CLI commands:

ksef2 profile use prod-token
ksef2 --json profile current
bash

Or select a profile for one shell or one command:

export KSEF2_PROFILE=prod-token
ksef2 --json auth login

ksef2 --profile test-company --json auth login
bash

Profile selection order is the same in the CLI and SDK:

  1. Explicit profile name.
  2. KSEF2_PROFILE.
  3. active_profile in 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")
python

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,
)
python

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")
python

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.
  1. Put secrets into environment variables.

    Use KSEF2_TOKEN, KSEF2_KEY_PASSWORD, or KSEF2_P12_PASSWORD.

  2. Keep non-secret defaults in one place.

    Use application config for fully custom setups, or ksef2-cli profiles when the same environment is also operated from the command line.

  3. Create the root client for the selected environment.

    Use Client(Environment.TEST), Client(Environment.DEMO), or Client(Environment.PRODUCTION).

  4. 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}")
python

Next workflows