Developer guides

LEI lookup: the GLEIF API, the golden copy and how to map an LEI to a website

GLEIF publishes every Legal Entity Identifier as open data (CC0), through a free REST API and a daily full file; what it does not give you is a website, so mapping an LEI to a domain needs a second source. Source: Arcadium Data, data as of .

An LEI is the 20-character ISO 17442 identifier of a legal entity: banks, funds, listed companies and a growing number of ordinary firms that need one for financial reporting. GLEIF (the Global Legal Entity Identifier Foundation) runs the central index and publishes it for anyone to reuse. For a developer that is good news: no key, no contract, a clean JSON:API interface. The catch is what is missing. An LEI record has a legal name, addresses, a registration authority and a national registration number. It has no website, no VAT number and no industry code you can rely on.

This guide covers the official API and files, the status values that change how you treat a record, and the join to a domain.

The official route: GLEIF

The REST API

The API lives at https://api.gleif.org/api/v1/, returns JSON:API documents and needs no key. The calls you need:

Rate limits are documented on the GLEIF site (60 requests a minute per client at the time of writing); read the current figure before you plan a bulk job, and use the files below for anything large.

curl

# One record by LEI
curl -s "https://api.gleif.org/api/v1/lei-records/OW6OFBNCKXC4US5C7523"

# Search by the national registration number (Norway 923609016)
curl -s -G "https://api.gleif.org/api/v1/lei-records" \
  --data-urlencode "filter[entity.registeredAs]=923609016" \
  --data-urlencode "page[size]=5"

Python

import requests

API = "https://api.gleif.org/api/v1/lei-records"

def lei_by_registration(number: str, country: str):
    r = requests.get(
        API,
        params={
            "filter[entity.registeredAs]": number,
            "filter[entity.legalAddress.country]": country,
            "page[size]": 5,
        },
        timeout=30,
    )
    r.raise_for_status()
    for rec in r.json()["data"]:
        a = rec["attributes"]
        yield rec["id"], a["entity"]["legalName"]["name"], a["entity"]["status"], a["registration"]["status"]

def lei_checksum_ok(lei: str) -> bool:
    """ISO 7064 MOD 97-10 on the 20 characters (letters become 10..35)."""
    if len(lei) != 20 or not lei.isalnum():
        return False
    digits = "".join(str(int(c, 36)) for c in lei.upper())
    return int(digits) % 97 == 1

print(lei_checksum_ok("OW6OFBNCKXC4US5C7523"))
print(list(lei_by_registration("923609016", "NO")))

TypeScript

export function leiChecksumOk(lei: string): boolean {
  if (!/^[A-Z0-9]{20}$/i.test(lei)) return false;
  const digits = [...lei.toUpperCase()].map((c) => parseInt(c, 36).toString()).join('');
  let rest = 0;
  for (const ch of digits) rest = (rest * 10 + Number(ch)) % 97;
  return rest === 1;
}

const url = 'https://api.gleif.org/api/v1/lei-records/OW6OFBNCKXC4US5C7523';
const res = await fetch(url, { headers: { Accept: 'application/vnd.api+json' } });
const { data } = (await res.json()) as {
  data: { id: string; attributes: { entity: { legalName: { name: string }; status: string } } };
};
console.log(data.id, data.attributes.entity.legalName.name, data.attributes.entity.status);

The golden copy files

For bulk work do not page through the API. GLEIF publishes the full Level 1 file (who is who), the Level 2 relationship file (who owns whom: direct and ultimate parents) and the reporting exceptions file as downloads in CSV, JSON and XML, refreshed several times a day, plus deltas. The data is released under CC0, so you can reuse it without attribution; keep the download date next to what you store.

Status values that change what you do

API or file?

Use the API when a user types one name or number and you need one answer in under a second, or when you want the live status of a record you already hold. Use the golden copy when you need more than a few thousand records, when you join LEIs to your own tables, or when you need the parent relationships: loading the file once and querying it locally is faster, cheaper for GLEIF and immune to the rate limit. Keep the file's publication date with your copy and refresh it on a schedule, because registration status changes (renewals lapse every year).

Mapping an LEI to a company website

No official field links an LEI to a domain, so every mapping is inference. Three evidence types work, in descending strength: the company states its LEI on its own site (investor relations and legal notice pages often do), Wikidata links the LEI (property P1278) to an item that has an official website, or the registration number in the LEI record matches a national register entry that lists a website. Keep the evidence and a confidence with each mapping; do not map a subsidiary's LEI to the parent's domain without saying so.

Pitfalls

The fast route: LEI to domain, national id and status

The Arcadium Data resolve route takes an LEI as id (or type=lei) and returns the company domain, the registered name, the national registry ids and VAT number we hold for it, and the GLEIF entity and registration status. The other direction works too: send a domain and read the LEI, with the confidence and the sources that showed it.

Calls on this page work without a key from one IP (10 requests a minute, 100 a day, short answers, point lookups). A free key lifts the limits: sign up. Routes, parameters and fields: OpenAPI.

curl

curl -s "https://api.arcadiumdata.io/v1/companies/resolve?id=OW6OFBNCKXC4US5C7523&type=lei"

curl

curl -s "https://api.arcadiumdata.io/v1/companies/resolve?domain=equinor.com"

Each row carries lei and leiStatus ({"entity": "ACTIVE", "registration": "ISSUED"} in the example above), and registryIds lists every id with type, value, confidence and sources (gleif, wikidata, register_no_brreg and so on). When a domain shows more than one LEI, the rows differ in confidence; the GLEIF-sourced one is the safer pick.

Python

import requests

def lei_for_domain(domain: str):
    r = requests.get("https://api.arcadiumdata.io/v1/companies/resolve?domain=" + domain, timeout=30)
    r.raise_for_status()
    best = None
    for row in r.json()["data"]:
        for i in row["registryIds"]:
            if i["type"] == "lei" and (best is None or i["confidence"] > best["confidence"]):
                best = i
    return best

print(lei_for_domain("equinor.com"))

TypeScript

const res = await fetch('https://api.arcadiumdata.io/v1/companies/resolve?id=OW6OFBNCKXC4US5C7523&type=lei');
const body = (await res.json()) as {
  found: boolean;
  data: { domain: string | null; legalName: string | null; leiStatus: { entity: string; registration: string } | null }[];
};
for (const row of body.data) console.log(row.domain, row.legalName, row.leiStatus?.registration);

Two things to keep in mind. First, the answer is stored data: the LEI status is as of the last GLEIF refresh, not live. For a live GLEIF record call the GLEIF API as shown above. Second, we map LEIs to domains for companies we could tie to a website; an LEI without a known site answers found: false, which is a fact about our coverage and not about the LEI.

Agents can use the same lookup through the MCP server. The registration number guide shows the national registers that confirm the ids.

Comparison

GLEIF APIGLEIF golden copyArcadium Data resolve
Best forOne record, name searchBulk loads, relationshipsLEI to website and national ids
KeyNoneNoneNone for the anonymous tier
FreshnessLiveSeveral refreshes a dayStored; GLEIF status as of last refresh
Website or domainNoNoYes, with confidence and sources
National ids and VATRegistration number onlyRegistration number onlyRegistry ids from several sources
Parent and ultimate parentLevel 2 endpointsLevel 2 fileNot provided
LicenceCC0CC0Per source, shown on each dataset

Get the data without the plumbing

Arcadium Data serves these datasets from one REST API and one MCP server, with sources, licences and dates on every answer. No key is needed to try the routes in this guide.

Sources

Last updated 2026-10-25. This guide is ours and independent of the organisations it describes. Found a mistake? Tell us and we correct it.

Questions

Is the GLEIF API free?

Yes. The LEI data is published under CC0 and the API at api.gleif.org needs no key. It has a documented rate limit, so use the golden copy files for bulk work.

How do I check that an LEI is valid?

An LEI has 20 alphanumeric characters and a check value (ISO 7064 MOD 97-10) in the last two. The checksum proves the shape, not that the LEI is current: read the registration status (ISSUED, LAPSED and so on) from GLEIF.

Does GLEIF list a company’s website?

No. The record holds the legal name, addresses, registration authority and registration number. A website has to come from another source; our resolve route returns it with a confidence value.

What does LAPSED mean?

The LEI was not renewed on time. The legal entity may still exist and be active; the identifier is simply no longer maintained.

Can I download all LEIs?

Yes, from the GLEIF golden copy: full files in CSV, JSON and XML with several refreshes a day, plus delta files and a relationship file.

Cite as: Arcadium Data, "LEI lookup: the GLEIF API, the golden copy and how to map an LEI to a website", https://arcadiumdata.io/guides/lei-lookup-gleif-api/, data as of 2026-10-25.