Access methods

SDK for Python

The official package for Python 3.9 and later, using only the standard library. Every method returns a dict with the same fields as the API.

Installation

#

The package quellenkontor runs on Python 3.9 and later and only uses the standard library. So there are no dependencies that could conflict with your project.

Terminal
pip install quellenkontor
uv or poetry
uv add quellenkontor
poetry add quellenkontor

Setup

#
Python
from quellenkontor import Quellenkontor

# reads the key from QK_KEY
qk = Quellenkontor()

# or explicitly, with options
qk = Quellenkontor(api_key="qk_live_…", timeout=10.0, wiederholungen=3)
ParameterDefaultMeaning
api_keyEnvironment variable QK_KEYYour API key
basis_urlhttps://api.quellenkontor.dev/v1Only for testing against a different server
timeout15.0Timeout per request, in seconds
wiederholungen2Retries on network errors and status 502, 503, 504, with 0.3 and 0.6 second delays
cacheTrueTurn the in-memory cache for this instance on or off, see below
cache_ttl300.0 (5 minutes)How long a response comes from the cache without a new request, in seconds
offlineTrueUse the bundled offline data as a fallback when the API is unreachable, see below

Cache and ETag

Within cache_ttl seconds, a repeated request with the same parameters comes back from this instance's cache without any network call. After that, the SDK asks again with the stored ETag in the If-None-Match header: if the value has not changed, the API responds with 304, the SDK returns the cached response, and the request does not count against your quota. More on saving requests under Quotas and limits.

Python
qk = Quellenkontor(cache=False)  # always a fresh request

# or clear the cache on purpose, for example after a webhook
qk2 = Quellenkontor()
qk2.cache_leeren()

Offline data

If the API is unreachable after every retry, the SDK falls back to bundled offline data: the history of every table with a history, generated into the package from the current data set (the same data as /export). That response then carries offline: True and the package's own datenstand instead of the currently official one, without the computed extra fields such as zitat. Plain calculators without a table, for example notice period, vacation entitlement or company car, have no offline data and stay a QuellenkontorFehler with code netzwerk without a connection.

Python
qk = Quellenkontor(offline=False)  # always throw the network error instead

# with the offline fallback (default): recognizable by the offline field
qk_mit_fallback = Quellenkontor()
ml = qk_mit_fallback.hr.mindestlohn(datum="2027-01-15")
if ml.get("offline"):
    print("Offline data from", ml["datenstand"])

All methods

#

Every dataset is a method under qk.hr. It returns a dict with the same fields as the API. You can leave out optional parameters or pass None.

MethodReference
qk.hr.mindestlohn(datum=None)Minimum wage
qk.hr.mindestausbildungsverguetung(beginn=None, ausbildungsjahr=None, bestandteil=None)Apprentice pay
qk.hr.pflegemindestlohn(datum=None, bestandteil=None)Care minimum wage
qk.hr.rechengroessen(jahr=None, datum=None)Contribution ceilings
qk.hr.beitragssaetze(datum=None)Contribution rates
qk.hr.sachbezugswerte(jahr=None, datum=None)Meal and lodging values
qk.hr.pfaendungsfreigrenzen(datum=None, unterhaltspflichten=None, netto=None)Garnishment exemptions
qk.hr.uebergangsbereich(datum=None)Midi-job zone
qk.hr.minijob_abgaben(datum=None, bestandteil=None)Mini-job levies
qk.hr.kuenstlersozialabgabe(jahr=None, datum=None, bestandteil=None)Artists' social levy
qk.hr.ausgleichsabgabe(jahr=None, datum=None, arbeitsplaetze=None, besetzt=None, bestandteil=None)Compensatory levy
qk.hr.steuerfreie_betraege(datum=None, bestandteil=None)Tax-free amounts
qk.hr.reisekosten_inland(datum=None, bestandteil=None)Travel expenses
qk.hr.sfn_zuschlaege(datum=None, grundlohn_stunde=None, bestandteil=None)Night and holiday premiums
qk.hr.dienstwagen(listenpreis: float, antrieb=None, anschaffung=None, ueberlassung=None, entfernung_km=None, fahrten_monat=None, zuzahlung_monat=None, co2_g_km=None, reichweite_km=None, batterie_kwh=None, datum=None)Company car
qk.hr.einkommensteuer_eckwerte(jahr=None, datum=None, bestandteil=None)Basic tax allowance
qk.hr.kuendigungsfrist(eintritt: str, zugang: str, seite=None, probezeit=None)Notice period
qk.hr.urlaubsanspruch(arbeitstage_pro_woche: float, jahr=None, eintritt=None, austritt=None)Vacation entitlement
qk.hr.mutterschutz(termin=None, geburt=None, fall=None, ssw=None)Maternity protection
qk.hr.feiertage(jahr=None, land=None)Public holidays
qk.hr.arbeitstage(von: str, bis: str, land: str, samstag=None, regionale=None)Working days
qk.hr.regelaltersgrenze(geburtsdatum=None, geburtsjahr=None, vertrauensschutz=None)Retirement age
qk.hr.pausen(arbeitszeit_stunden: float, jugendlich=None)Rest breaks
qk.hr.verlauf(datensatz)all steps of a table since 2015
qk.datensaetze()Catalog, no key needed
qk.aenderungen()Changelog, no key needed
qk.anfrage(pfad, werte, format="json")raw request to any path, including CSV

Pass booleans as True or False; the SDK writes them for the API as true and false.

Examples

#

Notice period (Kündigungsfrist)

Python
frist = qk.hr.kuendigungsfrist(eintritt="2017-03-01", zugang="2026-11-10")
print(frist["ende"])  # 2027-02-28

Vacation entitlement for part-time work

Python
urlaub = qk.hr.urlaubsanspruch(arbeitstage_pro_woche=3, jahr=2027)
print(urlaub["anspruch_tage_jahr"])

Contribution rates on an effective date

Python
saetze = qk.hr.beitragssaetze(datum="2026-07-01")
for b in saetze["bestandteile"]:
    print(b["name"], b["satz_prozent"])

Handling errors

#

If the API responds with an error, the SDK raises QuellenkontorFehler, with the attributes status, code and parameter. Without a connection, the status is 0 and the code is netzwerk.

Python
from quellenkontor import Quellenkontor, QuellenkontorFehler

try:
    r = qk.hr.rechengroessen(jahr=2030)
except QuellenkontorFehler as e:
    if e.code == "kein_wert":
        print("Not promulgated yet:", e)
    elif e.status == 429:
        print("Quota used up")
    else:
        raise

CSV and pandas

#

With format="csv", anfrage returns the CSV text. The SDK removes the byte order mark, so you can read the text directly:

Python
import io
import pandas as pd

csv = qk.anfrage("/hr/mindestlohn/verlauf", {}, format="csv")
df = pd.read_csv(io.StringIO(csv), parse_dates=["gueltig_ab"])
print(df[["gueltig_ab", "mindestlohn_brutto_stunde"]].tail())

Something missing or unclear? Write to us and we will extend the docs.