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
companies-house.api-keycompanies-house.base-urlcompanies-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).
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