Fundamentals

Responses, formats and CSV

How responses are structured, how numbers and dates are encoded and how to get lists as CSV into Excel or your database.

JSON

#

All responses come as JSON in UTF-8, with the header Content-Type: application/json; charset=utf-8. Field names are German, lowercase and underscored, for example mindestlohn_brutto_stunde. The REST API, the SDK, the CLI with --format json and MCP (in the structuredContent field) all return the same fields in the same form.

An example, the public holidays in Hesse (Hessen) for 2027 (the list is shortened to two entries here):

Response, shortened
{
  "datensatz": "feiertage",
  "jahr": 2027,
  "land": "HE",
  "land_name": "Hessen",
  "anzahl": 10,
  "anzahl_landesweit_montag_bis_freitag": 6,
  "feiertage": [
    {
      "datum": "2027-01-01",
      "id": "neujahr",
      "name": "Neujahr",
      "wochentag": "Freitag",
      "regional": false,
      "regional_hinweis": null,
      "sonntag": false
    },
    {
      "datum": "2027-03-26",
      "id": "karfreitag",
      "name": "Karfreitag",
      "wochentag": "Freitag",
      "regional": false,
      "regional_hinweis": null,
      "sonntag": false
    }
  ],
  "rechtsgrundlage": "Hessisches Feiertagsgesetz (HFeiertagsG)",
  "quelle": {
    "titel": "Hessisches Feiertagsgesetz (HFeiertagsG), Hessen",
    "url": "https://www.rv.hessenrecht.hessen.de/bshe/document/jlr-FeiertGHE1952pP1"
  },
  "quellen": [
    {
      "titel": "Hessisches Feiertagsgesetz (HFeiertagsG), Hessen",
      "url": "https://www.rv.hessenrecht.hessen.de/bshe/document/jlr-FeiertGHE1952pP1"
    }
  ],
  "hinweise": [
    "Regionale Feiertage gelten nur in Teilen des Landes und sind mit regional: true gekennzeichnet.",
    "sonntag: true steht für gesetzliche Feiertage, die immer auf einen Sonntag fallen. Das ist für Zuschläge nach § 3b EStG wichtig.",
    "Einmalige Feiertage sind enthalten, soweit sie bis zum Datenstand beschlossen sind. Neue Beschlüsse trägt der wöchentliche Prüflauf nach."
  ],
  "stand": "2026-09-23",
  "lizenz": "Berechnung nach den genannten Normen. Nutzung nach den Nutzungsbedingungen von Quellenkontor.",
  "zitat": "Gesetzliche Feiertage 2027 in Hessen: 10, davon 6 landesweit von Montag bis Freitag. Landesweit: Neujahr Fr 01.01., Karfreitag Fr 26.03., Ostermontag Mo 29.03., Tag der Arbeit Sa 01.05., Christi Himmelfahrt Do 06.05., Pfingstmontag Mo 17.05., Fronleichnam Do 27.05., Tag der Deutschen Einheit So 03.10., 1. Weihnachtstag Sa 25.12., 2. Weihnachtstag So 26.12.. Regionale Feiertage stehen in der Antwort. Rechtsgrundlage: Hessisches Feiertagsgesetz (HFeiertagsG). Quelle: Hessisches Feiertagsgesetz (HFeiertagsG), Hessen, https://www.rv.hessenrecht.hessen.de/bshe/document/jlr-FeiertGHE1952pP1. Daten: Quellenkontor (quellenkontor.dev).",
  "datenstand": "2026-09-23.1"
}

Numbers, amounts and dates

#
TypeRepresentationExample
Monetary amountsNumber in euros with a period as the decimal separator, no currency symbol13.9
PercentagesNumber in percent, not as a fraction14.6 means 14.6 percent
DatesString in the format YYYY-MM-DD2027-01-01
Booleanstrue or falsetrue
No valuenull, when a field does not apply in this case or is still opennull
ListsJSON array, even when it has just one entry[]

In your own software, it is best to calculate monetary amounts in cents or with decimal types, not floating-point numbers. The API returns amounts exactly as they appear in the legal source.

Units of the components

Datasets built from components, for example mini-job levies (Minijob-Abgaben) or tax-free amounts, name the field einheit for each value:

einheitMeaning
euroEuros
euro_stundeEuros per hour
euro_tagEuros per day
euro_monatEuros per month
euro_jahrEuros per year
euro_kmEuros per kilometer
euro_uebernachtungEuros per overnight stay
prozentPercent
prozent_listenpreisPercent of the gross list price
tageDays
anzahlplain count, no unit
fahrtenTrips
arbeitsplaetzePositions
kmKilometers

Fields in every response

#
FieldMeaning
datensatzId of the dataset, for example mindestlohn
rechtsgrundlageLegal provision the value or calculation is based on
hinweiseList of limitations and assumptions you should show your users
datenstandDate and sequence number of the last changelog entry affecting this dataset, for example 2026-09-24.14

Table datasets also return gueltig_ab, gueltig_bis, quelle and stand, see Validity in the response. All fields of every dataset are listed in the reference.

datenstand is built for auditors: two responses with the same datenstand rest on the same checked data, whenever you fetched them. The id points straight to the entry in the changelog. The header X-Datenstand carries the same value and, for CSV, is the only place it appears (CSV has no field for it).

CSV

#

Lists are also available as a CSV file with format=csv: every history, the public holidays, the public holidays on working days from the working-days calculator, and the components of the contribution rates. There is no CSV for single values; the API then responds with ungueltiger_parameter.

  • Built to RFC 4180: first line with column names, CRLF line endings, fields containing the delimiter or quotes wrapped in quotes.
  • UTF-8 with a BOM, so Excel displays German umlauts correctly.
  • Nested fields become their own columns: quelle.titel becomes quelle_titel.
  • The filename is in the Content-Disposition header, for example feiertage.csv.
Terminal
curl "https://api.quellenkontor.dev/v1/hr/feiertage?jahr=2027&land=HE&format=csv" \
  -H "Authorization: Bearer $QK_KEY" -o feiertage-2027-he.csv
feiertage-2027-he.csv, first lines
datum,id,name,wochentag,regional,regional_hinweis,sonntag
2027-01-01,neujahr,Neujahr,Freitag,false,,false
2027-03-26,karfreitag,Karfreitag,Freitag,false,,false
2027-03-29,ostermontag,Ostermontag,Montag,false,,false

CSV in Excel

#

Excel with German settings expects semicolons as the delimiter and commas in decimal numbers. With trennzeichen=semikolon you get exactly that, and the file opens correctly with a double click:

Terminal
curl "https://api.quellenkontor.dev/v1/hr/mindestlohn/verlauf?format=csv&trennzeichen=semikolon" \
  -H "Authorization: Bearer $QK_KEY" -o mindestlohn.csv
mindestlohn.csv, last lines
gueltig_ab;mindestlohn_brutto_stunde;minijob_grenze_monat;rechtsgrundlage;quelle_url
2025-01-01;12,82;556;Vierte Mindestlohnanpassungsverordnung vom 24. November 2023 (BGBl. 2023 I Nr. 321), Stufe 2;https://www.recht.bund.de/bgbl/1/2023/321/VO.html
2026-01-01;13,9;603;Fünfte Mindestlohnanpassungsverordnung vom 5. November 2025 (BGBl. 2025 I Nr. 268), Stufe 1;https://www.recht.bund.de/bgbl/1/2025/268/VO.html
2027-01-01;14,6;633;Fünfte Mindestlohnanpassungsverordnung vom 5. November 2025 (BGBl. 2025 I Nr. 268), Stufe 2;https://www.recht.bund.de/bgbl/1/2025/268/VO.html
Google Sheets cannot send a header with IMPORTDATA, and therefore no key. Download the CSV file and import it, or use Apps Script with UrlFetchApp and the Authorization header.

Response headers

#
HeaderContent
Content-Typeapplication/json or text/csv, each with charset=utf-8
X-Kontingent-LimitRequests per month under your plan, on every response made with a key
X-Kontingent-VerbrauchtRequests used in the current month, including this one
X-Datenstandthe same value as the field datenstand, also for CSV
Cache-Controlfor dataset responses private, max-age=…, must-revalidate until the next midnight German time, see Saving requests; otherwise no-store
ETagbuilt from datenstand and the request, for If-None-Match, see Saving requests
Access-Control-Allow-Origin*, calls from the browser are technically possible, see REST API
WWW-Authenticateonly with status 401

Full export and offline data

#

GET https://api.quellenkontor.dev/v1/export returns the entire table inventory in one call: for every dataset with a history (15 of 23) the full history as JSON, plus a link to the dataset's own CSV file. Useful for a first import into your own database or for a backup. Plain calculators without a table, for example notice period or company car, are not included: they have no history to export.

The export needs a key and counts as a single request, no matter how many datasets it contains.

Terminal
curl "https://api.quellenkontor.dev/v1/export" \
  -H "Authorization: Bearer $QK_KEY" -o quellenkontor-export.json
Shape, shortened
{
  "datenstand": "2026-09-24.16",
  "erzeugt_am": "2026-09-24T18:00:00.000Z",
  "datensaetze": [
    {
      "id": "mindestlohn",
      "name": "Mindestlohn und Minijob-Grenze",
      "anzahl": 7,
      "csv_url": "https://api.quellenkontor.dev/v1/hr/mindestlohn/verlauf?format=csv",
      "verlauf": [
        "…"
      ]
    },
    "…"
  ]
}

Offline data in the JavaScript and Python SDKs

Both SDKs ship the same history that /export returns, built into the package itself. If the API is unreachable after every retry, the SDK works out the matching step for the requested date itself from the bundled data instead of throwing an error. That response then carries offline: true and the package's own datenstand, not the currently official one, and it is missing the computed extra fields such as zitat, vorheriger_wert or naechster_wert. Plain calculators without a history stay a network error without a connection; there is no offline data for them. Details and how to turn it off are under JavaScript SDK and Python SDK.

The offline data lives in the package source and is generated from the current data set when a new package version is built. Between two package versions it ages like any local copy, hence its own datenstand in the response.

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