Verify a business against the Companies House register
POST /api/v1/kyb/verify
POST https://api.trustverify.co.uk/api/v1/kyb/verify
Either companyNumber or companyName is required. The company is verified against the live Companies House register: a companyNumber resolves directly; a companyName must clear a similarity threshold against the registered name — below it, ranked "did you mean" candidates are returned instead of a guess. Registry-verified companies (registered name + active officers) are then screened against sanctions and PEP lists with material-hit scoring, and an LEI register lookup runs when lei is supplied or checks.leiLookup is true. Statuses: passed (registry-verified, active, screens clear) · review (verified but flagged, or screening unavailable) · failed (not on the register) · unverified (registry unavailable, ambiguous name, or unsupported jurisdiction — never a pass). Test-mode keys receive deterministic sandbox fixtures labelled environment:"sandbox".
Request body#
| Field | Type | Description |
|---|---|---|
| companyNumber | string | |
| companyName | string | |
| lei | string | LEI to verify in the global LEI register |
| jurisdiction | string | Only GB (Companies House) is currently supported; other values return status "unverified" |
| checks | object | |
| checks.sanctionsScreening | boolean | Set false to skip sanctions and PEP list screening |
| checks.leiLookup | boolean | Set true to look up an LEI in the global LEI register by registered name |
| generateReport | boolean | Include a reportUrl (RPT-002 PDF) in the response |
| metadata | object |
Example request#
curl -sS -X POST 'https://api.trustverify.co.uk/api/v1/kyb/verify' \
-H "Authorization: Bearer $TRUSTVERIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"companyNumber": "00000000",
"jurisdiction": "GB"
}'Responses#
200 KYB result — status reflects the actual registry outcome
| Field | Type | Description |
|---|---|---|
| checkIdrequired | string | |
| statusrequired | string: "passed" | "review" | "failed" | "unverified" | |
| riskLevelrequired | string: "low" | "medium" | "high" | "unknown" | "unknown" when the company could not be verified |
| riskScore | number | 0–100 composite (registry + screening); present when registry-verified |
| reason | string | Machine-readable cause for non-passed statuses, e.g. company_not_found, ambiguous_name_match, registry_unavailable, aml_match |
| jurisdictionrequired | string | |
| companyNumberrequired | string,null | |
| companyNamerequired | string,null | |
| companyrequired | object,null | Registered company data; null unless registry-verified |
| company.companyNumberrequired | string | |
| company.companyNamerequired | string | |
| company.statusrequired | string | |
| company.typerequired | string | |
| company.incorporatedOnrequired | string | |
| company.registeredOfficerequired | object,null | |
| company.sicCodesrequired | array of string | |
| company.officerCountrequired | number | |
| company.officersrequired | array of object | |
| company.officers[].namerequired | string | |
| company.officers[].rolerequired | string | |
| company.officers[].appointedOnrequired | string,null | |
| company.officers[].nationalityrequired | string,null | |
| company.pscCountrequired | number | |
| company.pscs | array of object | PSC bands and nature-of-control codes. Omitted when owner screening is not enabled on your account. |
| company.pscs[].namerequired | string | |
| company.pscs[].ownershipBand | string | Companies House band, e.g. "25-50%" or "more than 75%". Present when owner screening is enabled on your account. |
| company.pscs[].natureOfControl | array of string | |
| company.pscs[].nationality | string | |
| company.pscs[].kind | string: "person" | "organization" | |
| company.pscs[].sanctions | string: "Clear" | "Review" | "Match" | "Not screened" | Owner sanctions result. "Not screened" means the screen did not run. Present when owner screening is enabled on your account. |
| company.insolventrequired | boolean | |
| company.registryRiskScorerequired | number | |
| registryrequired | object | |
| registry.sourcerequired | string: "companies_house" | |
| registry.verifiedrequired | boolean | |
| registry.availablerequired | boolean | |
| registry.matchedBy | string: "number" | "name" | |
| registry.nameSimilarity | number | |
| candidates | array of object | "Did you mean" list when a name search had no sufficiently similar match |
| candidates[].companyNumberrequired | string | |
| candidates[].companyNamerequired | string | |
| candidates[].companyStatusrequired | string | |
| candidates[].similarityrequired | number | |
| amlrequired | object | |
| aml.clearrequired | boolean,null | null when screening did not run |
| aml.riskLevelrequired | string | clear | review | hit | not_screened |
| aml.companyMatch | boolean | |
| aml.officerMatches | number | |
| aml.discardedWeakHits | number | Low-score / wrong-entity-type candidates excluded by material-hit scoring |
| aml.pscScreened | boolean | Whether every PSC was screened. Present only when owner screening is enabled on your account. |
| aml.pscServiceAvailable | boolean | |
| aml.pscMatches | number | |
| completedAtrequired | string | |
| reportUrl | string | |
| callback | string: "not_sent" | Present when the request carried a webhookUrl: per-request callbacks are paused and nothing was sent. The result is in this response. |
| callbackReason | string |