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.
| Operation | Endpoint |
|---|---|
| Check checkout disclosure text | POST /v1/checks/disclosure |
| Check Stripe Checkout Session params | POST /v1/checks/stripe_checkout_session |
| Check Stripe Payment Link params | POST /v1/checks/stripe_payment_link |
| Check a subscription lifecycle email | POST /v1/checks/email |
| Check a checkout page (HTML or URL) | POST /v1/checks/page |
| Get the dates each required notice must be sent | POST /v1/checks/notice_schedule |
The DisclosureCheckResult object
Verdict on a checkout disclosure plus a verified replacement.
| Field | Type | Description |
|---|---|---|
id | string | Id of this check run (chk_…). Checks are stateless and not stored. |
object | enum | String representing the object's type. Always "check_result". |
livemode | boolean | true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). |
created | integer | When the check ran. Unix timestamp in seconds. |
kind | enum | Which check ran. One of disclosure, stripe_checkout_session, stripe_payment_link, email, page. |
verdict | enum | Overall: 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. |
summary | object | Counts by status. |
summary.pass | integer | Checks passing. |
summary.fail | integer | Checks failing. |
summary.needs_review | integer | Checks needing review. |
summary.not_applicable | integer | Checks not applicable. |
checks | array of CheckVerdicts | Every evaluated check. |
requirements | array of CheckRequirementVerdicts | Verdict per legal requirement (federal first, then by state). |
warnings | array of CheckWarnings | Notes about the input. |
jurisdictions | enum | Jurisdictions evaluated. |
as_of | string | Date the law was evaluated at. |
rules_version | string | Version of the check implementations. |
catalog_version | string | Version of the legal catalog. |
catalog_hash | string | sha256 of the canonical legal catalog. |
disclaimer | string | Not legal advice. |
next_action | NextAction | What the caller (often an AI agent) should do next. |
replacement | CheckReplacement | A 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
| Field | Type | Description |
|---|---|---|
text required | string | The disclosure shown next to the purchase button, exactly as rendered. |
merchant_name | string | Brand shown to subscribers; used in generated text. |
plan_name | string | Plan / product name. |
price | number | Recurring price in major units (19.99). Or give amount in minor units. |
amount | integer | Recurring price in minor units (1999 = $19.99), Stripe style. |
currency | string | Three-letter ISO currency (default usd). |
interval required | string | Billing interval: day, week, month or year (required). |
interval_count | integer | Number of intervals between charges (default 1). |
trial_days | integer | Free-trial length in days (0 or absent = no trial). |
cancel_url | string | https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). |
cancel_timing | enum | When a cancellation takes effect (default period_end). One of period_end, immediately. |
button_text | string | Label of the purchase button (default "Subscribe", or "Start free trial" with a trial). |
order_summary | string | Other text next to the button (order summary), if any. |
jurisdictions | enum | Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). |
placement | object | Where and how the disclosure is shown. |
placement.above_button | boolean | The disclosure is shown before / above the purchase button (default true). |
placement.same_page_as_payment | boolean | The disclosure is on the same page as the payment form and button (default true). |
placement.font_size_px | number | Rendered font size of the disclosure (default 14). |
placement.contrast_ratio | number | WCAG contrast ratio of the text against its background (default ≈14.7). |
placement.bold | boolean | The disclosure is bold / semibold. |
placement.boxed | boolean | The disclosure is set off in a bordered or shaded box. |
placement.body_font_size_px | number | Font size of the surrounding body text (default 14). |
consent | object | The consent checkbox, if any. Omitted = no checkbox. |
consent.checkbox required | boolean | A checkbox the customer must tick to agree to the renewal terms. |
consent.prechecked | boolean | The checkbox is ticked by default. |
consent.label | string | The checkbox label (default "I agree to the automatic renewal terms above."). |
consent.required | boolean | The form cannot be submitted without ticking it (default true). |
as_of | string | Evaluate 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"
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const check = await checkbox.checks.disclosure({
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',
});
console.log(check);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
check = checkbox.checks.disclosure(
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",
)
print(check){
"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
| Field | Type | Description |
|---|---|---|
params required | object | Exactly the object your code passes to Stripe (checkout.sessions.create / paymentLinks.create), or a retrieved Payment Link. |
merchant | CheckPlanTerms | What Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id. |
merchant.merchant_name | string | Brand shown to subscribers; used in generated text. |
merchant.plan_name | string | Plan / product name. |
merchant.price | number | Recurring price in major units (19.99). Or give amount in minor units. |
merchant.amount | integer | Recurring price in minor units (1999 = $19.99), Stripe style. |
merchant.currency | string | Three-letter ISO currency (default usd). |
merchant.interval | string | Billing interval: day, week, month or year. |
merchant.interval_count | integer | Number of intervals between charges (default 1). |
merchant.trial_days | integer | Free-trial length in days (0 or absent = no trial). |
merchant.cancel_url | string | https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). |
merchant.cancel_timing | enum | When a cancellation takes effect (default period_end). One of period_end, immediately. |
jurisdictions | enum | Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). |
as_of | string | Evaluate 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"
}
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const check = await checkbox.checks.stripeCheckoutSession({
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',
},
});
console.log(check);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
check = checkbox.checks.stripe_checkout_session(
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",
},
)
print(check){
"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": []
}
}Check Stripe Payment Link params
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
| Field | Type | Description |
|---|---|---|
params required | object | Exactly the object your code passes to Stripe (checkout.sessions.create / paymentLinks.create), or a retrieved Payment Link. |
merchant | CheckPlanTerms | What Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id. |
merchant.merchant_name | string | Brand shown to subscribers; used in generated text. |
merchant.plan_name | string | Plan / product name. |
merchant.price | number | Recurring price in major units (19.99). Or give amount in minor units. |
merchant.amount | integer | Recurring price in minor units (1999 = $19.99), Stripe style. |
merchant.currency | string | Three-letter ISO currency (default usd). |
merchant.interval | string | Billing interval: day, week, month or year. |
merchant.interval_count | integer | Number of intervals between charges (default 1). |
merchant.trial_days | integer | Free-trial length in days (0 or absent = no trial). |
merchant.cancel_url | string | https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). |
merchant.cancel_timing | enum | When a cancellation takes effect (default period_end). One of period_end, immediately. |
jurisdictions | enum | Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). |
as_of | string | Evaluate 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"
}
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const check = await checkbox.checks.stripePaymentLink({
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',
},
});
console.log(check);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
check = checkbox.checks.stripe_payment_link(
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",
},
)
print(check){
"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
| Field | Type | Description |
|---|---|---|
kind required | enum | Which 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 required | string | Subject line. |
text | string | Plain-text body (give text, html or both). |
html | string | HTML body. |
terms required | CheckPlanTerms | The plan the email is about (price, interval and cancel_url at least). |
terms.merchant_name | string | Brand shown to subscribers; used in generated text. |
terms.plan_name | string | Plan / product name. |
terms.price | number | Recurring price in major units (19.99). Or give amount in minor units. |
terms.amount | integer | Recurring price in minor units (1999 = $19.99), Stripe style. |
terms.currency | string | Three-letter ISO currency (default usd). |
terms.interval | string | Billing interval: day, week, month or year. |
terms.interval_count | integer | Number of intervals between charges (default 1). |
terms.trial_days | integer | Free-trial length in days (0 or absent = no trial). |
terms.cancel_url | string | https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). |
terms.cancel_timing | enum | When a cancellation takes effect (default period_end). One of period_end, immediately. |
terms.previous_price | number | price_change only: the OLD price before the change, major units. price / amount is the NEW price the email announces. |
terms.previous_amount | integer | Price before a price change, minor units. |
terms.support_contact | string | Support email / URL shown in the generated template. |
jurisdictions | enum | Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). |
as_of | string | Evaluate 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. …"
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const check = await checkbox.checks.email({
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. …',
});
console.log(check);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
check = checkbox.checks.email(
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. …",
)
print(check){
"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
| Field | Type | Description |
|---|---|---|
html | string | Checkout page HTML (rendered, after JavaScript, for client-side apps). Give html or url. |
url | string | Fetch this live page instead (live mode, activated accounts only; public addresses only). |
page_kind | enum | What the page is (default checkout). One of checkout, pricing. |
terms | CheckPlanTerms | What Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id. |
terms.merchant_name | string | Brand shown to subscribers; used in generated text. |
terms.plan_name | string | Plan / product name. |
terms.price | number | Recurring price in major units (19.99). Or give amount in minor units. |
terms.amount | integer | Recurring price in minor units (1999 = $19.99), Stripe style. |
terms.currency | string | Three-letter ISO currency (default usd). |
terms.interval | string | Billing interval: day, week, month or year. |
terms.interval_count | integer | Number of intervals between charges (default 1). |
terms.trial_days | integer | Free-trial length in days (0 or absent = no trial). |
terms.cancel_url | string | https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). |
terms.cancel_timing | enum | When a cancellation takes effect (default period_end). One of period_end, immediately. |
jurisdictions | enum | Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). |
as_of | string | Evaluate 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"
}
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const check = await checkbox.checks.page({
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',
},
});
console.log(check);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
check = checkbox.checks.page(
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",
},
)
print(check){
"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
| Field | Type | Description |
|---|---|---|
terms required | CheckPlanTerms | What Stripe params do not say: merchant_name, cancel_url, and price / interval when line_items reference a Price id. |
terms.merchant_name | string | Brand shown to subscribers; used in generated text. |
terms.plan_name | string | Plan / product name. |
terms.price | number | Recurring price in major units (19.99). Or give amount in minor units. |
terms.amount | integer | Recurring price in minor units (1999 = $19.99), Stripe style. |
terms.currency | string | Three-letter ISO currency (default usd). |
terms.interval | string | Billing interval: day, week, month or year. |
terms.interval_count | integer | Number of intervals between charges (default 1). |
terms.trial_days | integer | Free-trial length in days (0 or absent = no trial). |
terms.cancel_url | string | https URL where subscribers cancel online (used in generated text; a {{cancel_url}} placeholder otherwise). |
terms.cancel_timing | enum | When a cancellation takes effect (default period_end). One of period_end, immediately. |
start_date | string | Sign-up date of the subscription to plan for (default today). |
price_change | object | A planned price change to schedule the notice for. |
price_change.effective_date required | string | Date the new price is first charged. |
price_change.new_price | number | New recurring price, major units. |
cycles | integer | How many renewals to plan (default: one year of renewals). |
payment_methods | array of enum | Payment methods offered (some notices apply only to debit / ACH). |
jurisdictions | enum | Where you sell: "all" (default) or state codes ("US-CA", "CA", "US-NY"; "US-FED" is always included). |
as_of | string | Evaluate 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"
}
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const check = await checkbox.checks.noticeSchedule({
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',
},
});
console.log(check);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
check = checkbox.checks.notice_schedule(
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",
},
)
print(check){
"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.