Glossary
A reference for the domain concepts and project-specific terms used throughout
jobsuche-cli. The Jobsuche domain is German; this glossary gives the English
term used in the CLI/library (where one exists) alongside the original German
field/parameter name the API uses on the wire.
Translation table (the API’s German names → CLI flag / English term):
German (API) CLI flag / English term was --was— job title / keywordwo --wo— locationberufsfeld --berufsfeld— occupational fieldarbeitgeber --arbeitgeber— employerumkreis --umkreis— radius (km)veroeffentlichtseit --veroeffentlicht-seit— published since (days)zeitarbeit --zeitarbeit/--no-zeitarbeit— only / no temp-work agenciesangebotsart --angebotsart— offer type codeStellenangebot job listing / offer Stellenlokation work location
The Jobsuche API
Bundesagentur für Arbeit (BA). Germany’s Federal Employment Agency. It runs the public job-search service this tool wraps.
Jobsuche API. The open REST API behind the BA’s job board — Germany’s largest
job database. Base URL https://rest.arbeitsagentur.de, service path
/jobboerse/jobsuche-service. Documented at
jobsuche.api.bund.dev. This tool implements its
two open, read-only endpoints (search + details).
X-API-Key. The API requires a static, publicly-documented API key
(jobboerse-jobsuche) on every request. It is not a secret, but it is not
bundled with the client — supply it via --api-key, the JOBSUCHE_API_KEY env
var, or the apiKey client option, else the header is omitted and the API
answers 401/403. Surrounding whitespace is trimmed and a blank key counts as none,
on every path. For CI / live testing the public key can be fetched out-of-band
with the CLI’s own obtain-key command (npm run obtain-key in a built
checkout), which reads it from the upstream source at run time.
Endpoints
Search (/pc/v6/jobs). Returns a page of job-listing summaries matching the
search parameters. CLI: search. Library: client.search(params). (The older
/pc/v4/jobs answers an empty 403 even with the right key since 2026-09; the
upstream documents /pc/v6/jobs as the search step.)
Details (/pc/v4/jobdetails/{encryptedJobCode}). Returns the full payload
for a single listing, addressed by its encryptedJobCode. CLI: details.
Library: client.details(refnr).
Resources & identifiers
Stellenangebot (job listing / offer). One job posting. In a search result it
is a summary carrying referenznummer, stellenangebotsTitel, firma,
hauptberuf, stellenlokationen, entfernung, publication/entry dates, often
salary and home-office flags, and an optional externeURL — the same field names
as the details payload. The full description is fetched separately via
details. (Stellenangebot in packages/client/src/types.ts.)
refnr / referenznummer (reference number). The stable identifier of a
listing, returned in each search result’s referenznummer field (called refnr
in older API versions and in this CLI’s help) — e.g. 10001-1002716922-S, the hex form
14225-dafcdd47aabe512d-S, or a purely numeric 1002716922. It is made of
digits, letters and hyphens, and some 15 % of live listings also have _ or :
(13635-dc8d6fe5_JB5255995-S, 17296-0008159:01-S). This is the argument you
pass to details.
encryptedJobCode. The form a refnr must take in the details URL: the
base64 encoding of the refnr. The client base64-encodes the refnr for you;
an already-base64-encoded code is detected (by an exact base64 round-trip that
decodes to a refnr — a digit first, then printable characters — not charset
sniffing) and passed through unchanged, whatever characters the refnr has.
Stellenlokation (work location). One entry of a listing’s
stellenlokationen array: adresse (strasse, hausnummer, plz postal code,
ort city/town, region, land country) plus breite/laenge
(latitude/longitude). A listing’s entfernung is the distance in km from the
searched location, present when wo was given.
firma / arbeitgeber (employer). The hiring organisation named on a listing
(firma); arbeitgeber is the search filter (--arbeitgeber) and the employer
facet. The filter matches the registered name exactly and case-sensitively
(checked live: "Siemens AG" 72 listings, "Siemens" and "siemens ag" none);
the facet’s keys are those exact names.
hauptberuf / berufsfeld. hauptberuf is the occupation on a listing
(alleBerufe lists every one); berufsfeld (occupational field) is a broader
category usable as a search filter (--berufsfeld).
Search parameters
was. Free-text job title or keyword (--was). An empty/whitespace value is
rejected before any request, as it is for wo, berufsfeld and arbeitgeber: the
CLI makes it a usage error, the library client a JobsucheValidationError. Dropping
it would silently run the search unfiltered, and sending it gets HTTP 400 from the
live API (an empty was=). Leave a filter out to search without it.
wo. The location to search in or around (--wo). The API echoes the resolved
location back as woOutput in the result: bereinigterOrt (the place it used) and
suchmodus (UMKREISSUCHE, ORTSUCHE, or UNGUELTIG when it did not recognise
the place). It never rejects a place: a typo is corrected silently (Berln →
Berlin), a garbled name can resolve to another town (Hambrugxx Nord →
Tackesdorf-Nord, 150 km away), and an unknown one gives UNGUELTIG and an empty
result. The CLI prints a warning on stderr in those cases (woNote in the
library); a postcode is unambiguous.
umkreis. Search radius in kilometres around wo (--umkreis), 0–200: the
API answers a larger radius with HTTP 400, so the CLI and the library reject it
before any request. 0 searches the place itself (suchmodus ORTSUCHE).
veroeffentlichtseit (published since). Restrict results to listings published
within the last N days (--veroeffentlicht-seit), 0 to 100
(MAX_VEROEFFENTLICHT_SEIT). The API silently ignores a larger value (the unfiltered
set comes back), so the CLI rejects it as a usage error and the library client with a
JobsucheValidationError.
zeitarbeit (temp work). Temporary-work / staffing-agency listings. By default
(no parameter) they are included with the rest; zeitarbeit=true
(--zeitarbeit) returns only them, zeitarbeit=false (--no-zeitarbeit)
leaves them out. Checked live: the two counts add up to the default’s. Giving both
flags is a usage error, and the library takes only true or false.
angebotsart (offer type). A numeric code selecting the kind of offer
(--angebotsart): 1 job vacancy (Arbeit), 2 self-employment
(Selbstständigkeit), 4 apprenticeship or dual study (Ausbildung / Duales
Studium), 34 internship or trainee post (Praktikum / Trainee). These are the
codes in the upstream bundesAPI OpenAPI spec (ANGEBOTSART_CODES); the CLI rejects
any other code as a usage error and the library client with a
JobsucheValidationError, since the API answers one with an empty result.
page / size. Pagination: page is 1-based (the API answers page=0 with
HTTP 400, so the CLI and the library client reject it), size is the page size
(--page, --size), a non-negative integer.
Result envelope
JobSearchResult. The search response: ergebnisliste (the array of
listings), maxErgebnisse (total number of matches), page, size, facetten
(aggregation facets), and woOutput (the location the API actually searched).
(JobSearchResult in packages/client/src/types.ts.)
ergebnisliste. The array of Stellenangebot summaries on a result page. It
is absent (not []) when nothing matched or with --size 0; on no match
facetten is absent too.
maxErgebnisse. The total count of matching listings across all pages. Every
search answer has it, 0 included; a 200 body without it (null, {}, an
error envelope from a proxy) is rejected as a parse error, exit 1, rather than
read as “nothing matched”. A details answer must carry its referenznummer.
facetten (facets). Aggregated counts the API returns alongside results (e.g. by location or employer), surfaced as a raw object.
JobDetails. The full single-job payload from the details endpoint, kept as
a faithful raw JSON object rather than a narrowed type.
Search & API concepts
Public, no-auth (read-only). Only the open GET search and details endpoints
are implemented. The static X-API-Key is not a credential a user must obtain.
Rate limiting / transient errors. The API may return 429 (too many
requests) or 503; the client retries these automatically (--max-retries,
default 2, at most 10), waiting the server’s Retry-After when it asks for up
to 30 s, else a linear backoff. A longer Retry-After is not retried: the error
names the wait.
Credential stripping on redirect. Credentials (the X-API-Key, a base URL’s
user:password@, Authorization, Cookie) go only to the base URL’s origin.
They are dropped for the rest of the chain if the API redirects to another scheme,
host or port — http: → https: on the same host included — so the key cannot
leak to a third-party host. Same-origin redirects keep them. If the target then
answers 401/403, the error says the redirect dropped the key (for http: →
https:: “use an https base URL”) instead of blaming the key.
Log record. Every diagnostic line the CLI writes to stderr: a timestamp, a level
(ERROR, WARN, INFO) and a topic jobsuche.<area>, as text (log4j style) or with
--log-format jsonl as one JSON object per line. The areas: cli (usage errors,
commander’s messages, unexpected errors), api (the API’s answers: an error status, the
401/403 hints, the --wo warning, and a malformed answer — bad JSON, the wrong shape or
content type), http (the connection, the cleartext warning, one WARN per retry before it waits), config (the credentials
file), obtain-key and output (stdout failures). A record is always one line; control
characters in it are escaped.
Library & internals. Terms for the TypeScript client and its internals —
JobsucheClient, the request engine, transport, retry/backoff, error types, query builder — now live in DEVELOPING.md.