JavaScript and Python

Call the API from your code

The CompanyStack API is plain HTTPS and JSON, so fetch in JavaScript or requests in Python is all you need. Every endpoint is in the OpenAPI spec and the API Explorer.

You need an API key (it starts with cs_). Create one free, then set it in COMPANYSTACK_API_KEY.

The companystack client libraries for npm and PyPI are not published yet; this page will show their install commands when they are. Until then, the examples below call the API directly and work as they are.

JavaScript and TypeScript

Node 18 or later (built-in fetch), Deno or Bun. Run it on your server: your key is a secret, and the API does not accept browser requests from other websites.

Get a company
const API = 'https://api.companystack.co.uk';
const headers = { Authorization: `Bearer ${process.env.COMPANYSTACK_API_KEY}` };

const res = await fetch(`${API}/company/00445790`, { headers });
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).error}`);
const company = await res.json();
console.log(company.company_name, company.accounts?.next_due);
Search, errors, retries and paging
// One helper: waits out a 429 (Retry-After) and turns plan errors into a clear message
async function cs(path, params = {}) {
  const url = new URL(path, 'https://api.companystack.co.uk');
  for (const [k, v] of Object.entries(params)) url.searchParams.set(k, String(v));
  for (let attempt = 0; ; attempt++) {
    const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.COMPANYSTACK_API_KEY}` } });
    if (res.status === 429 && attempt < 3) {
      await new Promise((r) => setTimeout(r, Number(res.headers.get('retry-after') ?? 1) * 1000));
      continue;
    }
    const body = await res.json();
    if (res.status === 403 && body.code === 'plan_upgrade_required') {
      throw new Error(`Needs the ${body.required_plan} plan: ${body.upgrade_url}`);
    }
    if (!res.ok) throw new Error(`${res.status}: ${body.error}`);
    return body;
  }
}

const { results } = await cs('/company/search', { q: 'tesco plc', limit: 5 });
for (const c of results) console.log(c.company_number, c.company_name, c.company_status);

// Paging: stop when a page comes back short. On the Free plan you get only the
// first page (up to 10 results; offset is not applied), so this stops after one.
for (let offset = 0; ; offset += 100) {
  const page = await cs('/company/search', { q: 'bakery', town: 'LEEDS', limit: 100, offset });
  for (const c of page.results) console.log(c.company_name);
  if (page.results.length < 100) break;
}

Python

Python 3.9 or later with requests (pip install requests).

Get a company and search
import os, time, requests

API = "https://api.companystack.co.uk"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['COMPANYSTACK_API_KEY']}"

def cs(path, **params):
    # GET an endpoint; waits out a 429 (Retry-After) and explains plan errors
    for attempt in range(4):
        res = session.get(API + path, params=params, timeout=30)
        if res.status_code == 429 and attempt < 3:
            time.sleep(int(res.headers.get("Retry-After", "1")))
            continue
        body = res.json()
        if res.status_code == 403 and body.get("code") == "plan_upgrade_required":
            raise RuntimeError(f"Needs the {body['required_plan']} plan: {body['upgrade_url']}")
        res.raise_for_status()
        return body

company = cs("/company/00445790")
print(company["company_name"], company.get("accounts", {}).get("next_due"))

for c in cs("/company/search", q="tesco plc", limit=5)["results"]:
    print(c["company_number"], c["company_name"], c["company_status"])

Good to know

  • Send the key as Authorization: Bearer cs_… or X-Api-Key: cs_…. Limits are per account, and every response carries X-RateLimit-Remaining and X-RateLimit-Reset.
  • An endpoint outside your plan answers 403 with "code": "plan_upgrade_required", required_plan and upgrade_url, and doesn't use your allowance. A path that doesn't exist answers 404.
  • On the Free plan, search returns only the first page (up to 10 results) and offset is not applied. Paid plans page with limit (up to 100) and offset.
  • Money values from filed accounts are whole pounds (GBP) as filed, not pence. The health score is a rules-based 0–100 indicator, not a credit rating.
  • Which endpoints each plan includes is on the pricing page.

Using another language? The OpenAPI 3.1 spec works with most client generators, and the collections give you every request ready to run. For SI agents, connect the hosted MCP server.