Browse documentation
Risk signals
Growth and Enterprise keys receive a risk_signals object on entity lookups and from the /risk endpoint. Flag codes are stable: they are only ever added, never renamed or removed, so you can match on them in code.
For how to read a score, especially when evidence is incomplete, see Interpreting risk signals.
Where risk_signals appears
| Surface | Growth and Enterprise | Free |
|---|---|---|
GET /v1/entity/{company_number} | Top-level risk_signals key, computed from the sources in sources_checked (your tier's sources, or the ?sources= subset). | risk_signals key omitted. |
GET /v1/entity/{company_number}/risk | company_number, risk_signals, fetched_at. Always fetches ch, ch_psc, insolvency, charges and officers. | 403 risk_tier_required |
MCP lookup_uk_company | Same as the entity lookup. | risk_signals key omitted. |
MCP get_company_risk | Same as the /risk endpoint. | risk_tier_required error. |
On a Free key, treat a missing risk_signals key as "not entitled", never as "no risk".
Example
One flag triggered and one flag indeterminate because the insolvency source failed.
{
"score": 20,
"score_is_floor": true,
"potential_score": 70,
"coverage": ["ch", "ch_psc", "charges", "officers"],
"flags": [
{
"code": "ACCOUNTS_OVERDUE",
"severity": "warning",
"description": "Company accounts are overdue",
"triggered_at": "2026-10-12T09:41:07+00:00"
}
],
"indeterminate": [
{
"code": "INSOLVENCY_ACTIVE",
"severity": "critical",
"source": "insolvency",
"reason": "source_unavailable"
}
]
}risk_signals object
Every field is present whenever the object is present.
| Field | Type | Description |
|---|---|---|
score | integer | 0–100. Sum of the points of every triggered flag, capped at 100. |
score_is_floor | boolean | true when indeterminate is non-empty. score is then a lower bound. |
potential_score | integer | 0–100. score plus the points of every indeterminate flag, capped at 100. Equals score when indeterminate is empty. |
coverage | string[] | Risk-bearing sources consulted successfully for this score: requested, not failed, and not resolved unknown. A source absent from this list was not assessed. |
flags | Flag[] | Triggered flags. Empty array when none. |
indeterminate | Indeterminate[] | Flags that could not be evaluated. Empty array when none. |
Flag entry
One entry in flags. Points are not returned per flag; they are listed in the flag tables below.
| Field | Type | Description |
|---|---|---|
code | string | Stable flag code. Match on this field. |
severity | enum | critical, warning or info. |
description | string | Human-readable summary for display. Wording can change. |
triggered_at | string (ISO 8601) | Time of the assessment that produced this response. Not the date the underlying condition began. |
Indeterminate entry
One entry in indeterminate. It has no description or triggered_at.
| Field | Type | Description |
|---|---|---|
code | string | Flag code, from the same set as flags[].code. |
severity | enum | critical, warning or info: the severity the flag would carry if triggered. |
source | string | The first of the flag's required sources that was unavailable. |
reason | enum | Why the flag could not be evaluated. See below. |
reason values
| Value | Emitted | Meaning |
|---|---|---|
source_unavailable | Yes | A required source failed, resolved unknown, or (for DIRECTOR_DISQUALIFIED) did not carry enough data to clear the flag. Often temporary. |
not_requested | Reserved | The caller scoped the source out. Not emitted today. |
feature_disabled | Reserved | The source is switched off platform-wide. Not emitted today. |
Handle unknown reason values without failing.
Indeterminacy rules
| When | Result |
|---|---|
A required source failed during this request (the entity lookup also lists it in sources_failed). | Every flag that requires it is indeterminate. The source is absent from coverage. |
The charges or officers data resolved with status unknown. | Treated as a failed source: same result as above. |
DIRECTOR_DISQUALIFIED did not trigger, the company has at least one live director, and either officers.disqualification_checks.unknown_count is greater than 0 or the disqualification_checks rollup is missing. Only the first 10 live directors are checked, so later directors count as unknown. | Only DIRECTOR_DISQUALIFIED is indeterminate. officers stays in coverage. |
A source was not requested (for example ?sources=ch). | Not indeterminate. Its flags appear in neither flags nor indeterminate, and the source is absent from coverage. |
Source codes
Values that can appear in coverage, in indeterminate[].source and in the Required source(s) column below.
| Source | Description |
|---|---|
ch | Companies House company profile: status, company type, incorporation date, filing deadlines. |
ch_psc | Companies House register of persons with significant control. |
insolvency | Insolvency case records for the company. |
charges | Companies House register of charges (security interests). |
officers | Companies House officers register, with a disqualification check for each live director. |
Severity levels
| Severity | Definition |
|---|---|
| critical | A serious finding on its own: the company is insolvent or dissolved, or a live director is disqualified. |
| warning | A compliance, governance or creditor issue that warrants review. |
| info | Context that is low-weight in isolation. |
Flag codes
Each row links to itself, for example /docs/risk-signals#DIRECTOR_DISQUALIFIED. A flag is evaluated only when all its required sources are available; otherwise it is indeterminate.
Company status, filings and insolvency
| Code | Severity | Points | Required source(s) | Fires when |
|---|---|---|---|---|
INSOLVENCY_ACTIVE | critical | +50 | insolvency | insolvency.is_insolvent is true: at least one insolvency case on record has a status other than closed. |
COMPANY_DISSOLVED | critical | +50 | ch | The top-level status is dissolved. |
ACCOUNTS_OVERDUE | warning | +20 | ch | ch.accounts_overdue is true. |
CONFIRMATION_OVERDUE | warning | +15 | ch | ch.confirmation_overdue is true. |
COMPANY_VERY_NEW | info | +5 | ch | ch.incorporated_on is less than 90 days before the assessment. |
People with significant control
| Code | Severity | Points | Required source(s) | Fires when |
|---|---|---|---|---|
NO_PSC_RECORDED | info | +10 | ch_psc, ch | All of: ch_psc.persons has no active PSC (it is empty, or every entry has a ceased_on date); ch.company_type is ltd or llp; ch.incorporated_on is more than 90 days before the assessment. Never fires for other company types, including plc. Does not change with include_ceased. |
Charges
| Code | Severity | Points | Required source(s) | Fires when |
|---|---|---|---|---|
OUTSTANDING_CHARGES | warning | +15 | charges | charges.status is present and outstanding_count + part_satisfied_count is greater than 0. Part-satisfied charges count as live. Satisfied-only history does not fire. Count-based, so a truncated items list cannot affect it. |
ALL_ASSETS_CHARGED | warning | +10 | charges | charges.status is present and any item with status outstanding or part_satisfied has floating_charge_covers_all set to true. Reads items, so it can miss a charge when truncated is true. Normally fires with OUTSTANDING_CHARGES (+25 together). |
Officers
A live director is an item in officers.items whose officer_role is director, corporate-director, nominee-director or corporate-nominee-director, with resigned_on null. The result does not change with include_resigned.
| Code | Severity | Points | Required source(s) | Fires when |
|---|---|---|---|---|
DIRECTOR_DISQUALIFIED | critical | +40 | officers | officers.disqualification_checks.disqualified_count is greater than 0: at least one live director has a disqualified verdict. Verdicts match on a Companies House identifier, never on a name alone. A disqualification whose disqualified_until date has passed reads as clear. A confirmed hit fires even when other directors could not be checked. Has an extra indeterminacy rule (see indeterminacy rules). |
NO_ACTIVE_DIRECTORS | warning | +20 | officers | All of: the top-level status is active; officers.status is present or none; there is no live director. An active company with a confirmed none officers record fires it. |
SOLE_DIRECTOR_IS_CORPORATE | info | +10 | officers | There is exactly one distinct live director and its officer_role is corporate-director or corporate-nominee-director. Items sharing a non-null officer_id count once; items with a null officer_id each count separately. |
IDENTITY_VERIFICATION_OVERDUE | info | +5 | officers | Any live director has an identity_verification block with identity_verified_on null and an appointment_verification_statement_due_on date that has passed. A null block never fires. |
Related
- Interpreting risk signals — score floors, coverage and incomplete evidence.
sources_checkedandsources_failedare entity envelope fields, documented in the API reference.