# Company Registry Intelligence - GLEIF LEI + Wikidata (`darknezz/company-registry-intelligence`) Actor

Resolve a company legal name or LEI to hard registry facts from the open GLEIF LEI API - legal name, jurisdiction, legal form, registration authority, addresses, status and last legal event - enriched with Wikidata website, country, HQ and industry. No API key.

- **URL**: https://apify.com/darknezz/company-registry-intelligence.md
- **Developed by:** [Oaida Adrian](https://apify.com/darknezz) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 company record extracteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Company Registry Intelligence — GLEIF LEI + Wikidata

Resolve a company **legal name** (or a known **LEI code**) to hard, citable registry facts: legal name and other names, LEI, jurisdiction, legal form, registration authority and registration number, registered + headquarters address, entity and registration status, corroboration level, the last recorded legal event, and successor entity — enriched with **Wikidata** statements (official website, country, headquarters, industry, inception, employees, stock exchange).

Built for KYC/onboarding research, vendor due-diligence, CRM and data-warehouse enrichment, counterparty screening and agentic pipelines that need *identifiers and registry facts* rather than a marketing page.

### Why this Actor

Firmographic charts (Crunchbase-style) are gated, rate-limited and hostile to automation. The **GLEIF LEI registry** is the global, open, machine-readable alternative: it is the authoritative source for the Legal Entity Identifier used in payments, securities and regulatory reporting, it needs **no API key**, and it exposes precisely the facts a diligence workflow has to cite. **Wikidata** then fills the human-readable layer (website, HQ, industry) under a CC0 licence.

Both sources were feasibility-probed from Apify datacenter IPs before this Actor was built — no proxy, no credentials:

| Probe target | Result |
|---|---|
| `api.gleif.org` — `filter[entity.legalName]` | 200, real LEI records |
| `api.gleif.org` — record by LEI | 200 |
| `api.gleif.org` — `fuzzycompletions` | 200 |
| `www.wikidata.org/w/api.php` — search + entities | 200 |
| (`searchapi.io`, Crunchbase, G2, Quora) | **Cloudflare / 502 — retired, not used here** |

### What it does

1. Resolves each **legal name** against the GLEIF registry (`filter[entity.legalName]`, exact), with an automatic **full-text fallback** when the exact filter returns nothing.
2. Fetches **LEI codes** directly, skipping the search step entirely.
3. Applies optional **jurisdiction / category / active-only filters**.
4. Maps each LEI record into a flat, spreadsheet- and warehouse-friendly row (addresses flattened, dates ISO-8601, the most recent legal event hoisted to `lastLegalEvent`).
5. **Enriches the top N records from Wikidata**: official website, country, headquarters, industry, legal form, stock exchange, inception date, employee count — with QIDs *and* resolved English labels.
6. Reports near-miss legal names (`fuzzycompletions`) under the run's `SUMMARY` key-value record when a name resolves to nothing.

### Input

```json
{
  "legalNames": ["Stripe", "Siemens AG"],
  "leis": [],
  "maxResultsPerQuery": 5,
  "matchMode": "legalName",
  "fallbackToFulltext": true,
  "enrichWithWikidata": true
}
```

| Option | Type | Description |
|--------|------|-------------|
| `legalNames` | string\[] | Company legal names to resolve (default `["Stripe"]`). Matching is exact on `entity.legalName`, with a full-text fallback. |
| `leis` | string\[] | Exact 20-character LEI codes to fetch directly (default `[]`). Bypasses search. |
| `maxResultsPerQuery` | integer | Max LEI records output per name/LEI (default 5, max 50). |
| `matchMode` | string | `legalName` (default, exact) or `fulltext` (wider, noisier). |
| `fallbackToFulltext` | boolean | Retry a zero-result exact match as full-text (default `true`). |
| `jurisdictions` | string\[] | Keep only entities matching any of these jurisdiction/country/region codes, e.g. `["US-DE","RO"]` (default `[]` = all). |
| `entityCategories` | string\[] | Keep only these GLEIF categories, e.g. `["GENERAL","BRANCH"]` (default `[]` = all). |
| `activeOnly` | boolean | Keep only `ACTIVE` entities (default `false`). |
| `enrichWithWikidata` | boolean | Add the Wikidata block (default `true`). |
| `wikidataMaxRecords` | integer | Cap on enriched records — each enrichment costs two Wikidata calls (default 25, max 200). |

### Output — one item per LEI record

| Field | Description |
|-------|-------------|
| `lei` | Legal Entity Identifier (20 chars) |
| `legalName`, `legalNameLanguage` | Registered legal name and its language |
| `otherNames` | Other registered names (incl. transliterations) |
| `entityStatus` | `ACTIVE`, `INACTIVE`, `MERGED`, `RETIRED`, `ANNULLED` |
| `registrationStatus` | LEI registration status (`ISSUED`, `LAPSED`, …) |
| `jurisdiction` | Legal jurisdiction code, e.g. `US-DE`, `RO`, `BE` |
| `entityCategory`, `entitySubCategory` | `GENERAL`, `BRANCH`, `SOLE_PROPRIETOR`, `FUND`, … |
| `legalFormCode`, `legalFormOther` | ELF legal-form code / free text |
| `registeredAtAuthority`, `registeredAs` | Registration authority id + company number as registered |
| `country` | Country of the legal address |
| `legalAddress`, `headquartersAddress` | `{lines, addressNumber, city, region, country, postalCode, language}` |
| `initialRegistrationDate`, `lastUpdateDate`, `nextRenewalDate` | LEI lifecycle dates |
| `managingLou`, `corroborationLevel`, `conformityFlag`, `validatedAs` | Who issues and corroborates the record |
| `lastLegalEvent` | `{type, status, effectiveDate, recordedDate, groupType}` — most recent legal event |
| `successorEntityLei`, `successorEntityName` | Successor after a merger, when recorded |
| `bic`, `mic`, `ocid` | Bank / market / OCID identifiers when present |
| `matchedOn` | `legalName`, `fulltext` or `lei` — how the record was found |
| `query` | The input value that produced this record |
| `gleifApiUrl` | Canonical API URL of the source record |
| `wikidata` | `{qid, label, description, website, country, headquarters, industry, legalForm, stockExchange, instanceOf, inception, employees}` or `null` |
| `scrapedAt` | Extraction timestamp (UTC ISO-8601) |

### Worked example

Input:

```json
{ "legalNames": ["Stripe"], "maxResultsPerQuery": 1, "enrichWithWikidata": true }
```

Output (trimmed):

```json
{
  "lei": "894500EDC64T52PGFL08",
  "legalName": "STRIPE",
  "entityStatus": "ACTIVE",
  "registrationStatus": "ISSUED",
  "jurisdiction": "BE",
  "legalFormCode": "3W7E",
  "registeredAtAuthority": "RA000025",
  "registeredAs": "0888373015",
  "country": "BE",
  "legalAddress": {"lines": ["Fazantenlaan 2"], "city": "Hoeilaart", "region": "BE-VBR",
                   "country": "BE", "postalCode": "1560", "language": "nl"},
  "initialRegistrationDate": "2018-03-21T13:04:33Z",
  "corroborationLevel": "FULLY_CORROBORATED",
  "conformityFlag": "CONFORMING",
  "lastLegalEvent": {"type": "CHANGE_LEGAL_FORM", "status": "COMPLETED",
                     "recordedDate": "2024-03-05T13:32:11Z"},
  "matchedOn": "legalName",
  "gleifApiUrl": "https://api.gleif.org/api/v1/lei-records/894500EDC64T52PGFL08",
  "wikidata": {"qid": "Q7624104", "label": "Stripe",
               "description": "Irish-American payment technology company",
               "website": "https://stripe.com/",
               "country": {"qid": "Q30", "label": "United States"},
               "inception": "2010-09-01"}
}
```

A 100-company diligence list costs about **$1.00** in event fees.

### Run it from your code or on a schedule

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("darknezz/company-registry-intelligence").call(
    run_input={"legalNames": ["Stripe", "Siemens AG"], "maxResultsPerQuery": 5},
    max_total_charge_usd=5.00,
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["legalName"], item["lei"], item["jurisdiction"])
```

REST equivalent:

```bash
curl -X POST "https://api.apify.com/v2/acts/darknezz~company-registry-intelligence/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"legalNames":["Stripe","Siemens AG"],"maxResultsPerQuery":5}'
```

Point an Apify **Schedule** at a new batch of counterparty names each night, or trigger it from your onboarding flow and write the rows straight into your CRM/warehouse. `max_total_charge_usd` (Console → *Run options* → *Maximum cost per run*) caps the spend; a batch of 500 names with `maxResultsPerQuery=1` costs about $5.00.

### Pricing

Pay per event: **$0.01 per company record** (`company-extracted` primary event), charged once per LEI record returned — regardless of how many API calls the enrichment needed. 100 companies ≈ **$1.00**; 10,000 companies ≈ **$100**. No charge for a query that resolves to nothing (near-miss suggestions are reported in `SUMMARY` instead).

### FAQ

**Do I need a GLEIF or Wikidata API key?** No. Both are open, unauthenticated public APIs.

**How fresh is the data?** Whatever GLEIF's golden copy currently serves — every record carries `lastUpdateDate` and `nextRenewalDate`, and `lastLegalEvent` shows the most recent recorded change.

**Why did an exact name return nothing?** Legal names differ from trading names (`Stripe` vs `STRIPE`, `Google LLC` vs `Alphabet Inc.`). Keep `fallbackToFulltext` on, then check the `SUMMARY` key-value record — it lists near-miss legal names from GLEIF's fuzzy completion endpoint for every zero-result query.

**Which entity do I get when a name is ambiguous?** Up to `maxResultsPerQuery` records (default 5), each with `jurisdiction`, `registeredAs` and `entityStatus` so you can pick the right one. Use `jurisdictions` to narrow by country/state.

**What exactly does the Wikidata block add?** The public-facing layer: official website, country, headquarters, industry, legal form, stock exchange listings, inception date and employee count, each with QIDs and English labels.

**Is a Wikidata miss a failure?** No. `wikidata: null` just means no Wikidata item scored as a company (the matcher prefers items with a website plus a country plus a company-like description). Registry fields are always present.

**Can it do fuzzy name matching?** Not as a resolver — GLEIF's fuzzy endpoint returns name completions, not scored entity matches, so guessing a match would be dishonest. Near-misses are *reported*, never silently substituted.

**How do I cut cost on a big list?** Set `maxResultsPerQuery: 1`, turn off `enrichWithWikidata` (or lower `wikidataMaxRecords`) and filter hard with `jurisdictions`/`entityCategories`/`activeOnly`.

**Is this Crunchbase data?** No — and deliberately so. Crunchbase blocks datacenter traffic behind Cloudflare (probed directly), so this Actor is built on open registry data you can cite: GLEIF (LEI) and Wikidata (CC0).

### Limitations

- **GLEIF covers entities that have (or had) an LEI.** Private companies, sole traders and many early-stage startups have none — that is a registry fact, not an Actor defect, and `SUMMARY.errors` never hides it.
- **Wikidata is community-maintained.** Website/HQ/industry come from statements that a human editor wrote; they can be stale or missing. Treat the registry block as authoritative and the Wikidata block as convenience enrichment.
- **Legal names are matched literally.** Names in non-Latin scripts are matched via GLEIF's own transliterations; exotic aliases may need the full-text fallback or a direct LEI.
- **No financials, funding rounds or headcount beyond Wikidata's `employees` statement.** This Actor reports registry identity, not company financials.

# Actor input Schema

## `legalNames` (type: `array`):

Legal names to resolve in the GLEIF LEI registry, e.g. "Stripe", "Siemens AG", "Societe Generale". Matching is exact on entity.legalName by default, with an automatic full-text fallback.

## `leis` (type: `array`):

Optional exact 20-character LEI codes to fetch directly (e.g. 5493001KJTIIGC8Y1R12). Skip the search step entirely for known entities.

## `maxResultsPerQuery` (type: `integer`):

Maximum number of LEI records to output per name or LEI.

## `matchMode` (type: `string`):

How a company name is matched. "Exact legal name" uses the GLEIF entity.legalName filter; "Full-text search" searches across all LEI record fields (wider, noisier).

## `fallbackToFulltext` (type: `boolean`):

When an exact legal-name match returns nothing, retry the query as a full-text search. When the fallback also misses, near-miss legal names are reported in the SUGGESTIONS key-value record.

## `jurisdictions` (type: `array`):

Optional filter — keep only entities whose jurisdiction, country or region matches any of these codes, e.g. \["US-DE", "RO", "GB"]. Empty keeps everything.

## `entityCategories` (type: `array`):

Optional filter on the GLEIF entity category, e.g. \["GENERAL", "BRANCH", "SOLE\_PROPRIETOR", "FUND", "INTERNATIONAL\_ORGANIZATION"]. Empty keeps everything.

## `activeOnly` (type: `boolean`):

Keep only entities whose GLEIF entity status is ACTIVE (drops INACTIVE, MERGED, RETIRED and ANNULLED records).

## `enrichWithWikidata` (type: `boolean`):

Add official website, country, headquarters, industry, legal form, stock exchange, inception and employee count from Wikidata statements.

## `wikidataMaxRecords` (type: `integer`):

Maximum number of output records to enrich from Wikidata (each enrichment costs two Wikidata API calls). Records beyond the cap keep registry data with wikidata = null.

## Actor input object example

```json
{
  "legalNames": [
    "Stripe"
  ],
  "leis": [],
  "maxResultsPerQuery": 5,
  "matchMode": "legalName",
  "fallbackToFulltext": true,
  "jurisdictions": [],
  "entityCategories": [],
  "activeOnly": false,
  "enrichWithWikidata": true,
  "wikidataMaxRecords": 25
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `legalName` (type: `string`):

No description

## `lei` (type: `string`):

No description

## `entityStatus` (type: `string`):

No description

## `jurisdiction` (type: `string`):

No description

## `registeredAs` (type: `string`):

No description

## `website` (type: `string`):

No description

## `scrapedAt` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "legalNames": [
        "Stripe"
    ],
    "leis": [],
    "jurisdictions": [],
    "entityCategories": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("darknezz/company-registry-intelligence").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "legalNames": ["Stripe"],
    "leis": [],
    "jurisdictions": [],
    "entityCategories": [],
}

# Run the Actor and wait for it to finish
run = client.actor("darknezz/company-registry-intelligence").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "legalNames": [
    "Stripe"
  ],
  "leis": [],
  "jurisdictions": [],
  "entityCategories": []
}' |
apify call darknezz/company-registry-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,darknezz/company-registry-intelligence"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rurcNXkg7MJAoE8II/builds/WGrxMldio0LrlEOYz/openapi.json
