---
title: "Get company directors with their other appointments"
method: GET
path: "/v1/company/{company_number}/directors"
tags: ["Directors"]
---

# Get company directors with their other appointments

`GET /v1/company/{company_number}/directors`

## Request

- Base URL: `https://api.registrum.co.uk`
- URL: `https://api.registrum.co.uk/v1/company/{company_number}/directors`
- Auth: API key in header `X-API-Key`

Get all directors for a company, split into current and past, with their other board appointments.

For each director, the response includes every other company they sit on (or have sat on),
enabling you to map connections between companies through shared board members.

- **current_directors** - officers with no resignation date, including secretaries
  (never filtered - a secretary is a real officer that KYB checks need to see)
- **past_directors** - officers who have resigned
- **other_appointments** - every other company each director is or was appointed to

Each director carries ECCTA identity verification state: **verification_status**
(`verified` | `pending` | `overdue` | `unknown` | `not_applicable`),
**verification_deadline** (this person's own CH-authoritative deadline, only set
when pending or overdue), and **is_board_director** (true for every officer except
secretaries - a `corporate-director` IS a board director even though it cannot
personally verify an identity, so `verification_status` is `not_applicable` for it
while `is_board_director` stays `true`). `pending` means a deadline has been
recorded but has NOT passed - nothing has been missed. Top-level counts
(`directors_verified`, `directors_pending`, `directors_overdue`, `directors_unknown`,
`directors_verification_required`) exclude officers ECCTA does not apply to
(corporate officers and secretaries), so they can be smaller than `total_current`.

Data is cached for 30 days. If the Companies House API is down, stale cached data
is returned with `cached: true` in the response.

**Example:** `/v1/company/00445790/directors` returns all Tesco PLC directors.

---

**Upstream usage:** This endpoint is upstream-intensive on first fetch.
It makes **1 call per director** (to retrieve their appointment history), plus 1–2 calls
for the officer list itself. A company with 10 directors uses ~12 upstream calls;
a company with 50 directors uses ~52. After the first fetch, the result is cached for
30 days and subsequent calls are free.

At high volume, **querying more than ~8 different companies per minute on cold cache**
will cause responses to slow while upstream capacity recovers (typically 5–15 seconds).
For bulk use cases, space requests out or pre-warm the cache during off-peak hours.

## Path parameters

- `company_number` string, required: The Companies House company number. 8 alphanumeric characters (e.g., `00445790` for Tesco PLC). Numeric-only numbers are automatically zero-padded.

## Response `200`

Directors list returned successfully, split into current and past

- DirectorsEnvelope: Response envelope for GET /v1/company/{company_number}/directors.
  - `status` string: 'success' or 'error'
  - `data` DirectorsResponse: Directors for a company, split into current (active) and past (resigned) with their other appointments.
    - `company_number` string, required: 8-character Companies House number
    - `company_name` string, nullable: Registered company name
    - `company_status` string, nullable: Company status: 'active', 'dissolved', 'liquidation', etc. Useful context - a dissolved company's directors may show no resignation date even though the company no longer exists
    - `current_directors` Director[]: Directors currently serving on the board
      - `name` string, required: Full name as registered at Companies House (usually SURNAME, Forenames)
      - `officer_role` string, required: Role at the target company (e.g., 'director', 'secretary', 'llp-member')
      - `appointed_on` string, date, nullable: Date this person was appointed to the target company
      - `resigned_on` string, date, nullable: Date this person resigned (null if still serving)
      - `nationality` string, nullable: Nationality as declared to Companies House
      - `occupation` string, nullable: Declared occupation
      - `date_of_birth` DateOfBirth: Month and year of birth only - Companies House redacts the full date for privacy.
        - `month` integer, nullable: Birth month (1-12)
        - `year` integer, nullable: Birth year
      - `officer_id` string, nullable: Companies House officer ID (extracted from appointment links)
      - `other_appointments` DirectorAppointment[]: Other companies this person is or was appointed to - the basis for network mapping
        - `company_number` string, required: 8-character Companies House number of the appointed company
        - `company_name` string, required: Registered name of the appointed company
        - `company_status` string, nullable: Status of the appointed company: 'active', 'dissolved', etc.
        - `officer_role` string, required: Role held at this company (e.g., 'director', 'secretary')
        - `appointed_on` string, date, nullable: Date this appointment started
        - `resigned_on` string, date, nullable: Date the appointment ended (null if still active)
      - `identity_verified` boolean, nullable: ECCTA identity verification status, collapsed to a tri-state boolean for convenience. True = verified with Companies House (a confirmed identity_verified_on date exists). False = genuinely overdue - Companies House recorded a deadline that HAS passed with no verification. Before CH-Api#52 this also covered pending people (a future deadline), which wrongly branded ~70% of live officers as unverified; it no longer does. None covers every other case - pending (a deadline recorded but not yet due), unknown (no verification data on record at all), or not_applicable (this officer is outside ECCTA verification, e.g. a corporate officer or secretary). See verification_status to distinguish those three.
      - `identity_verified_on` string, date, nullable: Date identity verification was completed, as recorded by Companies House. Only set when identity_verified is True.
      - `verification_status` string, nullable: The full ECCTA verification state: 'verified' (identity_verified_on present), 'pending' (Companies House recorded a deadline or verification window that has NOT passed - nothing has been missed, this person owes nothing yet), 'overdue' (a recorded deadline has passed with no verification), 'unknown' (no verification data on record at all - not evidence of non-compliance, just absence of data), or 'not_applicable' (this officer is outside ECCTA identity verification entirely - a corporate officer, which has no personal identity to verify, or a secretary, who is not in scope of the regime).
      - `verification_deadline` string, date, nullable: This person's own verification deadline as recorded by Companies House - authoritative and per-person, not a company-wide date. Set only when verification_status is 'pending' or 'overdue'. Companies House writes 9999-12-31 internally to mean an open-ended verification window; that sentinel is never surfaced here - an open-ended window returns null rather than a fake calendar date a chase email could quote.
      - `is_board_director` boolean: True if this officer is a genuine board director (governance role), False only for secretaries. Distinct from ECCTA scope: a corporate director (a company acting as director) IS a board director (is_board_director: true) even though it cannot personally verify an identity (verification_status: not_applicable). Secretaries remain in current_directors/past_directors - this field controls only who counts toward the verification totals and who contributes to /network connections, not who appears in the officer list.
    - `past_directors` Director[]: Directors who have resigned
      - `name` string, required: Full name as registered at Companies House (usually SURNAME, Forenames)
      - `officer_role` string, required: Role at the target company (e.g., 'director', 'secretary', 'llp-member')
      - `appointed_on` string, date, nullable: Date this person was appointed to the target company
      - `resigned_on` string, date, nullable: Date this person resigned (null if still serving)
      - `nationality` string, nullable: Nationality as declared to Companies House
      - `occupation` string, nullable: Declared occupation
      - `date_of_birth` DateOfBirth: Month and year of birth only - Companies House redacts the full date for privacy.
        - `month` integer, nullable: Birth month (1-12)
        - `year` integer, nullable: Birth year
      - `officer_id` string, nullable: Companies House officer ID (extracted from appointment links)
      - `other_appointments` DirectorAppointment[]: Other companies this person is or was appointed to - the basis for network mapping
        - `company_number` string, required: 8-character Companies House number of the appointed company
        - `company_name` string, required: Registered name of the appointed company
        - `company_status` string, nullable: Status of the appointed company: 'active', 'dissolved', etc.
        - `officer_role` string, required: Role held at this company (e.g., 'director', 'secretary')
        - `appointed_on` string, date, nullable: Date this appointment started
        - `resigned_on` string, date, nullable: Date the appointment ended (null if still active)
      - `identity_verified` boolean, nullable: ECCTA identity verification status, collapsed to a tri-state boolean for convenience. True = verified with Companies House (a confirmed identity_verified_on date exists). False = genuinely overdue - Companies House recorded a deadline that HAS passed with no verification. Before CH-Api#52 this also covered pending people (a future deadline), which wrongly branded ~70% of live officers as unverified; it no longer does. None covers every other case - pending (a deadline recorded but not yet due), unknown (no verification data on record at all), or not_applicable (this officer is outside ECCTA verification, e.g. a corporate officer or secretary). See verification_status to distinguish those three.
      - `identity_verified_on` string, date, nullable: Date identity verification was completed, as recorded by Companies House. Only set when identity_verified is True.
      - `verification_status` string, nullable: The full ECCTA verification state: 'verified' (identity_verified_on present), 'pending' (Companies House recorded a deadline or verification window that has NOT passed - nothing has been missed, this person owes nothing yet), 'overdue' (a recorded deadline has passed with no verification), 'unknown' (no verification data on record at all - not evidence of non-compliance, just absence of data), or 'not_applicable' (this officer is outside ECCTA identity verification entirely - a corporate officer, which has no personal identity to verify, or a secretary, who is not in scope of the regime).
      - `verification_deadline` string, date, nullable: This person's own verification deadline as recorded by Companies House - authoritative and per-person, not a company-wide date. Set only when verification_status is 'pending' or 'overdue'. Companies House writes 9999-12-31 internally to mean an open-ended verification window; that sentinel is never surfaced here - an open-ended window returns null rather than a fake calendar date a chase email could quote.
      - `is_board_director` boolean: True if this officer is a genuine board director (governance role), False only for secretaries. Distinct from ECCTA scope: a corporate director (a company acting as director) IS a board director (is_board_director: true) even though it cannot personally verify an identity (verification_status: not_applicable). Secretaries remain in current_directors/past_directors - this field controls only who counts toward the verification totals and who contributes to /network connections, not who appears in the officer list.
    - `total_current` integer: Count of current directors
    - `total_past` integer: Count of past directors
    - `directors_verified` integer: Current directors with confirmed ECCTA identity verification (identity_verified_on present). Excludes corporate officers and secretaries (see directors_verification_required).
    - `directors_pending` integer: Current directors with a Companies House verification deadline or window that has NOT yet passed. Nothing has been missed - this is not a risk indicator, it reflects the ongoing Nov 2025 - Nov 2026 ECCTA transition.
    - `directors_overdue` integer: Current directors with a recorded verification deadline that HAS passed with no verification on record. The only state that represents genuine non-compliance.
    - `directors_unverified` integer: Documented alias of directors_overdue, retained for backwards compatibility. Before CH-Api#52 this field also counted pending directors (a future deadline); it no longer does - it now means exactly 'overdue'.
    - `directors_unknown` integer: Current directors with no identity_verification_details in the CH API response at all - absence of data, not evidence of non-compliance.
    - `directors_verification_required` integer: Count of current directors ECCTA verification actually applies to - excludes corporate officers and secretaries, who are not_applicable and therefore never counted here. Invariant: directors_verified + directors_pending + directors_overdue + directors_unknown == directors_verification_required <= total_current.
  - `cached` boolean: True if this response was served from cache rather than fetched live
  - `cache_age_seconds` integer, nullable: How many seconds ago this data was fetched from Companies House (null if not cached)
  - `fetched_at` string, nullable: ISO 8601 instant (UTC) when this data was actually fetched from Companies House. Use this, not cache_age_seconds, to show a user when the data was last checked: an age is measured at the moment this response was produced, so anything that caches the response downstream will overstate freshness by however long it held it. This instant does not drift. Null when unknown - render nothing rather than a guessed date.
  - `data_source` string: 'live' - fetched from Companies House right now; 'cached' - served from local cache (data is recent, no upstream call needed); 'cached_rate_conserved' - served from cache because the CH API budget is above 70% utilisation; data may be up to 30 days old in this state
  - `credits_used` integer: Number of API credits consumed by this request
  - `credits_remaining` integer, nullable: API credits remaining this month (null in dev mode)

## Other responses

- `400`: Invalid company number format, or the company number is empty (blank path segment)
- `401`: Missing or invalid API key
- `404`: Company not found at Companies House
- `422`: Validation Error
- `502`: Companies House API is temporarily unavailable
- `503`: Request shed to protect shared Companies House capacity; retry after the seconds given in the Retry-After header

---

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