# LEI Lookup & Renewal Monitor: Bulk Legal Entity Identifier API (`optimistprime/lei-lookup-renewal-monitor`) Actor

Bulk LEI lookup from official GLEIF data: status, renewal date, lapsed LEIs, parents, BIC. Daily watchlist monitor. MCP-ready, $1 per 1,000. Not affiliated with or endorsed by GLEIF.

- **URL**: https://apify.com/optimistprime/lei-lookup-renewal-monitor.md
- **Developed by:** [Derek VanLaningham](https://apify.com/optimistprime) (community)
- **Categories:** Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 lei record returneds

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 & Renewal Monitor: Bulk Legal Entity Identifier API

**Check thousands of LEIs in seconds, and get told when one lapses.** Bulk LEI lookup and daily renewal monitoring from official GLEIF data, no API key, **$1 per 1,000**.

**Not affiliated with or endorsed by GLEIF.**

Use it for KYC/AML onboarding, EMIR/MiFIR/SFTR trade-reporting checks, treasury counterparty lists, LEI renewal leads, BIC/ISIN → LEI mapping, and AI agents via the [Apify MCP server](https://mcp.apify.com/?tools=optimistprime/lei-lookup-renewal-monitor).

### What you get

One typed `lei-record` row per legal entity:

| Field | Meaning |
|---|---|
| `lei`, `legalName`, `otherNames` | Identifier and names |
| `registrationStatus`, `entityStatus` | ISSUED / LAPSED / … and ACTIVE / INACTIVE |
| `nextRenewalDate`, `daysToRenewal`, `renewalState` | Computed: `current`, `renewal-due`, `overdue`, `lapsed`, `inactive-registration` |
| `legalAddress`, `headquartersAddress`, `jurisdiction` | Registered addresses |
| `bics`, `managingLou`, `registeredAs` | BIC list, issuer LOU, company number |
| `directParent`, `ultimateParent` | Optional (set `includeParents: true`) |
| `changeType`, `changedFields` | Monitor mode only |
| `licence`, `goldenCopyDate`, `apiUrl` | CC0 attribution, data freshness, verification link |

Sole-proprietor LEIs (named after individuals) are **always excluded**.

### Why this Actor

- **200 LEIs per request** — batch lookup, not one call per code
- **`renewalState` / `daysToRenewal` computed** — no date arithmetic for agents
- **Watchlist monitor** with old → new diffs (status, renewal window, name, address, parents)
- **New-LEI and renewal-due feeds** by country
- **BIC and ISIN → LEI**
- **Parent companies** (direct + ultimate)
- **MCP-ready** `timeBudgetSeconds` (default 45)
- **Sole proprietors excluded** for privacy

### Use cases

- Counterparty KYC/AML onboarding
- EMIR/MiFIR/SFTR trade-reporting LEI validation
- Treasury and vendor master data
- LEI renewal and new-entity lead lists for LEI agents / LOU partners
- Fintech entity resolution
- AI agents doing counterparty checks

### How to use

#### How to do a bulk LEI lookup (validate a list of LEIs)

```json
{
  "mode": "lookup",
  "leis": ["HWUPKR0MPOU8FGXBT394", "529900W18LQJJN6SJ336", "5493001KJTIIGC8Y1R12"],
  "includeParents": true,
  "maxItems": 0
}
```

Invalid or unknown LEIs are listed in `RUN_SUMMARY.notFound` / `invalidInputs` and are **not charged**.

#### How to monitor LEI renewals and lapsed LEIs daily

1. Create a task with your watchlist and `"monitorMode": true`, `"monitorId": "treasury-watch"`.
2. Schedule it daily at **09:00 America/Chicago** (after the Golden Copy at 08:00 UTC).
3. Hook a webhook to Slack / email / Make / n8n on dataset items.

Day 1 baselines every LEI (`changeType: "new"`). Later runs return **only changes** (or LEIs that crossed into renewal-due / overdue / lapsed). Unchanged LEIs cost `$0.0002` each (`lei-checked`).

#### How to find new LEI registrations by country

```json
{
  "mode": "search",
  "countries": ["US", "GB"],
  "registeredWithinDays": 3,
  "maxItems": 200,
  "monitorMode": true,
  "monitorId": "new-lei-us-gb"
}
```

Use `registeredWithinDays: 3` daily so weekend lag is covered; already-seen LEIs are skipped for free in monitor mode.

#### How to convert BIC or ISIN to LEI

```json
{ "mode": "lookup", "bics": ["APLEUS66XXX"], "isins": ["US0378331005"] }
```

### LEI statuses explained

| Status | Meaning |
|---|---|
| `ISSUED` | Valid and current (renew annually) |
| `LAPSED` | Renewal overdue — breaks EMIR/MiFIR reporting |
| `PENDING_TRANSFER` / `PENDING_ARCHIVAL` | In process |
| `RETIRED` / `ANNULLED` / `DUPLICATE` | No longer usable |

**Why LEIs lapse:** the legal entity (or its LOU) did not renew by `nextRenewalDate`. `renewalState = renewal-due` means the date is within your `renewalAlertDays` window (default 30).

**Golden Copy:** GLEIF publishes a daily snapshot at **08:00 UTC**. Check `goldenCopyDate` on every row.

### Output and RUN_SUMMARY

Dataset views: **overview** and **changes**. Key-value `RUN_SUMMARY` includes:

`mode`, `requested`, `invalidInputs`, `notFound`, `skippedSoleProprietors`, `searchTotal`, `pushed`, `checkedUnchanged`, `requests`, `goldenCopyDate`, `truncated`, `stopReason`, `charged`.

### Pricing

Pay per event (no "+ usage"):

| Event | FREE | BRONZE+ |
|---|---|---|
| `lei-record` (row returned; monitor: new/changed only) | $0.0010 | $0.0008 |
| `lei-checked` (unchanged watchlist LEI) | $0.0002 | $0.0002 |
| Actor start | $0.002 | $0.002 |

Minimum max charge per run: **$0.02**. Not-found and invalid LEIs are free.

**Examples (FREE):** default 3-LEI run ≈ $0.005; 1,000-LEI KYC check ≈ $1.002; daily 500-LEI watchlist after baseline ≈ a few cents/day when few change.

### Use as an MCP tool

Endpoint: `https://mcp.apify.com/?tools=optimistprime/lei-lookup-renewal-monitor`

Example prompts:

- "Is LEI 529900W18LQJJN6SJ336 still valid, and who is its ultimate parent?"
- "Which of these 50 counterparty LEIs lapse in the next 30 days?"
- "Find the LEI for BIC APLEUS66XXX."

Minimal agent call:

```json
{ "mode": "lookup", "leis": ["5493001KJTIIGC8Y1R12"], "includeParents": true }
```

### Data source, licence, privacy

Data comes from the Global LEI System via the public GLEIF API (CC0 1.0). **This Actor is not affiliated with, endorsed by or a service of GLEIF or any LEI issuer (LOU).** Sole-proprietor LEIs, which name individuals, are excluded. GLEIF does not warrant that LEI data is accurate or current; check `goldenCopyDate`.

We call only `api.gleif.org` (documented, keyless), stay under 40 requests/min against the published 60/min limit, and never use the GLEIF logo or imply affiliation in the title.

### FAQ

**Is this the official GLEIF tool?** No. It uses GLEIF's public API; the data is CC0. Not affiliated with or endorsed by GLEIF.

**Why is my LEI "not found"?** Typos fail the ISO 17442 check digit (`invalidInputs`). Unknown but well-formed LEIs appear in `notFound` (the API returns an empty page, not HTTP 404).

**Why are sole proprietors excluded?** Those records are named after individuals. We drop them everywhere for privacy.

**How fresh is the data?** Daily Golden Copy at 08:00 UTC — see `goldenCopyDate`.

**Can I get subsidiaries?** Not in v1 (direct-children is planned for v1.1).

### Ready-to-run examples

| Example | What it does | Sample run |
|---|---|---|
| [Bulk LEI Check for KYC](https://apify.com/optimistprime/lei-lookup-renewal-monitor/tasks/bulk-lei-check-kyc) | 3 LEIs + parents | 3 rows |
| [UK LEIs Due for Renewal in the Next 30 Days](https://apify.com/optimistprime/lei-lookup-renewal-monitor/tasks/uk-lei-renewals-due-30-days) | GB renewals, max 100 | 100 rows |
| [New LEI Registrations: US & UK](https://apify.com/optimistprime/lei-lookup-renewal-monitor/tasks/new-lei-registrations-us-uk) | Registered in last 2 days | 14+ rows |

### Changelog

See [CHANGELOG.md](./CHANGELOG.md).

# Changelog

This Actor's version history is a separate document: https://apify.com/optimistprime/lei-lookup-renewal-monitor/changelog.md

# Actor input Schema

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

lookup = check the LEIs, BICs, ISINs or legal names you list. search = query the whole LEI register with the filters below (new LEIs, renewals due, lapsed, by country).

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

Lookup mode. 20-character Legal Entity Identifiers, up to 5,000. Checked 200 per request. Invalid or unknown LEIs are reported in the run summary and not charged.

## `bics` (type: `array`):

Lookup mode. Find the LEI behind each BIC (8 or 11 characters), e.g. APLEUS66XXX. One request per BIC.

## `isins` (type: `array`):

Lookup mode. Find the issuer LEI for each ISIN (12 characters), e.g. US0378331005. One request per ISIN.

## `names` (type: `array`):

Lookup mode. Company or fund legal names. Name matching is fuzzy, so up to 'Matches per name' best matches are returned with matchQuery set. One request per name.

## `matchesPerName` (type: `integer`):

Lookup mode, names only.

## `countries` (type: `array`):

Search mode. ISO 3166 two-letter codes, e.g. US, GB, DE. Empty = all countries.

## `categories` (type: `array`):

Search mode. Empty = all except sole proprietors (always excluded for privacy).

## `registrationStatuses` (type: `array`):

Search mode. ISSUED = valid and renewed; LAPSED = renewal overdue; RETIRED/ANNULLED/DUPLICATE = no longer usable; PENDING_TRANSFER/PENDING_ARCHIVAL = in process. Empty = all.

## `entityStatus` (type: `string`):

Search mode. ACTIVE or INACTIVE legal entity. ANY = both.

## `registeredWithinDays` (type: `integer`):

Search mode. New-LEI feed: only LEIs whose initial registration date is in the last N days (0 = off). Around 800-1,300 new LEIs are issued worldwide per weekday.

## `updatedWithinDays` (type: `integer`):

Search mode. Only LEI records updated in the last N days (0 = off).

## `renewalDueWithinDays` (type: `integer`):

Search mode. Only ISSUED LEIs whose next renewal date falls in the next N days (0 = off), soonest first. Renewal-lead and compliance lists.

## `renewalAlertDays` (type: `integer`):

Both modes. An ISSUED LEI whose renewal date is within this many days gets renewalState = renewal-due (and, in monitor mode, an alert when it enters the window).

## `fullText` (type: `string`):

Search mode. Optional words matched anywhere in the LEI record (names, addresses, identifiers).

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

Add the direct and ultimate parent (LEI, legal name, country) when reported. Costs up to 2 extra requests per row, so large lists take longer (about 20 rows per 45 s budget).

## `monitorMode` (type: `boolean`):

Lookup: return only LEIs that changed since the last run (status, renewal date, name, address, successor, parent, or crossing into renewal-due/overdue/lapsed). Unchanged LEIs cost $0.0002 each. Search: return only LEIs this monitor hasn't returned before. Schedule daily.

## `monitorId` (type: `string`):

Name of the monitor state (letters, digits, dashes). Use different IDs for different watchlists.

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

Stop after this many rows (0 = no limit). Lookup mode with a long list: set 0 or at least the list size.

## `timeBudgetSeconds` (type: `integer`):

Stop fetching after this many seconds and return what was found so far (truncated: true). 0 = no limit. Keeps AI-agent calls fast.

## Actor input object example

```json
{
  "mode": "lookup",
  "leis": [
    "HWUPKR0MPOU8FGXBT394",
    "529900W18LQJJN6SJ336",
    "5493001KJTIIGC8Y1R12"
  ],
  "bics": [],
  "isins": [],
  "names": [],
  "matchesPerName": 3,
  "countries": [],
  "categories": [],
  "registrationStatuses": [],
  "entityStatus": "ANY",
  "registeredWithinDays": 0,
  "updatedWithinDays": 0,
  "renewalDueWithinDays": 0,
  "renewalAlertDays": 30,
  "fullText": "",
  "includeParents": false,
  "monitorMode": false,
  "monitorId": "default",
  "maxItems": 100,
  "timeBudgetSeconds": 45
}
```

# Actor output Schema

## `leiRecords` (type: `string`):

Dataset of LEI records (status, renewal, parents, addresses).

## `runSummary` (type: `string`):

RUN_SUMMARY key-value entry: pushed, notFound, invalidInputs, charged, goldenCopyDate.

# 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",
        "529900W18LQJJN6SJ336",
        "5493001KJTIIGC8Y1R12"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("optimistprime/lei-lookup-renewal-monitor").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",
        "529900W18LQJJN6SJ336",
        "5493001KJTIIGC8Y1R12",
    ],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("optimistprime/lei-lookup-renewal-monitor").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",
    "529900W18LQJJN6SJ336",
    "5493001KJTIIGC8Y1R12"
  ],
  "maxItems": 100
}' |
apify call optimistprime/lei-lookup-renewal-monitor --silent --output-dataset

```

## MCP server setup

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

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/MTgoRoqMEzW6L4ad5/builds/Kll0fhHA7XGkXs3Fs/openapi.json
