The UK Companies House Public Data API (https://api.company-information.service.gov.uk) and Document API (https://document-api.company-information.service.gov.uk).

Auth: a free REST API key from the Companies House developer hub, sent as the username of HTTP Basic auth with an empty password. Set companies-house.api-key or pass {api-key: ...} per call. The sandbox (https://api-sandbox.company-information.service.gov.uk, test data only) takes a sandbox key; point base-url at it.

Rate limit: 600 requests per 5 minutes per key; a 429 carries retry-after in the HttpError.

Paging: lists use items_per_page and start_index; next-start computes the next offset and collect follows it.

Streaming API (stream.companieshouse.gov.uk, a separate stream key and long-lived connections) is not wrapped: a run should not hold a connection open indefinitely. Poll filing-history from a schedule instead, or run a dedicated consumer outside Hot.

Context Vars

Optional
  • companies-house.api-key
  • companies-house.base-url
  • companies-house.document-base-url

Functions

auth-header

fn (api-key: Str): Str

Basic base64("{api-key}:"): the key is the username and the password is empty (pure).

ch-get

fn (path: Str, params: Map, opts: Map): Any

charges

fn (number: Any): Map
fn (number: Any, opts: Map): Map

One page of a company's charges (mortgages and security interests).

collect

fn (fetch: Fn, opts: Map, limit: Int): Vec

Follow start_index pages of a Companies House list until limit items or the end. fetch takes opts (with start-index and items-per-page set) and returns one page. An Err on any page is returned in place of the items.

Example

::ch ::companies-house
all-officers ::ch/collect((o) { ::ch/officers("00445790", o) }, {}, 300)

collect-pages

fn (fetch: Fn, start: Int, size: Int, limit: Int, acc: Vec): Vec

company

fn (number: Any): Map?
fn (number: Any, opts: Map): Map?

The company profile (company_name, company_status, type, date_of_creation, registered_office_address, sic_codes, accounts, confirmation_statement, links, ...), or null when there is no such company.

company-number

fn (number: Any): Str

Normalize a UK company number: trimmed, upper-cased, and zero-padded to eight characters when it is all digits ("6" → "00000006"); prefixed numbers such as "SC123456" or "OC301540" are kept. An Err for anything that is not one to eight letters and digits.

company-path

fn (number: Any): Str

document-content

fn (link-or-id: Str): Map
fn (link-or-id: Str, content-type: Str): Map
fn (link-or-id: Str, content-type: Str, opts: Map): Map

Download a document as {content-type, bytes}. content-type (default "application/pdf") must be one listed in the metadata's resources. The Document API answers with a redirect to a short-lived signed URL; the API key is not sent to that host. Documents above http.max-response-bytes (16 MiB by default) fail.

Example

::ch ::companies-house
history ::ch/filing-history("00445790", {category: "accounts", items-per-page: 1})
pdf ::ch/document-content(first(history.items).links.document_metadata, "application/pdf")
pdf.bytes

document-id

fn (link-or-id: Str?): Str?

The document id from a filing's links.document_metadata URL (any host, e.g. https://frontend-doc-api.company-information.service.gov.uk/document/abc123), or the id itself (pure). Null when there is none.

document-metadata

fn (link-or-id: Str): Map
fn (link-or-id: Str, opts: Map): Map

A document's metadata from the Document API: resources maps each available content type (application/pdf, often application/xhtml+xml for iXBRL accounts) to its size, plus pages, created_at and links.

filing

fn (number: Any, transaction-id: Str): Map
fn (number: Any, transaction-id: Str, opts: Map): Map

One filing-history item by transaction id.

filing-history

fn (number: Any): Map
fn (number: Any, opts: Map): Map

One page of a company's filing history, newest first. opts: category (e.g. "accounts", "confirmation-statement", or a comma list), items-per-page (max 100), start-index. Each item's links.document_metadata points to the Document API (see document-id).

next-start

fn (page: Any): Int?

The start_index of the page after page (start_index + items while below total_results), or null on the last page (pure).

officer-appointments

fn (officer-id: Str): Map
fn (officer-id: Str, opts: Map): Map

One page of an officer's appointments across companies. officer-id comes from an officer's links.officer.appointments (see officer-id-from-link).

fn (link: Str?): Str?

The officer id in a link such as /officers/AbC123/appointments (pure), or null.

officers

fn (number: Any): Map
fn (number: Any, opts: Map): Map

One page of a company's officers. opts: items-per-page (max 100), start-index, register-type ("directors", "secretaries", "llp-members"), register-view, order-by ("appointed_on", "resigned_on", "surname").

page-params

fn (opts: Map): Map

items_per_page and start_index from opts.items-per-page and opts.start-index, omitted when unset (pure).

persons-with-significant-control

fn (number: Any): Map
fn (number: Any, opts: Map): Map

One page of a company's persons with significant control (individuals, corporate entities, legal persons, and beneficial owners), with natures_of_control. opts: items-per-page, start-index, register-view.

psc-statements

fn (number: Any): Map
fn (number: Any, opts: Map): Map

One page of a company's PSC statements (e.g. no registrable person).

registered-office-address

fn (number: Any): Map
fn (number: Any, opts: Map): Map

The registered office address.

search-all

fn (q: Str): Map
fn (q: Str, opts: Map): Map

Search companies, officers and disqualified officers together (/search).

search-companies

fn (q: Str): Map
fn (q: Str, opts: Map): Map

Search companies by name or number. Returns {items, total_results, start_index, items_per_page}; each item has title, company_number, company_status, company_type, date_of_creation, address. opts: items-per-page, start-index, restrictions, plus api-key.

Example

found ::companies-house/search-companies("tesco", {items-per-page: 5})
first(found.items).company_number

search-disqualified-officers

fn (q: Str): Map
fn (q: Str, opts: Map): Map

Search disqualified directors by name.

search-officers

fn (q: Str): Map
fn (q: Str, opts: Map): Map

Search officers (directors, secretaries, LLP members) by name. Items link to /officers/{id}/appointments.

with-key

fn (opts: Map, f: Fn): Any