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.

ParameterTypeRequiredDescription
leistringone key20-character LEI, ISO 17442 check digits verified
bicstringone key8- or 11-character BIC (ISO 9362 has no check digit - form only)
isinstringone key12-character ISIN, Luhn check digit verified
sirenstringone key9-digit French SIREN, Luhn check digit verified - the SIREN-to-LEI bridge
namestringwith countryCompany name - exact normalized match only, never fuzzy
countrystringwith nameISO 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:

  1. authority gate - only RA000189 (Sirene) and RA000192 (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;
  2. separators stripped, then 9 digits with a valid Luhn -> SIREN;
  3. 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_of is the publication date of the GLEIF Golden Copy that backed the answer.

Fields of data

FieldTypeDescription
queryobjectThe key that was used, echoed back - { key, value } (+ country for a name lookup)
entityobjectThe resolved entity - null when the key is ambiguous (see below)
matchesarrayShort identity of every candidate when the key is ambiguous, capped at 10; [] otherwise
total_matchesnumberExact 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

FieldTypeDescription
leistringThe 20-character LEI
legal_namestringLegal name as published to GLEIF
other_namesarray{ name, type } - trading, transliterated or previous names; [] when none
legal_formstringELF code (ISO 20275) as published - GLEIF publishes no label, so none is invented
legal_jurisdictionstringISO 3166 jurisdiction of incorporation
entity_statusstringACTIVE, INACTIVE, or the literal NULL GLEIF publishes on some records
entity_categorystringGLEIF entity category (GENERAL, BRANCH, FUND, SOLE_PROPRIETOR…); null when unpublished
registrationobject{ status, initial_registration_date, last_update_date, next_renewal_date, managing_lou }
legal_addressobject{ country, region, city, postal_code, line }
headquarters_addressobjectSame shape - may differ from the legal address
registration_authorityobject{ ra_code, registration_number } (+ siren, verified_against_sirene when bridged)
identifiersobject{ 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). Serving false here 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

FieldClosed set
entity_statusACTIVE · INACTIVE · the literal NULL GLEIF publishes on ~9k records
registration.statusISSUED · 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. name is 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_form is 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.

StatuscodeCase
400INVALID_INPUTZero or two keys, name without country (or the reverse), malformed key, non alpha-2 country
400INVALID_CHECKSUMWell-formed key failing its check digits (LEI ISO 17442, ISIN Luhn, SIREN Luhn) - a probable typo
404NOT_FOUNDWell-formed key unknown to the reference; also unknown routes
503DATA_UNAVAILABLEThe GLEIF dataset has not been ingested yet; or siren= on an image predating the SIREN bridge
500INTERNALInternal 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 /catalog and how settlement works.