# LEI Lookup – GLEIF Legal Entity Search (`sfoln/lei-lookup`) Actor

Look up Legal Entity Identifiers (LEI) by code or company name in the official GLEIF database: legal name, status, legal form, addresses, registry id, BIC, renewal dates and direct and ultimate parent companies. $2 per 1,000 LEI records; no API key needed.

- **URL**: https://apify.com/sfoln/lei-lookup.md
- **Developed by:** [SFOLN LLC](https://apify.com/sfoln) (community)
- **Categories:** Automation, Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.80 / 1,000 lei records

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/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

**LEI Lookup – GLEIF Legal Entity Search** looks up Legal Entity Identifiers (LEI) by code, or finds the LEI of a company by name, in the official GLEIF database and returns one record per lookup: legal name and other names, entity and registration status, jurisdiction, ISO 20275 legal form, legal and headquarters addresses, the company's id in its national register, BIC codes, renewal dates and the direct and ultimate parent companies. Built for onboarding and KYB checks, counterparty and vendor data, compliance tools and AI agents. $0.002 per LEI record found; no API key needed.

- **What you get:** `lei`, `legalName`, `otherNames`, `entityStatus` (ACTIVE / INACTIVE), `registrationStatus` (ISSUED, LAPSED, RETIRED …), `jurisdiction`, `legalForm` (code and name), `legalAddress` and `headquartersAddress`, `registrationAuthority` (register and the company's id in it), `bic`, `nextRenewalDate` and `renewalOverdue`, `directParent` and `ultimateParent` (or the reason none is reported), and a link to the record on search.gleif.org.
- **By code or by name:** LEI codes are checked (ISO 17442 check digits) and fetched 100 at a time; a company name returns the best-matching record with its match score and the next candidates.
- **Price:** $0.002 per record found (`lei-record`); unknown LEIs, names without a close match, invalid codes and errors are free.
- **Works everywhere:** API, MCP for AI agents, Make, Zapier, n8n, schedules and webhooks.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `leis` | string\[] | – | 20-character LEI codes, one per line; spaces and dashes are ignored. Codes with wrong check digits are returned as `skipped_invalid` without a lookup. |
| `companyNames` | string\[] | – | Company names to search, one per line (a plain string is split on line breaks and semicolons). Via the API an element can also be `{ "name": "…", "country": "DE" }`. An LEI given here is looked up as a code. |
| `country` | string | – | Limit name searches to companies whose legal address is in this country (ISO code like DE or a country name). Empty searches worldwide. |
| `includeParents` | boolean | true | Add the direct and ultimate accounting-consolidation parents (GLEIF level 2), or the reporting exception that explains why none is reported. |
| `resolveCodes` | boolean | true | Add the names of the legal form and of the registration authority (one extra request per distinct code and run). |
| `maxCandidates` | integer | 3 | Other matching records (LEI, name, country, status, score) listed under `candidates` for a name search (0–10); they are not charged. |
| `minNameScore` | number | 0.8 | How close (0.5–1) a GLEIF name must be to the searched name to be returned as the match; below it the record is `not_found` with the candidates. |
| `maxItems` | integer | 1000 | Safety cap on LEIs plus names per run (up to 10,000); further inputs are ignored and counted as `inputItemsDropped` in the `OUTPUT` record. |
| `concurrency` | integer | 3 | Lookups processed in parallel (1–5). |
| `includeRaw` | boolean | false | Attach the unmodified GLEIF JSON:API records (with the parent records) under `raw`. |

```json
{
  "leis": ["HWUPKR0MPOU8FGXBT394"],
  "companyNames": ["Siemens Healthineers AG"],
  "country": "DE"
}
```

### Output

One dataset record per LEI or company name. An LEI lookup:

```json
{
  "input": { "lei": "HWUPKR0MPOU8FGXBT394" },
  "status": "ok",
  "charged": true,
  "chargedEvent": "lei-record",
  "source": "gleif",
  "fetchedAt": "2026-10-14T23:17:00.296Z",
  "found": true,
  "query": "HWUPKR0MPOU8FGXBT394",
  "lei": "HWUPKR0MPOU8FGXBT394",
  "legalName": "Apple Inc.",
  "legalNameLanguage": "en",
  "otherNames": [{ "name": "Apple Computer, Inc.", "type": "PREVIOUS_LEGAL_NAME", "language": "en" }],
  "transliteratedNames": [],
  "entityStatus": "ACTIVE",
  "registrationStatus": "ISSUED",
  "jurisdiction": "US-CA",
  "country": "US",
  "category": "GENERAL",
  "subCategory": null,
  "legalForm": { "code": "H1UM", "name": "For-Profit Corporation General Stock" },
  "legalAddress": {
    "lines": ["C/O C T Corporation System", "330 N. Brand Blvd", "Suite 700"],
    "city": "Glendale",
    "region": "US-CA",
    "postalCode": "91203",
    "country": "US",
    "formatted": "C/O C T Corporation System, 330 N. Brand Blvd, Suite 700, 91203 Glendale, US"
  },
  "headquartersAddress": {
    "lines": ["One Apple Park Way"],
    "city": "Cupertino",
    "region": "US-CA",
    "postalCode": "95014",
    "country": "US",
    "formatted": "One Apple Park Way, 95014 Cupertino, US"
  },
  "registrationAuthority": { "id": "RA000598", "name": "Business Entity Records", "entityId": "806592" },
  "entityCreationDate": "1977-01-03T00:00:00Z",
  "initialRegistrationDate": "2012-06-06T15:53:00Z",
  "lastUpdateDate": "2026-03-03T16:34:33Z",
  "nextRenewalDate": "2027-03-08T17:27:20Z",
  "renewalOverdue": false,
  "managingLou": "5493001KJTIIGC8Y1R12",
  "corroborationLevel": "FULLY_CORROBORATED",
  "bic": ["APLEUS66XXX"],
  "mic": [],
  "ocid": null,
  "successorEntity": null,
  "expiration": null,
  "directParent": null,
  "directParentException": { "category": "DIRECT_ACCOUNTING_CONSOLIDATION_PARENT", "reason": "NATURAL_PERSONS" },
  "ultimateParent": null,
  "ultimateParentException": { "category": "ULTIMATE_ACCOUNTING_CONSOLIDATION_PARENT", "reason": "NATURAL_PERSONS" },
  "gleifUrl": "https://search.gleif.org/#/record/HWUPKR0MPOU8FGXBT394",
  "goldenCopyPublishedAt": "2026-10-14T08:00:00Z"
}
```

A name search adds the match and the next candidates (other fields as above, trimmed here):

```json
{
  "input": { "name": "Siemens Healthineers AG", "country": "DE" },
  "status": "ok",
  "charged": true,
  "chargedEvent": "lei-record",
  "source": "gleif",
  "fetchedAt": "2026-10-14T23:17:00.954Z",
  "found": true,
  "query": "Siemens Healthineers AG",
  "lei": "529900QBVWXMWANH7H45",
  "legalName": "Siemens Healthineers AG",
  "entityStatus": "ACTIVE",
  "registrationStatus": "ISSUED",
  "country": "DE",
  "directParent": { "lei": "W38RGI023J3WT1HWRP32", "legalName": "Siemens Aktiengesellschaft", "country": "DE", "entityStatus": "ACTIVE", "registrationStatus": "ISSUED" },
  "ultimateParent": { "lei": "W38RGI023J3WT1HWRP32", "legalName": "Siemens Aktiengesellschaft", "country": "DE", "entityStatus": "ACTIVE", "registrationStatus": "ISSUED" },
  "match": { "query": "Siemens Healthineers AG", "country": "DE", "matchedName": "Siemens Healthineers AG", "score": 1 },
  "candidates": []
}
```

| Field | Description |
| --- | --- |
| `entityStatus` / `registrationStatus` | Whether the legal entity is ACTIVE or INACTIVE, and the state of its LEI: ISSUED, LAPSED (not renewed on time), RETIRED, ANNULLED, MERGED, DUPLICATE, PENDING_TRANSFER, PENDING_ARCHIVAL. |
| `registrationAuthority` | GLEIF code (`id`) and name of the business register, and the entity's id in it (`entityId`, e.g. a company number). |
| `directParent` / `ultimateParent` | `{ lei, legalName, country, entityStatus, registrationStatus }` of the consolidating parents; when none is reported, `directParentException` / `ultimateParentException` give the reason (NATURAL_PERSONS, NON_CONSOLIDATING, NO_KNOWN_PERSON …). |
| `match` / `candidates` | Name searches only: the matched name and its score (0–1), and the next records, best first (free). |
| `goldenCopyPublishedAt` | Publication time of the GLEIF data that answered. |

`status` is one of:

- `ok`: an LEI record was found (charged);
- `not_found`: GLEIF has no record for the LEI, or no name is close enough (`error.code` `not_found` or `no_match`, with `candidates`; not charged);
- `error`: GLEIF could not be reached or answered with an error (not charged);
- `skipped_invalid`: the LEI has the wrong length or check digits, or the name has no letters or digits (not charged);
- `skipped_budget`: your **Maximum cost per run** was reached (not charged);
- `skipped_free_plan`: beyond the free-plan limit below (not charged);
- `skipped_unmetered`: the run is not pay-per-event (not charged).

### Pricing

Store discounts: the FREE and BRONZE tiers use the list prices below. SILVER receives 5% off; GOLD, PLATINUM and DIAMOND receive 10% off billable result events. The platform start fee is unchanged. Check the Actor's Store pricing table for the prices currently in effect.

Pay-per-event. You are charged only for records found:

| Event | Price | When |
| --- | --- | --- |
| `lei-record` | $0.002 | once per LEI record returned (`status: "ok"`), by code or as the best match of a name, parents included |

1,000 LEI records cost $2. Set **Maximum cost per run** on the run to cap spend; the Actor stops cleanly (records marked `skipped_budget`) when the cap is reached. Accounts on the Apify free plan can process up to 10 LEIs or names per run; further inputs are returned with `status: "skipped_free_plan"` and are not charged. Upgrade to any paid Apify plan for full batches.

### Use with AI agents (MCP)

Use this Actor from Claude, ChatGPT, Cursor, VS Code or any other MCP client through the [Apify MCP server](https://mcp.apify.com). Add this server URL to your client and sign in with your Apify account when asked:

```text
https://mcp.apify.com?tools=sfoln/lei-lookup
```

To run the MCP server locally instead, start `npx -y @apify/actors-mcp-server --tools sfoln/lei-lookup` with your `APIFY_TOKEN` in the environment.

Example prompt:

> Look up the LEI HWUPKR0MPOU8FGXBT394 and find the LEI of Siemens Healthineers AG, including their parent companies.

Runs started by an agent are billed like any other run (see Pricing). Agents can cap what a run may spend with `maxTotalChargeUsd`.

### API usage

Run the Actor and get its dataset items in one call (the call waits up to 5 minutes for the run to finish):

```bash
curl -X POST "https://api.apify.com/v2/acts/sfoln~lei-lookup/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"leis": ["HWUPKR0MPOU8FGXBT394"], "companyNames": ["Siemens Healthineers AG"]}'
```

For large inputs, start the run asynchronously and download the dataset when it has finished:

```bash
## 1. Start a run: the response holds the run ID (data.id) and its dataset ID (data.defaultDatasetId)
curl -X POST "https://api.apify.com/v2/acts/sfoln~lei-lookup/runs" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"leis": ["HWUPKR0MPOU8FGXBT394"], "companyNames": ["Siemens Healthineers AG"]}'
## 2. Repeat until data.status is SUCCEEDED (each call waits up to 60 s)
curl "https://api.apify.com/v2/actor-runs/<runId>?waitForFinish=60" -H "Authorization: Bearer <APIFY_TOKEN>"
## 3. Download the results (format=json, csv or xlsx)
curl "https://api.apify.com/v2/datasets/<defaultDatasetId>/items?format=json" -H "Authorization: Bearer <APIFY_TOKEN>"
```

Python ([apify-client](https://pypi.org/project/apify-client/)):

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("sfoln/lei-lookup").call(run_input={"leis": ["HWUPKR0MPOU8FGXBT394"], "companyNames": ["Siemens Healthineers AG"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

Instead of polling, you can attach a webhook to the run (see Integrations). The API tab of this page shows the same calls for JavaScript and the Apify CLI.

### Integrations

- **Make, Zapier and n8n:** run `sfoln/lei-lookup` with the Apify app (in n8n, the Apify node) and pass the dataset items to the next step of your workflow.
- **Google Sheets:** add the items to a sheet with the Google Sheets step of Make, Zapier or n8n, or download them as CSV or Excel from the run's Storage tab or the API (`format=csv` or `format=xlsx`).
- **Webhooks:** get a POST request when a run succeeds or fails: add a webhook in the Actor's Integrations tab, or pass `webhooks` when you start a run through the API.
- **Schedules:** run it hourly, daily or weekly with the same input from Apify Schedules; every run keeps its results in its own dataset.
- **More:** Slack, Google Drive, GitHub, LangChain, LlamaIndex and other [Apify integrations](https://docs.apify.com/platform/integrations).

### Related Actors

- [KYB Company Check – Registry, LEI, VAT](https://apify.com/sfoln/kyb-company-check)
- [Sanctions Screening – OFAC, EU, UK, UN Lists](https://apify.com/sfoln/sanctions-screening)
- [EU VAT Number Validator (VIES)](https://apify.com/sfoln/vat-number-validator)
- [Website Contact Details Scraper](https://apify.com/sfoln/company-contacts-finder)
- [Domain WHOIS & DNS Lookup](https://apify.com/sfoln/domain-intelligence)

See [all our Actors](https://apify.com/sfoln) on Apify Store.

### FAQ

#### How much does it cost, and am I charged for failed items?

You pay per event at the prices under Pricing above, plus a run start fee of $0.00005 per GB of memory, with no subscription; platform usage is included. Errors and skipped items (`skipped_…` statuses) are never charged; a lookup that finds nothing is charged only where Pricing says so, and every record's `charged` field shows whether it was billed. Set **Maximum cost per run** to cap what a single run can spend.

#### How fresh is the data?

Each run queries its source while it runs, so you get what the source returns at that moment. Source-specific details, such as how often a provider refreshes its own database, are under Limits & notes.

#### What are the limits?

Per-run caps (for example the maximum number of items) are listed under Input, source limits under Limits & notes, and the free-plan limit under Pricing. For big batches, start the run asynchronously (see API usage) and read the dataset when it has finished.

#### Can I schedule runs or get results by webhook?

Yes. Create a schedule in Apify Console to run it hourly, daily or weekly with the same input, and add a webhook to get a POST request when a run finishes (see Integrations).

#### What does this Actor record about my runs?

This Actor records operational metrics about each run (item counts, duration, charges, error codes and a pseudonymous hash of your Apify user ID) to monitor reliability and costs. It never stores your input or results.

#### Where does the data come from?

From the GLEIF LEI database (api.gleif.org), the official global directory of Legal Entity Identifiers, published as open data (CC0). Every record carries the golden-copy publication time.

#### What are direct and ultimate parents?

GLEIF level-2 data: the companies that consolidate the entity in their accounts. When no parent is reported, the reporting exception (for example NATURAL_PERSONS or NON_CONSOLIDATING) is returned instead.

#### What does a LAPSED registration mean?

The LEI was not renewed on time (registrationStatus LAPSED, renewalOverdue true). The entity may still exist; many regulated counterparties require an ISSUED LEI.

#### How do I get help?

Open an issue in the Actor's Issues tab and include the link to the run, so we can reproduce the problem. Feature requests are welcome there too.

### Limits & notes

- Data: the GLEIF LEI database (api.gleif.org), more than 2.5 million LEI records with level-2 parent data. Only entities that applied for an LEI are listed (banks, issuers, funds, many large and mid-size companies); most small businesses have none.
- Name search covers legal, previous, trading and transliterated names; scores below `minNameScore` return `not_found` with the closest candidates so you can pick one by LEI.
- GLEIF allows about 60 requests per minute; the Actor paces itself, fetches LEI codes 100 per request, resolves all parents of a batch in one more request and looks up each legal form and register name once per run. A name search takes one or two requests.
- Up to 10,000 lookups per run (`maxItems`).

# Actor input Schema

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

20-character Legal Entity Identifiers, one per line (e.g. HWUPKR0MPOU8FGXBT394). Codes with wrong check digits are reported, not looked up. Accounts on the Apify free plan can process up to 10 LEIs or names per run.

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

Company names to search, one per line; the best-matching LEI record is returned with the next candidates. Via the API an element can also be {"name": "…", "country": "DE"}.

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

Limit name searches to companies whose legal address is in this country (ISO code like DE or a country name). Leave empty to search worldwide.

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

Add the direct and ultimate accounting-consolidation parents (GLEIF level 2), or the reporting exception that explains why none is reported.

## `resolveCodes` (type: `boolean`):

Add the names of the ISO 20275 legal form and the registration authority (one extra GLEIF request per distinct code and run).

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

How many other matching LEI records to list (LEI, name, country, status, score) under candidates for a name search; they are not charged.

## `minNameScore` (type: `number`):

How close (0.5–1) a GLEIF name must be to the searched name to be returned as the match; below it the record is not_found with the candidates.

## `maxItems` (type: `integer`):

Safety cap on LEIs plus names per run; further inputs are ignored and counted in the OUTPUT record.

## `concurrency` (type: `integer`):

Lookups processed in parallel (GLEIF allows about 60 requests per minute; LEI codes are fetched 100 at a time).

## `includeRaw` (type: `boolean`):

Attach the unmodified GLEIF JSON:API records (with the parent records) under raw.

## Actor input object example

```json
{
  "leis": [
    "HWUPKR0MPOU8FGXBT394"
  ],
  "companyNames": [
    "Siemens Healthineers AG"
  ],
  "includeParents": true,
  "resolveCodes": true,
  "maxCandidates": 3,
  "minNameScore": 0.8,
  "maxItems": 1000,
  "concurrency": 3,
  "includeRaw": false
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "HWUPKR0MPOU8FGXBT394"
    ],
    "companyNames": [
        "Siemens Healthineers AG"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sfoln/lei-lookup").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": ["HWUPKR0MPOU8FGXBT394"],
    "companyNames": ["Siemens Healthineers AG"],
}

# Run the Actor and wait for it to finish
run = client.actor("sfoln/lei-lookup").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": [
    "HWUPKR0MPOU8FGXBT394"
  ],
  "companyNames": [
    "Siemens Healthineers AG"
  ]
}' |
apify call sfoln/lei-lookup --silent --output-dataset

```

## MCP server setup

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

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/OGIKjvsjeo9vlS6lQ/builds/QeO8oEWaF7TwvA0dv/openapi.json
