---
title: "Company health score"
method: GET
path: "/intelligence/health/{number}"
tags: ["Intelligence"]
---

# Company health score

`GET /intelligence/health/{number}`

## Request

- Base URL: `https://api.companystack.co.uk`
- URL: `https://api.companystack.co.uk/intelligence/health/{number}`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-Api-Key`

A rules-based health score (0 to 100) with a grade, the dimensions and signals behind it, red flags and positive signals, built from public records and the company's filed accounts. It is an indicator, not a credit rating.

On the Free plan: 100 calls a UTC day to this endpoint and GET /accounts/{number} together, inside the daily request limit. Each such call carries `X-Preview-Daily-Limit`, `X-Preview-Daily-Remaining` and `X-Preview-Daily-Reset` (Unix time of the next midnight UTC); when the day's calls are used the answer is 429 with `code: preview_limit_reached`, not counted against the request limit. Starter and above have no separate limit.

## Path parameters

- `number` string, required

## Response `200`

Health score with grade and factors

- HealthScore: CompanyStack Health Score: a rules-based indicator from 0 to 100 built from public records, including the company's filed accounts and the record of other companies controlled by the same people. Not a credit rating, and not statistically validated against outcomes (lib/health-score.ts).
  - `company_number` string
  - `company_name` string
  - `company_status` string
  - `score_version` string
  - `overall_score` integer, required
  - `grade` 'A+' | 'A' | 'B+' | 'B' | 'C+' | 'C' | 'D' | 'F', required: A+ ≥90, A ≥80, B+ ≥70, B ≥60, C+ ≥50, C ≥40, D ≥30, F <30
  - `risk_level` 'very_low' | 'low' | 'medium' | 'high' | 'critical', required: very_low ≥75, low ≥60, medium ≥45, high ≥30, critical <30
  - `dimensions` object[]
    - `dimension` string
    - `score` number
    - `weight` number: Percentage weight in the overall score
    - `confidence` 'high' | 'medium' | 'low'
    - `signals` object[]
      - `signal` string
      - `impact` 'positive' | 'negative' | 'neutral'
      - `detail` string
  - `excluded_dimensions` object[]
    - `dimension` string
    - `reason` string
  - `red_flags` string[]
  - `positive_signals` string[]
  - `positive_signals_note` string, nullable: Why positive_signals is empty: set for a company in insolvency proceedings or dissolved (v3.2)
  - `uncapped_score` integer: The score before score_caps were applied (v3.2)
  - `score_caps` object[]: Ceilings on the score, and why (v3.2). The lowest binds. Rules: no_financial_evidence and stale_financial_evidence (74), loss_latest_year (74), repeated_losses (69), net_liabilities (64), persistent_net_liabilities (54). Since v3.3 nothing about other companies of the same people caps the score.
    - `rule` string
    - `cap` integer
    - `reason` string
  - `check_items` object[]: Things worth checking that are not scored (v3.3), each matched on name and month and year of birth only, stated as a fact, and possibly a different person: other companies whose person with significant control has the same name and month and year of birth as one of this company's, and which entered insolvency or were dissolved with accounts overdue in the last five years (linked_name_dob_*); and current entries on the disqualified directors register with the same name and month and year of birth as one of this company's people with significant control (disqualified_name_dob_match): a possible match to review (possible_match true) unless the register entry also names this company (match_basis name_month_year_of_birth_and_company). Never a red flag, and never a statement that anyone at the company is disqualified. Empty for the website's public demo key, and while a dispute about the company is reviewed; enrichment.disqualification_matches and enrichment.possible_disqualification_matches are withheld in the same cases.
    - `rule` 'linked_name_dob_insolvency' | 'linked_name_dob_struck_off' | 'disqualified_name_dob_match'
    - `text` string: The fact in words, ending with the reminder that this may be a different person
    - `company_number` string, nullable: Director linkage: the other company. Null for a disqualified directors register match.
    - `company_name` string, nullable
    - `register_name` string: Disqualified directors register match only: the name as the register gives it
    - `date` string, nullable: Director linkage: when the other company failed (see date_basis). Register match: when the disqualification ends.
    - `date_basis` 'gazette_notice' | 'dissolution_date' | 'last_accounts_made_up' | 'incorporation_date' | 'disqualified_until' | 'null', nullable
    - `match_basis` 'name_and_month_year_of_birth'
    - `scored` false
  - `score_confidence` object: How much evidence the score rests on (v3.2): low without accounts figures or with figures over two years old
    - `level` 'high' | 'medium' | 'low'
    - `reasons` string[]
  - `credit_rating` object: rated false (reason "Not rated for credit risk: files dormant accounts"): the score is for information, not a credit rating, because a company that files dormant accounts has no trading figures to score and some are shells. Do not present its grade or risk_level as reassurance.
    - `rated` boolean
    - `reason` string, nullable
  - `enrichment` object
  - `methodology` string
  - `disclaimer` string
  - `notice` string: Who the data is prepared for and that CompanyStack accepts no responsibility to anyone else who relies on it (Terms 15B). Keep it with the data if you show it to others (Terms 17.5).
  - `data_as_of` string, nullable
  - `data_coverage` object
    - `available_dimensions` integer
    - `total_dimensions` integer
    - `data_sources` string[]
    - `data_sources_count` integer
    - `confidence` string

## Other responses

- `401`: API key missing, malformed or revoked
- `403`: The key's plan does not include this endpoint (`code: plan_upgrade_required`, with `upgrade_url`), the key may not call it, or the key is beyond the plan's key limit after a downgrade (`code: key_limit_exceeded`: the newest keys are paused until keys are deleted or the plan upgraded)
- `404`: Company not found
- `429`: Per-minute or per-day limit reached (`code: rate_limited`, `window: minute|day`). Wait `Retry-After` seconds; when both windows are full the day is reported. A refused request does not count against either limit. A bulk lookup (`POST /company/bulk`) counts each company number in it as one request, so one that is more than you have left is refused whole, and the body adds `requested` and `fits`.

---

[API](https://skmtc.dev/companystack/apis/companystack-api.md) · [All operations](https://skmtc.dev/companystack/apis/companystack-api/llms.txt) · [OpenAPI document](https://skmtc.dev/companystack/apis/companystack-api/revisions/8f3234237d2d?raw)
