PSC

Resolve PSC ownership chain to find ultimate beneficial owners

Resolve the PSC ownership chain for a company, traversing corporate entity PSCs recursively.

Starting from the given company, fetches its PSCs. When a PSC is a corporate entity registered at Companies House, follows it to find that company's PSCs, and so on, until reaching natural persons, foreign entities, or the depth limit.

Terminal reasons explain why a branch stopped:

  • natural_person - reached an individual (ultimate beneficial owner)
  • legal_person - reached a legal person (e.g., government body)
  • super_secure - person's details protected by court order
  • foreign_entity - corporate entity with no registration number filed at all
  • unverified_registry - a registration number is filed, but it cannot be tied to the Companies House register (a foreign registry, or a registry name we do not recognise). The branch stops rather than following a number that may belong to an unrelated UK company. registry_number and registry_name on the node say what was filed.
  • depth_limit - max traversal depth reached
  • not_found - company not found or API error
  • cycle_detected - circular ownership detected
  • psc_exempt - company exempt from PSC filing (e.g., listed PLC)
  • unknown_kind - Companies House returned a PSC kind we have not classified. The branch stops rather than guessing; kind_raw carries the raw value.

ECCTA identity verification. Every individual node in the tree - at any depth, including the ultimate beneficial owners the chain exists to find - carries the same four fields as /company/{number}/psc, with the same meanings:

  • verification_status - verified | pending | overdue | unknown
  • identity_verified - true (verified), false (overdue only), or null for pending and unknown. A pending person has missed nothing.
  • identity_verified_on - set only when verification_status is verified
  • verification_deadline - that person's own Companies House deadline, set only when pending or overdue. Companies House's open-ended-window sentinel (9999-12-31) is never surfaced; such a person is pending with a null deadline.

Corporate-entity, legal-person, super-secure and unknown nodes omit these fields entirely - a company has no personal identity to verify, so a status on one would imply an obligation that does not exist.

Before 2026-08-17 the chain reported no verification data at all, so the same person could appear verified on /psc and blank here (CH-Api#104). Every person in the tree is classified against a single date fixed at the start of the traversal.

Credits: Each company resolved in the chain costs 1 upstream API call. The chain_metadata.total_credits field shows the total cost.

Example: /v1/company/12345678/psc/chain?max_depth=3

get/v1/company/{company_number}/psc/chain

Request

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

Path parameters

company_numberstring required

The Companies House company number to start the chain from.

Example:12345678

Query parameters

max_depthinteger

Maximum depth to traverse the ownership chain (1-10). Each level costs 1 upstream API call per corporate entity.

Response

PSC chain resolved successfully

statusstring

'success' or 'error'

cachedboolean

True if this response was served from cache rather than fetched live

cache_age_secondsinteger nullable

How many seconds ago this data was fetched from Companies House (null if not cached)

fetched_atstring 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_sourcestring

'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_usedinteger

Number of API credits consumed by this request

credits_remaininginteger nullable

API credits remaining this month (null in dev mode)

Example response

{
  "cache_age_seconds": 3421,
  "cached": true,
  "credits_remaining": 487,
  "credits_used": 1,
  "data": {
    "company_age_years": 78,
    "company_name": "TESCO PLC",
    "company_number": "00445790",
    "company_status": "active",
    "company_type": "plc"
  },
  "data_source": "cached",
  "status": "success"
}

Changes

No recorded changes to this operation across all 1 revision of this API.