Browse documentation
UK Entity API · v1
API reference
Every REST endpoint with its parameters, responses and error codes. All endpoints use GET, take path and query parameters, and return JSON.
Aggregates UK regulatory data from Companies House and HMLR into a single normalised JSON response. Designed for AI agents performing due diligence and KYB checks on UK companies.
- Base URL
- https://api.rotuli.co.uk/v1
- Authentication
- Authorization: Bearer uk_live_your_key
Conventions
Authentication
Send your API key as a Bearer token in the Authorization header of every request. Keys start with uk_live_ and are issued in the dashboard. Call the API from your server: never put a key in browser or mobile code. MCP clients connect with OAuth instead; see MCP server.
A request without a valid key returns 401 with missing_token, invalid_token or key_inactive.
Response guarantees
- Documented fields are always present. A value that is unknown or absent is
nullor empty, never omitted. The one exception isrisk_signals, which Free keys do not receive. - Enum values and codes are stable. New values may be added, so handle values you don't recognise. Existing values are never renamed or removed.
- An unavailable secondary source does not fail the request. You get a
200partial response with the failure recorded insources_failed.
Source reporting
Entity responses report which sources were used to build them.
| Field | Type | Description |
|---|---|---|
sources_checked | string[] | Sources the API tried for this request: every source your tier can use, or the subset you asked for with ?sources=. |
sources_failed | object<string, string> | Sources that could not be queried, keyed by source name, each with a human-readable reason. Always present, and empty when nothing failed. Its keys are always a subset of sources_checked. |
The sources actually consulted are sources_checked minus the keys of sources_failed. For how a failed source affects risk scores, see Interpreting risk signals.
Response headers
| Header | Example | Description |
|---|---|---|
X-RateLimit-Limit | 10000 | Requests allowed in your current quota window. |
X-RateLimit-Remaining | 9847 | Requests left in your current quota window. |
X-RateLimit-Reset | 1743465600 | Unix timestamp, in seconds, at which your current quota window ends. |
Retry-After | 30 | Seconds to wait before retrying. Sent only with 429 and 503 responses. |
X-Response-Time | 84ms | Server processing time. Informational, and not sent on every response. |
A call costs one request from your monthly quota, however many sources it touches. Authentication failures are free and some upstream failures are refunded; see request cost.
Errors
Every error response has the same shape. Build your logic on the stable error code, not on message. Each endpoint below lists the codes it can return; see Error codes for what each means and what to do.
{
"error": "company_not_found",
"message": "Company not found: 01234567"
}Entity
/entity/{company_number}entity.show
- Cost
- 1 request
- Auth
- Bearer API key
Parameters
Path parameters
company_numberstringrequiredQuery parameters
sourcesstringoptionalfreshstringoptionaldefault: falseinclude_resignedbooleanoptionaldefault: falseInclude resigned officers in officers.items (default false — active officers only). total_results, active_count and resigned_count always reflect the full officer set regardless of this flag.
include_ceasedbooleanoptionaldefault: falseInclude ceased persons with significant control in ch_psc.persons (default false — active PSCs only). Ceased entries carry a non-null ceased_on. total_results, active_count and ceased_count always reflect the full PSC set regardless of this flag.
land_limitintegeroptionalMaximum number of land titles to return in land_holdings, newest first (1–200). Omit for every title. land_summary always reports counts over the full list. Out-of-range or non-integer values return 422 invalid_land_limit.
Example request
curl "https://api.rotuli.co.uk/v1/entity/01234567" \
-H "Authorization: Bearer uk_live_your_key"Error codes
Responses
Body
company_numberstringrequirednamestring | nullrequiredstatusstring | nullrequiredfetched_atstringdate-timerequiredsources_checkedstring[]requiredSources the API attempted to query for this request — the requested set (defaults to all available for your tier, or the ?sources= subset). A source that failed remains listed here and also appears in sources_failed; sources_failed is a subset of sources_checked. Successfully consulted sources = sources_checked minus the keys of sources_failed.
Array items — allowed values
chch_pscinsolvencylandchargesofficerssources_failedobjectrequiredSources that could not be queried, as an object keyed by source name with a human-readable failure reason. Empty object when every attempted source succeeded. Always present. Its keys are always a subset of sources_checked.
Object with dynamic string keys; each value is string.
chobjectrequiredCompanies House profile data
namestringoptionalcompany_numberstringoptionalstatusstringoptionaltypestring | nulloptionalincorporated_onstring | nulldateoptionaldissolved_onstring | nulldateoptionalsic_codesstring[]optionalregistered_office_addressobject | nulloptionalaccounts_overduebooleanoptionalconfirmation_overduebooleanoptionalhas_chargesbooleanoptionalhas_insolvency_historybooleanoptionalpostcodestring | nulloptionalch_fetched_atstringdate-timeoptionalch_pscobjectrequiredPersons with significant control
corporate_psc_countinteger | nullrequiredActive corporate PSC count, independent of include_ceased; null when active kinds cannot be classified.
control_graph_availablebooleanrequiredCaller entitlement to the separate graph feature, not a completeness guarantee or assessment status.
personsobject[]requiredArray items
namestring | nullrequirednature_of_controlstring[]requirednotified_onstring | nulldaterequirednationalitystring | nullrequiredcountry_of_residencestring | nullrequiredceased_onstring | nulldaterequiredDate the person ceased to be a PSC. Null for an active PSC. Ceased entries are only present when ?include_ceased=true.
kindstring | nullrequiredcompany_numberstring | nullrequiredConservative UK lookup pointer. Null for foreign or unresolved corporate registration details.
source_urlstring | nullrequiredidentificationobject | nullrequiredcountry_registeredstring | nullrequiredplace_registeredstring | nullrequiredregistration_numberstring | nullrequiredlegal_formstring | nullrequiredlegal_authoritystring | nullrequiredtotal_resultsintegerrequiredFull PSC count Companies House holds, regardless of include_ceased.
active_countintegerrequiredPSCs with a null ceased_on. Always a full count.
ceased_countintegerrequiredPSCs with a non-null ceased_on. Always a full count, even when the entries themselves are filtered out.
insolvencyobjectrequiredInsolvency proceedings
has_active_insolvencybooleanrequiredcasesobject[]requiredinsolvency_fetched_atstringdate-timerequiredland_holdingsobject[]requiredLand titles ordered by date_added, newest first (undated titles last), then title_number ascending. Every title unless land_limit is passed.
Array items
title_numberstring | nullrequiredtenurestring | nullrequiredAllowed values
freeholdleaseholdaddressstring | nullrequiredPostcode only. Full street address withheld pending Royal Mail PAF licence.
price_paidinteger | nullrequiredSale price in GBP. Sourced from the APPD column of the CCOD dataset where HMLR recorded a price. Null where no price was captured (e.g. nil-consideration transfers, portfolio deals, pre-capture acquisitions).
date_addedstring | nulldaterequiredDate the proprietor was registered with HMLR.
land_summaryobjectrequiredCounts over every land title the company holds, regardless of land_limit. Present whenever land_holdings is.
total_countintegerrequiredEvery title held, including any with an unrecorded tenure.
returned_countintegerrequiredTitles included in land_holdings.
freehold_countintegerrequiredleasehold_countintegerrequiredtruncatedbooleanrequiredTrue when land_holdings omits titles because of land_limit.
chargesobjectrequiredCompanies House registered charges (security interests) against company assets. Always present; a tri-state status distinguishes "no charges" from "not requested / fetch failed".
statusstringrequired"none" = confirmed no charges recorded. "present" = one or more charges exist (satisfied charges are included as borrowing history). "unknown" = not requested, or the fetch failed (then charges also appears in sources_failed). Never "none" for a skipped or failed fetch.
Allowed values
nonepresentunknowntotal_countintegerrequiredsatisfied_countintegerrequiredpart_satisfied_countintegerrequiredoutstanding_countintegerrequiredDerived: total_count minus satisfied_count minus part_satisfied_count.
truncatedbooleanrequiredTrue when upstream pagination could not return every charge — items is shorter than total_count and must not be treated as a complete list.
itemsobject[]requiredArray items
charge_numberintegerrequiredstatusstringrequiredAllowed values
outstandingsatisfiedfully_satisfiedpart_satisfiedothercreated_onstring | nulldaterequireddelivered_onstring | nulldaterequiredsatisfied_onstring | nulldaterequiredpersons_entitledstring[]requiredclassificationstring | nullrequiredparticularsstring | nullrequiredcontains_floating_chargeboolean | nullrequiredFrom CH structured particulars. Null when Companies House did not supply the flag.
floating_charge_covers_allboolean | nullrequiredTrue when the floating charge covers the whole undertaking (debenture-style). Null when Companies House did not supply the flag.
assets_ceased_releasedstring | nullrequiredofficersobjectrequiredCompanies House officers (directors, secretaries, LLP members) for this company. Always present; a tri-state status distinguishes "no officers" from "not requested / fetch failed". Active officers only by default — pass ?include_resigned=true to add resigned officers to items; total_results, active_count and resigned_count are always full counts regardless of include_resigned.
statusstringrequired"none" = confirmed no officers recorded (only assertable once company existence is proven). "present" = one or more officers exist. "unknown" = not requested, or the fetch failed (then officers also appears in sources_failed). Never "none" for a skipped or failed fetch.
Allowed values
nonepresentunknowntotal_resultsintegerrequiredFull officer count Companies House holds, regardless of include_resigned.
active_countintegerrequiredresigned_countintegerrequiredtruncatedbooleanrequiredTrue when the fetched items fell short of total_results (defensive pagination against unreliable upstream paging).
itemsobject[]requiredActive officers only by default; resigned officers are included when include_resigned=true.
Array items
officer_idstring | nullrequiredStable CH officer identifier, parsed from the appointments link. Null when absent or unparseable.
namestring | nullrequiredofficer_rolestring | nullrequiredRaw Companies House officer_role value (28 upstream values, e.g. director, corporate-director, nominee-director, corporate-nominee-director, secretary, llp-member). Stored intact — callers should tolerate unknown values.
appointed_onstring | nulldaterequiredappointed_beforestring | nulldaterequiredSet instead of appointed_on for appointments predating Companies House's digital record (pre-1992).
is_pre_1992_appointmentbooleanrequiredresigned_onstring | nulldaterequiredNull means the officer is currently active.
nationalitystring | nullrequiredcountry_of_residencestring | nullrequireddate_of_birthobject | nullrequiredMonth and year only — the day is never returned (data minimisation, same treatment as PSC dates of birth).
monthintegerrequiredyearintegerrequiredformer_namesobject[]requiredArray items
forenamesstring | nullrequiredsurnamestring | nullrequiredidentificationobject | nullrequiredCorporate officers only. Null for natural persons.
legal_formstring | nullrequiredplace_registeredstring | nullrequiredregistration_numberstring | nullrequiredlegal_authoritystring | nullrequiredidentity_verificationobject | nullrequiredECCTA identity verification details. Null when the upstream record carries none.
identity_verified_onstring | nulldaterequiredauthorised_corporate_service_provider_namestring | nullrequiredanti_money_laundering_supervisory_bodiesstring[]requiredappointment_verification_statement_due_onstring | nulldaterequiredappointment_verification_statement_start_onstring | nulldaterequiredappointment_verification_statement_end_onstring | nulldaterequiredpreferred_namestring | nullrequireddirectorsobject[]requiredArray items
officer_idstring | nullrequirednamestring | nullrequiredappointed_onstring | nulldaterequiredresigned_onstring | nulldaterequiredrisk_signalsobjectoptionalRisk signals derived from the assembled profile. Paid feature: omitted entirely for free-tier keys (treat absence as "not entitled", not "no risk"), so it is not a required field.
scoreintegerrequiredPoints from confirmed (triggered) flags only, 0-100. A floor (lower bound) when score_is_floor is true.
score_is_floorbooleanrequiredWhen true, a required source was unavailable so score is a lower bound — a low value does not mean low risk.
potential_scoreintegerrequiredWorst-case ceiling: score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty.
coveragestring[]requiredRisk-bearing sources actually consulted for this score. A source absent here was not assessed.
Array items — allowed values
chch_pscinsolvencychargesofficersflagsobject[]requiredArray items
codestringrequiredAllowed values
INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUEseveritystringrequiredAllowed values
criticalwarninginfodescriptionstringrequiredtriggered_atstringdate-timerequiredindeterminateobject[]requiredFlags that could not be evaluated because a required source was unavailable.
Array items
codestringrequiredAllowed values
INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUEseveritystringrequiredAllowed values
criticalwarninginfosourcestringrequiredAllowed values
chch_pscinsolvencychargesofficersreasonstringrequiredAllowed values
source_unavailablenot_requestedfeature_disabledBody
errorstringrequiredAllowed values
company_not_foundmessagestringrequiredBody
messagestringrequiredErrors overview.
errorsobjectrequiredA detailed description of each field that failed validation.
Object with dynamic string keys; each value is string[].
Response headers
Retry-AfterSeconds to wait before retrying.Body
errorstringrequiredAllowed values
upstream_capacitymessagestringrequired/entity/{company_number}/riskentity.risk
- Cost
- 1 request
- Auth
- Bearer API key
Parameters
Path parameters
company_numberstringrequiredExample request
curl "https://api.rotuli.co.uk/v1/entity/01234567/risk" \
-H "Authorization: Bearer uk_live_your_key"Error codes
Responses
Body
company_numberstringrequiredrisk_signalsobjectrequiredRisk signals derived from the assembled profile. Paid feature: omitted entirely for free-tier keys (treat absence as "not entitled", not "no risk"), so it is not a required field.
scoreintegerrequiredPoints from confirmed (triggered) flags only, 0-100. A floor (lower bound) when score_is_floor is true.
score_is_floorbooleanrequiredWhen true, a required source was unavailable so score is a lower bound — a low value does not mean low risk.
potential_scoreintegerrequiredWorst-case ceiling: score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty.
coveragestring[]requiredRisk-bearing sources actually consulted for this score. A source absent here was not assessed.
Array items — allowed values
chch_pscinsolvencychargesofficersflagsobject[]requiredArray items
codestringrequiredAllowed values
INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUEseveritystringrequiredAllowed values
criticalwarninginfodescriptionstringrequiredtriggered_atstringdate-timerequiredindeterminateobject[]requiredFlags that could not be evaluated because a required source was unavailable.
Array items
codestringrequiredAllowed values
INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUEseveritystringrequiredAllowed values
criticalwarninginfosourcestringrequiredAllowed values
chch_pscinsolvencychargesofficersreasonstringrequiredAllowed values
source_unavailablenot_requestedfeature_disabledfetched_atstringdate-timerequiredBody
errorstringrequiredAllowed values
company_not_foundmessagestringrequiredBody
messagestringrequiredErrors overview.
errorsobjectrequiredA detailed description of each field that failed validation.
Object with dynamic string keys; each value is string[].
Response headers
Retry-AfterSeconds to wait before retrying.Body
errorstringrequiredAllowed values
upstream_capacitymessagestringrequired/entity/{company_number}/control-graphcontrolGraph.show
- Tiers
- Growth and Enterprise
- Cost
- 1 request
- Auth
- Bearer API key
Parameters
Path parameters
company_numberstringrequiredQuery parameters
directionstringoptionalDefault group. Ancestors follows controllers upward; group also follows bounded descendants from the snapshot index.
ancestorsgroupmax_depthintegeroptionalUpward depth: 1–4 for Growth, 1–6 for Enterprise. Defaults to the tier cap.
max_nodesintegeroptionalTotal company nodes: 1–12 for Growth, 1–24 for Enterprise. Defaults to the tier cap.
Example request
curl "https://api.rotuli.co.uk/v1/entity/01234567/control-graph" \
-H "Authorization: Bearer uk_live_your_key"Error codes
Responses
Body
company_numberstringrequireddirectionstringrequiredAllowed values
ancestorsgroupstatusstringrequiredComplete only within this corporate PSC dataset, direction, vintage and declared scope. Never a guarantee of a complete ownership structure.
Allowed values
completepartialfetched_atstringdate-timerequiredsnapshotobject | nullrequiredidstringrequiredas_ofstringdaterequiredpublished_atstringdate-timerequireddiscovery_sourcestringrequiredAllowed values
psc_snapshotlive_pscnodesobject[]requiredArray items
company_numberstringrequirednamestring | nullrequiredstatusstring | nullrequiredis_insolventboolean | nullrequiredrelationshipstringrequiredAllowed values
subjectcorporate_pscindirect_controllercontrolled_companyshared_controllerdepthintegerrequiredpathstring[]requiredassessment_statusstringrequiredAllowed values
not_assessedassessedpartialsources_checkedstring[]requiredsources_failedobjectrequiredobserved_atobjectrequiredchstring | nullrequiredinsolvencystring | nullrequirededgesobject[]requiredArray items
idstringrequiredcontrolled_company_numberstringrequiredcontroller_company_numberstring | nullrequiredcontroller_namestring | nullrequiredkindstring | nullrequirednature_of_controlstring[]requiredidentificationobject | nullrequiredcountry_registeredstring | nullrequiredplace_registeredstring | nullrequiredregistration_numberstring | nullrequiredlegal_formstring | nullrequiredlegal_authoritystring | nullrequirednotified_onstring | nullrequiredceased_onstring | nullrequiredsource_urlstring | nullrequiredobserved_atstring | nullrequireddiscovery_sourcestringrequiredrelated_riskobjectrequiredstatusstringrequiredAllowed values
assessedpartialfindingsobject[]requiredArray items
codestringrequiredAllowed values
RELATED_COMPANY_INSOLVENCYRELATED_COMPANY_DISSOLVEDseveritystringrequiredAllowed values
warningcompany_numberstringrequiredrelationshipstringrequiredpathstring[]requiredobserved_atstring | nullrequiredcoverageobjectrequireddiscovery_completebooleanrequiredassessment_completebooleanrequiredassessed_countintegerrequiredunassessed_countintegerrequiredfrontierobject[]requiredArray items
company_numberstring | nullrequirededge_idstring | nullrequiredreasonstringrequiredlimitsobjectrequiredmax_depthintegerrequiredmax_nodesintegerrequiredmax_requestsintegerrequireddeadline_secondsnumberrequireddescendant_depthintegerrequiredmax_edgesintegerrequiredusageobjectrequiredoutbound_requestsintegerrequiredcache_hitsintegerrequiredBody
errorstringrequiredAllowed values
control_graph_tier_requiredmessagestringrequiredBody
errorstringrequiredAllowed values
company_not_foundmessagestringrequiredBody
errorstringrequiredAllowed values
invalid_company_numberinvalid_control_graph_optionsmessagestringrequiredResponse headers
Retry-AfterSeconds to wait before retrying.Body
errorstringrequiredAllowed values
control_graph_capacitymessagestringrequiredBody
errorstringrequiredAllowed values
internal_errormessagestringrequiredSearch
/searchsearch.search
- Cost
- 1 request
- Auth
- Bearer API key
Parameters
Query parameters
qstringoptionaltypestringoptionalApply ?type= filter on raw items before normalisation
active_onlystringoptionaldefault: falseExample request
curl "https://api.rotuli.co.uk/v1/search?q=acme" \
-H "Authorization: Bearer uk_live_your_key"Error codes
Responses
Body
querystringrequiredtotal_resultsintegerrequiredOption 1 — any
Option 2 — integer
Allowed values
0resultsany[]requiredBody
errorstringrequiredAllowed values
invalid_querymessagestringrequiredAllowed values
The q parameter is required and must be at least 2 characters.Response headers
Retry-AfterSeconds to wait before retrying.Body
errorstringrequiredAllowed values
upstream_unavailablemessagestringrequiredOfficers
/officers/{officer_id}/appointmentsofficer.appointments
- Cost
- 1 request
- Auth
- Bearer API key
Parameters
Path parameters
officer_idstringrequiredExample request
curl "https://api.rotuli.co.uk/v1/officers/xyzOfficerId1/appointments" \
-H "Authorization: Bearer uk_live_your_key"Responses
Body
objectoptionalObject with dynamic string keys; each value is any.
fetched_atstringrequiredBody
errorstringrequiredAllowed values
officer_not_foundmessagestringrequiredBody
errorstringrequiredAllowed values
invalid_officer_idmessagestringrequiredAllowed values
Officer id must be 1–64 characters from the set [A-Za-z0-9_-].Body
errorstringrequiredAllowed values
upstream_capacitymessagestringrequiredAllowed values
Upstream registry capacity reached. Please retry shortly.