---
title: "Get a full Know Your Business (KYB) report"
method: GET
path: "/v1/company/{company_number}/kyb-report"
tags: ["KYB"]
---

# Get a full Know Your Business (KYB) report

`GET /v1/company/{company_number}/kyb-report`

## Request

- Base URL: `https://api.registrum.co.uk`
- URL: `https://api.registrum.co.uk/v1/company/{company_number}/kyb-report`
- Auth: API key in header `X-API-Key`

Get a comprehensive Know Your Business (KYB) report for a UK company.

Aggregates the company profile, financial data, director information, and a computed
set of risk flags into a single response. Suitable for onboarding, due diligence,
and automated KYB workflows.

**Report sections:**

- **profile** - enriched company profile (status, age, address, SIC codes)
- **financials** - latest filed accounts (balance sheet + P&L). `null` if no digital filing exists.
- **directors** - current and past directors with their other appointments
- **psc_chain** - PSC ownership chain resolved to ultimate beneficial owners. Each node has a
  `terminal_reason` (natural_person, foreign_entity, legal_person, psc_exempt, depth_limit,
  not_found, cycle_detected). `null` if chain resolution fails.
- **compliance** - ECCTA identity-verification snapshot for the directors and individual
  PSCs the regime actually applies to, identical to `/v1/company/{number}/compliance`.
  **Read `status` before calling anyone non-compliant**: `pending` means the deadline has
  not arrived yet and nothing has been missed, which is the majority state for UK
  directors during the Nov 2025 - Nov 2026 transition. Only `overdue` is a missed
  deadline. `null` for Free and Web plans, which the compliance endpoint does not cover.
- **risk_flags** - boolean flags derived from the profile and filing data:
  - `accounts_overdue` - accounts past their filing deadline
  - `confirmation_overdue` - confirmation statement overdue
  - `has_charges` - company has registered charges (e.g., mortgages)
  - `has_insolvency_history` - any insolvency history on record
  - `not_active` - company is not in active status (dissolved, liquidation, etc.)
  - `recently_incorporated` - less than 1 year old
  - `financials_unavailable` - no parseable digital accounts filing exists
  - `no_accounts_type` - no accounts type recorded (dormant or never filed)
- **summary_md** - LLM-ready Markdown combining profile + financials summaries

**Credits:** 1. A KYB report costs exactly one call against your quota, however many
sections it carries. `psc_chain.chain_metadata.total_credits` counts companies resolved
in the ownership chain, which is a measure of chain depth, not of quota spent.

**Cache behaviour:** All underlying data sources are served from cache where available.
Profile: 30-day TTL. Financials: 90-day TTL. Directors: 30-day TTL. PSC: fetched fresh per call.

**Example:** `/v1/company/00445790/kyb-report` returns a full KYB report for Tesco PLC.

## Path parameters

- `company_number` string, required: Companies House company number (e.g. `00445790` for Tesco PLC).

## Response `200`

KYB report returned. Financials and directors sections may be null if unavailable.

- KYBReportEnvelope: Response envelope for GET /v1/company/{company_number}/kyb-report.
  - `status` string: 'success' or 'error'
  - `data` KYBReport: Aggregated Know Your Business report.
    - `company_number` string, required: The queried company number
    - `profile` CompanyProfile, required: An enriched company profile with data derived from the Companies House record.
      - `company_number` string, required: 8-character Companies House number (e.g., '00445790')
      - `company_name` string, required: Official registered company name
      - `company_status` string, nullable: Current status: 'active', 'dissolved', 'liquidation', 'receivership', etc.
      - `company_type` string, nullable: Legal type: 'ltd', 'plc', 'llp', etc.
      - `date_of_creation` string, date, nullable: Date the company was incorporated
      - `company_age_years` integer, nullable: Calculated years since incorporation
      - `registered_office_address` Address: A UK registered office address.
        - `premises` string, nullable: Building name or number
        - `address_line_1` string, nullable: Street address
        - `address_line_2` string, nullable: Additional address line
        - `locality` string, nullable: Town or city
        - `region` string, nullable: County or region
        - `postal_code` string, nullable: UK postcode
        - `country` string, nullable: Country
      - `sic_codes` string[]: Standard Industrial Classification codes describing the business activity
      - `accounts` AccountsInfo: Filing status for the company's annual accounts.
        - `last_accounts_type` string, nullable: Type of last filed accounts (e.g., 'full', 'micro-entity', 'group')
        - `last_accounts_made_up_to` string, date, nullable: Period end date of last filed accounts
        - `next_accounts_due` string, date, nullable: Deadline for next accounts filing
        - `overdue` boolean: True if accounts are past their filing deadline
      - `confirmation_statement` ConfirmationStatement: Filing status for the company's annual confirmation statement.
        - `last_made_up_to` string, date, nullable: Date of last confirmation statement
        - `next_due` string, date, nullable: Deadline for next confirmation statement
        - `overdue` boolean: True if confirmation statement is overdue
      - `company_category` string, nullable: Inferred size: 'micro', 'small', 'medium', 'large', 'dormant'
      - `has_charges` boolean, nullable: Whether the company has registered charges (e.g., mortgages)
      - `has_insolvency_history` boolean, nullable: Whether the company has any insolvency history
      - `summary_md` string, nullable: Pre-formatted Markdown summary of the company profile, suitable for embedding directly into an LLM prompt or agent reasoning chain. Covers status, address, SIC codes, accounts filing dates, and key flags. Null only if company data is missing.
    - `financials` union: Latest filed accounts, or the `available: false` shape; null if the section failed
      - CompanyFinancials: Structured financial data extracted from a company's filed accounts. Source may be iXBRL (structured markup - precise) or PDF (text/table parsing - good coverage but check data_quality.field_confidence for per-field reliability). All monetary values are in actual GBP (pounds). A value of 5200000 means £5,200,000. The data_quality section explains what was and wasn't extracted, and why. Use accounts_type to understand what fields to expect: - 'full': all sections available - 'abbreviated': balance sheet only (no turnover or profit) - 'micro': balance sheet only (micro-entities are legally exempt from P&L disclosure) - 'dormant': minimal balance sheet only
        - `company_number` string, required: Companies House company number.
        - `company_name` string, nullable: Registered company name.
        - `accounts_type` string, required: Type of accounts filed. Mirrors data_quality.accounts_type for convenience.
        - `period_end` string, nullable: Accounting period end date (YYYY-MM-DD).
        - `period_start` string, nullable: Accounting period start date (YYYY-MM-DD).
        - `currency` string: Currency of all monetary values.
        - `data_quality` DataQuality, required: Metadata about what was extracted and why fields may be missing. This is the transparency layer - every null in profit_and_loss or balance_sheet has an explanation here.
          - `source` string: How financial data was extracted. 'ixbrl' = structured inline XBRL markup (high precision). 'pdf_extracted' = PDF text/table parsing (good coverage, see field_confidence for per-field reliability).
          - `accounts_type` string, required: Type of accounts filed: 'full', 'abbreviated', 'micro', 'dormant', or 'unknown'. Micro and abbreviated accounts legally exclude P&L - turnover and profit fields will be null. This is expected, not a data error. Changed 2026-08-01 (CH-Api#61): this was previously derived by keyword-matching Companies House's machine-readable filing code against a list of English prose phrases, and anything unmatched defaulted to 'full'. About 17% of filers were mis-typed - most commonly `unaudited-abridged`, which is now correctly 'abbreviated'. Values that were already right are unchanged. See `accounts_description_code` for the verbatim Companies House code and `accounts_type_source` for how this value was resolved.
          - `accounts_type_source` string, nullable: How `accounts_type` was determined: 'ch_filing_description' (read from the Companies House filing code - the normal case), 'xbrl_namespace' (inferred from the accounting taxonomy declared inside the document, e.g. FRS-105 = micro), 'pl_presence_inference' (the filing carries no type but the document plainly contains a profit and loss account), or 'unresolved' (nothing identified it; `accounts_type` is 'unknown' and scoring falls back to the balance sheet only).
          - `accounts_description_code` string, nullable: The verbatim Companies House accounts-type code from the filing description, e.g. 'total-exemption-full', 'unaudited-abridged', 'micro-entity'. Null when the filing description carries no accounts type at all (`accounts-with-made-up-date`). Exposed so you can apply your own classification rather than trusting ours.
          - `completeness` number, required: Fraction of expected fields successfully extracted (0.0–1.0). The denominator is set per accounts_type: 20 fields for 'full', 13 for 'abbreviated', 5 for 'micro', 4 for 'dormant', and 12 (balance sheet only) for 'unknown'. A score of 0.85 on full accounts is normal. Note this score generally ROSE on 2026-08-01 for abridged and small-company filers (CH-Api#61): they had been scored against a profit and loss account they are legally forbidden to file.
          - `fields_attempted` integer, required: Number of fields expected for this accounts_type - the denominator of `completeness`. 20 for 'full', 13 for 'abbreviated', 5 for 'micro', 4 for 'dormant', 12 for 'unknown'.
          - `fields_extracted` integer, required: Number of fields successfully extracted from the filing.
          - `has_profit_loss` boolean, required: Whether P&L data (turnover, profit, etc.) was found in the filing. False for micro-entities and abbreviated accounts - this is legal, not an error.
          - `has_balance_sheet` boolean, required: Whether balance sheet data was found. Should be True for all UK companies.
          - `missing_fields` string[], required: List of field names that are null in this response. For full accounts, this may include optional fields not filed. For micro/abbreviated accounts, this will include all P&L fields.
          - `field_confidence` object: Per-field confidence score (0.0–1.0) for PDF-extracted data. Empty for iXBRL (iXBRL extraction is deterministic - implicit 1.0). Use this to filter out low-confidence PDF extractions. Scores below 0.70 indicate a broad/fuzzy label match.
          - `period_end` string, nullable: Accounting period end date (YYYY-MM-DD) - the date the accounts are made up to. Until 2026-08-01 (CH-Api#60) this was the date the filing was submitted to Companies House, which is a different and later date (commonly by months). It is now taken from the filing's `made_up_date`, or from the document's own reporting contexts. See `period_end_source` for which. The submission date is still available, unchanged, as `filed_on`.
          - `period_end_source` string, nullable: Where `period_end` came from, so you can audit it: 'description_values.made_up_date' (the Companies House filing's own made-up-to date - the normal case), 'document_context' (the reporting period declared inside the filed document itself), 'description_values.action_date', or 'filing_date' (a legacy paper filing that carries no period metadata - treat with caution).
          - `filed_on` string, nullable: The date the selected filing was submitted to Companies House (YYYY-MM-DD). Distinct from `period_end`: accounts for a period ending 31 December are typically filed the following year.
          - `filing_type` string, nullable: The Companies House form code of the filing these figures were extracted from: 'AA' (annual accounts), 'AAMD' (amended accounts) or 'AC(NI)' (legacy Northern Irish accounts). Administrative forms in the same filing-history category - 'AA01' change of accounting reference date and friends - are never selected (CH-Api#60).
          - `period_start` string, nullable: Accounting period start date (YYYY-MM-DD), where available.
          - `currency` string: Currency of all monetary values. Almost always GBP for UK companies.
          - `taxonomy_version` string, nullable: XBRL taxonomy version detected from the filing namespace.
          - `turnover_tag_unmapped` boolean, nullable: Parse-failure flag for turnover (CH-Api#150). true = the iXBRL document contains a turnover/revenue-named tag that we do not recognise AND no turnover was extracted, so a null turnover here is probably our miss, not the filing omitting it - see `turnover_unmapped_concepts`. false = either turnover was extracted or no such tag exists (null turnover then genuinely means not published). null = not checked: PDF-extracted data, or a response cached before this check existed.
          - `turnover_unmapped_concepts` string[], nullable: Up to 5 raw tag names (e.g. 'core:TurnoverFromWidgets') behind `turnover_tag_unmapped: true`. Empty list when the flag is false; null when not checked (PDF data or a pre-existing cached response).
          - `turnover_untagged_suspected` boolean, nullable: true = turnover is null because the filing probably prints the Turnover row without any iXBRL tag (CH-Api#179): cost of sales or gross profit is tagged but no turnover is, and no turnover-named tag was missed. The figure exists in the filed document but cannot be read from its tags; we do not guess it from text. false = turnover extracted, or no evidence the filing has sales. null = not checked: PDF-extracted data, or a response cached before this check.
          - `dimensioned_fallback_fields` string[], nullable: Fields whose value comes from a dimension-qualified fact (e.g. one segment or business line) because the filing tags no entity-level total for them (CH-Api#180). Treat those values as a part, not the whole. Empty list when every value is entity-level; null for PDF-extracted data.
        - `profit_and_loss` ProfitAndLoss, required: Profit & loss account figures. Only available in full accounts.
          - `turnover` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `gross_profit` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `operating_profit` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `profit_before_tax` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `tax` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `profit_after_tax` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `depreciation` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
        - `balance_sheet` BalanceSheet, required: Balance sheet figures. Available for all companies (UK law mandates it).
          - `fixed_assets` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `intangible_assets` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `current_assets` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `stocks` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `debtors` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `cash` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `creditors_within_one_year` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `creditors_after_one_year` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `net_assets` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `equity` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `share_capital` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
          - `retained_earnings` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
        - `other` OtherMetrics, required: Non-financial metrics extracted from accounts.
          - `employees` FinancialValue: A financial figure with current and prior year comparison.
            - `current` integer, nullable: Value for the current reporting period, in actual GBP (£). Null if not reported in this filing.
            - `prior` integer, nullable: Comparative value for the prior reporting period, in actual GBP (£). Null if not included in the filing.
        - `summary_md` string, nullable: Pre-formatted Markdown table of key financial figures, suitable for embedding directly into an LLM prompt or agent reasoning chain. Covers turnover, profit, net assets, and employees with current and prior year comparisons. Null if no financial data is available (e.g. image-based PDF filing).
      - FinancialsUnavailable: The `/financials` payload when no accounts could be read for the company. Returned (with HTTP 200) instead of `CompanyFinancials` when the company has no filed accounts we can parse. Check `available` before reading anything else: when false, the `profit_and_loss`, `balance_sheet`, `other`, `data_quality` and `summary_md` keys are present but null.
        - `company_number` string, required: Companies House company number.
        - `company_name` string, nullable: Registered company name.
        - `available` boolean, required: Always false in this shape. `CompanyFinancials` payloads do not use this key to signal success; distinguish the two shapes by this key's presence.
        - `unavailable_reason` string, required: Why no financial data could be returned (e.g. no accounts filed, or filed as an image-only document).
        - `company_status` string, nullable: Company status from the Companies House profile (e.g. 'active').
        - `accounts_category` string, nullable: Companies House accounts category of the last filing (e.g. 'full', 'group', 'micro-entity').
        - `last_accounts_date` string, nullable: Period end date of the last filed accounts (YYYY-MM-DD).
        - `accounts_next_due` string, nullable: Date the next accounts are due (YYYY-MM-DD).
        - `profit_and_loss` unknown
        - `balance_sheet` unknown
        - `other` unknown
        - `data_quality` unknown
        - `summary_md` unknown
    - `directors` DirectorsResponse: Directors for a company, split into current (active) and past (resigned) with their other appointments.
      - `company_number` string, required: 8-character Companies House number
      - `company_name` string, nullable: Registered company name
      - `company_status` string, nullable: Company status: 'active', 'dissolved', 'liquidation', etc. Useful context - a dissolved company's directors may show no resignation date even though the company no longer exists
      - `current_directors` Director[]: Directors currently serving on the board
        - `name` string, required: Full name as registered at Companies House (usually SURNAME, Forenames)
        - `officer_role` string, required: Role at the target company (e.g., 'director', 'secretary', 'llp-member')
        - `appointed_on` string, date, nullable: Date this person was appointed to the target company
        - `resigned_on` string, date, nullable: Date this person resigned (null if still serving)
        - `nationality` string, nullable: Nationality as declared to Companies House
        - `occupation` string, nullable: Declared occupation
        - `date_of_birth` DateOfBirth: Month and year of birth only - Companies House redacts the full date for privacy.
          - `month` integer, nullable: Birth month (1-12)
          - `year` integer, nullable: Birth year
        - `officer_id` string, nullable: Companies House officer ID (extracted from appointment links)
        - `other_appointments` DirectorAppointment[]: Other companies this person is or was appointed to - the basis for network mapping
          - `company_number` string, required: 8-character Companies House number of the appointed company
          - `company_name` string, required: Registered name of the appointed company
          - `company_status` string, nullable: Status of the appointed company: 'active', 'dissolved', etc.
          - `officer_role` string, required: Role held at this company (e.g., 'director', 'secretary')
          - `appointed_on` string, date, nullable: Date this appointment started
          - `resigned_on` string, date, nullable: Date the appointment ended (null if still active)
        - `identity_verified` boolean, nullable: ECCTA identity verification status, collapsed to a tri-state boolean for convenience. True = verified with Companies House (a confirmed identity_verified_on date exists). False = genuinely overdue - Companies House recorded a deadline that HAS passed with no verification. Before CH-Api#52 this also covered pending people (a future deadline), which wrongly branded ~70% of live officers as unverified; it no longer does. None covers every other case - pending (a deadline recorded but not yet due), unknown (no verification data on record at all), or not_applicable (this officer is outside ECCTA verification, e.g. a corporate officer or secretary). See verification_status to distinguish those three.
        - `identity_verified_on` string, date, nullable: Date identity verification was completed, as recorded by Companies House. Only set when identity_verified is True.
        - `verification_status` string, nullable: The full ECCTA verification state: 'verified' (identity_verified_on present), 'pending' (Companies House recorded a deadline or verification window that has NOT passed - nothing has been missed, this person owes nothing yet), 'overdue' (a recorded deadline has passed with no verification), 'unknown' (no verification data on record at all - not evidence of non-compliance, just absence of data), or 'not_applicable' (this officer is outside ECCTA identity verification entirely - a corporate officer, which has no personal identity to verify, or a secretary, who is not in scope of the regime).
        - `verification_deadline` string, date, nullable: This person's own verification deadline as recorded by Companies House - authoritative and per-person, not a company-wide date. Set only when verification_status is 'pending' or 'overdue'. Companies House writes 9999-12-31 internally to mean an open-ended verification window; that sentinel is never surfaced here - an open-ended window returns null rather than a fake calendar date a chase email could quote.
        - `is_board_director` boolean: True if this officer is a genuine board director (governance role), False only for secretaries. Distinct from ECCTA scope: a corporate director (a company acting as director) IS a board director (is_board_director: true) even though it cannot personally verify an identity (verification_status: not_applicable). Secretaries remain in current_directors/past_directors - this field controls only who counts toward the verification totals and who contributes to /network connections, not who appears in the officer list.
      - `past_directors` Director[]: Directors who have resigned
        - `name` string, required: Full name as registered at Companies House (usually SURNAME, Forenames)
        - `officer_role` string, required: Role at the target company (e.g., 'director', 'secretary', 'llp-member')
        - `appointed_on` string, date, nullable: Date this person was appointed to the target company
        - `resigned_on` string, date, nullable: Date this person resigned (null if still serving)
        - `nationality` string, nullable: Nationality as declared to Companies House
        - `occupation` string, nullable: Declared occupation
        - `date_of_birth` DateOfBirth: Month and year of birth only - Companies House redacts the full date for privacy.
          - `month` integer, nullable: Birth month (1-12)
          - `year` integer, nullable: Birth year
        - `officer_id` string, nullable: Companies House officer ID (extracted from appointment links)
        - `other_appointments` DirectorAppointment[]: Other companies this person is or was appointed to - the basis for network mapping
          - `company_number` string, required: 8-character Companies House number of the appointed company
          - `company_name` string, required: Registered name of the appointed company
          - `company_status` string, nullable: Status of the appointed company: 'active', 'dissolved', etc.
          - `officer_role` string, required: Role held at this company (e.g., 'director', 'secretary')
          - `appointed_on` string, date, nullable: Date this appointment started
          - `resigned_on` string, date, nullable: Date the appointment ended (null if still active)
        - `identity_verified` boolean, nullable: ECCTA identity verification status, collapsed to a tri-state boolean for convenience. True = verified with Companies House (a confirmed identity_verified_on date exists). False = genuinely overdue - Companies House recorded a deadline that HAS passed with no verification. Before CH-Api#52 this also covered pending people (a future deadline), which wrongly branded ~70% of live officers as unverified; it no longer does. None covers every other case - pending (a deadline recorded but not yet due), unknown (no verification data on record at all), or not_applicable (this officer is outside ECCTA verification, e.g. a corporate officer or secretary). See verification_status to distinguish those three.
        - `identity_verified_on` string, date, nullable: Date identity verification was completed, as recorded by Companies House. Only set when identity_verified is True.
        - `verification_status` string, nullable: The full ECCTA verification state: 'verified' (identity_verified_on present), 'pending' (Companies House recorded a deadline or verification window that has NOT passed - nothing has been missed, this person owes nothing yet), 'overdue' (a recorded deadline has passed with no verification), 'unknown' (no verification data on record at all - not evidence of non-compliance, just absence of data), or 'not_applicable' (this officer is outside ECCTA identity verification entirely - a corporate officer, which has no personal identity to verify, or a secretary, who is not in scope of the regime).
        - `verification_deadline` string, date, nullable: This person's own verification deadline as recorded by Companies House - authoritative and per-person, not a company-wide date. Set only when verification_status is 'pending' or 'overdue'. Companies House writes 9999-12-31 internally to mean an open-ended verification window; that sentinel is never surfaced here - an open-ended window returns null rather than a fake calendar date a chase email could quote.
        - `is_board_director` boolean: True if this officer is a genuine board director (governance role), False only for secretaries. Distinct from ECCTA scope: a corporate director (a company acting as director) IS a board director (is_board_director: true) even though it cannot personally verify an identity (verification_status: not_applicable). Secretaries remain in current_directors/past_directors - this field controls only who counts toward the verification totals and who contributes to /network connections, not who appears in the officer list.
      - `total_current` integer: Count of current directors
      - `total_past` integer: Count of past directors
      - `directors_verified` integer: Current directors with confirmed ECCTA identity verification (identity_verified_on present). Excludes corporate officers and secretaries (see directors_verification_required).
      - `directors_pending` integer: Current directors with a Companies House verification deadline or window that has NOT yet passed. Nothing has been missed - this is not a risk indicator, it reflects the ongoing Nov 2025 - Nov 2026 ECCTA transition.
      - `directors_overdue` integer: Current directors with a recorded verification deadline that HAS passed with no verification on record. The only state that represents genuine non-compliance.
      - `directors_unverified` integer: Documented alias of directors_overdue, retained for backwards compatibility. Before CH-Api#52 this field also counted pending directors (a future deadline); it no longer does - it now means exactly 'overdue'.
      - `directors_unknown` integer: Current directors with no identity_verification_details in the CH API response at all - absence of data, not evidence of non-compliance.
      - `directors_verification_required` integer: Count of current directors ECCTA verification actually applies to - excludes corporate officers and secretaries, who are not_applicable and therefore never counted here. Invariant: directors_verified + directors_pending + directors_overdue + directors_unknown == directors_verification_required <= total_current.
    - `psc_chain` PSCChainNode: A company in the ownership chain with its active PSCs. The root node also carries `chain_metadata`.
      - `company_number` string, required: Companies House company number of this node
      - `company_name` string, nullable: Company name; null for deeper nodes not already cached, or when the name could not be fetched
      - `pscs` PSCChainEntry[]: Active PSCs of this company (ceased PSCs are skipped), or a single marker entry when the branch stopped
        - `kind` 'individual' | 'corporate-entity' | 'legal-person' | 'super-secure' | 'unknown' | 'exempt' | 'cycle' | 'error', required: Normalised PSC kind, or a marker kind (`exempt`, `cycle`, `error`) for a branch that stopped without a PSC
        - `kind_raw` string, nullable: Companies House's verbatim PSC kind (e.g. `individual-person-with-significant-control`); absent on marker kinds
        - `name` string, nullable: PSC name; absent on super-secure and marker entries
        - `terminal` boolean, required: True if the traversal stopped at this entry; false when it was followed into `children`
        - `terminal_reason` 'natural_person' | 'foreign_entity' | 'unverified_registry' | 'legal_person' | 'super_secure' | 'psc_exempt' | 'depth_limit' | 'not_found' | 'cycle_detected' | 'unknown_kind', nullable: Why the branch stopped; null when the entry was followed into `children`
        - `note` string, nullable: Human-readable explanation on marker entries (`exempt`, `cycle`, `error`)
        - `description` string, nullable: Super-secure PSCs only: Companies House's description code
        - `natures_of_control` string[], nullable: Raw Companies House control type codes
        - `natures_of_control_decoded` string[], nullable: Human-readable control descriptions
        - `notified_on` string, nullable: Date Companies House was notified (ISO 8601)
        - `nationality` string, nullable: Individuals only: nationality
        - `country_of_residence` string, nullable: Individuals only: country of residence
        - `identity_verified` boolean, nullable: Individuals only: true if verified, false if overdue only, null if pending or unknown. Same meaning as on /psc
        - `identity_verified_on` string, nullable: Individuals only: date verification was completed (ISO 8601); set only when `verification_status` is `verified`
        - `verification_status` 'verified' | 'pending' | 'overdue' | 'unknown', nullable: Individuals only: ECCTA verification state. Same meaning as on /psc; absent on non-individual entries
        - `verification_deadline` string, nullable: Individuals only: that person's own Companies House deadline, set only when `pending` or `overdue`
        - `company_number` string, nullable: Corporate entities only: normalised Companies House number if the entity is a confirmed UK registration, else null
        - `registry_number` string, nullable: Corporate entities only: registration number as filed, at whatever registry
        - `registry_name` string, nullable: Corporate entities only: registry name as filed
        - `registry_is_companies_house` boolean, nullable: Corporate entities only: true if the registration is confirmed as Companies House, false if no registration number is filed, null if a number is filed but cannot be tied to the UK register
        - `identification` PSCIdentification: Identification details for corporate entity or legal person PSCs.
          - `country_registered` string, nullable: Country of registration
          - `legal_authority` string, nullable: Governing legal authority
          - `legal_form` string, nullable: Legal form (e.g., 'Limited Company')
          - `place_registered` string, nullable: Place of registration (e.g., 'England And Wales')
          - `registration_number` string, nullable: Registration number at the registering authority
        - `children` PSCChainNode (recursive)
      - `chain_metadata` PSCChainMetadata: Traversal statistics for a PSC chain.
        - `companies_resolved` integer, required: Number of distinct companies whose PSC register was fetched
        - `max_depth_reached` boolean, required: True if any branch stopped at `max_depth`
        - `depth_used` integer, required: Number of distinct companies visited (the traversal's size, not its tree height)
        - `unresolved_branches` integer, required: Branches that stopped on `depth_limit`, `not_found` or `cycle_detected`
        - `total_credits` integer, required: Upstream Companies House calls spent resolving the chain (one per company); a measure of chain size, not of API quota spent
    - `compliance` ComplianceResponse: ECCTA identity verification health snapshot for a company.
      - `company_number` string, required: 8-character Companies House number
      - `directors_total` integer: Current, in-scope directors: resigned officers are excluded, AND so are corporate officers and secretaries, who are outside ECCTA identity verification (requires_identity_verification()). This is NOT the board size and does NOT equal /company/{number}/directors' `total_current`, which counts every current officer including secretaries and corporate officers.
      - `directors_verified` integer: Current directors with a confirmed ECCTA identity_verified_on date.
      - `directors_pending` integer: Current directors with a Companies House verification deadline that has NOT yet passed. They have missed nothing. During the Nov 2025 - Nov 2026 ECCTA transition this is the majority state for UK directors.
      - `directors_overdue` integer: Current directors whose verification deadline has passed with no verification recorded.
      - `directors_unverified` integer: DEPRECATED alias of `directors_overdue`, kept for backwards compatibility. It previously also counted directors with a future deadline, which mislabelled roughly 70% of officers as non-compliant (CH-Api#52). Use `directors_pending` and `directors_overdue`.
      - `directors_unknown` integer: Current directors where identity_verification_details is absent from the CH API response.
      - `pscs_total` integer: Active individual PSCs (corporate entities and legal persons are exempt from ECCTA IV).
      - `pscs_verified` integer: Active individual PSCs with a confirmed ECCTA identity_verified_on date.
      - `pscs_pending` integer: Active individual PSCs whose verification deadline has NOT yet passed.
      - `pscs_overdue` integer: Active individual PSCs whose verification deadline has passed with no verification recorded.
      - `pscs_unverified` integer: DEPRECATED alias of `pscs_overdue`, kept for backwards compatibility. See `directors_unverified`.
      - `pscs_unknown` integer: Active individual PSCs where identity_verification_details is absent.
      - `verification_rate` number: verified / (verified + pending + overdue), with directors and individual PSCs combined into one figure (not reported separately). Unknown persons are excluded from both the numerator and the denominator. Returns 0.0 when nobody is verified, pending or overdue.
      - `verification_risk` string, required: 'compliant' - all persons verified; 'partial' - some verified, some not; 'pending' - nobody verified yet but NO deadline has passed, so nothing is wrong; 'high_risk' - at least one person's deadline has passed with no verification; 'unknown' - no identity_verification_details on any person. A future deadline is deliberately NOT a risk: during the ECCTA transition most UK directors legitimately have one, and treating that as risk brands almost the whole register high_risk (CH-Api#52).
      - `unverified_persons` UnverifiedPerson[]: Every director/PSC whose status is 'pending' OR 'overdue' - see UnverifiedPerson.status. This is deliberately longer than directors_unverified + pscs_unverified, which count 'overdue' only; do not expect the two to match. Persons with an unknown status (no identity_verification_details on record) are excluded from this list.
        - `name` string, required: Full name as registered at Companies House
        - `role` string, required: Officer role (e.g. 'director') or 'individual' for PSCs
        - `kind` string, required: 'director' or 'psc'
        - `status` string: 'pending' - Companies House shows a verification deadline that has NOT yet passed; 'overdue' - the deadline has passed with no verification recorded.
        - `deadline` string, nullable: The person's own verification deadline from Companies House (appointment_verification_end_on, else appointment_verification_statement_due_on). This is authoritative and per-person - prefer it over any deadline computed from the company's confirmation-statement date.
      - `eccta_enforcement_deadline` string: The ECCTA identity verification enforcement deadline: 18 November 2026.
      - `risk_score` number, nullable: Numeric risk score from 0.0 (fully compliant) to 1.0 (fully non-compliant). Computed as 1.0 - verification_rate when at least one person's status is known. null when all persons have no identity_verification_details field (status unknown).
    - `risk_flags` KYBRiskFlags, required: Boolean risk flags derived from the profile and filing data.
      - `accounts_overdue` boolean, required: Accounts are past their filing deadline
      - `confirmation_overdue` boolean, required: Confirmation statement is overdue
      - `has_charges` boolean, required: Company has registered charges (e.g. mortgages)
      - `has_insolvency_history` boolean, required: Any insolvency history on record
      - `not_active` boolean, required: Company status is not active (dissolved, liquidation, etc.)
      - `recently_incorporated` boolean, required: Company is less than one year old
      - `financials_unavailable` boolean, required: No parseable digital accounts filing exists
      - `no_accounts_type` boolean, required: No accounts type recorded (dormant or never filed)
    - `summary_md` string, nullable: LLM-ready Markdown combining the profile and financials summaries; null when neither has one
  - `cached` boolean: True if this response was served from cache rather than fetched live
  - `cache_age_seconds` integer, nullable: How many seconds ago this data was fetched from Companies House (null if not cached)
  - `fetched_at` string, nullable: ISO 8601 instant (UTC) when this data was actually fetched from Companies House. Use this, not cache_age_seconds, to show a user when the data was last checked: an age is measured at the moment this response was produced, so anything that caches the response downstream will overstate freshness by however long it held it. This instant does not drift. Null when unknown - render nothing rather than a guessed date.
  - `data_source` string: 'live' - fetched from Companies House right now; 'cached' - served from local cache (data is recent, no upstream call needed); 'cached_rate_conserved' - served from cache because the CH API budget is above 70% utilisation; data may be up to 30 days old in this state
  - `credits_used` integer: Number of API credits consumed by this request
  - `credits_remaining` integer, nullable: API credits remaining this month (null in dev mode)

## Other responses

- `400`: Invalid company number format, or the company number is empty (blank path segment)
- `401`: Missing or invalid API key
- `404`: Company not found
- `422`: Validation Error
- `502`: Companies House API unavailable
- `503`: Request shed to protect shared Companies House capacity; retry after the seconds given in the Retry-After header

---

[API](https://skmtc.dev/registrum/apis/registrum-api.md) · [All operations](https://skmtc.dev/registrum/apis/registrum-api/llms.txt) · [OpenAPI document](https://skmtc.dev/registrum/apis/registrum-api/revisions/2bf0ecf7cc02?raw)
