Ownership
Shareholders, shareholdings and what the register can and cannot tell you.
What the register holds
Germany has no public register of beneficial ownership you can simply read. Ownership comes from the shareholder list (Gesellschafterliste), which a GmbH must file whenever its shareholders change.
This has three consequences you must design around:
- It is a document, not a field. The list is a PDF. What the API returns is what was extracted from it.
- It is only as fresh as the last filing. A company whose shareholders last changed in 2014 has a 2014 list, and that is correct.
- Not every legal form has one. An
AGfiles no shareholder list; a sole trader (e.K.) has no shareholders. An empty response is frequently the right answer.
Reading ownership
GET /companies/{company_id}/shareholders
returns who holds an interest in the company: shareholders, and for partnerships the general
and limited partners. Each one is a shareholding:
{
"object": "page",
"data": [
{
"object": "shareholding",
"id": "shr_01h455vb4pex5vsknk084sn02q",
"company": { "object": "company", "id": "cmp_01h455vb4pex5vsknk084sn02r", "name": "Beispiel Analytics GmbH" },
"holder": { "object": "company", "id": "cmp_01h455vb4pex5vsknk084sn02s", "name": "Beispiel Beteiligungs GmbH" },
"type": "shareholder",
"percentage": 40,
"nominal_amount": { "amount": "10000.00", "currency": "EUR" },
"liability_amount": null,
"match_confidence": 1,
"source": { "object": "document", "id": "doc_01h455vb4pex5vsknk084sn02t", "date": "2025-06-03", "type": "shareholder_list" }
}
],
"next_cursor": null,
"extract": { "status": "parsed", "fetched_at": "2025-06-10T08:12:44Z", "document_id": "doc_01h455vb4pex5vsknk084sn02t" }
}type says what the interest is: shareholder, general_partner (Komplementär) or
limited_partner (Kommanditist). source is the filing it was read from, and source.date
is the date of that filing. Always show it. A percentage without its as-of date is a claim
you cannot support.
holder is a party: object says whether the holder is a company or a person, and id leads
to its record. id is null when the register names a holder we could not match to a record,
such as a company registered abroad; name is then the name as filed.
Holders that are companies
Where a holder is itself a company,
GET /companies/{company_id}/ownership-tree
follows linked companies for the depth you ask, from 1 to 3. Each node is a shareholding
with its depth, its effective_percentage of the company you asked about (the product of the
percentages along the path), and via_shareholding_id, the holding one level down.
The chain stops, and says why, when it reaches a company we have not linked (foreign_entity
when that company is registered abroad, entity_not_linked when the country is Germany or not
stated), an AG, SE or KGaA
(stock_corporation; those forms file no shareholder list — a partnership worded "AG & Co. KG",
"AG & Co. OHG", "AG & Co. Kommanditgesellschaft" or "SE & Co. Offene Handelsgesellschaft" is not
one of them), a company whose list is not stored yet
(no_shareholder_list or extraction_pending), a percentage that cannot be published
(percentage_withheld), the depth you asked for (depth_limit), a cycle (cycle) or a
company that holds itself (self_holding). Those holdings are listed in unresolved, once
per reason when the same holding is reached by several paths. complete is true only when
that list is empty, the walk was not cut short, and list_reason is null. truncated is
true when depth or the cap of 250 nodes stopped it.
At depth 1, effective_percentage is the holding's own percentage. Further down it is the
product of the percentages along the path, rounded half up to four decimal places.
An empty nodes does not by itself say whether no shareholder list is on file or whether
it is not extracted yet. list_reason is no_shareholder_list or extraction_pending when
that list is missing or still being read, including when partners are listed, and complete
is false. The shareholder list still says which (extract.status).
Asking starts at most one shareholder extraction, for the company you asked about. Companies
further up are read from ownership already on file. A person with a Sperrung is left out at
every level. The call costs 10 credits whatever depth you ask. The percentages are computed
from filed shareholder lists. They are not an extract from the Transparenzregister and not
a determination under § 3 GwG.
Computed beneficial owners
GET /companies/{company_id}/beneficial-owners
is a separate read. It follows the same filings for five levels and lists each natural person
the computation qualifies. A company is never a beneficial owner. Each person carries
percentage, gwg_above_25, amlr_at_least_25, basis and paths: the shareholdings
from this company out to that person, and the percentage multiplied along each path.
Two holdings are the same person when exactly one person record is linked (matched_by is
person_id), or, failing that, when both give the same full name and the same birth date
(matched_by is name_birth_date). Otherwise the holding stays on its own (matched_by is
unidentified), and its direct and indirect stakes are not combined with another row.
unresolved includes unlinked_person when that unidentified person's largest possible
stake is still at least 25% of the capital, or their control stake is 25% or more, or when
the row has the same name as an identified holder and the two stakes together could reach
that line. Those rows are not combined into one person. A smaller unidentified stake, which
could not reach the line even together with such a holder, does not make the status partial.
gwg_above_25 is the GwG capital test: the paths sum to more than 25%. amlr_at_least_25
is the AMLR test: the paths sum to 25% or more. Exactly 25% sets the AMLR flag and not the
GwG flag. basis repeats those tests and adds control:
| Value | Meaning |
|---|---|
capital_over_25 | The paths sum to more than 25% of the capital. Same test as gwg_above_25. |
control_chain | The person's own stake in this company, plus the stakes of companies they control, is more than 25%. Control of another company is a majority, more than half, and stakes of several controlled companies in one company are added. |
amlr_25_or_more | The paths sum to 25% or more. Same test as amlr_at_least_25. It does not by itself clear the fictitious rule. |
status is complete, partial or none_found. unresolved always includes
voting_rights_unknown, because a shareholder list does not state votes; that reason alone
does not make the status partial. Other reasons do: a missing percentage, a holder
withheld by a Sperrung (withheld_person), an unidentified person who could still reach
25% (unlinked_person), a holder abroad or not linked, an AG, SE or KGaA, no shareholder
list, a list still being read, a partnership whose figure is only a Haftsumme proxy, the
five-level limit, the cap of 250 nodes, a cycle, or a company that holds itself.
fictitious_rule_applies follows the GwG test. It is true when the look is complete and
nobody has capital_over_25 or control_chain, including when the only qualification is
the AMLR test. It is false when the status is partial, so a withheld person is not
reported as nobody. The managing directors are not copied into beneficial_owners; they
stay on GET /companies/{company_id}/roles.
notice is the same sentence on every answer: computed from register filings (shareholder
lists and register entries); may be incomplete. It is not an extract from the
Transparenzregister, not the beneficial owners reported under §§ 19–20 GwG, and no
substitute for the due diligence a Verpflichteter must do. In German: rechnerisch aus
Gesellschafterlisten und Registereinträgen ermittelt; kann unvollständig sein. Kein Auszug
aus dem Transparenzregister, nicht die nach §§ 19–20 GwG gemeldeten wirtschaftlich
Berechtigten und kein Ersatz für die eigenen Sorgfaltspflichten eines Verpflichteten.
A person with a Sperrung is left out. The call costs 25 credits.
The reverse direction —
GET /companies/{company_id}/holdings
and GET /persons/{person_id}/holdings
— returns the shareholdings a company or a person holds in other companies. They are the same
shareholding objects, seen from the holder's side.
German group structures contain cycles, including a company that holds itself. The tree flags the holding that would close one and does not follow it. If you walk the chain yourself, cap the depth and keep a visited set per path, so a company reached two ways is counted twice.
When we hold no list yet
Asking for shareholders starts the work by itself. If we hold no shareholder list for this
company, the page says extract.status: "processing" with no holders, and the same request a
little later returns them. One call starts at most one extraction, for the company you asked
about.
That is why extract matters more than an empty data array:
extract.status | Meaning |
|---|---|
parsed | What you see is what is on file, as of fetched_at. |
processing | A list is being read now. Ask again in a few minutes. |
not_filed | No list exists to read. The empty page is the answer. |
not_fetched | We have not fetched the list from the register. |
failed | We fetched the list and could not read it. |
Re-reading the history of past lists is planned (see the roadmap). Either way, a rebuild re-reads filed documents; it cannot invent a list that was never filed.
What you cannot get
- The Transparenzregister, or an official determination. Neither is in this API. The
ownership tree's effective percentages, and
GET /companies/{company_id}/beneficial-owners, are computed from filed shareholder lists and register entries. They may be incomplete. - Share transfers between filings. Only the filed snapshots exist.
- Shareholdings in an AG. Not filed, therefore not available.