CheckboxDocs

Checks API

Preflight compliance checks (“check before you ship”) of disclosure text, Stripe params, lifecycle emails and checkout HTML — stateless, for AI coding agents and CI.

OperationEndpoint
Check checkout disclosure textPOST /v1/checks/disclosure
Check Stripe Checkout Session paramsPOST /v1/checks/stripe_checkout_session
Check Stripe Payment Link paramsPOST /v1/checks/stripe_payment_link
Check a subscription lifecycle emailPOST /v1/checks/email
Check a checkout page (HTML or URL)POST /v1/checks/page
Get the dates each required notice must be sentPOST /v1/checks/notice_schedule

The DisclosureCheckResult object

Verdict on a checkout disclosure plus a verified replacement.

FieldTypeDescription
idstringId of this check run (chk_…). Checks are stateless and not stored.
objectenumString representing the object's type. Always "check_result".
livemodebooleantrue for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox).
createdintegerWhen the check ran. Unix timestamp in seconds.
kindenumWhich check ran. One of disclosure, stripe_checkout_session, stripe_payment_link, email, page.
verdictenumOverall: fail if any check fails, else needs_review if any needs review, else pass (not_applicable when nothing applies). One of pass, fail, needs_review, not_applicable.
summaryobjectCounts by status.
summary.passintegerChecks passing.
summary.failintegerChecks failing.
summary.needs_reviewintegerChecks needing review.
summary.not_applicableintegerChecks not applicable.
checksarray of CheckVerdictsEvery evaluated check.
requirementsarray of CheckRequirementVerdictsVerdict per legal requirement (federal first, then by state).
warningsarray of CheckWarningsNotes about the input.
jurisdictionsenumJurisdictions evaluated.
as_ofstringDate the law was evaluated at.
rules_versionstringVersion of the check implementations.
catalog_versionstringVersion of the legal catalog.
catalog_hashstringsha256 of the canonical legal catalog.
disclaimerstringNot legal advice.
next_actionNextActionWhat the caller (often an AI agent) should do next.
replacementCheckReplacementA compliant replacement, verified by the engine.

Check checkout disclosure text

POST /v1/checks/disclosure

Checks the automatic-renewal disclosure you are about to show next to a subscribe button: what it says (renewal until canceled, price, frequency, trial, term, how to cancel), where it sits (above the button, same page) and how it looks (size, contrast, set off), and the consent checkbox (present, not pre-checked). Returns the verdict per check and per legal requirement, plus replacement: compliant text and drop-in HTML generated from your price/interval/trial/cancel_url and verified by the engine. Call it whenever you write or change checkout copy. Stateless and deterministic: nothing is stored, the same input on the same as_of date gives the same verdicts. Every verdict comes from the Checkbox rules engine over the legal catalog (federal ROSCA / EFTA plus the state automatic-renewal laws); the response carries rules_version, catalog_version and a disclaimer (not legal advice). Read verdict, then next_action: it tells you exactly what to change and to call the check again until verdict is pass.

Scope checks:read · Operation checkDisclosure

SDK: checkbox.checks.disclosure() (Node) · checkbox.checks.disclosure() (Python). MCP / agents: operation checkDisclosure.

Body

FieldTypeDescription
text requiredstringThe disclosure shown next to the purchase button, exactly as rendered.
merchant_namestringBrand shown to subscribers; used in generated text.
plan_namestringPlan / product name.
pricenumberRecurring price in major units (19.99). Or give amount in minor units.
amountintegerRecurring price in minor units (1999 = $19.99), Stripe style.
currencystringThree-letter ISO currency (default usd).
interval requiredstringBilling interval: day, week, month or year (required).
interval_countintegerNumber of intervals between charges (default 1).
trial_daysintegerFree-trial length in days (0 or absent = no trial).
cancel_urlstringhttps URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise).
cancel_timingenumWhen a cancellation takes effect (default period_end). One of period_end, immediately.
button_textstringLabel of the purchase button (default "Subscribe", or "Start free trial" with a trial).
order_summarystringOther text next to the button (order summary), if any.
jurisdictionsenumWhere you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included).
placementobjectWhere and how the disclosure is shown.
placement.above_buttonbooleanThe disclosure is shown before / above the purchase button (default true).
placement.same_page_as_paymentbooleanThe disclosure is on the same page as the payment form and button (default true).
placement.font_size_pxnumberRendered font size of the disclosure (default 14).
placement.contrast_rationumberWCAG contrast ratio of the text against its background (default ≈14.7).
placement.boldbooleanThe disclosure is bold / semibold.
placement.boxedbooleanThe disclosure is set off in a bordered or shaded box.
placement.body_font_size_pxnumberFont size of the surrounding body text (default 14).
consentobjectThe consent checkbox, if any. Omitted = no checkbox.
consent.checkbox requiredbooleanA checkbox the customer must tick to agree to the renewal terms.
consent.precheckedbooleanThe checkbox is ticked by default.
consent.labelstringThe checkbox label (default "I agree to the automatic renewal terms above.").
consent.requiredbooleanThe form cannot be submitted without ticking it (default true).
as_ofstringEvaluate the law as of this date (YYYY-MM-DD, default today).

Returns

Returns a DisclosureCheckResult object.

Errors use the standard envelope with a stable code and, where useful, next_action.

curl https://app.checkbox.site/v1/checks/disclosure \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "text": "Your subscription renews automatically every month at $19.99 until you cancel. Cancel anytime online at https://joybox.example/account/cancel.",
  "interval": "month",
  "merchant_name": "Joybox",
  "price": 19.99,
  "cancel_url": "https://joybox.example/account/cancel"
}'
Response
{
  "id": "chk_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "check_result",
  "livemode": false,
  "created": 1793318400,
  "kind": "disclosure",
  "verdict": "fail",
  "summary": {
    "pass": 6,
    "fail": 2,
    "needs_review": 1,
    "not_applicable": 1
  },
  "checks": [
    {
      "check_id": "signup.disclosure.price",
      "status": "fail",
      "severity": "critical",
      "title": "Discloses the recurring charge amount",
      "explanation": "The recurring charge amount is not stated in the terms next to the purchase button.",
      "confidence": 0.85,
      "requirements": [
        {
          "id": "US-CA.17602.a.1",
          "jurisdiction": "US-CA",
          "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
          "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
          "source_url": "https://leginfo.legislature.ca.gov/"
        }
      ],
      "fix": "Show the recurring charge amount in the terms next to the purchase button.",
      "static_estimate": "pass"
    }
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
      "source_url": "https://leginfo.legislature.ca.gov/"
    }
  ],
  "warnings": [
    {
      "code": "stripe_tos_url_required",
      "message": "consent_collection.terms_of_service needs a Terms of Service URL in Stripe.",
      "param": "params.consent_collection"
    }
  ],
  "jurisdictions": "all",
  "as_of": "2026-10-30",
  "rules_version": "1.2.0",
  "catalog_version": "2026.10.30.1",
  "catalog_hash": "b1c2…",
  "disclaimer": "Automated compliance check … not legal advice.",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  },
  "replacement": {
    "disclosure_text": "Your Joybox subscription automatically renews every month at $19.99 …",
    "consent_label": "I agree that my Joybox subscription renews automatically …",
    "button_text": "Subscribe — $19.99/month, renews automatically",
    "html": "<div class=\"checkbox-renewal-terms\">…</div>",
    "placeholders": [
      "{{cancel_url}}"
    ],
    "verified": true,
    "remaining_checks": [],
    "sha256": "3e49…"
  }
}

Check Stripe Checkout Session params

POST /v1/checks/stripe_checkout_session

Pass exactly the object your code gives stripe.checkout.sessions.create (plus merchant.merchant_name and merchant.cancel_url, and merchant.price/interval when line_items use a Price id). Checkbox models the Stripe-hosted page those params render and returns findings plus correction: a JSON Patch (RFC 6902) and the full corrected params (custom_text.submit with the renewal terms, consent_collection.terms_of_service = "required", custom_text.terms_of_service_acceptance as the consent label), verified by the engine. Stripe's own small grey styling keeps "clear and conspicuous" at needs_review on any Stripe-hosted page; also show the terms on your page before redirecting. Stateless and deterministic: nothing is stored, the same input on the same as_of date gives the same verdicts. Every verdict comes from the Checkbox rules engine over the legal catalog (federal ROSCA / EFTA plus the state automatic-renewal laws); the response carries rules_version, catalog_version and a disclaimer (not legal advice). Read verdict, then next_action: it tells you exactly what to change and to call the check again until verdict is pass.

Scope checks:read · Operation checkStripeCheckoutSession

SDK: checkbox.checks.stripeCheckoutSession() (Node) · checkbox.checks.stripe_checkout_session() (Python). MCP / agents: operation checkStripeCheckoutSession.

Body

FieldTypeDescription
params requiredobjectExactly the object your code passes to Stripe (checkout.sessions.create / paymentLinks.create), or a retrieved Payment Link.
merchantCheckPlanTermsWhat Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id.
merchant.merchant_namestringBrand shown to subscribers; used in generated text.
merchant.plan_namestringPlan / product name.
merchant.pricenumberRecurring price in major units (19.99). Or give amount in minor units.
merchant.amountintegerRecurring price in minor units (1999 = $19.99), Stripe style.
merchant.currencystringThree-letter ISO currency (default usd).
merchant.intervalstringBilling interval: day, week, month or year.
merchant.interval_countintegerNumber of intervals between charges (default 1).
merchant.trial_daysintegerFree-trial length in days (0 or absent = no trial).
merchant.cancel_urlstringhttps URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise).
merchant.cancel_timingenumWhen a cancellation takes effect (default period_end). One of period_end, immediately.
jurisdictionsenumWhere you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included).
as_ofstringEvaluate the law as of this date (YYYY-MM-DD, default today).

Returns

Returns a StripeCheckoutSessionCheckResult object.

Errors use the standard envelope with a stable code and, where useful, next_action.

curl https://app.checkbox.site/v1/checks/stripe_checkout_session \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "params": {
    "mode": "subscription",
    "line_items": [
      {
        "price_data": {
          "currency": "usd",
          "unit_amount": 1999,
          "recurring": {
            "interval": "month"
          },
          "product_data": {
            "name": "Joybox Pro"
          }
        },
        "quantity": 1
      }
    ],
    "success_url": "https://joybox.example/welcome"
  }
}'
Response
{
  "id": "chk_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "check_result",
  "livemode": false,
  "created": 1793318400,
  "kind": "disclosure",
  "verdict": "fail",
  "summary": {
    "pass": 6,
    "fail": 2,
    "needs_review": 1,
    "not_applicable": 1
  },
  "checks": [
    {
      "check_id": "signup.disclosure.price",
      "status": "fail",
      "severity": "critical",
      "title": "Discloses the recurring charge amount",
      "explanation": "The recurring charge amount is not stated in the terms next to the purchase button.",
      "confidence": 0.85,
      "requirements": [
        {
          "id": "US-CA.17602.a.1",
          "jurisdiction": "US-CA",
          "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
          "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
          "source_url": "https://leginfo.legislature.ca.gov/"
        }
      ],
      "fix": "Show the recurring charge amount in the terms next to the purchase button.",
      "static_estimate": "pass"
    }
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
      "source_url": "https://leginfo.legislature.ca.gov/"
    }
  ],
  "warnings": [
    {
      "code": "stripe_tos_url_required",
      "message": "consent_collection.terms_of_service needs a Terms of Service URL in Stripe.",
      "param": "params.consent_collection"
    }
  ],
  "jurisdictions": "all",
  "as_of": "2026-10-30",
  "rules_version": "1.2.0",
  "catalog_version": "2026.10.30.1",
  "catalog_hash": "b1c2…",
  "disclaimer": "Automated compliance check … not legal advice.",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  },
  "correction": {
    "patch": [
      {
        "op": "add",
        "path": "/consent_collection",
        "value": {
          "terms_of_service": "required"
        }
      }
    ],
    "corrected_params": {
      "consent_collection": {
        "terms_of_service": "required"
      }
    },
    "verification": {
      "checks": [
        {
          "check_id": "signup.consent.affirmative",
          "before": "fail",
          "after": "pass"
        }
      ],
      "passes": true,
      "remaining_checks": [],
      "note": "Stripe renders custom_text in its own small grey style …"
    },
    "placeholders": []
  }
}

POST /v1/checks/stripe_payment_link

Like checkStripeCheckoutSession, for stripe.paymentLinks.create params or a retrieved Payment Link object. For an existing link (params.id) the correction also gives update_params for stripe.paymentLinks.update (same URL); Stripe cannot add a consent checkbox to an existing link, so needs_new_link_for_consent says when a new link (corrected_params) is required. Stateless and deterministic: nothing is stored, the same input on the same as_of date gives the same verdicts. Every verdict comes from the Checkbox rules engine over the legal catalog (federal ROSCA / EFTA plus the state automatic-renewal laws); the response carries rules_version, catalog_version and a disclaimer (not legal advice). Read verdict, then next_action: it tells you exactly what to change and to call the check again until verdict is pass.

Scope checks:read · Operation checkStripePaymentLink

SDK: checkbox.checks.stripePaymentLink() (Node) · checkbox.checks.stripe_payment_link() (Python). MCP / agents: operation checkStripePaymentLink.

Body

FieldTypeDescription
params requiredobjectExactly the object your code passes to Stripe (checkout.sessions.create / paymentLinks.create), or a retrieved Payment Link.
merchantCheckPlanTermsWhat Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id.
merchant.merchant_namestringBrand shown to subscribers; used in generated text.
merchant.plan_namestringPlan / product name.
merchant.pricenumberRecurring price in major units (19.99). Or give amount in minor units.
merchant.amountintegerRecurring price in minor units (1999 = $19.99), Stripe style.
merchant.currencystringThree-letter ISO currency (default usd).
merchant.intervalstringBilling interval: day, week, month or year.
merchant.interval_countintegerNumber of intervals between charges (default 1).
merchant.trial_daysintegerFree-trial length in days (0 or absent = no trial).
merchant.cancel_urlstringhttps URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise).
merchant.cancel_timingenumWhen a cancellation takes effect (default period_end). One of period_end, immediately.
jurisdictionsenumWhere you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included).
as_ofstringEvaluate the law as of this date (YYYY-MM-DD, default today).

Returns

Returns a StripePaymentLinkCheckResult object.

Errors use the standard envelope with a stable code and, where useful, next_action.

curl https://app.checkbox.site/v1/checks/stripe_payment_link \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "params": {
    "mode": "subscription",
    "line_items": [
      {
        "price_data": {
          "currency": "usd",
          "unit_amount": 1999,
          "recurring": {
            "interval": "month"
          },
          "product_data": {
            "name": "Joybox Pro"
          }
        },
        "quantity": 1
      }
    ],
    "success_url": "https://joybox.example/welcome"
  }
}'
Response
{
  "id": "chk_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "check_result",
  "livemode": false,
  "created": 1793318400,
  "kind": "disclosure",
  "verdict": "fail",
  "summary": {
    "pass": 6,
    "fail": 2,
    "needs_review": 1,
    "not_applicable": 1
  },
  "checks": [
    {
      "check_id": "signup.disclosure.price",
      "status": "fail",
      "severity": "critical",
      "title": "Discloses the recurring charge amount",
      "explanation": "The recurring charge amount is not stated in the terms next to the purchase button.",
      "confidence": 0.85,
      "requirements": [
        {
          "id": "US-CA.17602.a.1",
          "jurisdiction": "US-CA",
          "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
          "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
          "source_url": "https://leginfo.legislature.ca.gov/"
        }
      ],
      "fix": "Show the recurring charge amount in the terms next to the purchase button.",
      "static_estimate": "pass"
    }
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
      "source_url": "https://leginfo.legislature.ca.gov/"
    }
  ],
  "warnings": [
    {
      "code": "stripe_tos_url_required",
      "message": "consent_collection.terms_of_service needs a Terms of Service URL in Stripe.",
      "param": "params.consent_collection"
    }
  ],
  "jurisdictions": "all",
  "as_of": "2026-10-30",
  "rules_version": "1.2.0",
  "catalog_version": "2026.10.30.1",
  "catalog_hash": "b1c2…",
  "disclaimer": "Automated compliance check … not legal advice.",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  },
  "correction": {
    "patch": [
      {
        "op": "add",
        "path": "/consent_collection",
        "value": {
          "terms_of_service": "required"
        }
      }
    ],
    "corrected_params": {
      "consent_collection": {
        "terms_of_service": "required"
      }
    },
    "verification": {
      "checks": [
        {
          "check_id": "signup.consent.affirmative",
          "before": "fail",
          "after": "pass"
        }
      ],
      "passes": true,
      "remaining_checks": [],
      "note": "Stripe renders custom_text in its own small grey style …"
    },
    "placeholders": [],
    "update_params": {
      "custom_text": {
        "submit": {
          "message": "…"
        }
      }
    },
    "needs_new_link_for_consent": true
  }
}

Check a subscription lifecycle email

POST /v1/checks/email

Checks the content of an acknowledgment (welcome) email, trial-ending reminder, renewal reminder, price-change notice, yearly terms reminder or cancellation confirmation against the requirements for that notice (renewal terms, amount, frequency, how to cancel, trial cancellation). The email is modelled as sent on time, so the verdict is about content; get send dates from checkNoticeSchedule. Returns required_by (requirements that make the email mandatory for this plan) and a compliant template with {{merge_tags}}, verified by the engine. Stateless and deterministic: nothing is stored, the same input on the same as_of date gives the same verdicts. Every verdict comes from the Checkbox rules engine over the legal catalog (federal ROSCA / EFTA plus the state automatic-renewal laws); the response carries rules_version, catalog_version and a disclaimer (not legal advice). Read verdict, then next_action: it tells you exactly what to change and to call the check again until verdict is pass.

Scope checks:read · Operation checkEmail

SDK: checkbox.checks.email() (Node) · checkbox.checks.email() (Python). MCP / agents: operation checkEmail.

Body

FieldTypeDescription
kind requiredenumWhich lifecycle email this is (the same names verifyTask, the plan and the X-Checkbox-Kind header use; trial_ending is an alias of trial_reminder, as in Notices). One of acknowledgment, trial_reminder, trial_ending, renewal_reminder, price_change, annual_terms, charge_notice, cancellation_confirmation.
subject requiredstringSubject line.
textstringPlain-text body (give text, html or both).
htmlstringHTML body.
terms requiredCheckPlanTermsThe plan the email is about (price, interval and cancel_url at least).
terms.merchant_namestringBrand shown to subscribers; used in generated text.
terms.plan_namestringPlan / product name.
terms.pricenumberRecurring price in major units (19.99). Or give amount in minor units.
terms.amountintegerRecurring price in minor units (1999 = $19.99), Stripe style.
terms.currencystringThree-letter ISO currency (default usd).
terms.intervalstringBilling interval: day, week, month or year.
terms.interval_countintegerNumber of intervals between charges (default 1).
terms.trial_daysintegerFree-trial length in days (0 or absent = no trial).
terms.cancel_urlstringhttps URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise).
terms.cancel_timingenumWhen a cancellation takes effect (default period_end). One of period_end, immediately.
terms.previous_pricenumberprice_change only: the OLD price before the change, major units. price / amount is the NEW price the email announces.
terms.previous_amountintegerPrice before a price change, minor units.
terms.support_contactstringSupport email / URL shown in the generated template.
jurisdictionsenumWhere you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included).
as_ofstringEvaluate the law as of this date (YYYY-MM-DD, default today).

Returns

Returns an EmailCheckResult object.

Errors use the standard envelope with a stable code and, where useful, next_action.

curl https://app.checkbox.site/v1/checks/email \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "trial_reminder",
  "subject": "Your free trial ends on December 4",
  "terms": {
    "merchant_name": "Joybox",
    "plan_name": "Pro",
    "price": 19.99,
    "amount": 1999,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "trial_days": 14,
    "cancel_url": "https://joybox.example/account/cancel",
    "cancel_timing": "period_end"
  },
  "text": "Your free trial ends on December 4, 2026. …"
}'
Response
{
  "id": "chk_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "check_result",
  "livemode": false,
  "created": 1793318400,
  "kind": "disclosure",
  "verdict": "fail",
  "summary": {
    "pass": 6,
    "fail": 2,
    "needs_review": 1,
    "not_applicable": 1
  },
  "checks": [
    {
      "check_id": "signup.disclosure.price",
      "status": "fail",
      "severity": "critical",
      "title": "Discloses the recurring charge amount",
      "explanation": "The recurring charge amount is not stated in the terms next to the purchase button.",
      "confidence": 0.85,
      "requirements": [
        {
          "id": "US-CA.17602.a.1",
          "jurisdiction": "US-CA",
          "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
          "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
          "source_url": "https://leginfo.legislature.ca.gov/"
        }
      ],
      "fix": "Show the recurring charge amount in the terms next to the purchase button.",
      "static_estimate": "pass"
    }
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
      "source_url": "https://leginfo.legislature.ca.gov/"
    }
  ],
  "warnings": [
    {
      "code": "stripe_tos_url_required",
      "message": "consent_collection.terms_of_service needs a Terms of Service URL in Stripe.",
      "param": "params.consent_collection"
    }
  ],
  "jurisdictions": "all",
  "as_of": "2026-10-30",
  "rules_version": "1.2.0",
  "catalog_version": "2026.10.30.1",
  "catalog_hash": "b1c2…",
  "disclaimer": "Automated compliance check … not legal advice.",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  },
  "email_kind": "trial_reminder",
  "required_by": [
    "US-CA.17602.a.3"
  ],
  "template": {
    "subject": "Your Joybox free trial ends on {{trial_end_date}}",
    "text": "Your free trial ends on {{trial_end_date}}. …",
    "html": "<p>Your free trial ends on {{trial_end_date}}. …</p>",
    "merge_tags": [
      "{{trial_end_date}}"
    ],
    "placeholders": [],
    "verified": true,
    "remaining_checks": []
  }
}

Check a checkout page (HTML or URL)

POST /v1/checks/page

Reads a checkout page's HTML (send the rendered HTML of client-side apps) with Checkbox's static extractor — purchase buttons, terms blocks, consent checkboxes, terms links — and runs the sign-up checks on it. Without a browser, placement and conspicuousness are estimates: a passing estimate is reported as needs_review (with static_estimate), never as pass; install the snippet or run a scan after deploying for rendered measurements. url (instead of html) fetches a public page and needs a live-mode key on an activated account. Pass terms to compare the disclosed price with your real one and get a verified replacement. Stateless and deterministic: nothing is stored, the same input on the same as_of date gives the same verdicts. Every verdict comes from the Checkbox rules engine over the legal catalog (federal ROSCA / EFTA plus the state automatic-renewal laws); the response carries rules_version, catalog_version and a disclaimer (not legal advice). Read verdict, then next_action: it tells you exactly what to change and to call the check again until verdict is pass.

Scope checks:read · Operation checkPage

SDK: checkbox.checks.page() (Node) · checkbox.checks.page() (Python). MCP / agents: operation checkPage.

Body

FieldTypeDescription
htmlstringCheckout page HTML (rendered, after JavaScript, for client-side apps). Give html or url.
urlstringFetch this live page instead (live mode, activated accounts only; public addresses only).
page_kindenumWhat the page is (default checkout). One of checkout, pricing.
termsCheckPlanTermsWhat Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id.
terms.merchant_namestringBrand shown to subscribers; used in generated text.
terms.plan_namestringPlan / product name.
terms.pricenumberRecurring price in major units (19.99). Or give amount in minor units.
terms.amountintegerRecurring price in minor units (1999 = $19.99), Stripe style.
terms.currencystringThree-letter ISO currency (default usd).
terms.intervalstringBilling interval: day, week, month or year.
terms.interval_countintegerNumber of intervals between charges (default 1).
terms.trial_daysintegerFree-trial length in days (0 or absent = no trial).
terms.cancel_urlstringhttps URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise).
terms.cancel_timingenumWhen a cancellation takes effect (default period_end). One of period_end, immediately.
jurisdictionsenumWhere you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included).
as_ofstringEvaluate the law as of this date (YYYY-MM-DD, default today).

Returns

Returns a PageCheckResult object.

Errors use the standard envelope with a stable code and, where useful, next_action.

curl https://app.checkbox.site/v1/checks/page \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "html": "<form>…<button>Subscribe</button></form>",
  "terms": {
    "merchant_name": "Joybox",
    "plan_name": "Pro",
    "price": 19.99,
    "amount": 1999,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "trial_days": 14,
    "cancel_url": "https://joybox.example/account/cancel",
    "cancel_timing": "period_end"
  }
}'
Response
{
  "id": "chk_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "check_result",
  "livemode": false,
  "created": 1793318400,
  "kind": "disclosure",
  "verdict": "fail",
  "summary": {
    "pass": 6,
    "fail": 2,
    "needs_review": 1,
    "not_applicable": 1
  },
  "checks": [
    {
      "check_id": "signup.disclosure.price",
      "status": "fail",
      "severity": "critical",
      "title": "Discloses the recurring charge amount",
      "explanation": "The recurring charge amount is not stated in the terms next to the purchase button.",
      "confidence": 0.85,
      "requirements": [
        {
          "id": "US-CA.17602.a.1",
          "jurisdiction": "US-CA",
          "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
          "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
          "source_url": "https://leginfo.legislature.ca.gov/"
        }
      ],
      "fix": "Show the recurring charge amount in the terms next to the purchase button.",
      "static_estimate": "pass"
    }
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous disclosure of automatic renewal offer terms",
      "source_url": "https://leginfo.legislature.ca.gov/"
    }
  ],
  "warnings": [
    {
      "code": "stripe_tos_url_required",
      "message": "consent_collection.terms_of_service needs a Terms of Service URL in Stripe.",
      "param": "params.consent_collection"
    }
  ],
  "jurisdictions": "all",
  "as_of": "2026-10-30",
  "rules_version": "1.2.0",
  "catalog_version": "2026.10.30.1",
  "catalog_hash": "b1c2…",
  "disclaimer": "Automated compliance check … not legal advice.",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  },
  "source": "html",
  "extraction": {
    "mode": "static_html",
    "url": "https://joybox.example/checkout",
    "purchase_buttons": [
      "Subscribe"
    ],
    "disclosures": [
      "Renews monthly at $19.99 until you cancel."
    ],
    "checkboxes": [
      {
        "label": "I agree to the automatic renewal terms.",
        "prechecked": false,
        "required": true
      }
    ],
    "links": [
      {
        "text": "Terms of Service",
        "href": "https://joybox.example/terms"
      }
    ],
    "limitations": [
      "Static HTML: stylesheets … were not applied."
    ]
  },
  "replacement": {
    "disclosure_text": "Your Joybox subscription automatically renews every month at $19.99 …",
    "consent_label": "I agree that my Joybox subscription renews automatically …",
    "button_text": "Subscribe — $19.99/month, renews automatically",
    "html": "<div class=\"checkbox-renewal-terms\">…</div>",
    "placeholders": [
      "{{cancel_url}}"
    ],
    "verified": true,
    "remaining_checks": [],
    "sha256": "3e49…"
  }
}

Get the dates each required notice must be sent

POST /v1/checks/notice_schedule

For a subscription plan (price, interval, trial) and where you sell, returns every legally required notice — acknowledgment, trial-ending reminder, renewal reminders, yearly terms reminder, price-change notice — with the recommended send time and the compliant window (opens / closes), the jurisdictions each send satisfies and the citations. Uses the same timing as Checkbox Notices: per-state windows intersected, or the fewest sends that cover conflicting windows. Stateless. Check each email's content with checkEmail, or let Checkbox Notices send them.

Scope checks:read · Operation checkNoticeSchedule

SDK: checkbox.checks.noticeSchedule() (Node) · checkbox.checks.notice_schedule() (Python). MCP / agents: operation checkNoticeSchedule.

Body

FieldTypeDescription
terms requiredCheckPlanTermsWhat Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id.
terms.merchant_namestringBrand shown to subscribers; used in generated text.
terms.plan_namestringPlan / product name.
terms.pricenumberRecurring price in major units (19.99). Or give amount in minor units.
terms.amountintegerRecurring price in minor units (1999 = $19.99), Stripe style.
terms.currencystringThree-letter ISO currency (default usd).
terms.intervalstringBilling interval: day, week, month or year.
terms.interval_countintegerNumber of intervals between charges (default 1).
terms.trial_daysintegerFree-trial length in days (0 or absent = no trial).
terms.cancel_urlstringhttps URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise).
terms.cancel_timingenumWhen a cancellation takes effect (default period_end). One of period_end, immediately.
start_datestringSign-up date of the subscription to plan for (default today).
price_changeobjectA planned price change to schedule the notice for.
price_change.effective_date requiredstringDate the new price is first charged.
price_change.new_pricenumberNew recurring price, major units.
cyclesintegerHow many renewals to plan (default: one year of renewals).
payment_methodsarray of enumPayment methods offered (some notices apply only to debit / ACH).
jurisdictionsenumWhere you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included).
as_ofstringEvaluate the law as of this date (YYYY-MM-DD, default today).

Returns

Returns a NoticeScheduleResult object.

Errors use the standard envelope with a stable code and, where useful, next_action.

curl https://app.checkbox.site/v1/checks/notice_schedule \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "terms": {
    "merchant_name": "Joybox",
    "plan_name": "Pro",
    "price": 19.99,
    "amount": 1999,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "trial_days": 14,
    "cancel_url": "https://joybox.example/account/cancel",
    "cancel_timing": "period_end"
  }
}'
Response
{
  "id": "chk_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "notice_schedule",
  "livemode": false,
  "created": 1793318400,
  "start_date": "2026-11-01",
  "notices": [
    {
      "kind": "trial_ending",
      "occasion": "Trial ends",
      "anchor_date": "2026-11-15",
      "send_date": "2026-11-03",
      "send_at": 1793750400,
      "window_opens_at": 1793318400,
      "window_closes_at": 1794182400,
      "days_before": 12,
      "jurisdictions": [
        "US-CA"
      ],
      "requirement_ids": [
        "US-CA.17602.a.3"
      ],
      "citations": [
        "Cal. Bus. & Prof. Code § 17602(a)(3)"
      ],
      "default_window": false
    }
  ],
  "not_required": [
    {
      "kind": "renewal_reminder",
      "reason": "Monthly term: renewal reminders apply to terms of 12+ months."
    }
  ],
  "jurisdictions": "all",
  "as_of": "2026-10-30",
  "rules_version": "1.2.0",
  "catalog_version": "2026.10.30.1",
  "catalog_hash": "b1c2…",
  "disclaimer": "Automated compliance check … not legal advice.",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  }
}

Checkbox is compliance software, not a law firm; nothing in these docs is legal advice (details). For AI agents: every page is available as Markdown at the same URL plus .md; the index is /llms.txt.