GET /company/ownership

Answers “who controls this counterparty?” from a LEI: the direct parent, the ultimate parent, the dated chain of links between them, and optionally the direct subsidiaries. The answer is served from a local store built from the official GLEIF Level 2 relationship records - the parents entities declare to GLEIF, published under CC0 - with no network call and no secret at request time.

This is what makes sanctions screening actually useful. A French counterparty whose own record is spotless, owned by a designated entity, is exactly the case an endpoint-by-endpoint check walks past. Screening the account tells you about the account; this tells you about the group above it. See the live /catalog for the authoritative endpoint listing and price.

x402 golden rule: the agent pays for the answer to its question. A chain that comes back empty because the entity published a reason for not reporting a parent is a successful answer -> 200 billed. Only requests the service cannot answer - an unknown LEI, a malformed input, a depth out of bounds - leave the 200 range, and they are not billed.

Accounting-consolidation parent ≠ beneficial owner

Read this before using the response. GLEIF Level 2 publishes the accounting consolidation parent - the entity that consolidates this one in its financial statements - and nothing else. It is not the ultimate beneficial owner (UBO) as defined by AML/KYC rules, it carries no ownership percentage (Level 2 publishes none), and the absence of a declared parent is not evidence of an absence of control.

The response says so itself, in a fixed data.limits sentence that is part of the contract. Treating ultimate_parent as a UBO would be selling one piece of data as another - so the service states the distinction rather than letting an integration assume it away.

If you need beneficial ownership, this endpoint is not it, and no endpoint in this catalog claims to be.

Parameters

ParameterTypeRequiredDescription
leistringyes20-character LEI, ISO 17442 check digits verified before any lookup
directionstringnoup (default) · down · both - walk parents, subsidiaries, or both
depthnumberno1-5, default 3 - how many links the upward walk may follow
GET /company/ownership?lei=9695000AHZHGK28ZO963&depth=5
GET /company/ownership?lei=R0MUWSFPU8MPRO8K5P83&direction=down

A depth outside 1..5 is a 400, never a silent clamp: an agent that asked for 7 must know it was not served at 7. An unknown direction is a 400 too.

200 response - UnifiedResponse

{
  "data": { "subject": { ... }, "direct_parent": { ... }, "ultimate_parent": { ... }, "chain": [ ... ], "limits": "..." },
  "provenance": {
    "source": "gleif",
    "fetched_at": "2026-07-29T15:44:09Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
  }
}

Fields of data

FieldTypeDescription
queryobject{ lei, direction, depth } echoed back, defaults resolved
subjectobjectShort identity of the queried entity - same shape as the matches of /company/lei
direct_parentobject{ status, link, exception } - the entity that directly consolidates the subject
ultimate_parentobjectSame shape - the top of the consolidation chain, as declared
chainarrayUpward walk, link by link, bounded by depth; null when direction=down
chain_truncatedboolThe walk stopped on the depth bound while a parent still existed above
cycle_detectedboolAn already-visited LEI cut the walk
direct_childrenarrayEntities declaring the subject as their direct parent, capped at 100; null when direction=up
children_truncatedboolThe cap hid subsidiaries
total_childrennumberExact count of direct subsidiaries; null when not requested
limitsstringThe fixed sentence above - parents are self-declared accounting consolidation, not beneficial ownership

null and [] are different answers. null means “you did not ask for this block”; [] means “you asked, and the reference declares nothing”. An agent must be able to tell those apart, so the service never collapses one into the other.

direct_parent / ultimate_parent

statusMeaningPopulated field
declaredA relationship is publishedlink
reporting_exceptionThe entity published a reason for not reporting a parentexception
not_declaredNeither a relationship nor a published exceptionneither

link and exception are never both populated.

  • link: { lei, entity, relationship_status, period: { start, end } }. The join to the identity record is an outer one: a declared parent whose Level 1 record is absent is served with its LEI and entity: null - the link is published, the record is not, and neither is hidden nor invented.
  • exception: { category, reasons }, carrying the GLEIF reason codes as published - NATURAL_PERSONS, NON_CONSOLIDATING, NO_KNOWN_PERSON, NO_LEI - with no added label, because the Golden Copy publishes none.

A parent in force always wins over a historical one. When several relationships exist, an ACTIVE one beats an INACTIVE one; at equal status, the most recent period, then the LEI. The order never depends on what the storage engine happens to return. The case is real - serving a stale link would name a wrong parent.

Relationship statuses are served as published, including the literal NULL GLEIF publishes on a handful of records.

Example - a bounded control chain

GET /company/ownership?lei=9695000AHZHGK28ZO963&depth=5, against the 2026-07-28 GLEIF snapshot. LE MARQUIS is a Paris property company whose own identity gives away nothing about its owner; the walk goes through CNP Assurances and La Banque Postale up to the Caisse des dépôts et consignations. depth=5 stops one link short of the top - the fact is told (chain_truncated: true), and the ultimate parent is still served because it is declared, not derived from the walk.

{
  "data": {
    "query": { "lei": "9695000AHZHGK28ZO963", "direction": "up", "depth": 5 },
    "subject": {
      "lei": "9695000AHZHGK28ZO963", "legal_name": "LE MARQUIS",
      "legal_jurisdiction": "FR", "legal_country": "FR",
      "entity_status": "ACTIVE", "registration_status": "ISSUED"
    },
    "direct_parent": {
      "status": "declared",
      "link": {
        "lei": "969500B5IW6GWFPJ1347",
        "entity": { "lei": "969500B5IW6GWFPJ1347", "legal_name": "ASSURECUREUIL PIERRE 4",
                    "legal_jurisdiction": "FR", "legal_country": "FR",
                    "entity_status": "ACTIVE", "registration_status": "ISSUED" },
        "relationship_status": "ACTIVE",
        "period": { "start": "2002-12-24", "end": null }
      },
      "exception": null
    },
    "ultimate_parent": {
      "status": "declared",
      "link": {
        "lei": "969500Q2PFTTP0Y5QL44",
        "entity": { "lei": "969500Q2PFTTP0Y5QL44",
                    "legal_name": "CAISSE DES DEPOTS ET CONSIGNATIONS",
                    "legal_jurisdiction": "FR", "legal_country": "FR",
                    "entity_status": "ACTIVE", "registration_status": "ISSUED" },
        "relationship_status": "ACTIVE",
        "period": { "start": "2002-12-24", "end": null }
      },
      "exception": null
    },
    "chain": [
      { "lei": "969500B5IW6GWFPJ1347", "entity": { "legal_name": "ASSURECUREUIL PIERRE 4", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "2002-12-24", "end": null } },
      { "lei": "969500QKVPV2H8UXM738", "entity": { "legal_name": "CNP ASSURANCES", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "1994-10-14", "end": null } },
      { "lei": "9695008OXM90U326XP05", "entity": { "legal_name": "CNP ASSURANCES HOLDING", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "2023-01-01", "end": null } },
      { "lei": "96950066U5XAAIRCPA78", "entity": { "legal_name": "LA BANQUE POSTALE", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "2009-07-25", "end": null } },
      { "lei": "9695000YG7TR7PAP0L59", "entity": { "legal_name": "LA POSTE", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "2005-12-31", "end": null } }
    ],
    "chain_truncated": true,
    "cycle_detected": false,
    "direct_children": null,
    "children_truncated": false,
    "total_children": null,
    "limits": "Relationships are self-declared by the entities to GLEIF and describe accounting consolidation (the parent that consolidates the entity in its financial statements). This is NOT beneficial ownership under AML/KYC rules, and Level 2 publishes no ownership percentage. The absence of a declared parent is not evidence of an absence of control."
  },
  "provenance": {
    "source": "gleif",
    "fetched_at": "2026-07-29T15:44:09Z",
    "freshness": { "kind": "snapshot", "as_of": "2026-07-28T00:00:00Z" }
  }
}

96950066U5XAAIRCPA78 (La Banque Postale) is reachable from /company/lei?bic=: an agent can chain iban/resolve -> company/lei -> company/ownership and end on the same entity.

Example - an absence that is a declaration, not a silence

GET /company/ownership?lei=2138002I6NWA7IG4J251. SOFIGA., a family holding: Level 2 names nobody, but says why. That is exactly where what the LEI reference knows stops - and the agent reads it in the response instead of inferring “no parent” from an empty block.

{
  "data": {
    "query": { "lei": "2138002I6NWA7IG4J251", "direction": "up", "depth": 3 },
    "subject": { "lei": "2138002I6NWA7IG4J251", "legal_name": "SOFIGA.",
                 "legal_jurisdiction": "FR", "legal_country": "FR",
                 "entity_status": "ACTIVE", "registration_status": "LAPSED" },
    "direct_parent": {
      "status": "reporting_exception",
      "link": null,
      "exception": { "category": "DIRECT_ACCOUNTING_CONSOLIDATION_PARENT",
                     "reasons": ["NATURAL_PERSONS"] }
    },
    "ultimate_parent": {
      "status": "reporting_exception",
      "link": null,
      "exception": { "category": "ULTIMATE_ACCOUNTING_CONSOLIDATION_PARENT",
                     "reasons": ["NATURAL_PERSONS"] }
    },
    "chain": [],
    "chain_truncated": false,
    "cycle_detected": false,
    "direct_children": null,
    "total_children": null,
    "limits": "…"
  }
}

NATURAL_PERSONS means the entity is held by individuals, who have no LEI - 1.15M records carry that reason. The subject’s own registration_status: "LAPSED" is served as-is: a diligence signal, not a verdict.

Example - direct subsidiaries, capped and counted

GET /company/ownership?lei=R0MUWSFPU8MPRO8K5P83&direction=down. BNP PARIBAS is a group head with no declared parent (published reason NO_KNOWN_PERSON) and 137 direct subsidiaries at the 2026-07-28 image, of which 100 are served.

{
  "data": {
    "query": { "lei": "R0MUWSFPU8MPRO8K5P83", "direction": "down", "depth": 3 },
    "subject": { "legal_name": "BNP PARIBAS", "…": "…" },
    "direct_parent": {
      "status": "reporting_exception", "link": null,
      "exception": { "category": "DIRECT_ACCOUNTING_CONSOLIDATION_PARENT",
                     "reasons": ["NO_KNOWN_PERSON"] }
    },
    "chain": null,
    "direct_children": [
      { "lei": "2138002Y7Q2J14MAI422",
        "entity": { "legal_name": "BNP PARIBAS FUND ADMINISTRATION SERVICES (IRELAND) LIMITED",
                    "legal_country": "IE", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "2017-05-15", "end": null } },
      { "lei": "21380036SM8RMK9HM241",
        "entity": { "legal_name": "CARDIF COLOMBIA SEGUROS GENERALES S A",
                    "legal_country": "CO", "…": "…" },
        "relationship_status": "ACTIVE", "period": { "start": "2017-07-11", "end": null } }
    ],
    "children_truncated": true,
    "total_children": 137,
    "limits": "…"
  }
}

chain: null (not requested) is not chain: [] (requested, nothing to walk). The distinction is the contract.

Cycles are cut and reported

The upward walk keeps the set of visited LEIs; an already-seen LEI stops it and raises cycle_detected: true. Real consolidation data has no cycle, but nothing in the format forbids one - and an infinite loop on a perfectly valid input would be a 5xx or worse. The guard is a behaviour of the contract, not an implementation detail: if it fires, the agent is told.

What this endpoint will not do

  • No beneficial ownership (UBO), no ownership percentages, no fund relationships - none of them are published in Level 2.
  • No automatic screening of the parents against the sanctions lists. That composition is the job of the /preflight/* composites, not of this route.
  • No multi-level downward org chart - only direct subsidiaries are served, capped at 100 with the exact total.
  • No coverage beyond the LEI reference. An entity without a LEI has no relationship record, and a company whose parents simply never declared has an empty chain. Neither is evidence of anything.

Freshness

Answers come from a snapshot of the GLEIF Golden Copy; freshness.as_of carries its publication date. If a refresh is missed, the last good snapshot keeps being served - honestly dated - and staleness is never turned into a 5xx.

Errors

Only requests the service cannot answer leave the 200 range - none of them are billed.

StatuscodeCase
400MISSING_PARAMETERlei absent
400INVALID_INPUTMalformed lei, depth outside 1..5, unknown direction
400INVALID_CHECKSUMWell-formed LEI failing its ISO 17442 check digits - a probable typo
404NOT_FOUNDWell-formed LEI unknown to the reference; also unknown routes
503DATA_UNAVAILABLEThe GLEIF dataset has not been ingested yet
500INTERNALInternal error (detail logged, not exposed)

An empty chain, a parent that is not declared and an empty subsidiary list are answers (“the reference declares nothing on this”), not errors, and they are served as billed 200s.

The 404 message is shared with /company/lei: the same key cannot exist for one route and not the other.

Attribution

Relationship data comes from the GLEIF Level 2 Golden Copy (relationship records and reporting exceptions), published under CC0 1.0 - no account, no key, no attribution requirement, redistributable.

See also

  • GET /company/lei - the legal identity behind a LEI, BIC, ISIN, SIREN or exact name plus country.
  • GET /company/report - the counterparty due-diligence report by SIREN, which carries the ultimate parent alongside identity, BODACC events, VAT and Peppol.
  • GET /iban/screen - OFAC/EU/UN sanctions screening on the counterparty’s bank account, the check this one completes.
  • For agents - discovery surfaces, the live /catalog and how settlement works.