Glossary
A reference for the domain concepts and project-specific terms used throughout
ausbildungssuche-cli. The domain is the German federal apprenticeship /
vocational-training catalogue; this glossary gives the English term used in the
CLI/library alongside the original German, and decodes the API’s terse
abbreviated query parameters.
Search-parameter cheat sheet. The upstream API names its query parameters with short German abbreviations. The CLI exposes them as flags of the same name, so they map one-to-one:
API param / flag Meaning swSuchwort — search keyword (currently ignored by the API) stySuchtyp — offer/search type ( 0..3)orteOrt — location ( Name_lon_lat)reRegion — Bundesland code ukUmkreis — search radius (km, or Bundesweit)idsBerufs-id(s) — occupation id(s) bartBildungsart — training/education type bgBildungsgutschein — education-voucher filter btBeginntermin — start-date code ( 2,101..112; not a date)page0-based page index sizepage size ( 1..20)
The programme & API
Ausbildungssuche. “Apprenticeship search” — the Bundesagentur für Arbeit’s public catalogue of apprenticeship and vocational-training offers (Ausbildungsangebote), searchable online at the agency’s portal and exposed by the REST API this tool wraps.
Bundesagentur für Arbeit (BA). The German Federal Employment Agency, which operates the Ausbildungssuche service and its API.
Ausbildungssuche API. The REST service at
rest.arbeitsagentur.de/infosysbub/absuche. It is part of the agency’s
infosysbub (Informationssystem Bildung und Beruf) family of services;
absuche is the Ausbildungssuche component. Documented at
ausbildungssuche.api.bund.dev.
X-API-Key. A static, publicly-documented API key
required on every request (documented by the community project bundesAPI, not by
the Bundesagentur für Arbeit itself). It is not bundled — obtain it with obtain-key or supply
it via --api-key, the AUSBILDUNGSSUCHE_API_KEY env var, a key stored with
ausbildungssuche config set api-key (CLI only), or the apiKey client option, else the header is omitted and the service answers 401/403. An
empty/whitespace key is treated as absent (no header sent); any other key is sent
with surrounding whitespace trimmed, however it was supplied. A key with an inner
control character or a character above U+00FF is rejected by the CLI (exit 2) and the
library before any request. For CI / live testing
the public key can be fetched out-of-band (never from the CLI) via
the CLI’s own obtain-key command (npm run obtain-key).
Resources / endpoints
Ausbildungsangebot (apprenticeship offer). The central resource — a single apprenticeship/training offer. The API surfaces it through two endpoints:
Search (/pc/v1/ausbildungsangebot). The offer-search collection. Accepts
the search parameters above and returns a HAL+JSON envelope. Served as
application/hal+json; it answers 406 to a plain application/json Accept,
so the client requests HAL explicitly. CLI: search. Library: client.search().
Details (/pc/v1/ausbildungsangebot/{id}). Full detail for one offer by id.
This endpoint serves application/json (and conversely answers 406 to a
HAL+JSON Accept), so the client requests plain JSON here. CLI: details <id>.
Library: client.details(id).
Search-result envelope (HAL+JSON)
HAL+JSON. Hypertext Application Language over JSON — the media type the search
endpoint returns. A HAL document carries the payload plus hypermedia metadata in
reserved _embedded and _links members.
_embedded. The container holding the embedded offer objects of a search
result. Offers are large and deeply nested, so the client keeps them as faithful
raw JSON objects rather than narrowing them to a partial type.
_links. HAL hypermedia links (self, next/prev page, etc.).
page (PageInfo). HAL paging metadata for a search result:
size, totalElements, totalPages, and number (the current 0-based page).
totalElements is capped at 10000: a broad query reports exactly 10000, meaning
“10000 or more”, and only those first 10000 results can be paged through.
Identifiers
Offer id. The identifier of one apprenticeship offer, passed to
details <id>. Offer ids are numeric (digits only, at least 1, at most 18
digits; leading zeros are fine): the CLI rejects anything else (exit 2) and the
library rejects it with a validation error, both before any request — the API
answers 0 or a 23-digit id with a bare HTTP 400.
Location (orte). The place used to scope a search, written as
Name_lon_lat with the longitude first, e.g. Köln_6.957_50.938. With the
latitude first the API silently returns 0 results. A bare name (Köln) gets HTTP 400 and
coordinates out of range get HTTP 500, so the CLI and the library reject both before any
request. Several places, comma-separated (Köln_6.957_50.938,Berlin_13.405_52.52), are
searched together — the offers near any of them — and every one is checked. On a place search each offer
carries its distance from the place in abstaende[].abstandInKm. A place only
restricts the search together with a radius (uk); on its own it just adds the
distances, so the CLI and the library require uk next to orte.
Profession id (ids). Identifier(s) of a profession/occupation used to scope
a search: the dkzId in an offer’s angebot.systematiken[] (e.g. 9162,
Staatlich anerkannter Erzieher). Several ids can be comma-separated. Ids are
numeric: a non-numeric id or an empty item (a trailing comma, 9162,) gets a bare
HTTP 400, so the CLI and the library reject it; an unknown number gives an empty
result. This is the only working occupation filter: the API ignores the keyword sw.
Region / state code (re). The 3-letter code of a Bundesland used to scope a
search: BAW, BAY, BER, BRA, BRE, HAM, HES, MBV, NDS, NRW,
RPF, SAA, SAC, SAN, SLH, THÜ. Several can be comma-separated. An
offer’s code is in adresse.ortStrasse.land.code; the 2-letter abbreviations
(e.g. BW) get HTTP 400, so the CLI (exit 2) and the library reject any other
code before any request. Both first trim, NFC-normalise and uppercase each code
(nrw → NRW).
Filter values, units & enums
Offer type (sty). A small integer code 0..3 selecting the kind of
offer/search. The API rejects 4 with HTTP 400; the CLI (exit 2) and the library
reject anything outside 0..3.
Radius (uk, Umkreis). The search radius around the location, in
kilometres — 10, 25, 50 or 100 — or the literal string Bundesweit
(“nationwide”) to search the whole country with no radius limit. Other values
(e.g. 30, 150, 200) get HTTP 400, so the CLI (exit 2) and the library reject
them; both send bundesweit in any case as Bundesweit. A kilometre radius needs a location
(orte): without one the API ignores it, so the CLI and the library reject uk 25
without orte.
Training type (bart, Bildungsart). The category of training/education being
searched: one numeric bildungsart.id, e.g. 101 Berufliche Grundqualifikation, 102
Berufsausbildung, 104 Fortbildung/Qualifizierung. A non-numeric value gets a bare
HTTP 400, so the CLI and the library reject it; an unknown number gives an empty
result.
Education voucher (bg, Bildungsgutschein). A boolean filter restricting
results to offers eligible for a Bildungsgutschein — a state-issued voucher
that funds an approved training measure.
Start date (bt, Beginntermin). A code for the desired training start, not a
date: per the upstream API description 2 means earlier dates and 101..112
January..December of the following year. 0 and 1 are accepted too and are real
filters — on 2026-10-05 each kept about half of one search’s offers (158 and 156 of
337) — but their meaning is undocumented, so don’t rely on them; any other value gets
HTTP 400, so the CLI (exit 2) and the library reject it.
Several codes can be comma-separated.
Page (page). Zero-based page index for paging through search results. The
API serves at most 10000 results of a query, so (page + 1) × size must be at most
10000 (MAX_RESULT_WINDOW; with the default size 20, the last page is 499); a later
page gets HTTP 500, so the CLI (exit 2) and the library reject it before any request.
Page size (size). Number of results per page, an integer 1..20
(MAX_PAGE_SIZE). The server silently overrides size=0 (to 20) and clamps any
larger value to 20 (it comes back as page.size 20, so page counts in pages of
20), so the CLI (exit 2) and the library reject anything outside 1..20 up front. The upstream API
description names 2000 as the maximum; the server does not honour it.
Exit codes
Exit codes. The CLI maps outcomes to process exit codes: 0 success;
2 usage / argument-validation errors; 3 on 401/403 (rejected request,
often the API key; 1 instead when a redirect to another origin dropped the key, so the
server that answered never saw it); 4 on 404; 5 on 406 (Accept negotiation failed);
6 on a network / transport failure (DNS, connection, timeout, response-size
cap); 1 for any other error. --help/--version return 0.
Log record. Every diagnostic line the CLI writes to stderr: a timestamp, a level
(ERROR, WARN, INFO) and a topic ausbildungssuche.<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 and
the hints after it, and a malformed answer — bad JSON, the wrong shape), http (the
connection, the cleartext warning, and one WARN per retry before it waits), config, obtain-key and output (a failed write
to stdout). A record is always one line; control characters in it are escaped.
Library & internals. Terms for the TypeScript client and its internals —
AusbildungssucheClient, the request engine, transport, retry/backoff, error types, query builder — now live in DEVELOPING.md.