Corporate Family Tree — Parents & Subsidiaries by LEI
Pricing
from $1.00 / 1,000 tree entities
Corporate Family Tree — Parents & Subsidiaries by LEI
Returns a company's corporate family tree from GLEIF: its direct and ultimate parents, its subsidiaries and theirs (two levels), one row per entity with LEI, name, country and status; failed and not-found rows are never charged. Not affiliated with or endorsed by GLEIF.
Pricing
from $1.00 / 1,000 tree entities
Rating
0.0
(0)
Developer
COMPASS DEV
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
14 days ago
Last modified
Categories
Share
Returns a company's corporate family tree from GLEIF: its direct and ultimate parents, its subsidiaries and theirs (two levels), one row per entity with LEI, name, country and status; failed and not-found rows are never charged.
Give LEIs (or exact legal names) and get each company's group as flat rows: the company itself, its direct and ultimate
parent, its direct subsidiaries and their subsidiaries, each with its LEI, legal name, country, legal form and status, and
where it sits in the tree (relation, level, parentLei). Built for KYB and supplier checks ("who owns this company,
and what else does the group own?"), group exposure, and AI agents. Not affiliated with or endorsed by GLEIF.
What it does
- Up and down the tree:
relationisself,direct_parent,ultimate_parentorsubsidiary;levelis 0, -1, 1 or 2; each subsidiary names its own parent in the tree (parentLei). - Two levels of subsidiaries (
depth2, the default), read only where GLEIF links children, so a small group takes a few requests and a large one is read 100 subsidiaries a request.subsidiariesTotalsays how many direct subsidiaries GLEIF lists. - Big groups stay bounded: a tree stops at
maxEntitiesrows (500 by default); its rows saytruncated. - LEIs or names: an LEI is looked up directly; a legal name must match a record exactly (case, punctuation and legal-form spelling ignored; add " | DE" for the country). Several matches give a free row with the candidates; for messy names, find the LEI first with LEI Lookup & Company Name Matcher.
- Watch mode (give a watch list name in
stateName): returns only entities new or changed in the trees since the last run (a new subsidiary, a new parent, a name or status change). A watch run with nothing new returns exactly one freeno_datarow that says so. - No people: organisation records only. A record that is, may be, or names a person (sole proprietors, legal forms
off GLEIF's organisation list, a person's name in a name or address) is never returned, only counted
(
peopleLeftOut); a company whose parent is a person is left out entirely. - You are never charged for failed results: failed, no_data and unchanged rows are free.
Quick start
{ "companies": ["5493003NRW7LS2QZRH60", "ICU Medical B.V. | NL"] }
A large group, direct subsidiaries only, without parents:
{ "companies": ["7LTWFZYICNSX8D621K86"], "depth": 1, "includeParents": false, "maxEntities": 1000 }
Watch your suppliers' groups every month (with an Apify schedule):
{ "companies": ["5493003NRW7LS2QZRH60"], "stateName": "supplier-groups" }
Input
| Field | Type | Default | Description |
|---|---|---|---|
companies | list of LEIs or legal names | — (prefilled with 2 examples) | One per line; a name may end with " | CC" (a country code). Never a URL; a person's name is refused |
depth | 1 or 2 | 2 | 1 = direct subsidiaries; 2 = their subsidiaries too |
includeParents | boolean | true | Return the direct and ultimate parents |
maxEntities | integer 1–5,000 | 500 | Most rows per company's tree; a larger group is cut there |
mode | watch or export | — | Empty: watch when stateName is given, otherwise export. An explicit mode wins |
stateName | string | — | Watch list name. Watch mode without a name uses the list default |
maxItems | integer 1–10,000 | 1000 | Most charged rows per run; in watch mode the rest come in the next run |
Output
{"status": "ok","attempts": 1,"error": null,"input": "5493003NRW7LS2QZRH60","mode": "export","watchList": null,"noDataReason": null,"rootLei": "5493003NRW7LS2QZRH60","rootName": "ICU MEDICAL, INC.","relation": "subsidiary","level": 1,"parentLei": "5493003NRW7LS2QZRH60","lei": "254900891YA8DKEHTV75","legalName": "ICU Medical B.V.","legalCountry": "NL","legalForm": "54M6","entityStatus": "ACTIVE","registrationStatus": "ISSUED","hasSubsidiaries": false,"subsidiariesTotal": 0,"peopleLeftOut": 0,"truncated": false,"changeType": null,"changedFields": null,"previousValues": null,"url": "https://search.gleif.org/#/record/254900891YA8DKEHTV75","source": "GLEIF API (Global Legal Entity Identifier Foundation). Not affiliated with or endorsed by GLEIF.","license": "CC0 1.0 (GLEIF LEI Data Terms of Use)","licenseUrl": "https://www.gleif.org/en/meta/lei-data-terms-of-use","scrapedAt": "2026-10-06T23:30:00.000Z"}
| Status | Meaning | Charged? |
|---|---|---|
ok | An entity of a company's tree | Export: yes. Watch: baseline, new and changed yes; unchanged entities no |
no_data | No LEI record with this code or a record left out, no exact name match, several, or nothing new since the last run | No |
failed | An invalid entry (a URL, a person's name, an LEI with wrong check digits) or no answer from GLEIF (error says why) | No |
The key-value store holds RUN_REPORT (counts, charged and free rows, trees cut, the GLEIF data set's date, stop reason).
Output fields
| Field | Type | Description |
|---|---|---|
status | string (or null) | ok = an entity of a company's tree (charged in export mode, and in watch mode when it is a baseline, new or changed entity); no_data = no such LEI or a record left out by the people filter, no exact name match, several, or nothing new since the last run (free); failed = an invalid entry (a URL, a person's name, a wrong LEI) or no answer (free) |
attempts | integer (or null) | Requests made for this row (retries included) |
error | string (or null) | Why a row is no_data or failed; null on ok rows |
input | string (or null) | The company as you gave it |
mode | string (or null) | watch or export |
watchList | string (or null) | Watch list name (watch mode); null in export mode |
noDataReason | string (or null) | not_found (no LEI record, or one left out), no_match (no exact legal name), ambiguous (several records with that name), nothing_new (watch); null otherwise |
rootLei | string (or null) | The LEI of the company asked for (the tree's root) |
rootName | string (or null) | The legal name of the company asked for |
relation | string (or null) | self (the company asked for), direct_parent, ultimate_parent or subsidiary |
level | integer (or null) | 0 for the company, -1 for a parent, 1 for a direct subsidiary, 2 for a subsidiary of a subsidiary |
parentLei | string (or null) | For a subsidiary: the LEI of its direct parent in the tree |
lei | string (or null) | The entity's Legal Entity Identifier (ISO 17442) |
legalName | string (or null) | The legal name on the entity's LEI record |
legalCountry | string (or null) | The country of the legal address (ISO 3166-1 alpha-2) |
legalForm | string (or null) | The legal form code on the record (ISO 20275 ELF code, or the text given) |
entityStatus | string (or null) | ACTIVE or INACTIVE (GLEIF) |
registrationStatus | string (or null) | ISSUED, LAPSED, RETIRED … (GLEIF) |
hasSubsidiaries | boolean (or null) | True when GLEIF links direct children to this entity |
subsidiariesTotal | integer (or null) | How many direct children GLEIF lists for this entity, when they were read (0 when it links none); null when not read (parents, or level 2) |
peopleLeftOut | integer (or null) | This entity's direct children left out by the people filter (are, may be, or name a person): counted, never listed |
truncated | boolean (or null) | True on every row of a tree cut at maxEntities |
changeType | string (or null) | Watch mode: baseline (first run of the list), new (an entity added to a tree) or changed (its parent, name or status); null in export mode |
changedFields | string (or null) | Watch mode: the tracked fields that changed, comma-separated |
previousValues | string (or null) | Watch mode: the changed fields' previous values, as JSON |
url | string (or null) | The entity's record on GLEIF's public LEI search |
source | string (or null) | Where the data comes from |
license | string (or null) | The terms of the data |
licenseUrl | string (or null) | Where the terms are published |
scrapedAt | string (or null) | When the row was written (ISO 8601, UTC) |
Pricing
Pay per event: one tree-entity event per entity row (export: every entity; watch: baseline, new and changed).
| Plan | Price per entity | Per 1,000 entities |
|---|---|---|
| Free (no discount) | $0.0015 | $1.50 |
| Bronze | $0.0013 | $1.30 |
| Silver | $0.00115 | $1.15 |
| Gold (and Platinum, Diamond) | $0.0010 | $1.00 |
- Never charged: failed rows, no_data rows and unchanged entities. You are never charged for failed results.
- Set
maxEntitiesanddepthto bound the cost for a large group. Apify also charges its small per-run start event; there are no usage fees on top, so the actor is eligible for x402 agent payments.
Use it from AI agents
One clear main input, companies (LEIs or exact legal names); every row has status, relation, level, lei,
legalName, legalCountry and parentLei. Call it through the Apify API, the Apify MCP server
(mouadapi/gleif-family-tree) or x402 agentic payments. Copy-paste call (your Apify token in place of YOUR_APIFY_TOKEN):
$curl -X POST "https://api.apify.com/v2/acts/mouadapi~gleif-family-tree/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" -H "Content-Type: application/json" -d '{"companies": ["5493003NRW7LS2QZRH60"]}'
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('mouadapi/gleif-family-tree').call({ companies: ['7LTWFZYICNSX8D621K86'], depth: 1, maxEntities: 200 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Limits
- Only relationships reported to GLEIF: a subsidiary without an LEI, or a parent the company reports as an exception, is not in the tree.
- Watch mode reports new and changed entities; an entity that left a tree is not reported.
- GLEIF publishes no rate limit: this actor sends one request a second at most. On HTTP 429 it pauses 60, 120 and 240
seconds on the same connection, then stops with free
failedrows. No other IP or proxy is ever tried.
Known issues
- A very large group (thousands of subsidiaries) is cut at
maxEntities; raise it, or usedepth1.
FAQ
Why does a company have no parents? GLEIF records no parent LEI for it: it is the top of its group, or it reported an exception (no consolidating parent, or a parent that is not to be disclosed).
Why did a watch run return one no_data row? Nothing changed in the trees since the last run of the watch list; the
row says how many entities were unchanged. It is free.
Data and licence
- Source: the GLEIF API (api.gleif.org), documented at https://www.gleif.org/en/lei-data/gleif-api.
- Licence: the LEI data are provided under CC0 1.0 (GLEIF LEI Data Terms of Use, https://www.gleif.org/en/meta/lei-data-terms-of-use).
- This actor is not affiliated with or endorsed by GLEIF.