Glossary

Domain and technical terms you meet when using abgeordnetenwatch. For commands and options see the README; every field of every entity is described in openapi.yaml. The data is German, so labels and free text are German too.

abgeordnetenwatch.de

abgeordnetenwatch.de. A German parliamentary-monitoring platform run by Parliament Watch e.V. (Verein zur Förderung der parlamentarischen Kontrolle e.V.). Its open API v2 (https://www.abgeordnetenwatch.de/api/v2) is read-only and needs no API key.

Entity / collection. One of the API’s 18 record types. The collection name is the URL path segment that list, get and count take as <entity>; abgeordnetenwatch entities prints all 18. Names are plural, with hyphens between words (parliament-periods; election-program is singular). The entity_type inside a record is singular with underscores; committees and polls report node, topics, cities and countries taxonomy_term.

Roll-call vote (namentliche Abstimmung). A vote that records each member’s choice by name. Only these appear as polls, so the data is a selection of a parliament’s decisions.

Entities

Collection entity_type One record is
parliaments parliament the Bundestag, the EU-Parlament or one of the 16 state parliaments
parliament-periods parliament_period a legislative period or an election of one parliament
politicians politician a person
candidacies-mandates candidacy_mandate a politician’s candidacy in an election, or their seat in a period
electoral-lists electoral_list a party list for one period (name, e.g. Landesliste SPD)
constituencies constituency a constituency (Wahlkreis) with number and name
parties party a party, with full_name and short_name
fractions fraction a parliamentary group (Fraktion) in one period
election-program election_program a party’s election programme for one period; file is the PDF URL
committees node a committee (Ausschuss) of one period
committee-memberships committee_membership a mandate’s membership in a committee
polls node a roll-call vote
votes vote how one mandate voted in one poll
sidejobs sidejob a disclosed side job (Nebentätigkeit)
sidejob-organizations sidejob_organization an organisation named in side jobs
topics taxonomy_term a topic term, e.g. Gesundheit
cities taxonomy_term a city term used by side jobs and organisations
countries taxonomy_term a country term used by side jobs and organisations

Parliaments and people

Parliament (parliaments). label is the short name (Bundestag, Hessen, EU-Parlament), label_external_long the full one (Landtag Hessen). current_project references the period that is active now, which can be an election period (Berlin Wahl 2026).

Parliament period (parliament-periods). A phase of one parliament, linked to its previous_period. type is legislature (a Wahlperiode such as Bundestag 2025 - 2029, with start_date_period and end_date_period) or election (such as Bundestag Wahl 2025, with election_date).

Politician (politicians). Key fields: first_name, last_name, field_title (academic title), sex (m, f, d for diverse, or null), year_of_birth (can be null), party (current party), occupation, qid_wikidata, and abgeordnetenwatch_url (the public profile).

Candidacy / mandate (candidacies-mandates). Links a politician to a parliament_period. type is candidacy (stood in an election period such as Bundestag Wahl 2025) or mandate (held a seat in a legislature period such as Bundestag 2025 - 2029). Votes, side jobs and committee memberships belong to the mandate, so resolve a politician id to a mandate id first.

current_on. A filter on candidacies-mandates. Without it the API returns only the records current today, so a politician’s earlier mandates are missing; current_on=all returns every record, current_on=2022-01-01 those current on that date.

Electoral data (electoral_data). Embedded in a candidacy/mandate: electoral_list, list_position, constituency, constituency_result (vote share in percent) and mandate_won, which is constituency (Direktmandat), list (won via the party list) or moved_up (nachgerückt as a successor).

Fraction membership (fraction_membership). An array on a candidacy/mandate: fraction, valid_from, valid_until (null while ongoing).

Party vs. fraction. A party (parties, e.g. CDU) is not tied to a period. A fraction belongs to one period: its label says which (SPD (Berlin 2021 - 2026)) and legislature references it. Politicians carry a party; votes carry the fraction at the time of the vote.

Polls, votes and committees

Poll (polls). label (title), field_poll_date, field_accepted (true/false), field_legislature (the period), field_intro (HTML description), field_topics, field_committees. Some labels describe a rejection (Ablehnung des Antrags …), so read field_accepted together with label and field_intro.

Vote (votes). One mandate’s vote in one poll: mandate, poll, fraction, reason_no_show (e.g. maternity_protection) and vote:

vote Meaning
yes voted yes
no voted no
abstain abstained
no_show did not take part; not a no

A poll has one vote record per mandate (630 for Bundestag poll 6600), so poll=<id> can need several pages. For EU-Parlament polls only the German MEPs’ votes are recorded (96 for poll 6593).

Committee membership (committee-memberships). Links a committee (which belongs to a period through field_legislature) to a candidacy_mandate. committee_role values seen: member, alternate_member, chairperson, vice_chairperson, spokesperson, advisory_member.

Side jobs

Side job (sidejobs). An activity disclosed for one or more mandates; label describes it.

Field Meaning
mandates the mandates it is disclosed for (an array)
sidejob_organization the organisation, a reference; can be null
income the declared amount, a number
income_level the income band, a string code ("1" to "10")
interval a payment interval code ("1", "2") or null
category a category code, a numeric string (e.g. "29231")
field_city, field_country, field_topics place and topic terms
additional_information HTML free text
data_change_date, created last change (date), creation time (Unix seconds)

Band vs. amount. Older disclosures (Bundestag 2013 - 2017) carry only income_level; recent ones (Bundestag 2025 - 2029) carry both income_level and income. Don’t turn a band into an amount. Both null means disclosed without an amount.

Taxonomy term (topics, cities, countries). A vocabulary entry (label, description, parent) that records point to through field_topics, field_city and field_country.

Ids and references

id / label. Every record has a numeric id, a display label, an api_url and often an abgeordnetenwatch_url (its page on the website). get <entity> <id> fetches one record; the CLI rejects 0 and non-numeric ids.

Reference. A related record embedded as a small object with id, entity_type, label, api_url and sometimes abgeordnetenwatch_url, e.g. party on a politician. Fetch the full record with get and the reference’s id.

Filter by relation. Pass the related record’s id under the field name used in the JSON:

To get Command
a parliament’s periods list parliament-periods parliament=<id>
a politician’s candidacies and mandates list candidacies-mandates politician=<id>
a period’s candidacies and mandates list candidacies-mandates parliament_period=<id>
a period’s polls list polls field_legislature=<id>
polls on a topic list polls field_topics=<id>
all votes in a poll list votes poll=<id>
a mandate’s votes list votes mandate=<id>
a mandate’s side jobs list sidejobs mandates=<id> (plural; mandate= fails)
an organisation’s side jobs list sidejobs sidejob_organization=<id>
a mandate’s committees list committee-memberships candidacy_mandate=<id>

Filtering, sorting and paging

Filter (key=value). Positional arguments after the entity, sent as query parameters (sex=f). A parameter the collection doesn’t accept returns HTTP 500, e.g. The following parameter(s) are not valid: mandate on sidejobs. The paging and sorting names (range_start, range_end, sort_by, sort_direction) are not filters: the CLI rejects them and points to the matching option, and the library rejects them too.

Operator (field[op]=value). A bracket suffix on the key: eq (equal), ne (not equal), gt, gte, lt, lte (greater or less than, or equal), cn (contains, ignoring case: 'last_name[cn]=reichinnek') and sw (starts with: 'last_name[sw]=Mü'). Quote these filters so the shell leaves the brackets alone. The CLI rejects a missing =, a blank key or value, a key that is not a field name with at most one operator ('[gt]=1990', 'year_of_birth[gt]x=1990'), any other operator ([in], the [entity.id] form), a repeated key and a plain key next to an operator key on the same field (sex=f 'sex[ne]=m': the API would keep only one) as usage errors; one field with two different operators is fine. The library’s list() and count() reject the same filters with AwValidationError before sending anything, because the API would drop them silently and return the unfiltered set. They also reject the names __proto__, constructor and prototype (no collection has such a field, and __proto__ used to vanish from the request), a filter value that is not one string, number or boolean (an array, which went out as repeated keys of which the API keeps one, NaN, an object), and a parameter other than filters, rangeStart, rangeEnd, sortBy and sortDirection (a misspelled filter returned the whole collection). Every CLI option takes one value: giving one twice (--range-end 5 --range-end 500) is a usage error.

Sorting (--sort-by, --sort-direction). Sent as sort_by and sort_direction (asc or desc). With --sort-by alone the API sorts descending; --sort-direction without --sort-by is a usage error (the API rejects it), and the library rejects sortDirection without sortBy, a blank sortBy and any other direction with AwValidationError. Not every field is sortable: polls reject id but accept field_poll_date. Without --sort-by the order depends on the collection (parliaments highest id first, topics by label).

Paging (--range-start, --range-end). Sent as range_start (0-based offset) and range_end, which is the page size, not an end index. Both are non-negative integers (the CLI and the library reject anything else). The API honours up to 1000; a larger value falls back to 100. Raise --range-start by the page size until you have meta.result.total records.

Output

Envelope (meta, data). Every response is { meta, data }; data is an array for list and an object for get. --data-only prints only data, --compact prints the JSON on one line. count prints { entity, total }, entities prints { entities: [...] }.

meta.result. For list: count (records in this page), total (all matches), range_start, range_end. For get: entity_id (the id as a string) and entity_type.

meta.status / meta.status_message. ok and an empty message on success. On an error the CLI prints the message, e.g. There is no party entity with id 99999999.

meta.abgeordnetenwatch_api. The same block on every response: version (2.9.0), changelog, licence (CC0 1.0), licence_link and documentation.

Data license

CC0 1.0. The data is dedicated to the public domain under CC0 1.0 Universal, as every response states in meta.abgeordnetenwatch_api.licence. You may use, change and redistribute it, commercially too. Attribution is not required but requested: Quelle: abgeordnetenwatch.de (https://www.abgeordnetenwatch.de) — Daten unter CC0 1.0.

Personal data. Names, votes and side-income disclosures are personal data: CC0 waives copyright, not GDPR (DSGVO) obligations. HTML fields such as field_intro can quote third-party material, and the website, logo and branding are not covered. See DATA_LICENSE.md.

Exit codes

Exit codes. 0 success (also --help, help and --version) · 1 API error, network or parse failure · 2 usage error (unknown entity, bad option, filter or id) · 4 HTTP 404 (unknown collection path).

HTTP 500. The API answers a missing id, a parameter it doesn’t accept and an unsortable field with HTTP 500, not 404 or 400; the CLI prints the reason and exits 1. HTTP 429 and 503 are retried automatically (--max-retries, default 2, at most 10); each retry is a WARN record of abgeordnetenwatch.http (HTTP 503 from host: retry 1 of 3 in 2 s), offered by the library as onRetry.

Log record. Every diagnostic line the CLI writes to stderr: a timestamp, a level (ERROR, WARN, INFO) and a topic abgeordnetenwatch.<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 its hints, and a malformed answer — bad JSON, the wrong shape or content type), http (the connection, the cleartext warning, and one WARN per retry before it waits) and output (a failed write to stdout). A record is always one line; control characters in it are escaped.

Library & internals. The TypeScript client, request engine, retries, redirects and error types are described in DEVELOPING.md.

View the source on GitHub →