Website: English · Deutsch — command reference, guides and API docs
A TypeScript API client and CLI for the Bundesagentur für Arbeit Entgeltatlas API — German median gross-monthly salary statistics by occupation (KldB-2010), sliced by requirement level, region, gender, age, and industry.
Read-only, zero runtime HTTP dependencies (built on node:http/https), strict
TypeScript, ESM.
npm install -g @maschinenlesbar.org/entgeltatlas-cli
The API needs a static X-API-Key (the BA's published community client_id).
No key is bundled with this tool — see Obtain key below.
Precedence is --api-key flag > ENTGELTATLAS_API_KEY env var > none. The
codes command works with no key at all.
The Bundesagentur für Arbeit publishes one community client_id for public use.
It is not a secret — the same value for everyone, printed in the upstream
bundesAPI/entgeltatlas-api
README — but finding and copying it shouldn't be your job either. obtain-key
reads it from that published source at run time and prints it:
entgeltatlas obtain-key # -> a UUID (provenance note on stderr)
From obtaining the key to having it where it is used, in one line:
# this shell only
eval "$(entgeltatlas obtain-key --export)"
# or keep it for later — appends one `export …` line to your shell profile
entgeltatlas obtain-key --export >> ~/.zshrc # ~/.bashrc on bash
--export prints a single shell-quoted export ENTGELTATLAS_API_KEY='…' line on
stdout (the "obtained from …" note goes to stderr, so it never lands in your
profile). The plain form composes too:
export ENTGELTATLAS_API_KEY="$(entgeltatlas obtain-key)"
Because the key is fetched rather than compiled in, a rotated key needs no
release of this CLI. If the source is unreachable or stops publishing a key,
obtain-key fails loudly with a non-zero exit rather than printing a guess.
Note that a successfully obtained key is still no guarantee the API will answer:
see the 403 heads-up below.
Heads-up — an empty 403 is ambiguous.
rest.arbeitsagentur.deanswers a wrong or missing key with HTTP 403 (empty body), and its Akamai WAF sends the same response when it refuses a network (datacenter/cloud/VPN IPs). If you get one (exit code3), re-check the key against the bundesAPI README first; if it matches, try from another network, e.g. a residential connection. The CLI's 403 message says as much.
entgeltatlas codes # dimension code tables (offline, no key)
entgeltatlas entgelte 84304 # salary stats for a KldB occupation
entgeltatlas entgelte 84304 -l 4 -r 1 -g 1 # Experte, Deutschland, all genders
entgeltatlas regionen # live region codes
entgeltatlas entgelte 84304 --compact | jq '.[0].entgelt'
entgelte <kldb> takes the numeric KldB-2010 code, not an occupation name —
this API has no name search. Resolve a name to a code via the BERUFENET/DKZ
sibling APIs or the KldB catalogue.
See Usage.md for the full command reference and GLOSSARY.md for the dimensions, the KldB system, and how to read censored/suppressed figures.
import { EntgeltatlasClient } from "@maschinenlesbar.org/entgeltatlas-cli";
const ea = new EntgeltatlasClient({ apiKey: process.env.ENTGELTATLAS_API_KEY });
const rows = await ea.entgelte("84304", { l: 4, r: 1 });
// rows[0].entgelt is the MEDIAN gross monthly EUR — or null when suppressed.
Errors are typed (EntgeltatlasApiError, EntgeltatlasNetworkError,
EntgeltatlasValidationError, EntgeltatlasParseError).
entgelt is the median (not the mean), in EUR gross per month, full-time.null when suppressed (too few observations) — never treat as 0.region.beitragsBemessungsGrenze), so the top can look artificially flat.npm install
npm run build # tsc -> dist/
npm test # builds, then node --test on dist/test
npm run typecheck
See DEVELOPING.md for architecture and API specifics.