{"openapi":"3.1.0","info":{"title":"UK Entity API","version":"1","description":"Aggregates UK regulatory data from Companies House into a single normalised JSON response. Designed for AI agents performing due diligence and KYB checks on UK companies."},"servers":[{"url":"https://api.rotuli.co.uk/v1"}],"security":[{"http":[]}],"paths":{"/entity/{company_number}":{"get":{"operationId":"entity.show","tags":["Entity"],"parameters":[{"name":"company_number","in":"path","required":true,"schema":{"type":"string"}},{"name":"sources","in":"query","schema":{"type":"string"}},{"name":"fresh","in":"query","schema":{"type":"string","default":"false"}},{"name":"include_resigned","in":"query","description":"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.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Full entity profile with risk signals","content":{"application/json":{"schema":{"type":"object","properties":{"company_number":{"type":"string"},"name":{"type":["string","null"]},"status":{"type":["string","null"]},"fetched_at":{"type":"string","format":"date-time"},"sources_checked":{"type":"array","description":"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.","items":{"type":"string","enum":["ch","ch_psc","insolvency","charges","officers"]}},"sources_failed":{"type":"object","description":"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.","additionalProperties":{"type":"string"}},"ch":{"type":"object","description":"Companies House profile data","properties":{"name":{"type":"string"},"company_number":{"type":"string"},"status":{"type":"string"},"type":{"type":["string","null"]},"incorporated_on":{"type":["string","null"],"format":"date"},"dissolved_on":{"type":["string","null"],"format":"date"},"sic_codes":{"type":"array","items":{"type":"string"}},"registered_office_address":{"type":["object","null"]},"accounts_overdue":{"type":"boolean"},"confirmation_overdue":{"type":"boolean"},"has_charges":{"type":"boolean"},"has_insolvency_history":{"type":"boolean"},"postcode":{"type":["string","null"]},"ch_fetched_at":{"type":"string","format":"date-time"}}},"ch_psc":{"type":"object","description":"Persons with significant control","properties":{"persons":{"type":"array","items":{"type":"object","properties":{"name":{"type":["string","null"]},"nature_of_control":{"type":"array","items":{"type":"string"}},"notified_on":{"type":["string","null"],"format":"date"},"nationality":{"type":["string","null"]},"country_of_residence":{"type":["string","null"]}}}}},"required":["persons"]},"insolvency":{"type":"object","description":"Insolvency proceedings","properties":{"has_active_insolvency":{"type":"boolean"},"cases":{"type":"array","items":{"type":"object"}},"insolvency_fetched_at":{"type":"string","format":"date-time"}},"required":["has_active_insolvency","cases","insolvency_fetched_at"]},"charges":{"type":"object","description":"Companies House registered charges (security interests) against company assets. Always present; a tri-state status distinguishes \"no charges\" from \"not requested / fetch failed\".","properties":{"status":{"type":"string","description":"\"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.","enum":["none","present","unknown"]},"total_count":{"type":"integer"},"satisfied_count":{"type":"integer"},"part_satisfied_count":{"type":"integer"},"outstanding_count":{"type":"integer","description":"Derived: total_count minus satisfied_count minus part_satisfied_count."},"truncated":{"type":"boolean","description":"True when upstream pagination could not return every charge — items is shorter than total_count and must not be treated as a complete list."},"items":{"type":"array","items":{"type":"object","properties":{"charge_number":{"type":"integer"},"status":{"type":"string","enum":["outstanding","satisfied","fully_satisfied","part_satisfied","other"]},"created_on":{"type":["string","null"],"format":"date"},"delivered_on":{"type":["string","null"],"format":"date"},"satisfied_on":{"type":["string","null"],"format":"date"},"persons_entitled":{"type":"array","items":{"type":"string"}},"classification":{"type":["string","null"]},"particulars":{"type":["string","null"]},"contains_floating_charge":{"type":["boolean","null"],"description":"From CH structured particulars. Null when Companies House did not supply the flag."},"floating_charge_covers_all":{"type":["boolean","null"],"description":"True when the floating charge covers the whole undertaking (debenture-style). Null when Companies House did not supply the flag."},"assets_ceased_released":{"type":["string","null"]}},"required":["charge_number","status","created_on","delivered_on","satisfied_on","persons_entitled","classification","particulars","contains_floating_charge","floating_charge_covers_all","assets_ceased_released"]}}},"required":["status","total_count","satisfied_count","part_satisfied_count","outstanding_count","truncated","items"]},"officers":{"type":"object","description":"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.","properties":{"status":{"type":"string","description":"\"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.","enum":["none","present","unknown"]},"total_results":{"type":"integer","description":"Full officer count Companies House holds, regardless of include_resigned."},"active_count":{"type":"integer"},"resigned_count":{"type":"integer"},"truncated":{"type":"boolean","description":"True when the fetched items fell short of total_results (defensive pagination against unreliable upstream paging)."},"items":{"type":"array","description":"Active officers only by default; resigned officers are included when include_resigned=true.","items":{"type":"object","properties":{"officer_id":{"type":["string","null"],"description":"Stable CH officer identifier, parsed from the appointments link. Null when absent or unparseable."},"name":{"type":["string","null"]},"officer_role":{"type":["string","null"],"description":"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_on":{"type":["string","null"],"format":"date"},"appointed_before":{"type":["string","null"],"format":"date","description":"Set instead of appointed_on for appointments predating Companies House's digital record (pre-1992)."},"is_pre_1992_appointment":{"type":"boolean"},"resigned_on":{"type":["string","null"],"format":"date","description":"Null means the officer is currently active."},"nationality":{"type":["string","null"]},"country_of_residence":{"type":["string","null"]},"date_of_birth":{"type":["object","null"],"description":"Month and year only — the day is never returned (data minimisation, same treatment as PSC dates of birth).","properties":{"month":{"type":"integer"},"year":{"type":"integer"}},"required":["month","year"]},"former_names":{"type":"array","items":{"type":"object","properties":{"forenames":{"type":["string","null"]},"surname":{"type":["string","null"]}},"required":["forenames","surname"]}},"identification":{"type":["object","null"],"description":"Corporate officers only. Null for natural persons.","properties":{"legal_form":{"type":["string","null"]},"place_registered":{"type":["string","null"]},"registration_number":{"type":["string","null"]},"legal_authority":{"type":["string","null"]}},"required":["legal_form","place_registered","registration_number","legal_authority"]},"identity_verification":{"type":["object","null"],"description":"ECCTA identity verification details. Null when the upstream record carries none.","properties":{"identity_verified_on":{"type":["string","null"],"format":"date"},"authorised_corporate_service_provider_name":{"type":["string","null"]},"anti_money_laundering_supervisory_bodies":{"type":"array","items":{"type":"string"}},"appointment_verification_statement_due_on":{"type":["string","null"],"format":"date"},"appointment_verification_statement_start_on":{"type":["string","null"],"format":"date"},"appointment_verification_statement_end_on":{"type":["string","null"],"format":"date"},"preferred_name":{"type":["string","null"]}},"required":["identity_verified_on","authorised_corporate_service_provider_name","anti_money_laundering_supervisory_bodies","appointment_verification_statement_due_on","appointment_verification_statement_start_on","appointment_verification_statement_end_on","preferred_name"]}},"required":["officer_id","name","officer_role","appointed_on","appointed_before","is_pre_1992_appointment","resigned_on","nationality","country_of_residence","date_of_birth","former_names","identification","identity_verification"]}},"directors":{"type":"array","items":{"type":"object","description":"Slim derived view of items filtered to the four director role variants (director, corporate-director, nominee-director, corporate-nominee-director), de-duplicated by officer_id. Only entries sharing the same non-null officer_id are merged — Companies House does not unify officer identity across appointments, so the same real person can still appear more than once under distinct IDs.","properties":{"officer_id":{"type":["string","null"]},"name":{"type":["string","null"]},"appointed_on":{"type":["string","null"],"format":"date"},"resigned_on":{"type":["string","null"],"format":"date"}},"required":["officer_id","name","appointed_on","resigned_on"]}}},"required":["status","total_results","active_count","resigned_count","truncated","items","directors"]},"risk_signals":{"type":"object","description":"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.","properties":{"score":{"type":"integer","description":"Points from confirmed (triggered) flags only, 0-100. A floor (lower bound) when score_is_floor is true."},"score_is_floor":{"type":"boolean","description":"When true, a required source was unavailable so score is a lower bound — a low value does not mean low risk."},"potential_score":{"type":"integer","description":"Worst-case ceiling: score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty."},"coverage":{"type":"array","description":"Risk-bearing sources actually consulted for this score. A source absent here was not assessed.","items":{"type":"string","enum":["ch","ch_psc","insolvency","charges"]}},"flags":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["INSOLVENCY_ACTIVE","COMPANY_DISSOLVED","ACCOUNTS_OVERDUE","CONFIRMATION_OVERDUE","COMPANY_VERY_NEW","NO_PSC_RECORDED","OUTSTANDING_CHARGES","ALL_ASSETS_CHARGED"]},"severity":{"type":"string","enum":["critical","warning","info"]},"description":{"type":"string"},"triggered_at":{"type":"string","format":"date-time"}},"required":["code","severity","description","triggered_at"]}},"indeterminate":{"type":"array","description":"Flags that could not be evaluated because a required source was unavailable.","items":{"type":"object","properties":{"code":{"type":"string","enum":["INSOLVENCY_ACTIVE","COMPANY_DISSOLVED","ACCOUNTS_OVERDUE","CONFIRMATION_OVERDUE","COMPANY_VERY_NEW","NO_PSC_RECORDED","OUTSTANDING_CHARGES","ALL_ASSETS_CHARGED"]},"severity":{"type":"string","enum":["critical","warning","info"]},"source":{"type":"string","enum":["ch","ch_psc","insolvency","charges"]},"reason":{"type":"string","enum":["source_unavailable","not_requested","feature_disabled"]}},"required":["code","severity","source","reason"]}}},"required":["score","score_is_floor","potential_score","coverage","flags","indeterminate"]}},"required":["company_number","name","status","fetched_at","sources_checked","sources_failed","ch","ch_psc","insolvency","charges","officers"]}}}},"404":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","const":"company_not_found"},"message":{"type":"string"}},"required":["error","message"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"429":{"description":"Companies 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.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["upstream_capacity"]},"message":{"type":"string"}},"required":["error","message"]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}}}},"/entity/{company_number}/risk":{"get":{"operationId":"entity.risk","tags":["Entity"],"parameters":[{"name":"company_number","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Risk signals for a company","content":{"application/json":{"schema":{"type":"object","properties":{"company_number":{"type":"string"},"risk_signals":{"type":"object","description":"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.","properties":{"score":{"type":"integer","description":"Points from confirmed (triggered) flags only, 0-100. A floor (lower bound) when score_is_floor is true."},"score_is_floor":{"type":"boolean","description":"When true, a required source was unavailable so score is a lower bound — a low value does not mean low risk."},"potential_score":{"type":"integer","description":"Worst-case ceiling: score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty."},"coverage":{"type":"array","description":"Risk-bearing sources actually consulted for this score. A source absent here was not assessed.","items":{"type":"string","enum":["ch","ch_psc","insolvency","charges"]}},"flags":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["INSOLVENCY_ACTIVE","COMPANY_DISSOLVED","ACCOUNTS_OVERDUE","CONFIRMATION_OVERDUE","COMPANY_VERY_NEW","NO_PSC_RECORDED","OUTSTANDING_CHARGES","ALL_ASSETS_CHARGED"]},"severity":{"type":"string","enum":["critical","warning","info"]},"description":{"type":"string"},"triggered_at":{"type":"string","format":"date-time"}},"required":["code","severity","description","triggered_at"]}},"indeterminate":{"type":"array","description":"Flags that could not be evaluated because a required source was unavailable.","items":{"type":"object","properties":{"code":{"type":"string","enum":["INSOLVENCY_ACTIVE","COMPANY_DISSOLVED","ACCOUNTS_OVERDUE","CONFIRMATION_OVERDUE","COMPANY_VERY_NEW","NO_PSC_RECORDED","OUTSTANDING_CHARGES","ALL_ASSETS_CHARGED"]},"severity":{"type":"string","enum":["critical","warning","info"]},"source":{"type":"string","enum":["ch","ch_psc","insolvency","charges"]},"reason":{"type":"string","enum":["source_unavailable","not_requested","feature_disabled"]}},"required":["code","severity","source","reason"]}}},"required":["score","score_is_floor","potential_score","coverage","flags","indeterminate"]},"fetched_at":{"type":"string","format":"date-time"}},"required":["company_number","risk_signals","fetched_at"]}}}},"404":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","const":"company_not_found"},"message":{"type":"string"}},"required":["error","message"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"429":{"description":"Companies 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.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["upstream_capacity"]},"message":{"type":"string"}},"required":["error","message"]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}}}},"/search":{"get":{"operationId":"search.search","tags":["Search"],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","description":"Apply ?type= filter on raw items before normalisation","schema":{"type":"string"}},{"name":"active_only","in":"query","schema":{"type":"string","default":"false"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"total_results":{"anyOf":[{},{"type":"integer","enum":[0]}]},"results":{"type":"array","items":{}}},"required":["query","total_results","results"]}}}},"422":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","const":"invalid_query"},"message":{"type":"string","const":"The q parameter is required and must be at least 2 characters."}},"required":["error","message"]}}}},"503":{"description":"Companies House upstream is at capacity (proactive shed or reactive CH 429), so the search could not be served. The search-endpoint counterpart of the entity endpoints' 429 upstream_capacity. Unrelated to the per-key rate_limit_exceeded quota — retry after the Retry-After interval.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","enum":["upstream_unavailable"]},"message":{"type":"string"}},"required":["error","message"]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}}}}}}}},"components":{"securitySchemes":{"http":{"type":"http","description":"API key prefixed with uk_live_ or uk_test_. Pass as: Authorization: Bearer uk_live_xxx","scheme":"bearer"}},"responses":{"ValidationException":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Errors overview."},"errors":{"type":"object","description":"A detailed description of each field that failed validation.","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["message","errors"]}}}}}}}