GET /company/lei
Resolves a company anywhere in the world into its official legal identity: legal name, jurisdiction, legal form, entity and registration status, legal and headquarters addresses, national registration number, and the market identifiers (BIC, ISIN) mapped to it. The answer is served from a local store built from the official GLEIF LEI reference - the global, public (CC0) identity register overseen by the LEI ROC - so a lookup resolves in milliseconds with no network call and no secret at request time.
This is the route that takes the Company family out of France.
GET /company/resolve answers on French legal
units from the INSEE Sirene register; this one answers on a German, Irish,
Colombian or Japanese counterparty just as well, and accepts the keys an agent
actually holds: a LEI, a BIC taken off an IBAN, an ISIN from a
security, a French SIREN, or an exact name plus country. See the live
/catalog for the authoritative endpoint listing and
price.
x402 golden rule: the agent pays for the answer to its question. An
entity found in the reference is a successful answer -> 200 billed, even
when its registration has lapsed - registration.status: "LAPSED" is the
diligence signal the agent came for. Requests the service cannot answer - a
key unknown to the reference, a malformed one, a failed check digit - leave the
200 range and are not billed.
Parameters
Exactly one key, as a query parameter (name and country count as one).
Zero keys, or two, is a 400 INVALID_INPUT. Input is trimmed and upper-cased
before validation: GLEIF publishes identifiers in upper case, an agent holds
whatever form it received.
| Parameter | Type | Required | Description |
|---|---|---|---|
lei | string | one key | 20-character LEI, ISO 17442 check digits verified |
bic | string | one key | 8- or 11-character BIC (ISO 9362 has no check digit - form only) |
isin | string | one key | 12-character ISIN, Luhn check digit verified |
siren | string | one key | 9-digit French SIREN, Luhn check digit verified - the SIREN-to-LEI bridge |
name | string | with country | Company name - exact normalized match only, never fuzzy |
country | string | with name | ISO 3166-1 alpha-2 country code |
GET /company/lei?lei=529900S21EQ1BO4ESM68
GET /company/lei?bic=BSUIFRPP
GET /company/lei?isin=DE0007164600
GET /company/lei?siren=542051180
GET /company/lei?name=SAP%20SE&country=DE
A key whose form is wrong (length, characters, a country that is not
alpha-2) is a 400 INVALID_INPUT. A well-formed key whose check digit
fails is a distinct 400 INVALID_CHECKSUM: it is almost certainly a typo, and
the agent should fix its input rather than conclude the entity does not exist.
bic: the IBAN -> BIC -> LEI bridge
The GLEIF BIC mapping only publishes BIC-11. An agent that holds the
BIC-8 of an IBAN must find the same entity, so the lookup queries both
forms: ?bic=BSUIFRPP resolves through the mapped BSUIFRPPXXX. That is what
makes the chain GET /iban/resolve ->
GET /company/lei?bic= -> GET /company/ownership
real: from a bank account to the entity behind it to who consolidates it.
siren: the bridge is derived at ingest, never guessed
GLEIF publishes, for each entity, a national registration authority and a self-declared, messy registration number. The SIREN bridge applies three rules and nothing else:
- authority gate - only
RA000189(Sirene) andRA000192(RCS, whose number is the SIREN) are bridged. The French fund register (RA000190, AMF) is excluded: its numbers are fund codes. French entities registered with another authority whose number merely looks like a SIREN are not bridged - a Luhn coincidence is not a declaration; - separators stripped, then 9 digits with a valid Luhn -> SIREN;
- 14 digits whose first 9 form a valid SIREN -> that prefix (a SIRET declared in place of the SIREN; the prefix is the SIREN).
Anything else is rejected and counted, never silently dropped. At the 2026-07-28 image: 169,226 links for 169,049 distinct SIREN, 26 numbers rejected out of 169,252 candidates (0.015%).
200 response - UnifiedResponse
{
"data": { "query": { ... }, "entity": { ... }, "matches": [], "total_matches": 1 },
"provenance": {
"source": "gleif",
"fetched_at": "2026-07-29T15:44:04Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
}
}
provenance.source:gleif, the served LEI reference.freshness.kind:snapshot;as_ofis the publication date of the GLEIF Golden Copy that backed the answer.
Fields of data
| Field | Type | Description |
|---|---|---|
query | object | The key that was used, echoed back - { key, value } (+ country for a name lookup) |
entity | object | The resolved entity - null when the key is ambiguous (see below) |
matches | array | Short identity of every candidate when the key is ambiguous, capped at 10; [] otherwise |
total_matches | number | Exact number of entities the key designates - always served |
Exactly one of entity / matches is populated. total_matches is always
told, so an agent knows whether the cap hid anything.
Fields of entity
| Field | Type | Description |
|---|---|---|
lei | string | The 20-character LEI |
legal_name | string | Legal name as published to GLEIF |
other_names | array | { name, type } - trading, transliterated or previous names; [] when none |
legal_form | string | ELF code (ISO 20275) as published - GLEIF publishes no label, so none is invented |
legal_jurisdiction | string | ISO 3166 jurisdiction of incorporation |
entity_status | string | ACTIVE, INACTIVE, or the literal NULL GLEIF publishes on some records |
entity_category | string | GLEIF entity category (GENERAL, BRANCH, FUND, SOLE_PROPRIETOR…); null when unpublished |
registration | object | { status, initial_registration_date, last_update_date, next_renewal_date, managing_lou } |
legal_address | object | { country, region, city, postal_code, line } |
headquarters_address | object | Same shape - may differ from the legal address |
registration_authority | object | { ra_code, registration_number } (+ siren, verified_against_sirene when bridged) |
identifiers | object | { bics, bics_total, isins, isins_total } - lists capped at 20, totals exact |
The national registration_number is served exactly as GLEIF publishes it,
spaces included (542 051 180 for TotalEnergies). Its normalized form lives
beside it in registration_authority.siren, never in its place.
verified_against_sirene - three states, not two
For a bridged French entity, the derived SIREN is cross-checked at ingest against the served Sirene register:
true- the SIREN exists in the register;false- GLEIF declares a SIREN that does not exist. The declaration is served with its flag and never corrected. It earns its keep on a real case: overseas entities registered under the Sirene authority that declare their RIDET number, which is 9 digits and passes Luhn by coincidence. No form rule tells them apart from a SIREN - only the register does;null- not verified (no Sirene stock in the store at build time). Servingfalsehere would assert a non-existence nobody observed.
At the 2026-07-28 image: 168,871 links verified, 178 pointing at a SIREN absent from the register.
Status is a fact, never a verdict
| Field | Closed set |
|---|---|
entity_status | ACTIVE · INACTIVE · the literal NULL GLEIF publishes on ~9k records |
registration.status | ISSUED · LAPSED · RETIRED · DUPLICATE · ANNULLED · PENDING_TRANSFER · PENDING_ARCHIVAL |
Both are served as published, with no editorial comment. A LAPSED LEI - a
registration the entity did not renew - is a diligence signal the agent
interprets, not a judgement the service passes. There is no risk score here,
and there never will be.
Example - a listed French company, resolved by LEI
GET /company/lei?lei=529900S21EQ1BO4ESM68, against the 2026-07-28 GLEIF
snapshot:
{
"data": {
"query": { "key": "lei", "value": "529900S21EQ1BO4ESM68" },
"entity": {
"lei": "529900S21EQ1BO4ESM68",
"legal_name": "TotalEnergies SE",
"other_names": [],
"legal_form": "TPNT",
"legal_jurisdiction": "FR",
"entity_status": "ACTIVE",
"entity_category": "GENERAL",
"registration": {
"status": "ISSUED",
"initial_registration_date": "2016-11-11",
"last_update_date": "2025-10-28",
"next_renewal_date": "2026-12-12",
"managing_lou": "5299000J2N45DDNE4Y28"
},
"legal_address": {
"country": "FR",
"region": "FR-IDF",
"city": "Courbevoie",
"postal_code": "92400",
"line": "2 Place Jean Millier - La Défense 6"
},
"headquarters_address": {
"country": "FR",
"region": "FR-IDF",
"city": "Courbevoie",
"postal_code": "92400",
"line": "2 Place Jean Millier - La Défense 6"
},
"registration_authority": {
"ra_code": "RA000192",
"registration_number": "542 051 180",
"siren": "542051180",
"verified_against_sirene": true
},
"identifiers": {
"bics": [],
"bics_total": 0,
"isins": [
"FR0000120271",
"FR0000CR5295",
"FR0000CR6103",
"FR0010314021",
"US89151E1091"
],
"isins_total": 5
}
},
"matches": [],
"total_matches": 1
},
"provenance": {
"source": "gleif",
"fetched_at": "2026-07-29T15:44:04Z",
"freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
}
}
Example - a non-French counterparty, by exact name and country
GET /company/lei?name=SAP%20SE&country=DE (extract):
{
"query": { "key": "name", "value": "sap se", "country": "DE" },
"entity": {
"lei": "529900D6BF99LW9R2E68",
"legal_name": "SAP SE",
"legal_form": "SGST",
"legal_jurisdiction": "DE",
"entity_status": "ACTIVE",
"registration": { "status": "ISSUED", "next_renewal_date": "2027-01-27", "…": "…" },
"legal_address": {
"country": "DE", "region": "DE-BW", "city": "Walldorf",
"postal_code": "69190", "line": "Dietmar-Hopp-Allee 16"
},
"registration_authority": { "ra_code": "RA000296", "registration_number": "HRB 719915" },
"identifiers": { "bics": ["SAPDDEFFXXX"], "bics_total": 1, "isins": ["DE0007164600", "…"], "isins_total": 10 }
},
"total_matches": 1
}
query.value echoes the normalized name (sap se): that is the key that
was actually looked up, and it is why an accented or punctuated input matches
(Société Générale -> societe generale). Note the absence of siren and
verified_against_sirene on a German entity - the bridge only applies to the
French registration authorities.
An ambiguous key returns the ambiguity, never a pick
Several entities can share the same normalized name in one country, and a BIC
or a SIREN can point at more than one registration. The service then serves
entity: null, the candidates in matches (capped at 10) and the
exact total_matches. It never picks one for you.
GET /company/lei?name=Victoire&country=FR (extract):
{
"query": { "key": "name", "value": "victoire", "country": "FR" },
"entity": null,
"matches": [
{ "lei": "9695003FOBCTRX2HMC63", "legal_name": "VICTOIRE",
"legal_jurisdiction": "FR", "legal_country": "FR",
"entity_status": "ACTIVE", "registration_status": "ISSUED" },
{ "lei": "969500M534WKMOFRE728", "legal_name": "VICTOIRE",
"legal_jurisdiction": "FR", "legal_country": "FR",
"entity_status": "ACTIVE", "registration_status": "LAPSED" },
"… 4 more …"
],
"total_matches": 6
}
Six VICTOIRE in France at the 2026-07-28 image. An agent that receives one
arbitrarily chosen entity has been handed a fact it cannot audit; an agent that
receives six knows it must narrow its key.
What this endpoint will not do
The limits are part of the contract, not a footnote:
- No fuzzy name search.
nameis an exact match after normalization (accents folded, case and punctuation removed). “Close enough” would be a guess with an official register’s authority behind it. - No search without a country, no search by address.
- No beneficial ownership. The LEI reference publishes the accounting
consolidation parent, never the ultimate beneficial owner under AML/KYC
rules - see
GET /company/ownership, where that distinction is spelled out. - No financials, no scoring, no invented labels.
legal_formis the raw ELF code because GLEIF publishes no label for it. - No LEI issuance or renewal. This is a read-only reference.
Coverage and freshness
The reference covers 3.3M+ entities across every jurisdiction and is
refreshed from the GLEIF Golden Copy; freshness.as_of carries the publication
date of the image that backed the answer. If a refresh is missed, the service
keeps serving the last good snapshot - honestly dated by as_of - and never
turns staleness into a 5xx.
Coverage is a register’s coverage, not the world’s: an entity only has a LEI if
it obtained one, typically because it trades on financial markets or reports
under regulations that require it. A small French company has no reason to
appear here, and its absence says nothing about it - that is what
GET /company/resolve is for.
Errors
Only requests the service cannot answer leave the 200 range - none of them are billed.
| Status | code | Case |
|---|---|---|
| 400 | INVALID_INPUT | Zero or two keys, name without country (or the reverse), malformed key, non alpha-2 country |
| 400 | INVALID_CHECKSUM | Well-formed key failing its check digits (LEI ISO 17442, ISIN Luhn, SIREN Luhn) - a probable typo |
| 404 | NOT_FOUND | Well-formed key unknown to the reference; also unknown routes |
| 503 | DATA_UNAVAILABLE | The GLEIF dataset has not been ingested yet; or siren= on an image predating the SIREN bridge |
| 500 | INTERNAL | Internal error (detail logged, not exposed) |
{ "error": "no entity found for this key in the GLEIF LEI reference", "code": "NOT_FOUND" }
{ "error": "lei failed its ISO 17442 check digits: likely a typo", "code": "INVALID_CHECKSUM" }
That last 503 deserves a word: an image published before the SIREN bridge
carries no bridge table. Answering 404 would assert “this SIREN has no LEI”
when the service has no means to say so. It serves an explicit, unbilled
unavailability instead, and the four other keys keep working.
Unlike GET /company/peppol, there is no
200 reachable: false equivalent here: the absence of a LEI is not a published
fact, it is the absence of a record.
Attribution
Legal-entity identity data comes from the GLEIF (Global Legal Entity Identifier Foundation) Level 1 Golden Copy, published under CC0 1.0 - no account, no key, no attribution requirement, redistributable.
See also
GET /company/ownership- who consolidates this entity: direct parent, ultimate parent, direct subsidiaries.GET /company/resolve- the French identity card behind a SIREN/SIRET, from the INSEE Sirene register.GET /company/report- the full counterparty due-diligence report by SIREN, in one settlement.GET /iban/resolve- the BIC behind an IBAN, the first link of the IBAN -> BIC -> LEI chain.- For agents - discovery surfaces, the live
/catalogand how settlement works.