# Legal Entity & LEI API (GLEIF) — verified company and legal-entity records, fuzzy company search, corporate ownership hierarchy and ISIN/BIC/MIC-to-LEI mapping

> One LEI → the full verified legal-entity record (Level-1 who-is-who): legal name, addresses, jurisdiction, legal form, registration status + honesty note, authority ids, renewal dates, BIC/ISIN-adjacent identifiers.
> ReefAPI engine `lei` · 7 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/lei/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed or blocked calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http, `Authorization: Bearer <key>`) and your assistant can call these actions directly.

## Endpoints

### POST /lei/v1/lookup — 1 credit
One LEI → the full verified legal-entity record (Level-1 who-is-who): legal name, addresses, jurisdiction, legal form, registration status + honesty note, authority ids, renewal dates, BIC/ISIN-adjacent identifiers.

**Parameters:**
- `lei` (string, required) — The 20-character Legal Entity Identifier (ISO 17442). Spaces/dashes are ignored; case-insensitive. Format + MOD-97-10 checksum are validated offline first — a malformed LEI returns a clean error with the reason, never an upstream call.
- `resolve_codes` (boolean, optional, default false) — If true, also resolve the legal-form ELF code and registration-authority code to their human-readable names (2 extra cached GLEIF calls; silently skipped if unavailable).
- `history` (boolean, optional, default false) — If true, append the record's field-modification audit trail (what changed, when, old/new value) — GLEIF Level-1 history.

**Returns:** entity{lei, legal_name, other_names[], entity_status, jurisdiction, category, legal_form{code,name?}, legal_address{}, hq_address{}, registration{status, status_note, authority_id, entity_id_at_authority, initial, last_update, next_renewal, managing_lou, corroboration_level}, expiration, successor, bic[], mic, spglobal[], conformity_flag} (+ field_modifications[] when history=true)

**Example request body:**
```json
{
  "lei": "HWUPKR0MPOU8FGXBT394"
}
```

### POST /lei/v1/search — 1 credit
Company name → ranked candidate entities with match_confidence for disambiguation (same-name entities across countries/legal-forms). Filters: country, status, jurisdiction, entity_status.

**Parameters:**
- `name` (string, required) — Company/entity name to search for. Matching is word-based on the GLEIF data pool; results are ranked by `match_confidence` (an explicit string-similarity heuristic) so same-name entities in different countries/forms are easy to disambiguate.
- `scope` (enum, optional, default "auto") — Which name surface to search. `auto` (default) queries BOTH the fulltext and the legal-name surface and merges by LEI — GLEIF's fulltext relevance alone can bury an exact legal-name match below the page cut. `fulltext` also matches former and transliterated names; `name` is strict legal-name matching. [one of: auto, fulltext, name]
- `country` (string, optional) — Filter by the entity's legal-address country (ISO-3166 alpha-2, e.g. US, DE).
- `status` (string, optional) — Filter by registration status (case-insensitive). Common values: ISSUED, LAPSED, RETIRED, ANNULLED, MERGED, DUPLICATE, PENDING_TRANSFER, PENDING_ARCHIVAL. NOTE: LAPSED only means the record's re-certification is overdue — not that the company is gone.
- `entity_status` (string, optional) — Filter by entity status: ACTIVE or INACTIVE (INACTIVE = the legal entity itself ceased to exist; different axis than `status`).
- `jurisdiction` (string, optional) — Filter by legal jurisdiction (ISO-3166 code, may include region subdivisions like US-DE for Delaware).
- `limit` (integer, optional, default 20) — Max results to return (1-200; GLEIF page cap is 200).
- `page` (integer, optional, default 1) — Result page number (1-based).
- `min_confidence` (number, optional) — Drop candidates whose match_confidence is below this 0-1 threshold.
- `typo` (boolean, optional, default true) — When the name has NO exact matches, attempt typo-recovery: probe GLEIF autocompletions with bounded misspelling-candidates and re-run the search on the best correction (did_you_mean). Recovers common typos (gogle→Google, deutsche bnk→Deutsche Bank); best-effort, never blocks an exact-match query. Set false to skip.

**Returns:** candidates[]{lei, legal_name, match_confidence, jurisdiction, entity_status, registration_status, status_note, city, country, legal_form_code}, count, total (full GLEIF match count), page, confidence_note, did_you_mean + typo_recovered (when a zero-result query was recovered from a misspelling)

**Example request body:**
```json
{
  "name": "Apple Inc",
  "country": "US"
}
```

### POST /lei/v1/autocomplete — 1 credit
Type-ahead suggestions for a partial company name (GLEIF autocompletions surface) — each suggestion carries its LEI for direct lookup.

**Parameters:**
- `name` (string, required) — Partial name (min 2 chars) to complete.

**Returns:** suggestions[]{value, highlighted, lei}, count

**Example request body:**
```json
{
  "name": "apple"
}
```

### POST /lei/v1/relationships — 2 credits
One LEI → Level-2 corporate hierarchy: direct & ultimate parent (entity OR the entity's declared reporting-exception with reason+meaning OR no_data), children list + total counts. detail=true adds the auditable relationship provenance.

**Parameters:**
- `lei` (string, required) — The 20-character Legal Entity Identifier (ISO 17442). Spaces/dashes are ignored; case-insensitive. Format + MOD-97-10 checksum are validated offline first — a malformed LEI returns a clean error with the reason, never an upstream call.
- `children_limit` (integer, optional, default 50) — Max direct/ultimate children to list (0-200). The TOTAL count is always returned in children_total regardless of this cap.
- `detail` (boolean, optional, default false) — If true, include the raw relationship-record provenance for each parent link (valid_from, accounting periods, corroboration level/documents) — the auditable Level-2 trail.

**Returns:** lei, direct_parent{type: entity|reporting_exception|no_data, ...record|reason+meaning}, ultimate_parent{same}, direct_children[]/ultimate_children[]{lei, legal_name, country, registration_status} (capped at children_limit), direct_children_total, ultimate_children_total (+ direct_parent.provenance/ultimate_parent.provenance when detail=true)

**Example request body:**
```json
{
  "lei": "5493006MHB84DD0ZWV18"
}
```

### POST /lei/v1/map — 1 credit
Identifier mapping: ISIN / BIC / MIC / QCC / S&P-Global-ID → LEI record(s), or reverse LEI → all its ISINs.

**Parameters:**
- `type` (enum, required) — Which identifier system to map. isin/bic/mic/qcc/spglobal map TO LEI records; lei_to_isin maps an LEI to its issued ISINs. [one of: isin, bic, mic, qcc, spglobal, lei_to_isin]
- `value` (string, required) — The identifier to map: an ISIN (e.g. US0378331005), BIC (e.g. DEUTDEFFXXX), MIC, QCC, S&P Global ID — or the LEI itself for type=lei_to_isin.
- `limit` (integer, optional, default 10) — Max results to return (1-200; GLEIF page cap is 200).

**Returns:** type, value, entities[]{lei, legal_name, jurisdiction, registration_status, bic[], ...} for *→LEI types; isins[] + count for type=lei_to_isin

**Example request body:**
```json
{
  "type": "isin",
  "value": "US0378331005"
}
```

### POST /lei/v1/reference — 1 credit
GLEIF reference collections: ISO-20275 legal forms, registration authorities, LEI issuers (LOUs), jurisdictions, countries, regions, field catalog — list or fetch one by code.

**Parameters:**
- `kind` (enum, required) — Which reference list to query. All are GLEIF live except 'mic', which is served from the embedded ISO 10383 registry snapshot. [one of: legal-forms, registration-authorities, lei-issuers, jurisdictions, countries, regions, fields, mic]
- `code` (string, optional) — Optional: fetch ONE reference item by its code/id (e.g. ELF code '8888', RA code 'RA000602', LOU LEI). Omit to list.
- `limit` (integer, optional, default 50) — Max results to return (1-200; GLEIF page cap is 200).
- `page` (integer, optional, default 1) — Result page number (1-based).

**Returns:** kind, items[] (raw GLEIF attributes per item, id included), count, total — or item{} when code= is given

**Example request body:**
```json
{
  "kind": "legal-forms"
}
```

### POST /lei/v1/batch — 2 credits
Up to 50 mixed lookup/search items in one call. Lookups are collapsed into one upstream request per 50 LEIs (GLEIF rate-friendly); searches are spaced.

**Parameters:**
- `items` (array, required) — Up to 50 items. Each is {type: lookup|search, ...}: lookup items carry `lei`; search items carry `name` (+ optional `country`). Lookups are collapsed into ONE upstream call per 50 LEIs (rate-friendly); searches run sequentially, spaced. A bad item yields its own error entry — it never fails the batch.

**Returns:** count, ok_count, results[] (each: {type, ok, entity|candidates|error, input echo}) in input order

**Example request body:**
```json
{
  "items": [
    {
      "type": "lookup",
      "lei": "HWUPKR0MPOU8FGXBT394"
    },
    {
      "type": "search",
      "name": "Deutsche Bank",
      "country": "DE"
    }
  ]
}
```

## More
- Try it live, no code: https://reefapi.com/playground?engine=lei
- Human docs page: https://reefapi.com/docs/lei
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
