Registrum vs Companies House API

What Registrum adds on top of Companies House

The Companies House API is free and official — but it returns raw metadata with no financial data, no computed fields, and no resilience. Registrum adds 15 data categories and the infrastructure to use it reliably in production.

The response, side by side

Same company (Tesco PLC, 00445790), same instant. Highlighted fields are computed, derived, or entirely new.

Companies House API — raw

{

"company_name": "TESCO PLC",

"company_number": "00445790",

"company_status": "active",

"type": "plc",

"date_of_creation": "1947-11-27",

"registered_office_address": { ... },

"sic_codes": ["47110"],

"accounts": { "next_accounts": { "due_on": "2024-07-24" }, "last_accounts": { "made_up_to": "2024-02-24" } },

"confirmation_statement": { "next_due": "2025-06-15" },

"links": { "filing_history": "...", "officers": "..." },

}

≈ 10 fields · No financial data · Dates require calculation · No quality signals

Registrum API — enriched+18 fields

{

"company_name": "TESCO PLC",

"company_number": "00445790",

"company_status": "active",

"company_age_years": 78,enriched

"accounts": { "overdue": false, "next_due": "2024-07-24" },enriched

"sic_codes": ["47110"],

"sic_descriptions": ["Retail sale in non-specialised stores"],enriched

"financials": { "turnover": { "current": 68190000000 }, "profit_after_tax": { "current": 1400000000 }, ... },new field

"cached": true,

"credits_remaining": 49,

}

enrichednew fieldimprovedinfrastructure

Field-by-field comparison

Data categoryCompanies House (direct)Registrum
Company name / number / statusRaw
Same
Company ageMust calculate from date_of_creation
company_age_years pre-computedenriched
Accounts overdueMust compare two date fields
accounts.overdue booleanenriched
Confirmation overdueMust compare two date fields
confirmation_statement.overdue booleanenriched
SIC code descriptionsCodes only (e.g. 47110)
Human-readable descriptions includedenriched
Revenue / turnoverLink to iXBRL filing document only
Parsed JSON integer (actual GBP)new field
Profit & loss statementNot available via API
Full P&L: gross profit, operating profit, PATnew field
Balance sheetNot available via API
Assets, liabilities, equity, net assetsnew field
Employee countNot available via API
average_employees from filingsnew field
Prior year financialsNot available via API
prior field on every financial valuenew field
Director listPaginated (multiple calls required)
Deduplicated, single endpointimproved
Director appointmentsOne API call per director
Included in directors responsenew field
Director network (related companies)Many paginated calls, manual dedup required
One network endpoint, auto-traversalnew field
Rate limit protection600 req/5min, errors propagate to your app
Cached responses, shared budget shieldedinfrastructure
Resilience on CH outage5xx errors propagate to your app
Stale cache served with X-Data-Stale headerinfrastructure
Request tracingNo correlation IDs
X-Request-Id on every responseinfrastructure
Data quality signalsNone
data_quality block with completeness rationew field

The real cost of doing it yourself

The director network endpoint collapses ~16 paginated CH API calls into one. Each of those raw calls counts toward your 600 req/5min limit — and produces no caching. With Registrum the result is cached for 24h and shared across all your requests.

Director network — raw CH API · ~16 API calls
# Python — director network with raw CH API
# Requires multiple paginated calls

import requests, base64

def get_network(company_number, ch_api_key):
    auth = base64.b64encode(f"{ch_api_key}:".encode()).decode()
    headers = {"Authorization": f"Basic {auth}"}
    base = "https://api.company-information.service.gov.uk"

    # Step 1: get officers
    officers = requests.get(
        f"{base}/company/{company_number}/officers",
        headers=headers
    ).json().get("items", [])

    network = {}
    seen_officers = set()

    for officer in officers:
        link = officer.get("links", {}).get("officer", {})
        appts_path = link.get("appointments", "")
        officer_id = appts_path.strip("/").split("/")[1]

        if officer_id in seen_officers:
            continue
        seen_officers.add(officer_id)

        # Step 2: one call per officer
        appts = requests.get(
            f"{base}/officers/{officer_id}/appointments",
            headers=headers
        ).json().get("items", [])

        for a in appts:
            cn = a.get("appointed_to", {}).get("company_number")
            if cn and cn != company_number:
                network.setdefault(cn, []).append(officer["name"])

    # Result: 1 + N calls (N = number of officers)
    # Tesco has ~15 officers = ~16 CH API calls
    # No caching. Rate limit consumed every time.
    return network
Director network — Registrum · 1 API call
# Python — director network with Registrum
# One call. Cached 24h. Rate-limit safe.

import requests

def get_network(company_number, api_key):
    r = requests.get(
        f"https://api.registrum.co.uk/v1/company/{company_number}/network",
        params={"depth": 1},
        headers={"X-API-Key": api_key},
    )
    data = r.json()["data"]
    return data["companies"]
    # Returns: list of connected companies
    # sorted by connection strength (shared directors)

Try it free

50 free calls per month. All endpoints. No credit card.