KYB Company Verifier — Cross-Registry Business Verification API avatar

KYB Company Verifier — Cross-Registry Business Verification API

Pricing

from $5.50 / 1,000 results

Go to Apify Store
KYB Company Verifier — Cross-Registry Business Verification API

KYB Company Verifier — Cross-Registry Business Verification API

KYB/AML company verification API. Given a company name, fans out to France (INSEE/RNE), GLEIF LEI, and US state registries and returns, per registry: exists, normalized status, jurisdiction, identifiers (SIREN/LEI), officers, address, and a match-confidence score. Keyless.

Pricing

from $5.50 / 1,000 results

Rating

0.0

(0)

Developer

Kyle Maloney

Kyle Maloney

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

11 days ago

Last modified

Share

KYB Company Verifier - Cross-Registry Business Verification API

Verify a company name against eight official, keyless company registries in one call and get, per registry: whether a record exists, the normalized legal status, jurisdiction, identifiers, formation date, registered agent, officers, and a graded name match.

This is a screening and grounding tool over public government registries. It is not a KYB, AML or compliance determination. A registry record is evidence, not a decision. Confirm identifiers against the source registry before onboarding, contracting or paying.

The rule this actor now enforces: a partial check is never presented as a complete one

Three things could previously make a partial verification look like a finished one. All were reproduced live and fixed on 2026-08-01.

  1. A registry that failed was skipped entirely - no row, no field, nothing. You got seven rows instead of eight and no way to tell which registry was never checked. If every registry failed, the run emitted zero rows and reported SUCCESS: a silent, confident "we found nothing". Now every unreachable registry emits an explicit row with exists: null, registry_status: "unavailable" and the error, and a run where no registry answered fails and bills nothing.
  2. A near name was presented as a match. Registry name search is not relevance-ranked. Live: querying GLEIF for Siemens AG returns ten records with zero exact matches, led by Siemens Energy AG (CH) - a different, spun-off company - at confidence 0.667. GLEIF registers the parent as Siemens Aktiengesellschaft, which is not on page one at all. With maxPerRegistry: 1 that wrong company was the answer. Every row now carries name_match_grade and verification_outcome, and only an exact normalized name match is ever called verified_exact_name_match.
  3. A negative was over-read. US-DE is the Delaware business licence list, not the Delaware corporate registry. Danone US, Inc. is a Delaware entity - Colorado publishes jurisdictonofformation: "DE" for it - and US-DE returned exists: false. Every row now carries registry_scope and registry_false_means, spelling out what a negative on that particular registry does and does not prove.

exists is tri-state: true matched, false the registry answered and nothing matched, null the registry was not checked. Never read null as a negative.

Three status defects fixed at the same time

RegistryWhat was wrongNow
US-CORegistered Agent Resigned (663 live entities) matched the word "registered" and was reported active.unknown, with the registry's own words in status_raw.
US-DEStatus was hard-coded to Licensed (so, active) while the licence expiry date was fetched and thrown away. An expired Delaware licence read as active.Status is computed from current_license_valid_to; an expired licence is inactive.
US-PAtypeofbusinessregistration was mapped to status. All 18 distinct live values are entity types ("Domestic Limited Liability Company"), so every one of ~4.5M rows produced unknown from a column that never held a status.PA publishes no status: status_basis says not_published_by_registry, and the value is surfaced in entity_type where it belongs.
US-NY / US-ORActive was hard-coded.Still active - the datasets are scoped to active registrations - but status_basis now reads implied_by_dataset_scope, not fetched.

status_raw carries the registry's own string on every row. The normalizer collapses 15 distinct Colorado statuses and 26 Connecticut ones into four buckets, and status_raw is what was actually published.

Who it's for

  • KYB / AML onboarding and vendor-risk teams grounding a company claim in an official registry record before contracting or paying.
  • Sales and RevOps enriching and de-duplicating accounts with a registry identifier.
  • Fintech and marketplace compliance confirming a merchant entity exists and is in good standing in its stated jurisdiction.
  • AI agents that need a chainable verification tool which can say "not checked" rather than guessing.

Registries covered

CodeRegistryWhat a negative means here
FR-INSEEFrench national register (INSEE SIRENE + RNE)No French entity matched. Says nothing about entities outside France.
GLEIFGlobal LEI registerNo LEI matched. Most companies worldwide have no LEI, so this is not evidence the company does not exist.
US-COColorado SoS business entities (all statuses)No Colorado-registered entity matched.
US-CTConnecticut SoS registrations (all statuses)No Connecticut registration matched.
US-NYNew York DOS, "Active Corporations: Beginning 1800"No active New York corporation matched. A dissolved NY entity also returns false.
US-OROregon SoS, "Active Businesses - ALL"No active Oregon registration matched.
US-PAPennsylvania DOS, current registered businessesNo current Pennsylvania registration matched.
US-DEDelaware business licence listNo Delaware licence matched. Not evidence the company is not a Delaware-incorporated entity - the Delaware Division of Corporations publishes no open bulk dataset.

Iowa was removed in July 2026: data.iowa.gov migrated off Socrata and every Iowa request returned the portal's HTML 404 page.

Example input

{ "companyName": "Danone", "maxPerRegistry": 5 }

Restrict the fan-out with country (FR or US; GLEIF is global and always included) or with an explicit registries list. maxPerRegistry caps candidates per registry, ranked by name-match confidence - but read name_match_grade rather than assuming the top row is the company you meant.

{ "companyName": "Acme Holdings LLC", "registries": ["US-CO", "US-NY", "GLEIF"] }

Output fields (53)

Verification verdict

FieldMeaning
input_nameThe company name you queried.
registryRegistry code this row came from.
verification_outcomeverified_exact_name_match, candidate_match_review_required, no_match_on_registry, or registry_unavailable_not_checked.
outcome_reasonPlain-language explanation, including what a negative does and does not prove here.
existsTri-state: true matched, false checked and no match, null not checked.
name_match_gradeexact, strong, partial, weak, none. Only exact is a name verification.
match_confidence0-1 token similarity after legal-form tokens are normalized away. null when not checked.
matched_nameThe registry's record name.
entity_idRegistry identifier: SIREN, LEI, entity id, filing number, licence number.

Status

FieldMeaning
statusNormalized active, inactive, dissolved, unknown. null when not checked.
status_rawThe registry's own status string, before normalization.
status_basisfetched, implied_by_dataset_scope, or not_published_by_registry.

Per-registry outcome contract (on every row)

FieldMeaning
registry_statusok or unavailable for the registry this row came from.
registry_errorWhy it did not answer, when unavailable.
registry_scopeWhat this registry actually covers.
registry_false_meansWhat exists: false does and does not prove here.
verification_completetrue only when every requested registry answered and passed its drift assertions.
registries_requestedEvery registry this run attempted.
registries_checkedThe ones that answered. The result is valid only against these.
registries_unavailableThe ones that did not. null on a complete run.
registry_errorsPer-registry failure detail.
registries_expected_count, registries_checked_countCoverage of this run.
fr_insee_status, gleif_status, us_co_status, us_ct_status, us_ny_status, us_or_status, us_pa_status, us_de_statusok / unavailable / not_requested per registry.

The registry record

FieldMeaning
jurisdictionRegistry jurisdiction, e.g. US-CO, FR, GLOBAL.
entity_typeLegal entity type as published.
formation_dateFormation or first-registration date, YYYY-MM-DD.
jurisdiction_of_formationWhere the entity was originally formed - often the key KYB fact.
addressPrincipal or legal address.
mailing_addressMailing or agent address, where published separately.
registered_agentRegistered agent or entity of record.
officersDirectors, officers or agent name, where published.
countyCounty of record (New York, Pennsylvania).
legal_form, registration_authority, entity_category, other_namesGLEIF LEI attributes.
trade_name, license_category, license_valid_from, license_valid_toDelaware business-licence detail.
activity_code, activity_section, employee_rangeINSEE activity and size data for French entities. The INSEE API publishes no human-readable activity label, only the NAF code and section letter.
source_urlLink to the registry record or search page.
retrieved_atISO 8601 timestamp of the query.

Everything in the last block except address, officers, jurisdiction, source_url and retrieved_at was already being fetched on every run since v1.0 and thrown away.

Sparse columns, with verified populating inputs

A dead-column audit over 22 live rows from the prefill (2026-08-01) found the Delaware licence block empty, because Danone holds no Delaware business licence. Each sparse column has an input recorded here so it can be re-verified:

ColumnInput that populates it (verified live 2026-08-01)
trade_name, license_category, license_valid_from, license_valid_to{"companyName":"Verizon","registries":["US-DE"]} returns VERIZON SERVICES CORP, category GENERAL SERVICES, valid 2026-01-01 to 2026-12-31
registry_error, registries_unavailable, registry_errorsany run where a registry does not answer, e.g. {"companyName":"Danone","registries":["US-CO","US-XX"]}
legal_form, registration_authority, other_names, entity_categoryGLEIF rows only: {"companyName":"Danone","registries":["GLEIF"]}
activity_code, activity_section, employee_rangeFR-INSEE rows only: {"companyName":"Danone","country":"FR"}
mailing_addressColorado and Connecticut rows
countyNew York and Pennsylvania rows

Live drift assertions

The dangerous failure here is not an outage. It is a registry that answers HTTP 200 with rows that were never actually filtered - arbitrary companies that read as matches. Every run asserts, before any billable row:

  • the name filter was really applied: every row a Socrata registry returns must contain the queried substring in its name column. One that does not fails that registry, which is then reported as unavailable rather than letting unfiltered rows through as matches.
  • the dataset was not replaced: at least half the expected columns must still be present. An unknown Socrata column simply comes back absent, which is indistinguishable from an empty value.
  • fuzzy results are related to the query: FR-INSEE and GLEIF run their own search, so containment cannot be asserted (querying Danone legitimately returns OLIVIA DANON), but at least one returned record must share a name token with the query.
  • a negative control: the nonsense name Qzxjvbmpwl Kdfhrtynugs Holdings is queried once per run and must match nothing. This is what catches a filter that has started matching everything.
  • not one registry answered fails the run and bills nothing.

Use as an MCP tool

Callable by AI agents (Claude, Cursor, etc.) via mcp.apify.com. An agent can verify a company and read back verification_outcome, name_match_grade, verification_complete and registry_false_means, so it can distinguish "verified", "candidate", "checked and absent" and "not checked" without guessing.

Pricing

Pay-per-result: one dataset record per registry match, per no-match verdict, or per unavailable registry. A run where no registry answered emits nothing and bills nothing beyond the fractional actor start.

FAQ

Does a false mean the company does not exist? No, and the row tells you what it does mean. Read registry_false_means. Most companies have no LEI, and most Delaware corporations hold no Delaware business licence.

Why does an exact-looking name come back as a candidate? Because registry name search is not relevance-ranked. Siemens AG on GLEIF returns Siemens Energy AG first. Only a match that is exact after legal-form normalization is graded exact.

What if a registry is down? You get a row with exists: null, registry_status: "unavailable" and the error, and verification_complete is false on every row of that run. Nothing is reported as "not found" that was not actually checked.

Do I need an API key? No. All eight sources are keyless public registries.

  • Sanctions Screening List Change Monitor - OFAC / BIS / State denied-party screening for the entity you just verified.
  • Medicaid Exclusion Screener - federal and state healthcare exclusion screening for clinician and vendor checks.
  • GLEIF Ownership Graph - parent and subsidiary structure for an entity with an LEI.