{
  "openapi": "3.1.0",
  "info": {
    "title": "UK Companies House Watch API",
    "version": "1.0.0",
    "description": "Per-company monitoring API on top of Companies House. Subscribe to UK\ncompany numbers, get a daily change feed surfacing diffs in profile,\nofficers, filing history, charges, and PSCs.\n",
    "contact": {
      "name": "Stratum APIs",
      "url": "https://stratumapis.com",
      "email": "support@stratumapis.com"
    },
    "termsOfService": "https://stratumapis.com/legal/terms",
    "x-logo": {
      "url": "https://stratumapis.com/icon.svg",
      "altText": "Stratum APIs"
    }
  },
  "servers": [
    {
      "url": "https://api.stratumapis.com/v1/ch",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/companies/{number}": {
      "get": {
        "summary": "Single company lookup, cached",
        "description": "Returns a normalised company profile plus active officers plus flag fields, fetched live from Companies House and cached for 24 hours.",
        "operationId": "getCompany",
        "parameters": [
          {
            "in": "path",
            "name": "number",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "00445790",
            "description": "Companies House number (eight chars; SC, NI, OC prefixes preserved; bare digits left-padded to eight)"
          }
        ],
        "responses": {
          "200": {
            "description": "Company found. `officers.active` lists every current officer (from the first 100 records); for a person it\nincludes the birth month and year and the identity verification Companies House shows for them.\n",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "officers": {
                      "type": "object",
                      "properties": {
                        "active": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "role": {
                                "type": "string"
                              },
                              "appointedOn": {
                                "type": "string",
                                "format": "date"
                              },
                              "nationality": {
                                "type": "string"
                              },
                              "dateOfBirth": {
                                "$ref": "#/components/schemas/BirthMonth"
                              },
                              "idVerification": {
                                "$ref": "#/components/schemas/IdVerification"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "404": {
            "description": "No such company"
          },
          "503": {
            "description": "Companies House could not be read just now (error code companies_house_unavailable). Not charged; try again shortly."
          }
        }
      }
    },
    "/companies/{number}/psc-tree": {
      "get": {
        "summary": "PSC tree + UBO computation (B-CH-2)",
        "description": "Walks the Persons-with-Significant-Control structure for a UK\ncompany, recursing into corporate PSCs that are themselves\nUK-registered, up to the requested depth limit (capped at 5).\nComputes UBOs (≥25% effective ownership through the chain, or\na control nature like right-to-appoint-and-remove-directors per\nMLR-2017 reg 5(1)(c)). Cycle + depth-limit cases are flagged\nvia `unresolved` + `unresolvedUboReason` so the caller can\nsurface the warning to the customer.\nCached server-side for 1 day.\n",
        "operationId": "getPscTree",
        "parameters": [
          {
            "in": "path",
            "name": "number",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "00445790",
            "description": "Companies House number of the corporate landlord / customer"
          },
          {
            "in": "query",
            "name": "depth",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5,
              "default": 5
            },
            "description": "Maximum recursion depth. Defaults to 5 hops."
          }
        ],
        "responses": {
          "200": {
            "description": "Tree + UBO list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "companyNumber",
                    "tree",
                    "ubos",
                    "unresolved",
                    "generatedAt",
                    "cached"
                  ],
                  "properties": {
                    "companyNumber": {
                      "type": "string"
                    },
                    "tree": {
                      "type": "object",
                      "description": "Recursive PscNode shape; root is the customer company itself. An individual PSC node carries\n`dateOfBirth` (BirthMonth) and `idVerification` (IdVerification) when Companies House shows them.\n"
                    },
                    "ubos": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "effectiveOwnershipPct": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 1
                          },
                          "reason": {
                            "type": "string",
                            "enum": [
                              "direct-share-25pct",
                              "indirect-share-25pct",
                              "control-nature"
                            ]
                          },
                          "pathCompanyNumbers": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "unresolved": {
                      "type": "boolean"
                    },
                    "unresolvedUboReason": {
                      "type": "string",
                      "enum": [
                        "cycle-detected",
                        "depth-limit-reached"
                      ],
                      "nullable": true
                    },
                    "generatedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "cached": {
                      "type": "boolean",
                      "description": "True when served from the 1-day cache"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such company"
          },
          "503": {
            "description": "Companies House could not be read just now (error code companies_house_unavailable). Not charged; try again shortly."
          }
        }
      }
    },
    "/monitored": {
      "get": {
        "summary": "List monitored Companies House numbers for this API key",
        "operationId": "listMonitored",
        "responses": {
          "200": {
            "description": "List"
          }
        }
      },
      "put": {
        "summary": "Replace the full set of monitored Companies House numbers",
        "operationId": "setMonitored",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "numbers"
                ],
                "properties": {
                  "numbers": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 0,
                    "maxItems": 1000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated"
          },
          "413": {
            "description": "Tier cap exceeded"
          }
        }
      }
    },
    "/monitored/{number}": {
      "delete": {
        "summary": "Remove a single Companies House number from the monitored set",
        "operationId": "removeMonitored",
        "parameters": [
          {
            "in": "path",
            "name": "number",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "00445790"
          }
        ],
        "responses": {
          "200": {
            "description": "Removed"
          },
          "404": {
            "description": "Not in the monitored set"
          }
        }
      }
    },
    "/changes": {
      "get": {
        "summary": "Changes feed for monitored companies since a given date",
        "operationId": "changes",
        "parameters": [
          {
            "in": "query",
            "name": "since",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Lower bound (YYYY-MM-DD). Capped at the tier history window (Starter 14d, Growth 90d, Pro 365d)."
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Change set"
          }
        }
      }
    },
    "/companies/{number}/psc-velocity": {
      "get": {
        "summary": "PSC ownership-velocity flag (W30 iter 3)",
        "description": "Counts PSC notification + cessation events on the company over\nthe trailing 12-month window. Severity bands: `low` (0-1\nchanges: stable BTL territory), `medium` (2 changes: one\nnormal ownership transfer = cessation+notification pair),\n`high` (3+ changes: restructure or fraud signal worth\ninvestigating). Fast path: one CH /psc fetch, no walk.\nReturns `{ changesIn12m, totalChangesObserved, lastChangeDate,\nseverity, hasActivePscs, message, generatedAt }`.\n",
        "operationId": "getPscVelocity",
        "parameters": [
          {
            "in": "path",
            "name": "number",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "00445790",
            "description": "Companies House number"
          }
        ],
        "responses": {
          "200": {
            "description": "Ownership-velocity payload",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "companyNumber": {
                      "type": "string"
                    },
                    "changesIn12m": {
                      "type": "integer"
                    },
                    "totalChangesObserved": {
                      "type": "integer"
                    },
                    "lastChangeDate": {
                      "type": "string",
                      "nullable": true
                    },
                    "severity": {
                      "type": "string",
                      "enum": [
                        "low",
                        "medium",
                        "high"
                      ]
                    },
                    "hasActivePscs": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "string"
                    },
                    "generatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No company with that number"
          }
        }
      }
    },
    "/disqualifications": {
      "post": {
        "summary": "People on the Companies House register of disqualified directors",
        "description": "Looks up each person (up to 50, for example a company's directors and owners) on the register of\ndisqualified directors. A register entry counts only when the first name and surname agree and, when both\nsides give one, the birth month and year agree (Companies House publishes the month and year for officers\nand owners). `status` is `disqualified` (a disqualification in force, or one not yet started),\n`previously-disqualified` (ended), `none`, or `not-checked` (the register did not answer; never read it as\n`none`). `nameOnly: true` means the match rests on the name alone because there was no birth date to compare.\nActing as a director while disqualified is an offence (Company Directors Disqualification Act 1986 s13).\nOne call against your plan.\n",
        "operationId": "checkDisqualifications",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "people"
                ],
                "properties": {
                  "people": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 50,
                    "items": {
                      "type": "object",
                      "required": [
                        "name"
                      ],
                      "properties": {
                        "name": {
                          "type": "string",
                          "example": "John Albert Smith"
                        },
                        "dateOfBirth": {
                          "type": "object",
                          "properties": {
                            "month": {
                              "type": "integer",
                              "minimum": 1,
                              "maximum": 12
                            },
                            "year": {
                              "type": "integer",
                              "minimum": 1900
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One answer per person, in the order sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "source": {
                      "type": "string"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "disqualified",
                              "previously-disqualified",
                              "none",
                              "not-checked"
                            ]
                          },
                          "nameOnly": {
                            "type": "boolean"
                          },
                          "records": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "name": {
                                  "type": "string"
                                },
                                "dateOfBirth": {
                                  "type": "string",
                                  "format": "date"
                                },
                                "disqualifications": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "from": {
                                        "type": "string",
                                        "format": "date"
                                      },
                                      "until": {
                                        "type": "string",
                                        "format": "date"
                                      },
                                      "type": {
                                        "type": "string",
                                        "example": "court-order"
                                      },
                                      "reason": {
                                        "type": "string"
                                      },
                                      "companyNames": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        }
                                      }
                                    }
                                  }
                                },
                                "permissionsToAct": {
                                  "type": "array",
                                  "items": {
                                    "type": "object",
                                    "properties": {
                                      "companyNames": {
                                        "type": "array",
                                        "items": {
                                          "type": "string"
                                        }
                                      },
                                      "grantedOn": {
                                        "type": "string",
                                        "format": "date"
                                      },
                                      "expiresOn": {
                                        "type": "string",
                                        "format": "date"
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid people list"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "BirthMonth": {
        "type": "object",
        "description": "Month and year of birth, as Companies House publishes them (never the day).",
        "properties": {
          "month": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12
          },
          "year": {
            "type": "integer"
          }
        }
      },
      "IdVerification": {
        "type": "object",
        "description": "Identity verification under the Economic Crime and Corporate Transparency Act 2023, as the register shows it.",
        "properties": {
          "verifiedOn": {
            "type": "string",
            "format": "date",
            "description": "The person's identity was verified on this date."
          },
          "statementDate": {
            "type": "string",
            "format": "date",
            "description": "The verification statement for this appointment was supplied on this date."
          },
          "statementDueOn": {
            "type": "string",
            "format": "date",
            "description": "The verification statement for this appointment is due by this date."
          },
          "acspName": {
            "type": "string",
            "description": "The authorised corporate service provider that verified them",
            "when one did.": null
          }
        }
      }
    },
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Stratum-Key"
      }
    }
  }
}