{
  "datasetVersion": "1.0.0",
  "title": "Cosmeds regulator transparency dataset",
  "summary": "Aggregate record of every credential check Cosmeds runs against UK regulator registers, and every credential status change it observes. Counts only — no business, credential or person is identified.",
  "licence": {
    "name": "Creative Commons Attribution 4.0 International (CC BY 4.0)",
    "url": "https://creativecommons.org/licenses/by/4.0/",
    "attribution": "Cosmeds regulator transparency dataset",
    "statement": "Free to reuse, republish and build on, including commercially, provided the dataset is credited and linked. Credit the source and link to the dataset page."
  },
  "page": "/regulator-transparency",
  "endpoints": {
    "json": "/api/open-data/regulator-transparency.json",
    "schema": "/api/open-data/regulator-transparency/schema.json",
    "monthlyCsv": "/api/open-data/regulator-transparency/monthly.csv",
    "regulatorsCsv": "/api/open-data/regulator-transparency/regulators.csv",
    "transitionsCsv": "/api/open-data/regulator-transparency/transitions.csv"
  },
  "disclosureControl": {
    "minimumCellCount": 3,
    "note": "Cells counting fewer than 3 events are withheld to prevent re-identification of a single business. In CSV a withheld cell is written empty with its companion \"…Withheld\" column set to true — an empty withheld cell is NOT a zero."
  },
  "jsonDocument": {
    "endpoint": "/api/open-data/regulator-transparency.json",
    "topLevelFields": {
      "datasetVersion": "Semantic version of this shape. A breaking column change bumps the major.",
      "asOf": "ISO timestamp the snapshot was computed.",
      "window": "Published window: start, end (exclusive), months, firstMonth, lastMonth.",
      "licence": "Licence name, url, required attribution and plain-language statement.",
      "totals": "Window totals across all regulators.",
      "byMonth": "One entry per complete month in the window, including months with no activity.",
      "byRegulator": "Window totals per regulator code.",
      "byMonthAndRegulator": "The monthly CSV table, as objects.",
      "statusChanges": "Direction totals, withheld-cell counts, and the surviving transition cells.",
      "coverage": "How much of what we hold is actively re-checked, and the median re-check age.",
      "derivations": "Plain-language formula for every derived figure.",
      "limitations": "What this dataset is not, stated before anyone cites it.",
      "unavailableSections": "Sections that could not be computed for this snapshot. A named section is unavailable, NOT zero.",
      "emptyReason": "Why the dataset is empty, when it is. Null otherwise.",
      "schema": "Path to this document.",
      "page": "Path to the human-readable dataset page."
    }
  },
  "tables": {
    "monthly": {
      "endpoint": "/api/open-data/regulator-transparency/monthly.csv",
      "grain": "One row per complete calendar month per regulator code.",
      "columns": {
        "month": "Calendar month, YYYY-MM (UTC). Only complete months are published.",
        "regulatorCode": "Regulator code, or UNSPECIFIED where the log row predates regulator tagging.",
        "regulatorName": "Canonical regulator name, empty where we hold no contract for the code.",
        "verificationEvents": "Logged verification actions in the month.",
        "registerChecks": "Events that were an attempt to read the register (initial_verify, re_verify, canary_check).",
        "statusChanges": "Observed credential status changes (status_change, auto_expire). Empty when withheld.",
        "statusChangesWithheld": "true when statusChanges was withheld under the small-cell rule.",
        "checksNotCompleted": "Checks we could not complete (errors and inconclusive outcomes). A gap in our checking, not a finding about a clinic."
      }
    },
    "regulators": {
      "endpoint": "/api/open-data/regulator-transparency/regulators.csv",
      "grain": "One row per regulator code across the whole window.",
      "columns": {
        "regulatorCode": "Regulator code, or UNSPECIFIED.",
        "regulatorName": "Canonical regulator name, empty where unknown.",
        "verificationEvents": "Logged verification actions in the window.",
        "registerChecks": "Attempts to read the register.",
        "statusChanges": "Observed credential status changes.",
        "checksNotCompleted": "Checks we could not complete.",
        "checksNotCompletedPct": "checksNotCompleted ÷ verificationEvents, one decimal. Empty when there is nothing to divide."
      }
    },
    "transitions": {
      "endpoint": "/api/open-data/regulator-transparency/transitions.csv",
      "grain": "One row per regulator × previous status × new status, after small-cell suppression.",
      "columns": {
        "regulatorCode": "Regulator code, or UNSPECIFIED.",
        "regulatorName": "Canonical regulator name, empty where unknown.",
        "previousStatus": "Credential status before the change: green, amber, red, pending, inconclusive, not_applicable, unknown.",
        "newStatus": "Credential status after the change, same vocabulary.",
        "direction": "improved / worsened / unchanged / not_comparable. Only green>amber>red are ranked; anything involving pending, inconclusive or not_applicable is not_comparable because it means we could not confirm the entry.",
        "count": "Events in the cell. Cells below the minimum count are absent from this table and counted in statusChanges.withheldCells in the JSON."
      }
    }
  }
}