GitHub

Use profiles

Share local ksef2-cli profile configuration with SDK authentication.

On this page

Profiles are local, named authentication settings shared by ksef2-cli and the SDK. Use them when the same developer workstation needs both terminal commands and Python scripts for the same KSeF context.

A profile stores non-secret settings: environment, NIP, authentication method, certificate paths, polling settings, and the name of the environment variable that contains a secret. It should not store KSeF token values, private-key passwords, or PKCS#12 passwords.

Create a profile with the CLI

The CLI is the most convenient way to create and inspect profile files.

ksef2 profile create test-company \
  --env test \
  --nip 5261040828 \
  --test-cert

ksef2 profile current
ksef2 profile show test-company
bash

Token and certificate profiles store the environment variable name that holds the secret, not the secret value:

export KSEF2_TOKEN=replace-with-a-real-ksef-token

ksef2 profile create prod-token \
  --env production \
  --nip 5261040828 \
  --token-env KSEF2_TOKEN
bash

See also:

  • CLI configuration: Create, select, inspect, and delete profiles with ksef2-cli.
  • CLI authentication: Choose token, TEST certificate, PEM XAdES, or PKCS#12 profile authentication from the command line.

Authenticate with a profile

with_profile() reads the same profile file as the CLI. Passing no name uses the currently selected profile.

from ksef2 import Client, Environment

with Client(Environment.TEST) as client:
    auth = client.authentication.with_profile()
python

Pass a name to ignore the active profile for one call:

from ksef2 import Client, Environment

with Client(Environment.TEST) as client:
    auth = client.authentication.with_profile("test-company")
python

The root client environment must match the selected profile environment. A test profile must be used with Client(Environment.TEST), a demo profile with Client(Environment.DEMO), and a production profile with Client(Environment.PRODUCTION).

If you want the profile to choose the client environment, load it first:

from ksef2 import Client
from ksef2.profiles import load_cli_profile

profile_name, profile = load_cli_profile("prod-token")

with Client(profile.sdk_environment) as client:
    auth = client.authentication.with_profile(profile_name)
python

Async clients use the same profile file and selection order:

from ksef2 import AsyncClient, Environment

async with AsyncClient(Environment.TEST) as client:
    auth = await client.authentication.with_profile("test-company")
python

Profile selection order

The SDK selects a profile in the same order as ksef2-cli:

  1. The explicit name passed to with_profile("name").
  2. KSEF2_PROFILE in the process environment.
  3. active_profile in the local profile config file.

By default, the profile file is:

~/.config/ksef2/config.toml
text

Existing ~/.config/ksef2-cli/config.toml files are still read as a legacy fallback.

Set KSEF2_CONFIG or pass config_path when the profile file lives somewhere else:

from ksef2 import Client, Environment

with Client(Environment.PRODUCTION) as client:
    auth = client.authentication.with_profile(
        "prod-token",
        config_path="./local.ksef2.toml",
    )
python

Manage profiles from SDK code

Use ProfileStore when a Python tool should create, update, select, or inspect the same profile file used by the CLI. Use with_profile() when you only need to authenticate.

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",
            context_type="nip",
        ),
        poll_interval=2.0,
        max_poll_attempts=90,
    ),
    activate=True,
    overwrite=True,
)
python

For a TEST certificate profile:

from ksef2 import Environment
from ksef2.profiles import Profile, ProfileStore, TestCertificateProfileAuth

store = ProfileStore.default()
store.save(
    "test-company",
    Profile(
        environment=Environment.TEST,
        nip="5261040828",
        auth=TestCertificateProfileAuth(),
    ),
    activate=True,
    overwrite=True,
)
python

You can perform basic profile management without the CLI, but the CLI is usually more convenient.

from ksef2.profiles import ProfileStore

store = ProfileStore.default()

profiles = store.list()
current = store.current()
profile = store.get("prod-token")
store.use("prod-token")
store.delete("old-profile")
python

current is either None or a (name, profile) tuple.

What the config contains

The rendered file uses the same field names as the public SDK profile models:

active_profile = "prod-token"

[profiles.prod-token]
environment = "production"
nip = "5261040828"
poll_interval = 2.0
max_poll_attempts = 90

[profiles.prod-token.auth]
type = "token"
token_env = "KSEF2_TOKEN"
context_type = "nip"
toml

For XAdES profiles, the profile stores paths and password environment variable names:

from ksef2 import Environment
from ksef2.profiles import Profile, ProfileStore, XadesP12ProfileAuth

store = ProfileStore.default()
store.save(
    "prod-p12",
    Profile(
        environment=Environment.PRODUCTION,
        nip="5261040828",
        auth=XadesP12ProfileAuth(
            p12="signing-credentials.p12",
            p12_password_env="KSEF2_P12_PASSWORD",
        ),
    ),
    activate=False,
    overwrite=True,
)
python

Legacy and unknown keys

Profiles written by ksef2-cli 0.0.2 may carry a flat auth_timeout (seconds). The SDK still accepts it, converts it to max_poll_attempts with the formula with_profile() uses (timeout = max_poll_attempts * poll_interval, so max_poll_attempts = ceil(auth_timeout / poll_interval), with a default interval of 1 second), and emits a DeprecationWarning. An explicit max_poll_attempts wins. auth_timeout may be removed no earlier than ksef2 2.0.0; replace it with max_poll_attempts and optionally poll_interval.

Any other unknown key in a profile is ignored without a warning, so tool-specific settings stored next to the SDK fields do not break loading.

  1. Put secret values in environment variables.

    Examples: KSEF2_TOKEN, KSEF2_KEY_PASSWORD, and KSEF2_P12_PASSWORD.

  2. Create or select the profile with ksef2-cli.

    This keeps terminal workflows and Python scripts aligned.

  3. Create the SDK root client for the same environment as the profile.

    The SDK validates this before authenticating.

  4. Call client.authentication.with_profile().

    The returned authenticated client is used like any other authenticated SDK client.

  • Quickstart: Run the first send-and-download workflow, then adapt it to use a profile.
  • Authenticate: Compare profiles with direct token, TEST certificate, and XAdES authentication.