# GLEIF LEI Lookup & Corporate Ownership Graph API (KYB) (`malonestar/gleif-ownership-graph`) Actor

LEI lookup and corporate ownership API: resolve a company name to its GLEIF LEI and traverse parent/child relationships into a normalized ownership graph. Map corporate hierarchies and beneficial ownership for KYB/AML. Keyless, open-license.

- **URL**: https://apify.com/malonestar/gleif-ownership-graph.md
- **Developed by:** [Kyle Maloney](https://apify.com/malonestar) (community)
- **Categories:** Developer tools, Lead generation, AI
- **Stats:** 2 total users, 0 monthly users, 86.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.60 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## GLEIF LEI Lookup & Corporate Ownership Graph API — KYB / AML / Beneficial Ownership

An **LEI lookup and corporate ownership API**. Resolve a company name to its
**GLEIF Legal Entity Identifier**, then traverse GLEIF's **Level-2 parent and
child relationships** into a normalized **corporate ownership graph** — with the
edge metadata that makes an ownership claim auditable, and an explicit
per-source status on every row so you always know the difference between
"GLEIF says there is no parent" and "we could not ask".

Keyless. Open licence (GLEIF data is free for commercial use). Agent-ready.

### Who it's for

- **KYB / KYC onboarding** — resolve a counterparty to a canonical LEI, pull its
  registry ID and company registration number, and confirm the LEI is current.
- **AML / sanctions & beneficial-ownership screening** — walk the ownership
  chain to the ultimate parent, screen previous legal names and transliterated
  aliases, and read GLEIF's published reason when no parent is reported.
- **Credit and counterparty risk** — map a group structure, count subsidiaries,
  and see whether the ownership filing itself is `PUBLISHED` or `LAPSED`.
- **RevOps / data enrichment** — attach LEI, BIC, ISIN, OpenCorporates and
  S\&P Global identifiers to an account record.
- **AI agents** — a clean, chainable "resolve company to LEI and ownership" tool
  over MCP.

### What it does

**Two modes.**

`search` returns ranked LEI candidates for a company name. GLEIF's own result
order is *not* relevance-ranked, so every candidate is graded (`exact`,
`exact_normalized`, `exact_core`, `prefix`, `contains`, ...) and ranked, and the
row tells you whether the top hit was ambiguous.

`graph` takes an LEI (or resolves one from a name) and returns the ownership
graph around it: the entity itself, its **direct** parent, its **ultimate**
parent, its direct subsidiaries and — optionally — its indirect subsidiaries.
Each parent row carries the GLEIF relationship record: edge type, ownership
period, accounting period, filing status and corroboration level. Every row also
carries the full ownership chain to the top of the group and the data vintage.

#### The contract this Actor keeps

- **`null` means "not checked". `false` means "checked, and the answer is no".**
  If the direct-parent probe fails, `has_direct_parent` is `null`,
  `parent_disclosure_status` is `unknown`, and `partial_result` is `true`. It is
  never rendered as "this entity has no parent".
- **Counts are never invented.** `direct_children_count` and
  `relationship_count` are `null` when a probe failed — a `0` there would be a
  claim the run did not earn.
- **A partial graph is never presented as complete.** `direct_children_truncated`
  tells you when `maxChildren` cut the subsidiary list short, alongside the true
  `direct_children_total_reported` from GLEIF.
- **Live drift assertions run before anything is billed.** Six probes verify the
  GLEIF envelope shape, golden-copy freshness, a known-good LEI, a parent-edge
  round trip, a negative control (a nonsense name must return zero, not the
  registry) and the reporting-exception endpoint. If any fails, the run fails and
  nothing is emitted or billed.
- **An unknown LEI fails loudly** instead of returning an empty graph.

### Example input

```json
{
  "mode": "graph",
  "name": "Apple Inc",
  "includeChildren": true,
  "maxChildren": 100,
  "resolveOwnershipChain": true,
  "includeUltimateChildren": false,
  "includeIsins": false,
  "strictNameMatch": false
}
```

Seed by exact LEI instead:

```json
{ "mode": "graph", "lei": "5493004SYPRAVRVNK561", "includeChildren": true }
```

Rank LEI candidates for a name:

```json
{ "mode": "search", "name": "Danone", "maxCandidates": 10 }
```

### Input fields

| Field | Type | Default | What it does |
|---|---|---|---|
| `mode` | string | `graph` | `search` = ranked LEI candidates for a name. `graph` = the ownership graph around an entity. |
| `name` | string | `Apple Inc` | Company name. GLEIF matches the **registered legal name** — `Siemens Aktiengesellschaft` resolves, `Siemens AG` does not. |
| `lei` | string | — | Exact 20-character LEI. Overrides `name` in graph mode. |
| `includeChildren` | boolean | `true` | Include direct subsidiaries. |
| `maxChildren` | integer | `100` | Cap on direct subsidiaries. Exceeding it sets `direct_children_truncated`. |
| `maxCandidates` | integer | `10` | Cap on search-mode candidates. |
| `includeUltimateChildren` | boolean | `false` | Also return indirect subsidiaries. Adds rows, so it adds cost. |
| `maxUltimateChildren` | integer | `100` | Cap on indirect subsidiaries. |
| `resolveOwnershipChain` | boolean | `true` | Walk parent edges to the top of the group. Adds no rows. |
| `includeIsins` | boolean | `false` | Fetch ISINs mapped to the seed LEI. Adds no rows. |
| `maxIsins` | integer | `50` | Cap on listed ISINs. |
| `strictNameMatch` | boolean | `false` | Fail the run instead of guessing when a name has no exact GLEIF legal-name match. Recommended for automated KYB pipelines. |

### Output fields

One row per graph node (or per search candidate). Every row carries the same
column set, so `null` always means "not applicable or not checked", never
"missing column".

| Field | Type | Description |
|---|---|---|
| `lei` | string | 20-character Legal Entity Identifier. |
| `legal_name` | string | Official legal name of the entity as registered with GLEIF. |
| `other_names` | array | Alternative, previous and trade names reported to GLEIF. |
| `jurisdiction` | string | Legal jurisdiction (ISO 3166 country or country-subdivision code). |
| `legal_form` | string | ISO 20275 ELF code for the entity's legal form (for example H1UM). |
| `entity_status` | string | Entity operating status: ACTIVE or INACTIVE. |
| `entity_category` | string | GLEIF entity category, e.g. GENERAL, BRANCH, FUND, SOLE\_PROPRIETOR. |
| `registration_status` | string | LEI registration status: ISSUED, LAPSED, RETIRED, ANNULLED, MERGED, PENDING\_TRANSFER, PENDING\_ARCHIVAL. |
| `country` | string | Legal address country. |
| `city` | string | Legal address city. For Apple Inc this is Glendale, its registered agent - see hq\_city for the operating headquarters. |
| `postal_code` | string | Legal address postal code. |
| `relation_to_seed` | string | How this row relates to the searched entity: self, direct\_parent, ultimate\_parent, direct\_child, ultimate\_child, or match (search mode). |
| `seed_lei` | string | The LEI the graph was built around. Null in search mode. |
| `gleif_url` | string | Link to this entity's record on search.gleif.org. |
| `legal_name_language` | string | ISO 639 language of the legal name. |
| `previous_legal_names` | array | Names GLEIF flags as PREVIOUS\_LEGAL\_NAME. Directly useful for AML name screening against historic aliases. |
| `other_name_types` | array | Distinct GLEIF name types present on this record (PREVIOUS\_LEGAL\_NAME, TRADING\_OR\_OPERATING\_NAME, ...). |
| `transliterated_other_names` | array | Latin-script transliterations of non-Latin legal names. |
| `business_registry_id` | string | GLEIF Registration Authority code of the registry the entity is registered in (for example RA000598 = California Secretary of State). |
| `business_registry_other` | string | Registry name when it is not in the GLEIF Registration Authorities List. |
| `company_registration_number` | string | The entity's number in its home business registry (GLEIF registeredAs). The join key to national company registers. |
| `legal_form_other` | string | Legal form when no ELF code applies. |
| `entity_sub_category` | string | GLEIF entity sub-category, e.g. CENTRAL\_GOVERNMENT, MUNICIPALITY. |
| `entity_creation_date` | string | Date the legal entity was created, per its registry. |
| `successor_lei` | string | LEI of the entity that succeeded this one (merger/absorption). |
| `successor_name` | string | Name of the successor entity. |
| `successor_leis` | array | All successor LEIs when an entity split into several. |
| `successor_entity_names` | array | Names of successor entities. GLEIF often publishes a successor by NAME with no LEI, so this is not always derivable from successor\_leis. |
| `conformity_flag` | string | GLEIF data-quality conformity flag: CONFORMING, NON\_CONFORMING, NOT\_APPLICABLE. |
| `corporate_event_group_count` | integer | Number of GLEIF corporate-event groups (mergers, spin-offs) recorded against this entity. |
| `legal_address_lines` | array | Street lines of the legal (registered) address. |
| `legal_address_region` | string | ISO subdivision of the legal address. |
| `hq_address_lines` | array | Street lines of the headquarters address. |
| `hq_city` | string | Headquarters city. Fetched by v1.0 and discarded; now emitted. |
| `hq_region` | string | ISO subdivision of the headquarters address. |
| `hq_country` | string | Headquarters country. Differs from the legal country for entities registered through an agent or in a holding jurisdiction. |
| `hq_postal_code` | string | Headquarters postal code. |
| `legal_and_hq_address_differ` | boolean | True when the legal and headquarters addresses are not the same place. Null when the record carries only one of them. |
| `other_addresses_count` | integer | Count of additional addresses on the record. |
| `initial_registration_date` | string | When the LEI was first issued. |
| `last_update_date` | string | When the LEI record was last updated. |
| `next_renewal_date` | string | When the LEI must next be renewed. |
| `days_to_next_renewal` | integer | Days until the next renewal date; negative means overdue. |
| `registration_renewal_overdue` | boolean | True when the next renewal date is in the past. Null when GLEIF publishes no renewal date. |
| `lei_is_current` | boolean | True only when registration\_status is ISSUED and entity\_status is ACTIVE. Null when either is missing - never guessed. |
| `lei_compliance_flag` | string | current (ISSUED) / attention (LAPSED, PENDING\_TRANSFER, PENDING\_ARCHIVAL) / not\_current (RETIRED, ANNULLED, MERGED, DUPLICATE). |
| `managing_lou` | string | LEI of the Local Operating Unit that maintains this record. |
| `corroboration_level` | string | How well GLEIF corroborated the record: FULLY\_CORROBORATED, PARTIALLY\_CORROBORATED, ENTITY\_SUPPLIED\_ONLY. |
| `validated_at_registry_id` | string | Registration Authority code GLEIF validated the record against. |
| `validated_as` | string | Registry identifier GLEIF validated the record against. |
| `other_validation_authority_count` | integer | Count of additional validation authorities on the record. |
| `bic_codes` | array | SWIFT/BIC codes mapped to this LEI. |
| `other_identifiers` | array | Cross-references as SCHEME:VALUE (BIC, MIC, OCID/OpenCorporates, QCC, GEM, SPGLOBAL). |
| `relationship_type` | string | GLEIF Level-2 edge type on parent rows: IS\_DIRECTLY\_CONSOLIDATED\_BY or IS\_ULTIMATELY\_CONSOLIDATED\_BY. Null on self and child rows. |
| `relationship_status` | string | ACTIVE or INACTIVE ownership relationship. |
| `relationship_valid_from` | string | validFrom on the GLEIF relationship record. |
| `relationship_period_start` | string | Start of the RELATIONSHIP\_PERIOD - when the ownership relationship began. |
| `relationship_accounting_period_start` | string | Start of the ACCOUNTING\_PERIOD the consolidation was reported for. |
| `relationship_accounting_period_end` | string | End of the ACCOUNTING\_PERIOD the consolidation was reported for. |
| `relationship_registration_status` | string | PUBLISHED, LAPSED, ANNULLED - whether the ownership filing itself is current. |
| `relationship_last_update_date` | string | When the ownership filing was last updated. |
| `relationship_corroboration_level` | string | How the ownership claim was corroborated, e.g. ENTITY\_SUPPLIED\_ONLY, FULLY\_CORROBORATED. |
| `relationship_corroboration_documents` | string | Document class used to corroborate the ownership claim. |
| `edge_from_lei` | string | Child side of the ownership edge (GLEIF startNode). |
| `edge_to_lei` | string | Parent side of the ownership edge (GLEIF endNode). |
| `ownership_depth` | integer | 0 = the seed, 1 = direct parent, n = ultimate parent n hops up, -1 = direct child, -2 = indirect (ultimate) child. |
| `gleif_golden_copy_date` | string | Publish date of the GLEIF golden copy this answer came from - the data vintage. |
| `retrieved_at` | string | UTC timestamp of this run. |
| `direct_parent_lei` | string | LEI of the seed's direct accounting-consolidation parent. Null when there is none OR when the probe failed - read has\_direct\_parent and source\_direct\_parent\_status to tell those apart. |
| `direct_parent_name` | string | Legal name of the direct parent. |
| `ultimate_parent_lei` | string | LEI of the seed's ultimate accounting-consolidation parent - the top of the ownership tree. |
| `ultimate_parent_name` | string | Legal name of the ultimate parent. |
| `has_direct_parent` | boolean | True = GLEIF returned a direct parent. False = GLEIF confirmed there is none. Null = the probe did not answer. Never guessed. |
| `has_ultimate_parent` | boolean | True / false / null on the same verified-negative contract as has\_direct\_parent. |
| `direct_parent_is_ultimate_parent` | boolean | True when the seed sits one level below the top of its group. |
| `seed_is_ultimate_parent` | boolean | True when the seed itself has no parent, i.e. it is the top of its own ownership tree. |
| `direct_parent_exception_reason` | string | Why GLEIF holds no direct parent: NATURAL\_PERSONS, NON\_CONSOLIDATING, NO\_LEI, NO\_KNOWN\_PERSON, LEGAL\_OBSTACLES, DISCLOSURE\_DETRIMENTAL, BINDING\_LEGAL\_COMMITMENTS, CONSENT\_NOT\_OBTAINED. A published reason is a materially different finding from missing data. |
| `direct_parent_exception_category` | string | GLEIF exception category, normally DIRECT\_ACCOUNTING\_CONSOLIDATION\_PARENT. |
| `ultimate_parent_exception_reason` | string | Same reason vocabulary at the ultimate-parent level. |
| `ultimate_parent_exception_category` | string | Normally ULTIMATE\_ACCOUNTING\_CONSOLIDATION\_PARENT. |
| `parent_disclosure_status` | string | disclosed = a parent LEI was returned. none\_reported\_REASON = GLEIF confirmed there is no parent and published why. unknown = the probe failed, so ownership above this entity is NOT established. |
| `ownership_chain_leis` | array | Ordered LEIs from the seed up to its ultimate parent, nearest first. |
| `ownership_chain_depth` | integer | Number of hops from the seed to the top of its ownership tree. Null when the walk could not complete. |
| `ownership_chain_truncated` | boolean | True when the upward walk hit its 10-hop bound before reaching the top. |
| `direct_children_count` | integer | Direct subsidiaries actually returned on this run. Null when the children probe failed - never 0. |
| `direct_children_total_reported` | integer | Total direct subsidiaries GLEIF reports, regardless of maxChildren. |
| `direct_children_truncated` | boolean | True when maxChildren cut the subsidiary list short, so the graph is incomplete by design. |
| `ultimate_children_count` | integer | Ultimate (indirect) subsidiaries returned. Null unless includeUltimateChildren was on. |
| `ultimate_children_total_reported` | integer | Total ultimate subsidiaries GLEIF reports. |
| `isin_count` | integer | Number of ISINs mapped to the seed LEI. Null unless includeIsins was on. |
| `isins_sample` | array | ISINs mapped to the seed LEI, up to maxIsins. Empty unless includeIsins was on. |
| `relationship_count` | integer | Ownership edges verified on this run. Null when any edge probe failed - a 0 here would be a claim the run did not earn. |
| `sources_failed` | array | GLEIF endpoints that did not answer on this run. Empty on a clean run. |
| `partial_result` | boolean | True when at least one GLEIF endpoint did not answer, so some fields are null-because-unchecked rather than null-because-absent. |
| `source_errors` | array | Human-readable errors for any endpoint that failed. |
| `name_query` | string | The company name searched for. Null when the run was seeded by LEI. |
| `name_match_type` | string | Match grade for a search-mode row: exact, exact\_normalized, exact\_core, prefix, contains, all\_tokens, token\_overlap, other. |
| `name_match_rank` | integer | Rank of this candidate after relevance grading (1 = best). GLEIF's own result order is not relevance-ranked. |
| `name_candidates_total` | integer | How many entities GLEIF matched for the name, before any cap. |
| `name_match_ambiguous` | boolean | True when no candidate matched the queried legal name exactly, so the top pick is a best guess. |
| `seed_resolved_from_name` | boolean | True when the graph seed came from a name search rather than an explicit LEI. |
| `seed_match_type` | string | Match grade of the candidate chosen as the graph seed. |
| `name_match_tied_count` | integer | How many candidates share the best match score. Greater than 1 means several GLEIF records match the queried name equally well, so the top pick is arbitrary -- two distinct records genuinely carry the legal name "Deutsche Bank Aktiengesellschaft". |
| `source_entity_status` | string | ok / unavailable / missing for the GLEIF lei-record lookup. |
| `source_direct_parent_status` | string | ok = a parent was returned. absent = GLEIF confirmed none. unavailable = the request failed, so no conclusion about ownership may be drawn. not\_requested = the probe was switched off. |
| `source_ultimate_parent_status` | string | Same ok / absent / unavailable / not\_requested contract. |
| `source_direct_parent_relationship_status` | string | Outcome of the direct-parent-relationship (edge metadata) request. |
| `source_ultimate_parent_relationship_status` | string | Outcome of the ultimate-parent-relationship request. |
| `source_direct_parent_exception_status` | string | Outcome of the direct-parent-reporting-exception request. |
| `source_ultimate_parent_exception_status` | string | Outcome of the ultimate-parent-reporting-exception request. |
| `source_direct_children_status` | string | ok / partial / unavailable / not\_requested for the paginated direct-children fetch. |
| `source_ultimate_children_status` | string | ok / partial / unavailable / not\_requested for the ultimate-children fetch. |
| `source_ownership_chain_status` | string | ok / partial / unavailable / not\_requested for the upward parent walk. |
| `source_isins_status` | string | ok / unavailable / not\_requested for the ISIN mapping fetch. |

#### Columns that are null on the default example, and how to populate them

The prefilled example (`Apple Inc`) is the top of its own ownership tree, so its
parent-edge columns are legitimately empty. Each of these has a verified live
input that fills it:

| Columns | Populate with |
|---|---|
| `relationship_*`, `edge_from_lei`, `edge_to_lei`, `direct_parent_lei`, `direct_parent_name`, `ultimate_parent_lei`, `ultimate_parent_name`, `direct_parent_is_ultimate_parent`, `ownership_chain_leis` | `{"mode":"graph","lei":"2549005JJKRFXSM5CC84"}` — a grandchild whose direct parent (Apple Operations International) differs from its ultimate parent (Apple Inc) |
| `ultimate_children_count`, `ultimate_children_total_reported` | `{"mode":"graph","lei":"HWUPKR0MPOU8FGXBT394","includeUltimateChildren":true}` |
| `isin_count`, `isins_sample` | `{"mode":"graph","lei":"HWUPKR0MPOU8FGXBT394","includeIsins":true}` (951 ISINs) |
| `name_match_type`, `name_match_rank`, `name_match_tied_count` | `{"mode":"search","name":"Deutsche Bank"}` -- two distinct LEIs share the legal name Deutsche Bank Aktiengesellschaft, so the top pick is flagged ambiguous |
| `transliterated_other_names` | `{"mode":"graph","lei":"636700VVHS50XM79JI98"}` |
| `business_registry_other` | `{"mode":"graph","lei":"894500L731TNWUALQL85"}` |
| `legal_form_other` | `{"mode":"graph","lei":"984500DCF3Q8K64CAB80"}` |
| `entity_sub_category` | `{"mode":"graph","lei":"815600AE25B2FEEFCE23"}` (LOCAL\_GOVERNMENT) |
| `successor_lei`, `successor_name`, `successor_leis` | `{"mode":"graph","lei":"747800X0S05A0KPBJ055"}` |
| `successor_entity_names` | `{"mode":"graph","lei":"8156006C115C3A98D766"}` — GLEIF names this successor with no LEI |
| `sources_failed`, `source_errors` | Only populated when a GLEIF endpoint fails. Empty here is good news. |

### Use as an MCP tool

Available to AI agents through `mcp.apify.com` as an LEI-lookup / ownership-graph
tool. Pass a company name or an LEI and get back the resolved entity, its
ownership chain and its subsidiaries. Agents should read `parent_disclosure_status`
and `partial_result` before asserting anything about ownership: `unknown` means
the question was not answered, not that the answer is "none".

### FAQ

**What is an LEI?** The Legal Entity Identifier — a global, permanent
20-character identifier for a legally distinct entity, issued under the GLEIF
system and required for reporting in most derivatives and securities regimes.

**Is this a KYB API?** Yes. It resolves and maps registered legal entities and
returns the home business registry (`business_registry_id`) plus the entity's
number in it (`company_registration_number`), which is the join key to national
company registers.

**Where does the ownership data come from?** GLEIF's Level-2 relationship
records — the direct and ultimate *accounting consolidation* parents an entity
reports. That is a defined, auditable relationship, not an inferred one.

**What if an entity reports no parent?** GLEIF publishes a machine-readable
reason. `parent_disclosure_status` will read, for example,
`none_reported_NATURAL_PERSONS` (the owners are natural persons — this is what
Apple Inc reports), `none_reported_NON_CONSOLIDATING`, or
`none_reported_NO_LEI`. That is a materially different finding from missing data,
and it is why a bare `null` parent is never good enough.

**Does GLEIF ownership equal beneficial ownership?** No, and the distinction
matters. GLEIF Level-2 covers accounting-consolidation parents. It is an
excellent corporate-hierarchy backbone and a strong input to a beneficial-owner
analysis, but it is not a UBO register.

**Why did my company name not resolve?** GLEIF filters on the *registered* legal
name. `Siemens AG` returns 14 entities, none of which is Siemens AG — GLEIF
registers it as `Siemens Aktiengesellschaft`. Use `mode: "search"` to see the
graded candidates, or set `strictNameMatch: true` to fail rather than guess.

**Is it keyless?** Yes. `api.gleif.org` needs no key and GLEIF data is published
under a fully open licence permitting commercial use.

**Why did my run fail instead of returning zero rows?** Because a zero that was
never verified is worse than an error. An unknown LEI, an unreachable GLEIF, or a
failed drift assertion all fail the run — and a failed run emits nothing and
bills nothing.

### Source

**GLEIF LEI API v1** (`api.gleif.org/api/v1`) — `lei-records`, `direct-parent`,
`ultimate-parent`, `direct-parent-relationship`, `ultimate-parent-relationship`,
`direct-parent-reporting-exception`, `ultimate-parent-reporting-exception`,
`direct-children`, `ultimate-children` and `isins`. Official, keyless,
open-licence. The GLEIF golden-copy publish date is stamped on every row as
`gleif_golden_copy_date`.

### Pricing (Pay Per Result)

Billed per record returned — one event per graph node or search candidate. A run
that fails, or one where GLEIF answered and matched nothing, emits no records and
costs nothing. `includeUltimateChildren` is the only switch that adds rows;
`resolveOwnershipChain` and `includeIsins` add fields, not cost.

### Related Actors

- **`kyb-company-verifier`** — business-registry verification for a named entity.
- **`sos-registry-monitor`** — US Secretary-of-State registration and status changes.
- **`consolidated-screening-list-delta`** — OFAC / BIS / State sanctions screening
  deltas; pair it with the ultimate parent this Actor resolves.
- **`ria-registration-delta-monitor`** — SEC investment-adviser roster and
  registration events, keyed by CRD.

# Actor input Schema

## `mode` (type: `string`):

search = find LEI candidates by name. graph = build the ownership graph (parents + children) around an entity.

## `name` (type: `string`):

Company name to search for (used as the seed in graph mode when no LEI is given). GLEIF matches the REGISTERED legal name, so "Siemens Aktiengesellschaft" resolves and "Siemens AG" does not; candidates are relevance-graded and the chosen match is reported on every row.

## `lei` (type: `string`):

Exact 20-character LEI to build the graph around. Overrides name in graph mode. An unknown LEI fails the run loudly rather than returning an empty graph.

## `includeChildren` (type: `boolean`):

Include direct children (subsidiaries) in the graph.

## `maxChildren` (type: `integer`):

Maximum number of direct subsidiaries to return. When GLEIF reports more than this, direct\_children\_truncated is set to true so a partial graph is never presented as complete.

## `maxCandidates` (type: `integer`):

Max LEI candidates to return in search mode.

## `includeUltimateChildren` (type: `boolean`):

Also return ultimate (indirect) subsidiaries - entities this one controls through intermediate holdings. Adds rows, so it adds cost.

## `maxUltimateChildren` (type: `integer`):

Maximum number of ultimate (indirect) subsidiaries to return.

## `resolveOwnershipChain` (type: `boolean`):

Walk direct-parent edges upward from the seed to the top of its group and report the full LEI path and its depth. Adds no rows.

## `includeIsins` (type: `boolean`):

Fetch the ISINs mapped to the seed LEI (isin\_count and isins\_sample). One extra request; adds no rows.

## `maxIsins` (type: `integer`):

Maximum number of ISINs to list in isins\_sample.

## `strictNameMatch` (type: `boolean`):

Fail the run instead of guessing when the company name has no exact GLEIF legal-name match. Recommended for automated KYB pipelines, where silently profiling the wrong company is worse than an error.

## Actor input object example

```json
{
  "mode": "graph",
  "name": "Apple Inc",
  "includeChildren": true,
  "maxChildren": 100,
  "maxCandidates": 10,
  "includeUltimateChildren": false,
  "maxUltimateChildren": 100,
  "resolveOwnershipChain": true,
  "includeIsins": false,
  "maxIsins": 50,
  "strictNameMatch": false
}
```

# Actor output Schema

## `results` (type: `string`):

Corporate ownership graph nodes (self, parents, subsidiaries) with GLEIF relationship metadata, in the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "graph",
    "name": "Apple Inc"
};

// Run the Actor and wait for it to finish
const run = await client.actor("malonestar/gleif-ownership-graph").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "graph",
    "name": "Apple Inc",
}

# Run the Actor and wait for it to finish
run = client.actor("malonestar/gleif-ownership-graph").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "graph",
  "name": "Apple Inc"
}' |
apify call malonestar/gleif-ownership-graph --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malonestar/gleif-ownership-graph",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/bFFRGOq7amfMZuUGb/builds/iWeOYHHUoOpREvXkK/openapi.json
