# API changelog

> Changes to the Checkbox API, SDKs, CLI, MCP server and legal catalog. API versions are dates; breaking changes only ship in a new version.

API versions are dates (`Checkbox-Version`). Backwards-compatible changes — new endpoints, new optional parameters, new
fields, new event types, new error codes — ship continuously; breaking changes only in a new version. Legal catalog
updates are announced as [law updates](https://checkbox.site/docs/api/law-updates) and the `law.changed` webhook.

Current API version: `2026-10-30`.

## One status on the wire {#no-score}

The deprecated 0-100 score is removed (there were no external integrations reading it yet).

- Removed: `score` and `insurable` from scans, evaluations, the site's `compliance` block and compliance plans;
  `score_before` / `score_after` from law-update site impacts; `result.score` from test runs; `score` from the public
  scan report. Read the status label instead: `compliance.status` / `compliance.label`.
- Scans gain `compliance` (`status`, `label`) once the scan's evaluation exists (null before).
- Webhooks: `site.compliance_changed` (data.object is the site with its current `compliance.status` and
  `compliance.label`) replaces `site.score_changed`, which is no longer sent. `plan.updated`'s `previous_attributes`
  carries the previous `status` only.
- `verifyTask` with `html`, `email` or Stripe params: `precheck.checks` lists each pre-checked check (`check_id`,
  `status`, one-line `reason`, `fix` when it does not pass).
- Notice schedule: a yearly terms reminder that applies to a plan of a year or longer is listed (or named in
  `not_required`), and a price-change notice without `price_change` is named in `not_required`, so the schedule's
  email kinds match the compliance plan's email tasks.

## Newest Checkout Session and Payment Link trials {#newest-session}

Backwards-compatible additions; nothing renamed or removed.

- Compliance plan, `stripe_checkout_params`: sessions are judged newest first by `created`, one per set of prices.
  The task's `why` and the `verifyTask` note name the judged session (`cs_… (created YYYY-MM-DD)`). Sessions a
  Payment Link created are judged as that Payment Link, not as Checkout Session parameters.
- Per-plan offers read a Payment Link's `subscription_data.trial_period_days` for the price it sells, so plan offer
  blocks, Notices trial timing and test runs carry the trial.
- Test runs: `subscription_created` events carry the subscription's actual trial end, and the mirrored Checkout
  Session is the newest one.
- Checkbox Elements `1.4.2` (no behaviour change). `1.4.1` and earlier stay available.

## Per-plan fixes, Stripe re-read and Notices expectations {#per-plan}

Backwards-compatible additions; nothing renamed or removed.

- Compliance plan, sign-up task: with two or more plans, `change.edits` holds one `insert_before` per plan button, each
  with that plan's price, interval and trial. `engine_verified` is false for per-plan patches (only the resolved plan's
  text is engine-verified until the page is seen live).
- `stripe_checkout_params`: engine-corrected params keep the `line_items` Price id and
  `subscription_data.trial_period_days`. With several failing sessions, `change.content` is still the first one's
  params; the explanation lists the others. Sign-up checks open only on Stripe Checkout pages count under this task.
  Stripe-hosted styling and placement are a note, never a fix.
- `verifyTask` re-reads Stripe (rate-limited) before judging a Stripe-dependent task. The verification's
  `precheck.note` says what was re-read; when there was no other pre-check, `precheck.source` is `billing_sync` with
  verdict `needs_review` (it only carries the note: the re-evaluation decides). `observed.billing_refresh` lists the
  re-reads.
- The plan's one-click `updateNoticeSettings` config adds `cancel_url` and `policy` (`confirm: true`) when Notices
  settings do not hold them yet.
- MCP `check_stripe_checkout_session`: the description says Stripe-hosted conspicuousness is a note in the plan.
- Improve: `SUGGESTIONS_VERSION` 2026.11.03.2.
- Descriptions across the OpenAPI document use neutral wording ("a requirement is clearly not met" instead of "a clear
  violation"). Field names, including `violations`, are unchanged.

## One status, one to-do list {#one-status}

Backwards-compatible; one field deprecated.

- The 0-100 `score` (site `compliance.score`, evaluations, scans, compliance plans, setup sessions) is **deprecated**.
  It stays populated for existing integrations, but no Checkbox surface (dashboard, emails, Slack, MCP, CLI, Stripe App)
  shows it any more. Read the site's one status instead: `compliance.status` / `compliance.label` (Compliant, Needs a
  fix, Not set up yet, Not checked yet, Your call, counted in tasks).
- The compliance plan is the only to-do list: its open required tasks, in plan order, are what the dashboard, emails,
  MCP `get_site_status` / `get_compliance_plan` and the CLI list. Setup sessions gain `compliance.todo` (task id, key,
  title, status, label); `compliance.failing`, `compliance.needs_review` and `compliance.top_findings` are deprecated
  (per-check evidence, not the to-do list).
- MCP `get_site_status` returns `data.todo` (the plan's open tasks) instead of `top_findings`; its headline is the
  status label, without a score.
- The compliance plan's `stripe_checkout_params` task follows the rules engine on Stripe Checkout: with no registered
  Checkout config, it judges the recent subscription Checkout Sessions read from Stripe (consent_collection, custom_text,
  line items) instead of asking you to register them. `verifyTask` on that task checks those sessions too when the
  request carries no params and none are registered.
- `checkNoticeSchedule` / notice timing: a trial-ending reminder is never scheduled before the trial started. The send
  day is picked on the law's window, then pulled inside the trial when the trial is shorter.
- Sign-up checks: consent is judged per form (a second plan's form gated by its own required box is not a bypass); Stripe's
  placement and styling of custom text on Stripe-hosted pages is "Looks compliant with a note" (hidden text still fails);
  a trial is only expected on the plan that has one.
- Checkbox Elements 1.4.1: rebuilt on the shared per-plan offer model; no behaviour change. 1.4.0 stays served unchanged.

## Structured reviews {#reviews}

Backwards-compatible additions.

- `POST /v1/feedback` (`createFeedback`) takes `type: "review"` with `score` (0-10), `liked`, `disliked`,
  `wrong_verdicts` (each `check id: reason`), `would_keep_using` and `stack`; `message` is optional for reviews. A
  review describes Checkbox the product: no site or request id is attached and URLs are removed. Free text in all
  feedback is redacted (secrets and API keys, card numbers, email addresses become `[redacted]`); the response gains
  `redacted`.
- `POST /v1/sites/:site/review_prompt` (`claimReviewPrompt`): the one-time review prompt for a compliant site
  (`show` is true once per site). The MCP tools `get_compliance_plan` and `verify_task` call it and add the hint;
  `send_feedback` accepts the review fields. Agents ask the human once and never send a review without a yes.

## Retention settings and legal hold {#retention}

Backwards-compatible additions.

- Account and site objects gain `retention` (`good_practice_years`, `problem_history_days`; sites also `inherited`) and
  `legal_hold` (`active`, `scope`: `site` or `account`, `set`, `reason`). Good-practice records are kept 7 years by
  default (1-10); problem history is deleted 30 days after a problem is resolved by default (7-730 days), keeping only
  counts. Open problems are never deleted.
- `updateAccount` and `updateSite` take `retention` (on a site, `null` returns a value to the account default) and
  `legal_hold: { active, reason? }`. Both need an admin key. Problem history also shows how fast you fixed things;
  keep it longer if you want that record.
- New error code `legal_hold_active` (409): shortening retention (including `updateReceiptSettings` `retention_days`)
  or erasing receipts while a legal hold covers the account or site.
- Evidence exports list records deleted under retention settings as `redacted: { at, reason }` with `file: null`;
  `verify.mjs` checks their chain links and reports them. Not in the MCP catalog (the tool list is at its size budget);
  agents can use `call_api`.

## Stripe checkouts, several plans, cancel gaps {#normal-round-2}

Backwards-compatible additions.

- `POST /v1/sites/:site/billing/resync` (`resyncBilling`): re-reads the site's billing-platform settings and
  re-evaluates. Answers `billing_sync` with the queued platforms; 409 `resource_conflict` (`next_action`
  `connect_billing`) when none is connected. Not in the MCP catalog yet; agents can use `call_api`.
- Sites: `facts.checkout_type` (`own_page`, `stripe_checkout`, `payment_link`): where shoppers pay.
- Roll-ups (`compliance` on sites, evaluations and plans) gain `checkouts`: one verdict per plan / checkout
  (`name`, `kind`, `plan`, `status`, `label`, `open`), present when a site has two or more checkouts or one on Stripe.
  Statuses include `not_set_up` and `not_checked`. Evaluations of the current site now apply the site's decisions,
  like the site object.
- `/v1/checks/disclosure` and the other plan terms take `intro_price` / `intro_amount` (below the recurring price) and
  `intro_periods`; Elements 1.4.0 takes `intro-amount`.
- Suggestions: `before.source` (`your_copy` or `example`); `account_url` and `sells_goods` parameters.
- Compliance plan `summary` text now starts with the site status label; parse `compliance` instead of the text.
- Notices preview: `priceProblem` when the stated amount contradicts the Stripe charge (the send is refused).

## SDKs 0.1.1 {#sdk-0-1-1}

- `@checkbox-site/node`, `@checkbox-site/mcp` and `checkbox-site` (Python) 0.1.1, regenerated from the current spec.
- Suggestions: `verification.compliance_status` and `verification.compliance_label` (the after-example's status
  roll-up, `compliant` for every offered suggestion) and `surfaces[].held_label` ("Needs a fix" while a failing check
  holds the surface). Backwards-compatible additions.
- Internal fields are marked internal and left out of the published spec and SDK types; responses still carry them, so
  nothing breaks for existing callers.

## Status labels and protection levels {#status-labels}

Backwards-compatible additions. Machine verdicts (`status`: `pass` / `fail` / `needs_review` / `not_applicable`) and
`verdict` are unchanged.

- Every check verdict (`/v1/checks/*`) and every `finding` gains `compliance_status` (`needs_fix`,
  `pending_live_check`, `verified_live`, `your_call`, `compliant`, `not_applicable`) and `compliance` (`label`, `reason`,
  `tier`, the one `fix`, a `note`, the `pending_live_check` {`what`, `completes`, `action`, `due`} or the `question`
  {`text`, `recommended`, `why`}). Check results, evaluations (`compliance`), sites (`compliance.status`,
  `compliance.label`, `compliance.rollup`) and compliance plans (`compliance`) gain a roll-up: needs_fix > your_call >
  compliant, where pending live checks count as compliant ("Compliant · 2 live checks pending"). Mapping:
  [Checks and verdicts](https://checkbox.site/docs/concepts/checks#status-labels).
- Tasks gain status `pending_live_check` (counts as compliant, never blocks the plan), `tier` (`required`,
  `recommended`, `extra`) and `compliance_status`; plans gain `protection_level`, `groups` and
  `counts.pending_live_check`. A plan is `compliant` when every required task is done or only waits for a live check.
- Sites gain `protection_level` (`minimum`, `balanced` — the default — or `maximum`), settable on create / update.
  `maximum` adds two optional extra tasks; `minimum` hides recommended ones.
- SDK types regenerated; MCP `update_site` takes `protection_level`, and tool headlines use the labels.
- Elements 1.3.0: `appearance="line"` (default — one semibold line in the page's own size and colours) or `"box"`.

## Compliant conversion suggestions {#suggestions}

Backwards-compatible additions.

- `GET /v1/sites/{site}/suggestions` (`listSiteSuggestions`, `?surfaces=`) and stateless `POST /v1/suggestions`
  (`suggestImprovements`; the same inputs as `/v1/checks/*` plus `cancellation_flow` and `other_plans`): new object
  `suggestion_report` (`sugr_…`, not stored) with `suggestions[]` (before / after, `apply`, `preconditions`,
  `guardrails`, `verification`), `withheld[]` and per-surface status. Scope `checks:read`.
- The compliance plan gains `optional_improvements.conversion_suggestions`, a pointer that is never a task and never
  changes `status`, `score` or `counts`.
- SDKs: `checkbox.suggestions.forSite / generate` (Python: `for_site`, `generate`). MCP tool `suggest_improvements`.
  Guide: [Compliant conversion suggestions](https://checkbox.site/docs/guides/compliant-conversion).

## Required emails you send {#merchant-notices}

Backwards-compatible additions.

- `GET /v1/notices/due` (`listDueNotices`), `GET /v1/notices/{notice}` (`retrieveDueNotice`),
  `POST /v1/notices/{notice}/sent` (`markNoticeSent`) and `POST /v1/notices/{notice}/missed` (`markNoticeMissed`): the
  emails a merchant owes each subscriber (`required` true for legally required ones, false for the recommended
  cancellation confirmation), with the window, the recommended send date, the rendered email, the subscriber's name and
  masked address and the notice's own `bcc` address (`<key>+<kind>.<token>@…`); new object `due_notice` (`ntd_…`).
  Live keys see live subscribers' notices, test keys test-mode ones. `markNoticeSent` refuses a send before
  `window_start` and a `sent_at` from before an overdue notice became overdue.
- `GET /v1/notices/templates` (`listNoticeTemplates`) and `POST /v1/notices/templates/check` (`checkNoticeTemplate`).
- New event types `notice.due` (on the notice's `send_at`) and `notice.overdue`.
- `notice_settings` gains `mode` (`merchant`, the default for new sites, or `checkbox`) and `bcc`. Turning on an
  `enabled_kinds` notice without `mode` switches the site to `checkbox`, as before.
- SDKs: `checkbox.notices.listDue / retrieve / markSent / markMissed / listTemplates / checkTemplate` (Python:
  `list_due`, `mark_sent`, `mark_missed`, …). MCP tools `list_due_notices`, `mark_notice_sent` (`missed: true`),
  `get_notice_templates`.
- A required notice overdue without proof makes its check fail (`confirmation.email.sent`, `reminder.*`) and adds the
  computed plan task `send_overdue_notices`; overdue notices older than 90 days, test-mode subscribers and recommended
  notices never do.

## Pilot fixes {#pilot-fixes}

Backwards-compatible additions and fixes.

- New endpoint `POST /v1/sites/{site}/integrations` (`connectBillingPlatform`): connect Stripe, Recharge or Shopify with
  read-only credentials, in test mode too. The response carries a `warning` when the key's mode does not match the site.
- `createSite` / `updateSite` take `terms_url` and `account_url`; `test_account.reset_url` re-activates the test
  subscription before each cancellation test.
- `verifyTask` takes `recheck: true`. A task verification whose checks are still needs_review is `failed` with
  `next_action.type = needs_review` (it was `passed`).
- `updateTask` takes `status: not_applicable` (with a reason): the task closes as `no_longer_applicable`.
- `updateNoticeSettings` reports every missing prerequisite at once, with `next_action`.
- Elements **1.2.0**: receipts record a bordered disclosure as `set_off: true`.
- `listReceipts?customer_reference=` also finds receipts by the reference attached with `updateConsent`.

## Feedback and public preview {#feedback}

Backwards-compatible additions.

- New endpoint `POST /v1/feedback` (`createFeedback`, any secret or restricted key, test or live) and MCP tool
  `send_feedback`: report a problem or a missing feature with context (site, request id, tool). 20 per key per hour.
- New crawler: the [public preview](https://checkbox.site/docs/preview) (`CheckboxPreview/1.0`) takes one look at a newly added website's
  public pages, at most once per domain per day, before the domain is verified.

## Consent receipts {#consent-receipts}

Backwards-compatible additions.

- New resource: [consent receipts](https://checkbox.site/docs/receipts) — `createReceiptToken`, `createReceipt`, `listReceipts`,
  `retrieveReceipt`, `renderReceipt`, `verifyReceipt`, `exportReceipt`, `eraseReceipts`, `retrieveReceiptSettings`,
  `updateReceiptSettings`; event `receipt.created`; error code `receipts_disabled`; scope `receipts`; MCP tools
  `list_receipts` and `get_receipt`.
- Receipts are off until you turn them on (`updateReceiptSettings`, after updating your privacy policy). Then
  Checkbox Elements 1.1.0 records a receipt with each consent (`consent.receipt`), and the snippet records receipts
  with `data-receipts="1"` and `data-publishable-key`.
- Stripe-hosted Checkout and Payment Links get receipts reconstructed from Stripe's record of the session.
- Compliance plans recommend "Turn on consent receipts" (low priority, never blocking) until a site records one.

## 2026-10-31 {#2026-10-31}

Backwards-compatible additions and fixes from the first agent usability test and security review.

- Every `next_action` that names an `operation_id` also names its `mcp_tool`. New MCP tool `update_site`;
  `setup_checkbox` applies the facts and runs the first checks in the call that receives the keys.
- Plans: `blocked_on`, `closed_reason`, `coverage`; `change.type: "needs_facts"` instead of patches with placeholders;
  `change.operation_id` / `endpoint` for config changes; a `stripe_checkout_params` task from registered Checkout params;
  a notice sent outside its window is an agent task, not a human question; answers that attest a legal fact need the
  human's confirmation (`ask_human_to_confirm`).
- Setup sessions: `merchant_name`; test keys only see sessions created in test mode. The summary email goes out when the
  setup is finished (every check passes, or `completeSetupSession`), not right after setup starts.
- Emails: `charge_notice` kind in `checkEmail` / `verifyTask`; `trial_ending` accepted as an alias; unresolved
  placeholders in a checked email are reported (`unresolved_placeholders`); inbound emails honour a `+kind`
  plus-address or the `X-Checkbox-Kind` header.
- Consents: browser-claimed references are `client_reference`; `customer_reference` is set by secret keys only.
- Test mode only scans, monitors, fetches and test-runs local hosts and verified domains (plus a small daily scan
  budget for others): new error codes `test_mode_domain_unverified`, `test_mode_scan_budget_exhausted`.
- CLI: `checkbox answer`; `checkbox init --merchant-name`, `--plan`, `--account-url`, and facts are remembered across
  a resumed login.
- Every website Checkbox visits must be verified, in live mode too and per domain
  ([details](https://checkbox.site/docs/concepts/activation#per-domain)): new error code `domain_not_verified`; site objects carry
  `monitoring.held_for_domain_verification` and `monitoring.verify_domains`; plans start with a `verify_domain` task
  (`verifyTask` checks the DNS record / file); test runs can fail with `domain_not_verified`. Test mode adds a
  deployment-wide daily budget for scans of unverified domains.

### Later the same day: scan gate closed, one-click MCP {#2026-10-31-round-6}

- **Scan gate closed in test mode.** Test mode no longer gives a daily allowance of scans of domains you have not
  verified: they are refused at once with `403 test_mode_domain_unverified` and `next_action.type: "verify_domain"`.
  `test_mode_scan_budget_exhausted` is no longer returned (it stays in the error catalog for older clients). Policy and
  homepage fetches follow the same rule.
- Redirects are followed only within verified websites (page fetch, policy fetch, and the scanner's browser, which
  also does not open other websites by navigation). Hosted checkout pages are reached by clicking through from your
  page; as a direct checkout / login URL they need a connected billing account.
- `/.well-known/checkbox-verify.txt` must be on `https://<domain>/` (default port; an apex redirect to the same file on
  `www.` is followed).
- Setup sessions of a site whose domain is not verified start with a `domain` step and `next_action.type:
  "verify_domain"`; `verifySite` answers `next_action.type: "verify_domain"` instead of "first check complete";
  `verifyTask` with `html` answers at once with `next_action.type: "deploy_and_reverify"`.
- Domain verification of a `localhost` site: no DNS record, the file URL on the site's own origin, and
  `next_action.type: "local_site"`.
- MCP: connect claude.ai, Claude Desktop, Claude Code or Cursor with one approval (OAuth); see [MCP](https://checkbox.site/docs/mcp).

## 2026-10-30 {#2026-10-30}

The first public version of the API.

- **API v1** at `https://app.checkbox.site/v1`: secret, restricted and publishable keys; an isolated test mode for
  every account; live mode by domain verification; prefixed ids, cursor pagination, `Idempotency-Key`, dated
  versions, `expand[]`, errors with stable codes and `next_action`. OpenAPI 3.1 at `/v1/openapi.json`.
- **Agent setup:** `checkbox init` with device-authorization login (one browser approval), setup sessions, Terms
  and policy checks.
- **Preflight checks** for disclosure text, Stripe Checkout Sessions and Payment Links, lifecycle emails, checkout
  HTML and notice schedules; also offline in the CLI.
- **Compliance plans:** ordered tasks with exact changes, verification and human questions.
- **Test runs:** synthetic subscriptions in Stripe test mode with test clocks.
- **Checkbox Elements:** the `<checkbox-disclosure>` web component and consent records.
- **Webhooks** for findings, scores, scans, plans, verifications, test runs, consents, certificates, notices and law
  changes.
- **MCP server** at `https://app.checkbox.site/mcp`; Node and Python SDKs (pre-release).
- **Free to start:** no plan limits on compliance features; fair-use limits apply.
