# LEI Corporate Tree: GLEIF Parents & Subsidiaries (`offerastudio/gleif-lei-corporate-tree`) Actor

Look up legal entity identifiers (LEIs) by code or company name and get each entity's legal data, direct and ultimate parent (or the reason none is reported), subsidiaries up to 3 levels, BIC and ISIN codes, and a one-line KYC summary. Official GLEIF data, CC0.

- **URL**: https://apify.com/offerastudio/gleif-lei-corporate-tree.md
- **Developed by:** [Offera Studio](https://apify.com/offerastudio) (community)
- **Categories:** Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 entity returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does LEI Corporate Tree do?

**LEI Corporate Tree** looks up legal entities in the **official GLEIF database of Legal Entity Identifiers (LEIs)**, by LEI or by company name, and shows **who owns whom**: each entity's **direct and ultimate parent** and its **subsidiaries**, up to three levels down. For every entity you get:

- 🆔 **LEI, legal name and other names** (previous, trading and other-language names)
- 🏛️ **legal form, entity status, jurisdiction**, the **registration authority** and the **local register number** (e.g. HRB 6684 at the Munich commercial register)
- 📍 **legal and headquarters addresses**
- 🔁 **LEI registration status and next renewal date**, so lapsed LEIs stand out
- 👪 **direct and ultimate parent** (LEI, name, country), or the **reporting exception** the entity gave instead, e.g. "no known person or entity controls it"
- 🌳 **subsidiaries** with their level in the tree
- 🏦 **BIC codes** and, on request, **ISINs** mapped to the LEI
- 📝 a **`kycSummary`**: one line of plain English you can paste into an onboarding or KYC file

### Who is this LEI lookup for?

- **KYC, AML and onboarding teams**: document a counterparty's identity, register number, parent and ultimate parent in one step.
- **Credit risk and procurement**: see which group a supplier or customer belongs to before you extend credit or sign.
- **Compliance and regulatory reporting** (EMIR, MiFID II, SFTR): check that counterparties' LEIs are valid and not lapsed.
- **Analysts and data teams**: map a group's subsidiaries with LEIs, or enrich a company list with LEIs, BICs and ISINs.

### How it works

The data comes from the **GLEIF API**, the free public interface of the Global Legal Entity Identifier Foundation. Its "Level 1" data says who an entity is; its "Level 2" data says who owns whom: each entity reports its **direct parent** and **ultimate parent** in the sense of accounting consolidation, or a **reporting exception** that explains why it reports none (for example, it is owned by private individuals, or its parent doesn't consolidate it).

- **LEIs** are checked offline first (ISO 17442 check digits), then looked up 100 at a time.
- **Company names** are matched against legal names and all other names. Legal forms are compared in short and long form, so "Siemens AG" finds "Siemens Aktiengesellschaft". Each match gets a **score from 0 to 100** (100 = same name, legal form aside; 95 = same name with another legal form; 80–94 = close, e.g. a typo or an extra word). Set a **country** to search only entities with their legal address there.
- **Subsidiaries** are the entities that report this entity as their direct parent. They are collected **breadth first**: all direct subsidiaries before any of their subsidiaries, up to the level and limit you set.

### How to use it

1. Enter **LEIs** (one per line), or **Company names** with an optional **Country**.
2. Keep **Include parents** on (free) and choose whether you want **subsidiaries**: how many levels (1–3) and how many at most per entity.
3. Choose whether subsidiaries and parents should be **their own rows** (full data, charged) or only **listed inside the row** (free).
4. Click **Start**. Tabs: **Entities**, **KYC summary**, **Corporate tree**, **Parents**, **BIC and ISIN codes**.

### Input example

```json
{
    "leis": ["W38RGI023J3WT1HWRP32", "KY37LUS27QQX7BB93L28"],
    "companyNames": ["Unilever PLC"],
    "country": "GB",
    "maxMatchesPerName": 1,
    "includeParents": true,
    "includeChildren": true,
    "childrenDepth": 1,
    "maxChildren": 5,
    "childrenAsRows": true,
    "includeIsins": false
}
```

### Output example

Real output from the default input on 1 October 2026 (Siemens AG and Nestlé S.A., one level of subsidiaries, at most 5 each: 12 rows). The input entity, shortened:

```json
{
    "lei": "W38RGI023J3WT1HWRP32",
    "legalName": "Siemens Aktiengesellschaft",
    "role": "lei-lookup",
    "depth": 0,
    "entityStatus": "ACTIVE",
    "legalFormCode": "6QQB",
    "legalFormName": "Aktiengesellschaft",
    "jurisdiction": "DE",
    "legalAddressText": "Werner-von-Siemens-Str. 1, 80333 München, DE-BY, DE",
    "registrationAuthorityId": "RA000304",
    "registrationAuthorityName": "Commercial Register, Local Court München",
    "registeredAs": "HRB 6684",
    "registrationStatus": "ISSUED",
    "nextRenewalDate": "2027-10-25T12:49:24Z",
    "directParent": {
        "status": "reporting-exception",
        "lei": null,
        "legalName": null,
        "country": null,
        "exceptionReason": "NO_KNOWN_PERSON",
        "exceptionReasonText": "no known person or entity controls it",
        "exceptionReference": null
    },
    "ultimateParent": { "status": "reporting-exception", "exceptionReason": "NO_KNOWN_PERSON" },
    "hasDirectChildren": true,
    "directChildrenTotal": 459,
    "children": [
        { "lei": "529900YQP0HHGTCX1K98", "legalName": "De Novo Software, LLC", "country": "US", "entityStatus": "ACTIVE", "depth": 1, "parentLei": "W38RGI023J3WT1HWRP32" },
        { "lei": "5299005SCD5ZIME65422", "legalName": "Siemens Malaysia Sdn. Bhd.", "country": "MY", "entityStatus": "ACTIVE", "depth": 1, "parentLei": "W38RGI023J3WT1HWRP32" }
    ],
    "bic": ["SIEMDEMMXXX"],
    "gleifUrl": "https://search.gleif.org/#/record/W38RGI023J3WT1HWRP32",
    "dataAsOf": "2026-10-01T00:00:00Z",
    "kycSummary": "Siemens Aktiengesellschaft (LEI W38RGI023J3WT1HWRP32) is an active Aktiengesellschaft registered in Germany, number HRB 6684 in the Commercial Register, Local Court München. Headquarters: München, Germany. LEI issued, next renewal due 2027-10-25. No parent reported because no known person or entity controls it. 459 direct subsidiaries with an LEI. Source: GLEIF, data as of 2026-10-01."
}
```

One of its subsidiaries, as its own row (shortened):

```json
{
    "lei": "5299005SCD5ZIME65422",
    "legalName": "Siemens Malaysia Sdn. Bhd.",
    "role": "child",
    "rootLei": "W38RGI023J3WT1HWRP32",
    "depth": 1,
    "parentLei": "W38RGI023J3WT1HWRP32",
    "legalFormName": "Private Limited Company",
    "jurisdiction": "MY",
    "registeredAs": "198201013259 (93008-X)",
    "directParent": { "status": "reported", "lei": "W38RGI023J3WT1HWRP32", "legalName": "Siemens Aktiengesellschaft", "country": "DE" },
    "ultimateParent": { "status": "reported", "lei": "W38RGI023J3WT1HWRP32", "legalName": "Siemens Aktiengesellschaft", "country": "DE" },
    "kycSummary": "Siemens Malaysia Sdn. Bhd. (LEI 5299005SCD5ZIME65422) is an active Private Limited Company registered in Malaysia, number 198201013259 (93008-X) in the Corporate Registry, Companies Commission of Malaysia. Headquarters: Kuala Lumpur, Malaysia. LEI issued, next renewal due 2027-04-30. Direct and ultimate parent: Siemens Aktiengesellschaft (LEI W38RGI023J3WT1HWRP32, DE). No subsidiaries with an LEI reported. Source: GLEIF, data as of 2026-10-01."
}
```

Name searches add `matchScore` and `matchedName`. Inputs without a result get a free row with an `error` code: `invalid-lei`, `lei-not-found`, `no-match`, `rate-limited` or `api-error`.

### How much does it cost?

This Actor uses **pay per event**: **$0.002 per entity returned as its own row** (`entity-returned`).

| What | Charged? |
| --- | --- |
| An entity from your LEI list, or a name match | **$0.002** per row |
| A subsidiary, when **Return subsidiaries as their own rows** is on (default) | **$0.002** per row |
| A parent, when **Also return parents as their own rows** is on (off by default) | **$0.002** per row |
| Parents summarised inside a row (LEI, name, country, reporting exception) | **free** |
| Subsidiaries listed inside a row (`children`) | **free** |
| BIC codes, ISINs, the KYC summary, the register details | **free** (part of the row) |
| Invalid or unknown LEIs, names without a match, API errors | **free** |

How it adds up:

- The default input (2 LEIs, one level of subsidiaries, at most 5 each) returns **12 rows: $0.024**.
- The same with **Return subsidiaries as their own rows** off returns **2 rows: $0.004**, and each row still lists its 5 subsidiaries.
- 1,000 LEIs without subsidiaries cost **$2**.
- An entity is returned and charged **at most once per run**, even if it is found several times (for example as an input and as another input's subsidiary, or as both direct and ultimate parent).
- **Matches per name** is the most rows a name search can return; set it to 1 if you only want the best match.
- The GLEIF API itself is free. Apify also charges a tiny standard start fee per run (about $0.0000125 at the default 256 MB).
- Set **Maximum cost per run** in the run options and the Actor stops when it is reached.

### Limitations

- **Only entities with an LEI.** Subsidiaries without an LEI are not in GLEIF, so the tree shows the part of a group that has LEIs. Large groups have many more subsidiaries than they have LEIs.
- **Parents follow accounting consolidation**, as reported by the entities and checked by the LEI issuers. That is not always the same as legal ownership or beneficial ownership, and GLEIF has no data on natural persons (owners who are individuals show up as the reporting exception "natural persons").
- **Speed:** GLEIF allows 60 requests per minute; the Actor stays at 50. A row needs 1–4 requests (parents, ISINs, names of legal forms and registers, which are cached), so expect roughly 15–40 rows a minute on large runs.
- **Name search** is a best-effort match on GLEIF's search, not a guarantee. Check the score and compare the register number or address with what you know before you rely on a match. Typos are found when GLEIF's own fuzzy search suggests the name.
- **ISINs:** up to 100 per entity are listed (banks can have thousands); `isinsTotal` always has the full count.
- Data is as current as the latest GLEIF Golden Copy (`dataAsOf`, published several times a day).

### Data source and licence

LEI data comes from GLEIF's API and is published under the **CC0** licence, free for any use. This Actor is not affiliated with, endorsed by or a service of GLEIF or any LEI issuer. GLEIF does not guarantee the accuracy of LEI data, which is reported by the entities themselves; check critical information with the entity.

### FAQ

#### What is an LEI?

A 20-character code (ISO 17442) that identifies a legal entity taking part in financial transactions, issued by accredited LEI issuers and published by GLEIF. Example: `W38RGI023J3WT1HWRP32` is Siemens AG.

#### Why does a company have no parent?

Either it is at the top of its group, or it reported an exception, for example because it is owned by individuals or its parent doesn't consolidate it. `exceptionReasonText` says which, in plain English.

#### What does "LAPSED" mean?

The entity didn't renew its LEI on time. The LEI still identifies the entity, but its data may be out of date, and many regulations require a current LEI for reporting.

#### Can I get every subsidiary of a large group?

Up to 1,000 per input entity and three levels. Very large groups (thousands of entities) need several runs, for example one per major subsidiary.

#### Can I run it on a schedule?

Yes. Save a task with your counterparties' LEIs and schedule it monthly; compare runs to spot lapsed LEIs or changed parents.

### More tools from the same developer

All pay-per-result, no proxy or login needed, built and maintained by the same developer:

**Website audits**

- [Website Accessibility Checker: WCAG 2.2 & EAA](https://apify.com/offerastudio/website-accessibility-audit): accessibility issues with fixes, SEO basics and security headers.
- [Cookie & Tracker Audit: GDPR Consent Checker](https://apify.com/offerastudio/cookie-tracker-audit): cookies and tracking tags that load before consent.
- [AI Crawler Access Checker: robots.txt & llms.txt](https://apify.com/offerastudio/ai-crawler-access-audit): which AI crawlers a site allows, plus llms.txt.
- [Website Change Monitor: Diffs, Prices & Alerts](https://apify.com/offerastudio/website-change-monitor): get a row only when a page changes, with a clean diff.

**Company data and compliance**

- [Company Contact Finder: Emails, Phones & Socials](https://apify.com/offerastudio/company-contact-finder): contact details published on company websites.
- [UK New Companies Feed: Companies House Daily](https://apify.com/offerastudio/uk-new-companies-feed): newly incorporated UK companies with sector filters.
- [EU VAT Number Validator: Bulk VIES Checker](https://apify.com/offerastudio/eu-vat-number-validator): bulk VAT checks with name, address and consultation number.

**Market signals**

- [US WARN Layoff Notices: 12 States Daily Feed](https://apify.com/offerastudio/us-warn-layoff-notices): layoff and plant closure notices from official state sources.
- [US Product Recalls Monitor: FDA & CPSC Feed](https://apify.com/offerastudio/us-product-recalls-monitor): FDA and CPSC recalls in one feed, with severity.

### Feedback

A match that should have been found, or a field you need? Open an issue on the **Issues** tab with the LEI or name.

# Changelog

This Actor's version history is a separate document: https://apify.com/offerastudio/gleif-lei-corporate-tree/changelog.md

# Actor input Schema

## `leis` (type: `array`):

Legal Entity Identifiers, 20 characters each, one per line (up to 5,000). Invalid or unknown LEIs get a free error row.

## `companyNames` (type: `array`):

Search by name instead of LEI, one name per line (up to 500), e.g. "Siemens AG" or "Unilever PLC". Legal forms such as AG and Aktiengesellschaft count as the same. Each match is scored 0–100; see the match settings below.

## `country` (type: `string`):

Optional 2-letter country code (ISO 3166-1, e.g. DE, GB, US). Name search then only returns entities whose legal address is in that country.

## `maxMatchesPerName` (type: `integer`):

How many of the best matches to return for each name. Each match is a row (and is charged), so keep this small.

## `minMatchScore` (type: `integer`):

Matches below this score are left out. 100 = same name (legal form aside), 95 = same name with another legal form, 80–94 = close (typos, word order, extra words).

## `includeParents` (type: `boolean`):

Adds each entity's direct and ultimate accounting-consolidation parent (LEI, name, country), or the reporting exception the entity gave instead (for example "controlled by natural persons"). Free: shown inside the row.

## `parentsAsRows` (type: `boolean`):

Returns the full record of each direct and ultimate parent as a separate row (charged like any entity). Off: parents are only summarised inside the row (free).

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

Lists subsidiaries (entities that report this entity as their direct parent), breadth first, up to the depth and limit below. Turn off to look up only the entities you entered.

## `childrenDepth` (type: `integer`):

1 = direct subsidiaries, 2 = also their subsidiaries, 3 = one level more.

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

Limit for each entity from your input, across all levels. Large groups have hundreds of subsidiaries with an LEI.

## `childrenAsRows` (type: `boolean`):

On: every subsidiary gets a full row (charged as an entity) and is also listed in its parent's "children". Off: subsidiaries are only listed inside the input entity's row (LEI, name, country, level), which is free.

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

Adds the securities (ISINs) mapped to each entity in GLEIF's ISIN-to-LEI data, up to 100 per entity, plus the total. BIC codes are always included when GLEIF has them.

## Actor input object example

```json
{
  "leis": [
    "W38RGI023J3WT1HWRP32",
    "KY37LUS27QQX7BB93L28"
  ],
  "maxMatchesPerName": 3,
  "minMatchScore": 80,
  "includeParents": true,
  "parentsAsRows": false,
  "includeChildren": true,
  "childrenDepth": 1,
  "maxChildren": 5,
  "childrenAsRows": true,
  "includeIsins": false
}
```

# Actor output Schema

## `entities` (type: `string`):

No description

## `kyc` (type: `string`):

No description

## `tree` (type: `string`):

No description

# 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 = {
    "leis": [
        "W38RGI023J3WT1HWRP32",
        "KY37LUS27QQX7BB93L28"
    ],
    "maxChildren": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("offerastudio/gleif-lei-corporate-tree").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 = {
    "leis": [
        "W38RGI023J3WT1HWRP32",
        "KY37LUS27QQX7BB93L28",
    ],
    "maxChildren": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("offerastudio/gleif-lei-corporate-tree").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "leis": [
    "W38RGI023J3WT1HWRP32",
    "KY37LUS27QQX7BB93L28"
  ],
  "maxChildren": 5
}' |
apify call offerastudio/gleif-lei-corporate-tree --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,offerastudio/gleif-lei-corporate-tree"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/SJ9cKZ2JQOyfe4gt9/builds/hiclIWaZ64djA6U4H/openapi.json
