# GLEIF LEI Lookup Scraper / API: Renewal & Status Watch (`kittiwake/gleif-lei-watch`) Actor

Watch your own LEIs in the GLEIF register: renewal warnings before a registration lapses, and what changed since the last run — status, name, address, successor, managing LOU.

- **URL**: https://apify.com/kittiwake/gleif-lei-watch.md
- **Developed by:** [Kittiwake Data](https://apify.com/kittiwake) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 lei checkeds

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

## GLEIF LEI Lookup Scraper / API: Renewal & Status Watch

**Know before a counterparty's LEI lapses.** An **LEI renewal and status monitor** on the official
GLEIF register: **LEI lookup** for a whole list, **renewal reminders** before an LEI expires, and an
alert when a status, name, address or successor changes.

Paste the LEIs you depend on — counterparties, clients, funds, issuers — and schedule this Actor
weekly. Each run reads those records from the official **GLEIF** register and tells you two things:

- **which renewals fall due** inside your warning window, before they lapse, and
- **what changed since the last run**: a registration that went `LAPSED`, `RETIRED` or `ANNULLED`, an
  entity that became `INACTIVE`, a new legal name or address, a successor entity, a new managing LOU.

It is a watchlist, not a scraper. It reads only the LEIs you list, and keeps the last snapshot of
each one so the next run can tell you what is different.

### What it is for

- **Trade and transaction reporting teams** — catch a counterparty LEI that is about to lapse while
  there is still time to ask them to renew.
- **KYC and onboarding teams** — a weekly check that the entities on your books still hold an
  issued LEI, with the date of the change and the value it replaced.
- **Fund administrators and issuers' agents** — watch a portfolio of fund and issuer LEIs for
  renewals, mergers and successor entities.

### What makes it different from searching GLEIF by hand

| | GLEIF search, one LEI at a time | this Actor |
|---|---|---|
| your list | look each one up | paste the whole list once; checked in batches of 50 |
| renewals | read `nextRenewalDate` and do the arithmetic | `daysToRenewal` on every row, and a `renewalWindow` flag the run it comes due |
| changes | remember what it said last time | `changeType` names every field that changed; `previousValues` shows what it was |
| lapses | notice the status | `registrationStatus` in `changeType`, with the old value beside it |
| schedule | a calendar reminder | an Apify schedule; switch on `onlyChanges` and get only the rows that need you |
| parents | follow the relationship links | optional `directParentLei` and `ultimateParentLei` |

### Quick start

**Check a list and warn 60 days before any renewal:**

```json
{
  "leis": ["HWUPKR0MPOU8FGXBT394", "2549008YU9EOMHFUA249"]
}
```

**Weekly schedule, only what needs attention, 90-day warning, with parents:**

```json
{
  "leis": ["HWUPKR0MPOU8FGXBT394", "2549008YU9EOMHFUA249", "1595HU08XQEECLKNGF93"],
  "renewalWarningDays": 90,
  "onlyChanges": true,
  "includeRelationships": true
}
```

The first run of a list records a baseline. It flags renewals already inside the window, but it
does not report anything else as a change — there is nothing earlier to compare with.

### Input

| field | type | default | what it does |
|---|---|---|---|
| `leis` | string\[] | **required** | The LEIs to watch. Case and spaces ignored, duplicates read once, invalid check digits skipped and listed in `RUN_SUMMARY` |
| `renewalWarningDays` | integer | `60` | Flag `renewalWindow` when the next renewal comes within this many days |
| `includeRelationships` | boolean | `false` | Also read direct and ultimate parent LEIs. Up to two extra requests per LEI |
| `includeSoleProprietors` | boolean | `false` | Records in the `SOLE_PROPRIETOR` category name an individual and are skipped unless you switch this on |
| `onlyChanges` | boolean | `false` | Write rows only for LEIs with at least one `changeType`. Every LEI is still checked |
| `stateStoreName` | string | `gleif-lei-watch-state` | The named key-value store that keeps last snapshots. Use one name per watchlist |
| `requestDelayMs` | integer | `1000` | Pause between requests to GLEIF |

### Output

One row per LEI checked:

```json
{
  "lei": "1595HU08XQEECLKNGF93",
  "legalName": "C & V Works ApS",
  "jurisdiction": "DK",
  "legalForm": "H8VP",
  "entityCategory": "GENERAL",
  "entityStatus": "ACTIVE",
  "registrationStatus": "LAPSED",
  "initialRegistrationDate": "2026-07-06T16:34:16Z",
  "lastUpdateDate": "2026-07-09T11:57:59Z",
  "nextRenewalDate": "2026-07-06T16:34:20Z",
  "daysToRenewal": -71,
  "managingLou": "98450045AN5EB5FDC780",
  "corroborationLevel": "FULLY_CORROBORATED",
  "legalAddressCountry": "DK",
  "legalAddressCity": "Ølstykke",
  "hqAddressCountry": "DK",
  "successorLei": null,
  "directParentLei": null,
  "ultimateParentLei": null,
  "changeType": ["registrationStatus"],
  "previousValues": { "registrationStatus": "ISSUED" },
  "checkedAt": "2026-09-14T21:30:20.163Z",
  "source": "https://api.gleif.org/api/v1/lei-records/1595HU08XQEECLKNGF93"
}
```

`changeType` values are field names — `registrationStatus`, `entityStatus`, `nextRenewalDate`,
`legalName`, `legalForm`, `jurisdiction`, `entityCategory`, `legalAddressCountry`,
`legalAddressCity`, `hqAddressCountry`, `successorLei`, `managingLou`, `directParentLei`,
`ultimateParentLei` — plus `renewalWindow`. `daysToRenewal` is negative once the date has passed.
A run summary (LEIs checked, changes, not found, invalid, skipped) is saved as `RUN_SUMMARY` in the
run's key-value store.

### What you pay for

| event | price | when |
|---|---|---|
| **LEI checked** | $0.002 | one LEI read, compared and its state saved — only when all three succeed |
| Change detected | $0.02 | an LEI changed since the last run, or came inside your renewal window. Once per LEI per run, however many fields changed |

Apify Store discounts apply by subscription plan: the prices above are the Free-plan prices;
Starter pays 10% less, Scale 20% less and Business 30% less on every event.

Nothing is charged for a failed request, an invalid LEI, an LEI GLEIF has no record of, or a
skipped sole proprietor. The run stops at the spending limit you set; rows already saved are yours.

### What this Actor does not do

- **No street addresses.** Rows carry country and city only. The full address stays on GLEIF's
  page, one click away through `source`.
- **No sole proprietors by default.** A sole proprietor's record names a person, so those records
  are skipped — not written, not stored, not charged — unless you opt in.
- **No bulk download.** It reads the LEIs you list and nothing else, with one identifying
  User-Agent and a pause between requests. If GLEIF refuses a request, the run fails and says so;
  it does not try again differently.
- **No guessing.** A record GLEIF does not return is listed as not found, never as a lapse.

### Source and accuracy

Data comes from the **Global LEI Foundation (GLEIF)** public API, `api.gleif.org`. GLEIF's terms of
use state that the data it makes available is provided under the **CC0 1.0** licence. This Actor
reformats what GLEIF publishes and adds only the comparison with your previous run; the `source`
URL on every row is the authority. GLEIF's register is updated from the Local Operating Units that
issue LEIs, so a change appears here when it appears there.

Nothing here is legal or regulatory advice about when an LEI is required.

### FAQ

**How do I check when an LEI expires?** Every row has `nextRenewalDate` and `daysToRenewal`, and
`renewalWindow` appears in `changeType` once the date comes inside your `renewalWarningDays`.

**Can I look up a single LEI?** Yes. A list of one works the same way: one LEI check, plus Apify's
per-run start event.

**What does it do when an LEI lapses?** The row carries `registrationStatus: "LAPSED"`, lists
`registrationStatus` in `changeType`, and shows the previous value in `previousValues`. Renewing is
done with the entity's own LOU; this Actor only reads.

**Can I export to CSV or Excel?** Yes. The dataset downloads as JSON, CSV, Excel or XML, or you can
read it over the Apify API.

### Support

Use the **Issues** tab on this Actor. Include the run id and the input you used.

# Actor input Schema

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

The 20-character Legal Entity Identifiers of your counterparties, clients, funds or issuers. Case and surrounding spaces are ignored; duplicates are read once; anything that fails the ISO 17442 check digits is skipped and listed in the run summary.

## `renewalWarningDays` (type: `integer`):

Flag an LEI with the change type renewalWindow when its next renewal date comes within this many days. Every row also carries daysToRenewal, so you can filter on 30 or 90 yourself.

## `includeRelationships` (type: `boolean`):

Also read each entity's direct and ultimate parent from GLEIF's relationship records. Up to two extra requests per LEI, so runs take longer.

## `includeSoleProprietors` (type: `boolean`):

Records whose entity category is SOLE\_PROPRIETOR name an individual, so they are left out unless you switch this on. Skipped records are not charged and not stored.

## `onlyChanges` (type: `boolean`):

Write a row only for LEIs with at least one change type. Every listed LEI is still checked and its state kept.

## `stateStoreName` (type: `string`):

Named key-value store that keeps the last snapshot of each LEI between runs. Use a different name per watchlist if you run several.

## `requestDelayMs` (type: `integer`):

Pause between requests to the GLEIF API. The default is deliberately polite; lowering it is not recommended.

## Actor input object example

```json
{
  "leis": [
    "HWUPKR0MPOU8FGXBT394",
    "7LTWFZYICNSX8D621K86",
    "Z2VZBHUMB7PWWJ63I008"
  ],
  "renewalWarningDays": 60,
  "includeRelationships": false,
  "includeSoleProprietors": false,
  "onlyChanges": false,
  "stateStoreName": "gleif-lei-watch-state",
  "requestDelayMs": 1000
}
```

# Actor output Schema

## `watchlist` (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",
        "7LTWFZYICNSX8D621K86",
        "Z2VZBHUMB7PWWJ63I008"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kittiwake/gleif-lei-watch").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",
        "7LTWFZYICNSX8D621K86",
        "Z2VZBHUMB7PWWJ63I008",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("kittiwake/gleif-lei-watch").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",
    "7LTWFZYICNSX8D621K86",
    "Z2VZBHUMB7PWWJ63I008"
  ]
}' |
apify call kittiwake/gleif-lei-watch --silent --output-dataset

```

## MCP server setup

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

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/y02oVCbjrQWrgkk5j/builds/ubUeMee69dBdZTP2F/openapi.json
