Checkbox Docs

Preflight checks

Stateless "check before you ship" calls for AI agents and CI — disclosure text, Stripe params, lifecycle emails, checkout HTML and notice timing — with verdicts per legal requirement and the exact fix.

Preflight checks judge what your code will produce, before anything is deployed. Nothing is stored, no site is needed, and test keys work. Send the text, params, email or HTML; get a verdict per check and per legal requirement, with citations, and a fix the engine has already verified.

CheckEndpointCLIOffline
Disclosure text, placement, consent checkboxPOST /v1/checks/disclosurecheckbox check disclosureyes
Stripe Checkout Session paramsPOST /v1/checks/stripe_checkout_sessioncheckbox check stripe-sessionyes
Stripe Payment Link paramsPOST /v1/checks/stripe_payment_linkcheckbox check payment-linkyes
A lifecycle emailPOST /v1/checks/emailcheckbox check emailyes
Checkout HTML (or a live URL)POST /v1/checks/pagecheckbox check page--file only
When each notice must be sentPOST /v1/checks/notice_schedulecheckbox check notice-scheduleno

--offline runs the same rules engine locally: no key, no network, the same JSON plus "mode": "offline".

Example

Shell
checkbox check disclosure \
  --text "Renews monthly at \$19.99 until you cancel." \
  --merchant-name Acme --price 19.99 --interval month \
  --consent-checkbox --offline

The same call over HTTP returns JSON like this (trimmed):

JSON
{
  "object": "check_result",
  "kind": "disclosure",
  "verdict": "fail",
  "checks": [
    {
      "check_id": "signup.disclosure.cancellation_policy",
      "status": "fail",
      "severity": "critical",
      "fix": "Explain the cancellation policy and exactly how to cancel in the checkout terms.",
      "requirements": [
        { "id": "US-FED.8403.1", "jurisdiction": "US-FED", "citation": "15 U.S.C. § 8403(1)" },
        { "id": "US-CA.17602.a.1", "jurisdiction": "US-CA", "citation": "Cal. Bus. & Prof. Code § 17602(a)(1); § 17601(a)(2)-(3)" }
      ]
    }
  ],
  "replacement": {
    "disclosure_text": "Your Acme subscription automatically renews every month at $19.99 (plus applicable taxes) until you cancel. You can cancel anytime online at {{cancel_url}}; cancellation takes effect at the end of your current billing period. To avoid the next charge, cancel before your next billing date (every month).",
    "placeholders": ["{{cancel_url}}"],
    "verified": true
  },
  "rules_version": "1.4.0",
  "catalog_version": "2026.11.01.1",
  "disclaimer": "Automated compliance check against Checkbox’s catalog of automatic-renewal laws. It is not legal advice…",
  "next_action": {
    "type": "replace_text",
    "message": "Failing: signup.disclosure.cancellation_policy (fail), signup.disclosure.conspicuous (needs_review). Replace the disclosure with replacement.disclosure_text, show it directly above the purchase button… then call this check again."
  }
}

next_action.type is one of none, replace_text, apply_patch, replace_template, fix_and_recheck, human_review, provide_input, schedule_notices. Loop until the verdict is pass.

replacement carries the same verified markup twice: html, and jsx for React / Next.js components (className, style objects, self-closed inputs). For emails, keep the template's lines and add your own greeting, sign-off and merge tags around them; date variables ({{endDate}}, ${trialEndDate}) are accepted as written. When next_action.type is fix_and_recheck because Checkbox cannot see what one of your merge tags holds, keep the tag in your code and check the email again with a sample value in its place.

In CI

The checkbox CLI is not on npm yet, so CI calls the HTTP API directly (round-3 pilot: the previous npx step could not run). The step fails the build when the verdict is fail (add needs_review to the case to make it strict):

.github/workflows/compliance.yml (excerpt)
- name: Checkbox preflight
  env:
    CHECKBOX_API_KEY: ${{ secrets.CHECKBOX_API_KEY }}
  run: |
    jq -n --slurpfile p checkout/session-params.json \
      '{params: $p[0], merchant: {merchant_name: "Acme", cancel_url: "https://acme.example/account/cancel"}}' \
      | curl -sS -X POST https://app.checkbox.site/v1/checks/stripe_checkout_session \
          -H "Authorization: Bearer $CHECKBOX_API_KEY" -H "Content-Type: application/json" --data @- > preflight.json
    verdict=$(jq -r .verdict preflight.json); echo "Checkbox verdict: $verdict"
    case "$verdict" in fail) jq '.checks[] | select(.status != "pass")' preflight.json; exit 1;; esac

Give CI a restricted key with only checks: read. Once the CLI is published, npx @checkbox-site/cli check stripe-session … does the same with stable exit codes (0 pass, 1 fail, 2 needs review with --strict).

To check every file on each pull request, list them once in checkbox.json and run checkbox ci (the GitHub Action checkbox-site/checkbox@v1): offline, no key, annotations on the files that need a fix and the corrected params in the job summary. See Compliance checks on every pull request.

Determinism and limits

  • Every result carries rules_version, catalog_version, catalog_hash, as_of and a disclaimer. The same input and as_of date give the same verdicts.
  • On any Stripe-hosted page, clear and conspicuous (signup.disclosure.conspicuous) stays needs_review: Stripe controls the styling.
  • The page check reads static HTML; buttons rendered by JavaScript are not found, so send the rendered HTML. Layout is estimated, and a passing estimate is reported as needs_review, never pass; a scan confirms it.
  • Disclosure and Stripe checks model a desktop page; mobile layouts are judged by scans.
  • Email checks judge content; real send timing is judged by monitoring.
  • Rate limit: 120 checks per minute per account (page with url: 20 per minute).

Checkbox is compliance software, not a law firm; nothing in these docs is legal advice (details). You remain solely responsible for your subscription program, and Checkbox takes on no legal liability for it (Terms). Checkbox is a System1 company; Trust center · Status. For AI agents: every page is available as Markdown at the same URL plus .md; the index is /llms.txt.