Entity Resolution With LEI: A GLEIF Lookup API for Counterparty KYC and Ownership Trees

"Apple Inc.", "Apple, Inc." and "APPLE INC" are three strings and one company. The LEI is a 20-character code that says so unambiguously, in every jurisdiction, and the data is public domain.
TL;DR
- •An LEI is a 20-character ISO 17442 code identifying one legal entity worldwide. Unlike a company name it is unambiguous; unlike a national register number it does not collide across jurisdictions.
- •GLEIF publishes the entire register under CC0 — public domain, no attribution required, no restriction on downstream use. That is rare for entity data and it is the reason this endpoint can exist.
- •Look up by LEI code for an exact record, or search by legal name when you only have a messy CRM string. Name search is relevance-ranked, not exact, so total_matches can be large.
- •registered_as carries the entity's number in its national company register — the bridge from a global identifier to local statutory filings.
- •Level 2 data gives direct parent, ultimate parent, and subsidiary count, each parent identified by its own LEI so you can walk the ownership tree upward or downward.
The join key problem
Every company that has ever tried to reconcile two systems knows this one. Your CRM says Apple Inc., the invoice says Apple, Inc., the sanctions screen says APPLE INC, and the contract says Apple Operations Europe, which is a different legal entity entirely. Fuzzy matching gets you most of the way and then produces a false positive that matters.
The Legal Entity Identifier exists to end this. It is a 20-character code, defined by ISO 17442, that identifies exactly one legal entity anywhere in the world. Anyone trading on regulated financial markets is required to have one, which means coverage of serious counterparties is high.
The part that makes it usable for the rest of us: GLEIF publishes the entire register under CC0 — public domain, no attribution, no restriction on downstream use. That is close to unheard of for entity data.
Two ways in
You have the code
curl "https://www.apipick.com/api/lei-lookup?lei=HWUPKR0MPOU8FGXBT394" \
-H "x-api-key: $APIPICK_KEY"
{
"mode": "lei",
"found": true,
"record": {
"lei": "HWUPKR0MPOU8FGXBT394",
"legal_name": "Apple Inc.",
"other_names": ["Apple Computer, Inc."],
"jurisdiction": "US-CA",
"legal_form": "H1UM",
"entity_status": "ACTIVE",
"registered_as": "806592",
"bic": ["APLEUS66XXX"],
"registration_status": "ISSUED",
"next_renewal_date": "2027-03-08T17:27:20Z",
"headquarters_address": { "city": "Cupertino", "region": "US-CA", ... }
}
}Two fields deserve attention. other_names carries previous legal names, which is how you match a contract signed under a name the company no longer uses. registered_as is the entity's number in its national company register — the bridge from a global identifier to local statutory filings.
You only have a messy string
Pass name instead, optionally narrowed by country.
GET /api/lei-lookup?name=Tesla,%20Inc.&country=US&limit=3
{
"mode": "search",
"total_matches": 43128,
"returned": 3,
"records": [
{ "lei": "54930043XZGB27CTOV49", "legal_name": "TESLA, INC.", ... },
{ "lei": "549300LFXY1VG8DI7B68", "legal_name": "Tesla General Insurance, Inc.", ... },
...
]
}Walking the ownership tree
Add include_relationships=true and you get GLEIF Level 2 data: direct parent, ultimate parent, and a count of direct subsidiaries. Because each parent comes back with its own LEI, walking upward is just another call.
import httpx, os
H = {"x-api-key": os.environ["APIPICK_KEY"]}
URL = "https://www.apipick.com/api/lei-lookup"
def climb(lei, depth=5):
"""Walk from an entity up to its ultimate parent."""
chain = []
for _ in range(depth):
r = httpx.get(URL, params={"lei": lei, "include_relationships": "true"},
headers=H).json()
if not r["found"]:
break
chain.append(r["record"]["legal_name"])
parent = r.get("relationships", {}).get("direct_parent")
if not parent:
break
lei = parent["lei"]
return chain
# ['APPLE OPERATIONS INDIA PRIVATE LIMITED', 'Apple Inc.']This is the question that matters before you extend credit or sign: not "who am I contracting with" but "who ultimately controls the entity I am contracting with." A subsidiary with a thin balance sheet and a parent with a strong one is a different deal from the same subsidiary standing alone.
Where it fits in an onboarding stack
These three answer different questions and are worth combining rather than choosing between:
- LEI — who is this entity, officially, and who owns it. Global, CC0.
- EU VAT — is this business registered for cross-border trade in the EU. Authoritative, but EU-only and says nothing about identity beyond a name.
- Company Facts — SEC filings and financials for US public companies.
A reasonable onboarding flow resolves the LEI first to fix the identity, then validates the VAT number for the tax treatment, then pulls financials if the counterparty is public.
Signals people miss
registration_status is not decoration. An LEI must be renewed annually, and a LAPSED status usually means the entity stopped trading in regulated markets or stopped paying attention — either of which is worth knowing before a large contract. entity_status: INACTIVE is stronger still: the entity has been dissolved or absorbed, and successorEntity often names what it became.
Build vs. call
| GLEIF API directly | Commercial vendor | API Pick | |
|---|---|---|---|
| Data licence | CC0 public domain | Redistribution terms | CC0 public domain |
| Response shape | JSON:API, 3 levels deep | Varies | Flat objects |
| Missing record | 404 as an HTML page | Varies | 200 with found:false |
| Ownership links | Separate endpoints per relation | Usually paid tier | One flag |
| Cost | Free + the plumbing | Per-seat or per-query | 3 credits/call |
GLEIF's own API is free and the data is identical — this is the same register either way. What you take on directly is JSON:API nesting, a 404 that arrives as an HTML error page rather than JSON, and separate endpoints for each relationship type.
Source and licensing
Records come from GLEIF, the Global Legal Entity Identifier Foundation, which maintains the LEI register on behalf of the Regulatory Oversight Committee. Level 1 reference data and Level 2 ownership data are both published under CC0. Three credits a call, charged only on success; a free key comes with 100 credits and no card.
Frequently Asked Questions
What is an LEI and why use it as a join key?
A Legal Entity Identifier is a 20-character code defined by ISO 17442 that identifies a single legal entity anywhere in the world. Anyone trading on regulated financial markets is required to have one. It beats a company name because names are ambiguous, change, and collide; it beats a national register number because those repeat across jurisdictions — a company number in Delaware and one in Ireland can be identical integers meaning entirely different companies. The LEI is globally unique, which is what a join key has to be.
Can I search if I only have a company name?
Yes. Pass name instead of lei to search the register by legal name, optionally narrowed with a country code. Be aware that GLEIF's name filter is a relevance match rather than an exact one, so total_matches can run into the tens of thousands for a common word. The returned records are the ranked head of that list, so treat the top hit as a candidate to confirm rather than a definitive answer.
How do I get a corporate ownership tree?
Add include_relationships=true to a lookup by LEI. You get the direct parent, the ultimate parent, and a count of direct subsidiaries. Each parent is identified by its own LEI, so you can issue further calls to walk the tree in either direction. This is GLEIF Level 2 data, self-reported by the entity under the 'who owns whom' reporting obligation.
How current is the register?
GLEIF publishes a new golden copy daily, and this endpoint queries their live API rather than a local snapshot. Entities must renew their LEI annually, so registration_status and next_renewal_date tell you whether a record is actively maintained or has lapsed. A LAPSED status is itself a useful signal — it often means the entity stopped trading in regulated markets, or stopped paying attention.
Is the data really free to redistribute?
Yes. GLEIF publishes both Level 1 reference data and Level 2 ownership data under CC0, placing it in the public domain with no attribution requirement and no restriction on downstream use. That is genuinely unusual for entity data — the same lookup from a commercial vendor normally arrives with redistribution terms attached — and it is the reason a low-cost endpoint over this data is possible at all.
APIs used in this article
Sarah Choy is the CEO of API Pick. She writes about building production-ready APIs for AI agents and LLM workflows.