Skip to content
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 null or empty, never omitted. The one exception is risk_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 200 partial response with the failure recorded in sources_failed.

Source reporting

Entity responses report which sources were used to build them.

FieldTypeDescription
sources_checkedstring[]Sources the API tried for this request: every source your tier can use, or the subset you asked for with ?sources=.
sources_failedobject<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

HeaderExampleDescription
X-RateLimit-Limit10000Requests allowed in your current quota window.
X-RateLimit-Remaining9847Requests left in your current quota window.
X-RateLimit-Reset1743465600Unix timestamp, in seconds, at which your current quota window ends.
Retry-After30Seconds to wait before retrying. Sent only with 429 and 503 responses.
X-Response-Time84msServer 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

get/entity/{company_number}

entity.show

Cost
1 request

Parameters

Path parameters

company_numberstringrequired

Query parameters

sourcesstringoptional
freshstringoptionaldefault: false
include_resignedbooleanoptionaldefault: false

Include 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: false

Include 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_limitintegeroptional

Maximum 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"

Responses

200Full entity profile with risk signals
Body
company_numberstringrequired
namestring | nullrequired
statusstring | nullrequired
fetched_atstringdate-timerequired
sources_checkedstring[]required

Sources 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_pscinsolvencylandchargesofficers
sources_failedobjectrequired

Sources 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.

chobjectrequired

Companies House profile data

namestringoptional
company_numberstringoptional
statusstringoptional
typestring | nulloptional
incorporated_onstring | nulldateoptional
dissolved_onstring | nulldateoptional
sic_codesstring[]optional
registered_office_addressobject | nulloptional
accounts_overduebooleanoptional
confirmation_overduebooleanoptional
has_chargesbooleanoptional
has_insolvency_historybooleanoptional
postcodestring | nulloptional
ch_fetched_atstringdate-timeoptional
ch_pscobjectrequired

Persons with significant control

corporate_psc_countinteger | nullrequired

Active corporate PSC count, independent of include_ceased; null when active kinds cannot be classified.

control_graph_availablebooleanrequired

Caller entitlement to the separate graph feature, not a completeness guarantee or assessment status.

personsobject[]required

Array items

namestring | nullrequired
nature_of_controlstring[]required
notified_onstring | nulldaterequired
nationalitystring | nullrequired
country_of_residencestring | nullrequired
ceased_onstring | nulldaterequired

Date the person ceased to be a PSC. Null for an active PSC. Ceased entries are only present when ?include_ceased=true.

kindstring | nullrequired
company_numberstring | nullrequired

Conservative UK lookup pointer. Null for foreign or unresolved corporate registration details.

source_urlstring | nullrequired
identificationobject | nullrequired
country_registeredstring | nullrequired
place_registeredstring | nullrequired
registration_numberstring | nullrequired
legal_formstring | nullrequired
legal_authoritystring | nullrequired
total_resultsintegerrequired

Full PSC count Companies House holds, regardless of include_ceased.

active_countintegerrequired

PSCs with a null ceased_on. Always a full count.

ceased_countintegerrequired

PSCs with a non-null ceased_on. Always a full count, even when the entries themselves are filtered out.

insolvencyobjectrequired

Insolvency proceedings

has_active_insolvencybooleanrequired
casesobject[]required
insolvency_fetched_atstringdate-timerequired
land_holdingsobject[]required

Land 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 | nullrequired
tenurestring | nullrequired

Allowed values

freeholdleasehold
addressstring | nullrequired

Postcode only. Full street address withheld pending Royal Mail PAF licence.

price_paidinteger | nullrequired

Sale 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 | nulldaterequired

Date the proprietor was registered with HMLR.

land_summaryobjectrequired

Counts over every land title the company holds, regardless of land_limit. Present whenever land_holdings is.

total_countintegerrequired

Every title held, including any with an unrecorded tenure.

returned_countintegerrequired

Titles included in land_holdings.

freehold_countintegerrequired
leasehold_countintegerrequired
truncatedbooleanrequired

True when land_holdings omits titles because of land_limit.

chargesobjectrequired

Companies 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

nonepresentunknown
total_countintegerrequired
satisfied_countintegerrequired
part_satisfied_countintegerrequired
outstanding_countintegerrequired

Derived: total_count minus satisfied_count minus part_satisfied_count.

truncatedbooleanrequired

True when upstream pagination could not return every charge — items is shorter than total_count and must not be treated as a complete list.

itemsobject[]required

Array items

charge_numberintegerrequired
statusstringrequired

Allowed values

outstandingsatisfiedfully_satisfiedpart_satisfiedother
created_onstring | nulldaterequired
delivered_onstring | nulldaterequired
satisfied_onstring | nulldaterequired
persons_entitledstring[]required
classificationstring | nullrequired
particularsstring | nullrequired
contains_floating_chargeboolean | nullrequired

From CH structured particulars. Null when Companies House did not supply the flag.

floating_charge_covers_allboolean | nullrequired

True when the floating charge covers the whole undertaking (debenture-style). Null when Companies House did not supply the flag.

assets_ceased_releasedstring | nullrequired
officersobjectrequired

Companies 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

nonepresentunknown
total_resultsintegerrequired

Full officer count Companies House holds, regardless of include_resigned.

active_countintegerrequired
resigned_countintegerrequired
truncatedbooleanrequired

True when the fetched items fell short of total_results (defensive pagination against unreliable upstream paging).

itemsobject[]required

Active officers only by default; resigned officers are included when include_resigned=true.

Array items

officer_idstring | nullrequired

Stable CH officer identifier, parsed from the appointments link. Null when absent or unparseable.

namestring | nullrequired
officer_rolestring | nullrequired

Raw 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 | nulldaterequired
appointed_beforestring | nulldaterequired

Set instead of appointed_on for appointments predating Companies House's digital record (pre-1992).

is_pre_1992_appointmentbooleanrequired
resigned_onstring | nulldaterequired

Null means the officer is currently active.

nationalitystring | nullrequired
country_of_residencestring | nullrequired
date_of_birthobject | nullrequired

Month and year only — the day is never returned (data minimisation, same treatment as PSC dates of birth).

monthintegerrequired
yearintegerrequired
former_namesobject[]required

Array items

forenamesstring | nullrequired
surnamestring | nullrequired
identificationobject | nullrequired

Corporate officers only. Null for natural persons.

legal_formstring | nullrequired
place_registeredstring | nullrequired
registration_numberstring | nullrequired
legal_authoritystring | nullrequired
identity_verificationobject | nullrequired

ECCTA identity verification details. Null when the upstream record carries none.

identity_verified_onstring | nulldaterequired
authorised_corporate_service_provider_namestring | nullrequired
anti_money_laundering_supervisory_bodiesstring[]required
appointment_verification_statement_due_onstring | nulldaterequired
appointment_verification_statement_start_onstring | nulldaterequired
appointment_verification_statement_end_onstring | nulldaterequired
preferred_namestring | nullrequired
directorsobject[]required

Array items

officer_idstring | nullrequired
namestring | nullrequired
appointed_onstring | nulldaterequired
resigned_onstring | nulldaterequired
risk_signalsobjectoptional

Risk 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.

scoreintegerrequired

Points from confirmed (triggered) flags only, 0-100. A floor (lower bound) when score_is_floor is true.

score_is_floorbooleanrequired

When true, a required source was unavailable so score is a lower bound — a low value does not mean low risk.

potential_scoreintegerrequired

Worst-case ceiling: score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty.

coveragestring[]required

Risk-bearing sources actually consulted for this score. A source absent here was not assessed.

Array items — allowed values

chch_pscinsolvencychargesofficers
flagsobject[]required

Array items

codestringrequired

Allowed values

INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUE
severitystringrequired

Allowed values

criticalwarninginfo
descriptionstringrequired
triggered_atstringdate-timerequired
indeterminateobject[]required

Flags that could not be evaluated because a required source was unavailable.

Array items

codestringrequired

Allowed values

INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUE
severitystringrequired

Allowed values

criticalwarninginfo
sourcestringrequired

Allowed values

chch_pscinsolvencychargesofficers
reasonstringrequired

Allowed values

source_unavailablenot_requestedfeature_disabled
404
Body
errorstringrequired

Allowed values

company_not_found
messagestringrequired
422Validation error
Body
messagestringrequired

Errors overview.

errorsobjectrequired

A detailed description of each field that failed validation.

Object with dynamic string keys; each value is string[].

429Companies House upstream is at capacity, so the CH core fetch was shed (proactive budget limiter or reactive CH 429). Distinct from rate_limit_exceeded, which is your per-key tier limit — upstream_capacity reflects the shared registry being saturated, not your usage. Retry after the Retry-After interval.
Response headers
Retry-AfterSeconds to wait before retrying.
Body
errorstringrequired

Allowed values

upstream_capacity
messagestringrequired
get/entity/{company_number}/risk

entity.risk

Cost
1 request

Parameters

Path parameters

company_numberstringrequired

Example request

curl "https://api.rotuli.co.uk/v1/entity/01234567/risk" \
  -H "Authorization: Bearer uk_live_your_key"

Responses

200Risk signals for a company
Body
company_numberstringrequired
risk_signalsobjectrequired

Risk 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.

scoreintegerrequired

Points from confirmed (triggered) flags only, 0-100. A floor (lower bound) when score_is_floor is true.

score_is_floorbooleanrequired

When true, a required source was unavailable so score is a lower bound — a low value does not mean low risk.

potential_scoreintegerrequired

Worst-case ceiling: score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty.

coveragestring[]required

Risk-bearing sources actually consulted for this score. A source absent here was not assessed.

Array items — allowed values

chch_pscinsolvencychargesofficers
flagsobject[]required

Array items

codestringrequired

Allowed values

INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUE
severitystringrequired

Allowed values

criticalwarninginfo
descriptionstringrequired
triggered_atstringdate-timerequired
indeterminateobject[]required

Flags that could not be evaluated because a required source was unavailable.

Array items

codestringrequired

Allowed values

INSOLVENCY_ACTIVECOMPANY_DISSOLVEDACCOUNTS_OVERDUECONFIRMATION_OVERDUECOMPANY_VERY_NEWNO_PSC_RECORDEDOUTSTANDING_CHARGESALL_ASSETS_CHARGEDDIRECTOR_DISQUALIFIEDNO_ACTIVE_DIRECTORSSOLE_DIRECTOR_IS_CORPORATEIDENTITY_VERIFICATION_OVERDUE
severitystringrequired

Allowed values

criticalwarninginfo
sourcestringrequired

Allowed values

chch_pscinsolvencychargesofficers
reasonstringrequired

Allowed values

source_unavailablenot_requestedfeature_disabled
fetched_atstringdate-timerequired
404
Body
errorstringrequired

Allowed values

company_not_found
messagestringrequired
422Validation error
Body
messagestringrequired

Errors overview.

errorsobjectrequired

A detailed description of each field that failed validation.

Object with dynamic string keys; each value is string[].

429Companies House upstream is at capacity, so the CH core fetch was shed (proactive budget limiter or reactive CH 429). Distinct from rate_limit_exceeded, which is your per-key tier limit — upstream_capacity reflects the shared registry being saturated, not your usage. Retry after the Retry-After interval.
Response headers
Retry-AfterSeconds to wait before retrying.
Body
errorstringrequired

Allowed values

upstream_capacity
messagestringrequired
get/entity/{company_number}/control-graph

controlGraph.show

Tiers
Growth and Enterprise
Cost
1 request

Parameters

Path parameters

company_numberstringrequired

Query parameters

directionstringoptional

Default group. Ancestors follows controllers upward; group also follows bounded descendants from the snapshot index.

ancestorsgroup
max_depthintegeroptional

Upward depth: 1–4 for Growth, 1–6 for Enterprise. Defaults to the tier cap.

max_nodesintegeroptional

Total 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"

Responses

200Bounded corporate control graph; Growth and Enterprise only. Partial results retain confirmed evidence and explicit coverage.
Body
company_numberstringrequired
directionstringrequired

Allowed values

ancestorsgroup
statusstringrequired

Complete only within this corporate PSC dataset, direction, vintage and declared scope. Never a guarantee of a complete ownership structure.

Allowed values

completepartial
fetched_atstringdate-timerequired
snapshotobject | nullrequired
idstringrequired
as_ofstringdaterequired
published_atstringdate-timerequired
discovery_sourcestringrequired

Allowed values

psc_snapshotlive_psc
nodesobject[]required

Array items

company_numberstringrequired
namestring | nullrequired
statusstring | nullrequired
is_insolventboolean | nullrequired
relationshipstringrequired

Allowed values

subjectcorporate_pscindirect_controllercontrolled_companyshared_controller
depthintegerrequired
pathstring[]required
assessment_statusstringrequired

Allowed values

not_assessedassessedpartial
sources_checkedstring[]required
sources_failedobjectrequired
observed_atobjectrequired
chstring | nullrequired
insolvencystring | nullrequired
edgesobject[]required

Array items

idstringrequired
controlled_company_numberstringrequired
controller_company_numberstring | nullrequired
controller_namestring | nullrequired
kindstring | nullrequired
nature_of_controlstring[]required
identificationobject | nullrequired
country_registeredstring | nullrequired
place_registeredstring | nullrequired
registration_numberstring | nullrequired
legal_formstring | nullrequired
legal_authoritystring | nullrequired
notified_onstring | nullrequired
ceased_onstring | nullrequired
source_urlstring | nullrequired
observed_atstring | nullrequired
discovery_sourcestringrequired
related_riskobjectrequired
statusstringrequired

Allowed values

assessedpartial
findingsobject[]required

Array items

codestringrequired

Allowed values

RELATED_COMPANY_INSOLVENCYRELATED_COMPANY_DISSOLVED
severitystringrequired

Allowed values

warning
company_numberstringrequired
relationshipstringrequired
pathstring[]required
observed_atstring | nullrequired
coverageobjectrequired
discovery_completebooleanrequired
assessment_completebooleanrequired
assessed_countintegerrequired
unassessed_countintegerrequired
frontierobject[]required

Array items

company_numberstring | nullrequired
edge_idstring | nullrequired
reasonstringrequired
limitsobjectrequired
max_depthintegerrequired
max_nodesintegerrequired
max_requestsintegerrequired
deadline_secondsnumberrequired
descendant_depthintegerrequired
max_edgesintegerrequired
usageobjectrequired
outbound_requestsintegerrequired
cache_hitsintegerrequired
403
Body
errorstringrequired

Allowed values

control_graph_tier_required
messagestringrequired
404
Body
errorstringrequired

Allowed values

company_not_found
messagestringrequired
422
Body
errorstringrequired

Allowed values

invalid_company_numberinvalid_control_graph_options
messagestringrequired
429Traversal admission or subject lookup capacity exhausted; retry after the indicated interval.
Response headers
Retry-AfterSeconds to wait before retrying.
Body
errorstringrequired

Allowed values

control_graph_capacity
messagestringrequired
500
Body
errorstringrequired

Allowed values

internal_error
messagestringrequired

Search

Officers

get/officers/{officer_id}/appointments

officer.appointments

Cost
1 request

Parameters

Path parameters

officer_idstringrequired

Example request

curl "https://api.rotuli.co.uk/v1/officers/xyzOfficerId1/appointments" \
  -H "Authorization: Bearer uk_live_your_key"

Responses

200
Body
objectoptional

Object with dynamic string keys; each value is any.

fetched_atstringrequired
404
Body
errorstringrequired

Allowed values

officer_not_found
messagestringrequired
422
Body
errorstringrequired

Allowed values

invalid_officer_id
messagestringrequired

Allowed values

Officer id must be 1–64 characters from the set [A-Za-z0-9_-].
429
Body
errorstringrequired

Allowed values

upstream_capacity
messagestringrequired

Allowed values

Upstream registry capacity reached. Please retry shortly.