syrto_get_company_structure returns the ownership and organisational structure of a company: who controls it, who owns shares in it, who runs it, and what entities sit below it.
Related tools: For company profile data (sector, location, employees), use Company overview. For financial metrics, use Company analysis. For a person’s contact details, use Person contacts.
Use this tool to
- Find out who owns or controls a company
- See officers, management, board members, and executives
- Explore subsidiaries and group structure
- Trace how a beneficial owner reaches the company, through the intermediate holdings
- Determine if a company is foreign-owned
Arguments
string[]
required
The companies to get the structure of - 1 to 20 IDs, no duplicates, always a list even for a single company. IDs come from
syrto_find_company or syrto_lookup_companies_by_tax_id.Past one company the lists inside each entry are capped much lower, because they share one response - see List caps below.string[]
Show only officers holding a role in these categories. Omit for every officer on record.Values:
GOVERNING_BODIES, ADMINISTRATION_AND_EXECUTIVES, AUDITING, REPRESENTATION_AND_AUTHORITY, EXTRAORDINARY_PROCEDURES, FUNCTIONAL_ROLES, PARTICIPATION_OWNERSHIP, CHIEF_EXECUTIVE_OFFICER, OTHER.For “who runs this company”, ["GOVERNING_BODIES", "CHIEF_EXECUTIVE_OFFICER"] is the useful pair: on a large company most rows are holders of a power of attorney (EXTRAORDINARY_PROCEDURES), which answers a different question.string
"en" for English (default) or "it" for Italian.Returns
result is { "companies": [...], "not_found": [...] } - the same shape for one ID as for twenty.
object[]
One entry per company, in the order you asked. It is shorter than your list when an ID returned nothing, so an entry’s position is not its position in your request - match entries by their own
company_id.string[]
IDs no structure came back for. This is part of a successful answer, not an error.
companies carries:
string
The ID this entry answers for.
string
Official legal name of the company.
string | null
Legal form of the entity, e.g.
"S.p.A.", "S.r.l.". null if not available.string | null
Category of the controlling entity. Common values:
FAMILY, INDUSTRIAL_GROUP, FINANCIALLY_OWNED_GROUP. null if not determined.boolean | null
Whether the company is majority foreign-owned.
null if not available.object[]
One entry per officer - a person holding two roles appears once, with both. Each entry has:
name- officer name (nullif not available)person_id- the person’s ID, ornullwhen the officer is a company (see Person IDs)roles- list of{ "role_category": ..., "role": ... }, the standardised category and the specific titleage- age in completed years (nullfor company officers or if unknown)
integer | null
Every officer role on record, before
role_categories is applied and before roles are grouped onto one entry per officer. Expect it to exceed the length of officers: a person holding two roles files two rows. It is not a sign anything was withheld - warning reports that separately.Direct shareholders. Each entry has:
name- shareholder name (nullif not available)person_id- the person’s ID, ornullfor a corporate shareholdertax_id- the tax ID of a corporate shareholder,nullfor a person (see Company references)share_percent- ownership percentage (nullif not publicly disclosed)age- age in completed years (nullfor corporate shareholders or if unknown)
object[]
Beneficial owners (ultimate controlling persons). Each entry has:
name- beneficial owner name (nullif not available)person_id- the person’s ID, ornullif the owner is not a persontax_id- the tax ID of an owner that is a company,nullfor a personshare_percent- effective ownership percentage (nullif not disclosed)age- age in completed years (nullif unknown)ownership_chains- the route or routes by which this owner reaches the company (see below)
object[][]
A list of routes, each route a list of hops ordered from the hop closest to this company out to the owner. Each hop carries
name, person_id (persons only), tax_id (companies only) and its share_percent in the hop before it.A chain never changes the owner’s share_percent - that figure is already the product of one route’s hops - it explains it. An owner who holds the company directly shows as one route of one hop naming themselves; that is what direct ownership looks like here, not a data problem. Routes come most-direct first, and warning says when an owner had more than were shown.object[]
Each entry has:
tax_id- Italian tax identifier (omitted on the rare entry with no tax ID on the registry)name- subsidiary name (nullif not available)share_percent- parent’s ownership stake (nullif not disclosed)
object[]
Companies controlled by the same parent entity (share ≥ 51%). Each entry has:
tax_id- Italian tax identifier (omitted on the rare entry with no tax ID on the registry)name- company name (nullif not available)
Companies that share a decision-maker with this company - an officer who sits in
GOVERNING_BODIES or is CHIEF_EXECUTIVE_OFFICER in both. Without that restriction the list fills with companies that merely use the same audit firm, whose staff sit on hundreds of boards. role_categories does not adjust it; that parameter narrows the officers list only. Each entry has:tax_id- Italian tax identifier (omitted on the rare entry with no tax ID on the registry)name- company name (nullif not available)
string | null
Present when any list was capped. It names the list and its true total - for example
"officer roles 50 of 63" - so a capped list is never mistaken for a complete one. On a multi-company call it reports a count of affected companies rather than naming each one. companies_with_shared_officers is the one exception: it is capped but reports no total.result, the response carries the fields every tool returns. Here display_title is the company’s legal name, or a count when several were asked for, and subtitle says how many IDs were not found.
Person IDs
person_id is a person ID the other person tools accept. Pass it straight to syrto_get_person_contacts or to the people filter section of Search companies, with no syrto_find_person lookup in between - that one is a name search, so it can land on the wrong namesake.
It is null on an officer, shareholder or owner that is a company rather than a person; a company can hold an office, such as an audit firm or a sole corporate shareholder. So null means “not a person”, never “a person we could not identify”.
Company references
subsidiaries, linked_companies and companies_with_shared_officers identify companies by tax_id, not by company ID. To analyse one of them, pass the tax IDs to syrto_lookup_companies_by_tax_id (up to 20 in one call) and use the company IDs it returns - which you can then feed to filters.company_ids in Search companies to sub-filter the participations. A tax ID may come back not_found, in which case that company is identifiable by name only.
A shareholder, beneficial owner or ownership-chain hop that is a company carries a tax_id too - the same identity subsidiaries carry. To tell whether an owner is a company you already hold, compare tax IDs rather than names: two companies can share a name, and a multi-company call shortens long names. tax_id is null on a person (use person_id), on an entity the registry could not classify, and on the rare company with no tax ID on the registry. An officer that is a company carries no tax_id.
List caps
Every list is capped to avoid unbounded pagination, and the caps are lower on a multi-company call because all the companies share one response.
The single-company subsidiaries cap is deliberately the same as the
filters.company_ids cap, so any subsidiary list shown here fits one ID filter when resolved on a single statement basis.
Across a batch, the *_total fields answer the interesting question - how big is this company’s board or group - rather than the lists themselves. What a batch is for is the fields above the lists: legal_entity_type, controlling_entity_category, is_foreign_owned, and the largest few shareholders. Ask for one company alone when you need its full board.
share_percent values may be null if not publicly disclosed.
Example
Get the ownership structure of Ferrari:- Shareholders and beneficial owners with names, ownership percentages where disclosed, a
person_idfor each person and atax_idfor each company controlling_entity_categoryandis_foreign_ownedfor ownership context- Officers grouped one entry per person, each with every role they hold
- Subsidiaries, linked companies and companies sharing a decision-maker, each identified by
tax_id