---
title: "Whole company page in one request"
method: GET
path: "/v1/company/{company_number}/bundle"
tags: ["Company"]
---

# Whole company page in one request

`GET /v1/company/{company_number}/bundle`

## Request

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

Fetch the profile, compliance, financials, PSC and directors in one call.

Everything the standalone endpoints return, assembled concurrently and
delivered in a single response. Intended for anything that renders a whole
company at once - a page, a report, a dashboard - where five round trips
cost five authentications and five quota decisions to answer one question.

**Sections are independent.** Each is fetched by the same code that serves
its own endpoint, so plan gating, caching and freshness behave identically.
If one fails, its key is `null` and `section_errors` says why; the rest of
the bundle is unaffected. A caller that requires a section must check for
`null` rather than assume presence.

**The profile is the exception.** It is always included and always fatal: a
company that does not exist returns 404 here, exactly as it does on
`/v1/company/{number}`.

**`section_fetched_at`** carries the per-section `fetched_at` instant. Show a
reader the *oldest* of them - collapsing five timestamps into one overstates
the freshness of whichever section was cached longest.

**Credits:** 1. A bundle costs exactly one call against your quota, however
many sections it carries - which is the point of it.

**Upstream usage:** identical to calling the same sections separately - this
saves our per-request overhead, not Companies House calls.

**Example:** `/v1/company/00445790/bundle?include=profile,financials`

## Path parameters

- `company_number` string, required: The Companies House company number (e.g. `00445790` for Tesco PLC). Numeric-only numbers are zero-padded.

## Query parameters

- `include` string, nullable: Comma-separated sections to return: `profile`, `compliance`, `financials`, `psc`, `directors`. Defaults to all five. `profile` is always included. An unrecognised name is a 400 rather than being ignored.

## Response `200`

Bundle returned; individual sections may be null with a reason in `section_errors`

- BundleEnvelope: Response envelope for GET /v1/company/{company_number}/bundle.
  - `status` string: 'success' or 'error'
  - `data` CompanyBundle: Everything needed to render a company page, in one response.
    - `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.
    - `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).
    - `financials` union: Financials, or the `available: false` shape; null if not requested or failed (see `section_errors`)
      - 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
    - `psc` PSCListResponse: Enriched PSC register for a company.
      - `company_number` string, required: The queried company number
      - `active_pscs` object[]: Currently active PSCs (individuals, corporate entities, legal persons, super-secure)
      - `ceased_pscs` object[]: PSCs that have ceased
      - `total_active` integer: Count of active PSCs
      - `total_ceased` integer: Count of ceased PSCs
      - `has_psc_exemption` boolean: True if company is exempt from PSC filing (e.g., listed PLCs)
    - `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.
    - `section_errors` object, required: Section name to the reason it is null (status-prefixed, e.g. `403: ...`); empty when every section succeeded
    - `section_fetched_at` object, required: Section name to that section's own `fetched_at` instant. Show readers the oldest, not a single collapsed value
  - `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 or empty company number (blank path segment), or an unknown value in `include`
- `401`: Missing or invalid API key
- `404`: Company not found at Companies House
- `422`: Validation Error
- `502`: Companies House API is temporarily 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)
