Suggestions API
Compliant conversion suggestions: optional ways to make the checkout, emails and cancellation flow perform better without breaking automatic-renewal laws.
| Operation | Endpoint |
|---|---|
| Get conversion suggestions for a site | GET /v1/sites/{site}/suggestions |
| Get conversion suggestions for copy you send | POST /v1/suggestions |
The SuggestionReport object
Optional, compliant conversion suggestions for a checkout, Stripe Checkout, lifecycle emails and the cancellation flow. Never a compliance task.
| Field | Type | Description |
|---|---|---|
id | string | Id of this report (sugr_…). Reports are computed on request and not stored. |
object | enum | String representing the object's type. Always "suggestion_report". |
livemode | boolean | true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). |
created | integer | When it was computed. Unix seconds. |
site | string | null | The site (GET /v1/sites/:site/suggestions), or null for POST /v1/suggestions. |
optional | enum | Always true: suggestions are optional and never block anything. |
counts_toward_compliance | enum | Always false: suggestions never count for or against compliance, the score or the plan status. |
summary | string | One paragraph for an LLM or a human. |
jurisdictions | enum | Jurisdictions the examples were checked for. |
as_of | string | Date the law was evaluated at. |
library_version | string | Version of the suggestion library. |
rules_version | string | Rules engine version. |
catalog_version | string | Legal catalog version. |
surfaces | array of objects | Per surface. |
suggestions | array of Suggestions | Offered suggestions: detected gaps in your own copy first. |
withheld | array of objects | Suggestions that would apply but are withheld, and why. |
next_action | object | Next step. |
next_action.type | enum | What to do next. One of apply_suggestion, fix_compliance_first, none. |
next_action.message | string | One or two sentences for an agent. |
next_action.operation_id | string | The operation to call next, when there is one. |
next_action.mcp_tool | string | The MCP tool for operation_id. |
disclaimer | string | Not legal advice; optional; results vary. |
Get conversion suggestions for a site
GET /v1/sites/{site}/suggestions
Suggestions for a site, detected from what Checkbox observed (checkout captures, emails, the test cancellation, billing settings, registered Stripe Checkout params) and its latest evaluation. Optional, deterministic suggestions (no LLM) from Checkbox’s curated library: each has the surface, what to change, why it commonly helps (no invented figures), a concrete before/after built from your plan terms, the exact copy / Stripe patch / flow change to apply, the legal guardrails it respects (catalog requirement ids, e.g. California’s and Minnesota’s save-offer rules), and the engine check of the after-example (only verified suggestions are offered). Surfaces whose compliance checks fail are held until fixed. Suggestions never block and never count toward compliance.
Scope checks:read · Operation listSiteSuggestions
SDK: checkbox.suggestions.forSite() (Node) · checkbox.suggestions.for_site() (Python). MCP / agents: operation listSiteSuggestions.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
site required | path | string | Unique identifier of the site (site_…). |
surfaces | query | string | Comma-separated surfaces to include (default all). |
Returns
Returns a SuggestionReport object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/suggestions \
-u "$CHECKBOX_SECRET_KEY:"import Checkbox from '@checkbox-site/node';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const suggestion = await checkbox.suggestions.forSite('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(suggestion);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
suggestion = checkbox.suggestions.for_site("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(suggestion){
"id": "sugr_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "suggestion_report",
"livemode": false,
"created": 1793318400,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"optional": true,
"counts_toward_compliance": false,
"summary": "6 optional suggestions (4 from your own copy, 2 recommended) across 3 surface(s).",
"jurisdictions": [
"US-CA",
"US-NY"
],
"as_of": "2026-11-02",
"library_version": "2026.11.02.2",
"rules_version": "1.4.0",
"catalog_version": "2026.11.01.1",
"surfaces": [
{
"surface": "checkout_page",
"status": "offered",
"observed": true,
"held_by": [],
"held_label": null,
"offered": 3
}
],
"suggestions": [
{
"key": "checkout.trial_button",
"object": "suggestion",
"surface": "checkout_page",
"title": "Name the trial on the button: “Start my free trial”",
"why": "A button that says exactly what happens next is clearer than “Subscribe”.",
"match": "detected",
"reason": "Your button says “Subscribe”, which does not mention the trial.",
"before": {
"label": "Button",
"text": "Subscribe"
},
"after": {
"label": "Button",
"text": "Start my 7-day free trial"
},
"apply": {
"type": "replace_text",
"where": "The purchase button label.",
"content": "Start my 7-day free trial",
"json_patch": [
{
"op": "add",
"path": "/payment_method_collection",
"value": "if_required"
}
],
"instructions": "Replace the purchase button label. Keep the renewal terms and the unchecked consent checkbox above it unchanged."
},
"preconditions": [
"Nothing is charged during the trial."
],
"guardrails": [
{
"rule": "Show any offer next to a prominent “Cancel subscription” button that stays visible the whole time; one click on it cancels.",
"requirement_ids": [
"US-CA.17602.e"
]
}
],
"verification": {
"operation_id": "checkDisclosure",
"verdict": "pass",
"verified": true,
"open_checks": [],
"compliance_status": "compliant",
"compliance_label": "Compliant",
"jurisdictions": "all",
"note": "The compliant baseline with this change applied was run through checkDisclosure."
},
"placeholders": []
}
],
"withheld": [
{
"key": "checkout.annual_equivalent",
"surface": "checkout_page",
"title": "Show the per-month figure next to the yearly charge",
"reason": "Your yearly plan starts with a free trial: next to a trial, a per-month figure reads as the charge after the trial."
}
],
"next_action": {
"type": "apply_suggestion",
"message": "Optional. Pick a suggestion, apply suggestion.apply.content exactly where apply.where says…",
"operation_id": "retrieveCompliancePlan",
"mcp_tool": "get_compliance_plan"
},
"disclaimer": "Optional suggestions to improve conversion and retention…"
}Get conversion suggestions for copy you send
POST /v1/suggestions
Stateless: send any of the inputs of /v1/checks/* (disclosure, page html, Stripe Checkout params, emails) plus a cancellation flow and your plan terms; get suggestions for them. The current status of what you send comes from the same preflight checks; nothing is stored. Optional, deterministic suggestions (no LLM) from Checkbox’s curated library: each has the surface, what to change, why it commonly helps (no invented figures), a concrete before/after built from your plan terms, the exact copy / Stripe patch / flow change to apply, the legal guardrails it respects (catalog requirement ids, e.g. California’s and Minnesota’s save-offer rules), and the engine check of the after-example (only verified suggestions are offered). Surfaces whose compliance checks fail are held until fixed. Suggestions never block and never count toward compliance.
Scope checks:read · Operation suggestImprovements
SDK: checkbox.suggestions.generate() (Node) · checkbox.suggestions.generate() (Python). MCP / agents: operation suggestImprovements.
Body
| Field | Type | Description |
|---|---|---|
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. |
other_plans | array of CheckPlanTerms | Other plans you sell (enables “point to a cheaper plan” and plan-choice suggestions). |
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). |
surfaces | array of enum | Only suggest for these surfaces (default: all). |
disclosure | object | Your own checkout: the same fields as checkDisclosure (without the plan terms, which go in terms). |
disclosure.text required | string | The disclosure shown next to the purchase button, exactly as rendered. |
disclosure.button_text | string | Label of the purchase button. |
disclosure.order_summary | string | Other text next to the button (order summary). |
disclosure.placement | object | Where and how the disclosure is shown (as in checkDisclosure). |
disclosure.consent | object | The consent checkbox (as in checkDisclosure). |
page | object | Your checkout page HTML (as in checkPage; html only). |
page.html required | string | Rendered checkout page HTML (as in checkPage). |
page.url | string | Where the page lives (resolves relative links). |
stripe_checkout_session | object | Stripe Checkout Session params (as in checkStripeCheckoutSession; plan terms in terms). |
stripe_checkout_session.params required | object | Exactly what your code passes to stripe.checkout.sessions.create. |
emails | array of objects | Lifecycle emails (as in checkEmail; plan terms in terms). |
cancellation_flow | object | Your cancellation flow as a subscriber sees it. |
cancellation_flow.steps required | array of objects | Screens from the account page to the confirmation, in order. |
cancellation_flow.confirmation_shown | boolean | A confirmation is shown at the end (default true). |
trial_reminders | boolean | You send a trial-ending reminder to every trial subscriber (false withholds suggestions that promise one). |
site_url | string | Your site’s base URL (used in example links). |
Returns
Returns a SuggestionReport object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/suggestions \
-u "$CHECKBOX_SECRET_KEY:" \
-H "Content-Type: application/json" \
-d '{}'import Checkbox from '@checkbox-site/node';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const suggestion = await checkbox.suggestions.generate();
console.log(suggestion);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
suggestion = checkbox.suggestions.generate()
print(suggestion){
"id": "sugr_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "suggestion_report",
"livemode": false,
"created": 1793318400,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"optional": true,
"counts_toward_compliance": false,
"summary": "6 optional suggestions (4 from your own copy, 2 recommended) across 3 surface(s).",
"jurisdictions": [
"US-CA",
"US-NY"
],
"as_of": "2026-11-02",
"library_version": "2026.11.02.2",
"rules_version": "1.4.0",
"catalog_version": "2026.11.01.1",
"surfaces": [
{
"surface": "checkout_page",
"status": "offered",
"observed": true,
"held_by": [],
"held_label": null,
"offered": 3
}
],
"suggestions": [
{
"key": "checkout.trial_button",
"object": "suggestion",
"surface": "checkout_page",
"title": "Name the trial on the button: “Start my free trial”",
"why": "A button that says exactly what happens next is clearer than “Subscribe”.",
"match": "detected",
"reason": "Your button says “Subscribe”, which does not mention the trial.",
"before": {
"label": "Button",
"text": "Subscribe"
},
"after": {
"label": "Button",
"text": "Start my 7-day free trial"
},
"apply": {
"type": "replace_text",
"where": "The purchase button label.",
"content": "Start my 7-day free trial",
"json_patch": [
{
"op": "add",
"path": "/payment_method_collection",
"value": "if_required"
}
],
"instructions": "Replace the purchase button label. Keep the renewal terms and the unchecked consent checkbox above it unchanged."
},
"preconditions": [
"Nothing is charged during the trial."
],
"guardrails": [
{
"rule": "Show any offer next to a prominent “Cancel subscription” button that stays visible the whole time; one click on it cancels.",
"requirement_ids": [
"US-CA.17602.e"
]
}
],
"verification": {
"operation_id": "checkDisclosure",
"verdict": "pass",
"verified": true,
"open_checks": [],
"compliance_status": "compliant",
"compliance_label": "Compliant",
"jurisdictions": "all",
"note": "The compliant baseline with this change applied was run through checkDisclosure."
},
"placeholders": []
}
],
"withheld": [
{
"key": "checkout.annual_equivalent",
"surface": "checkout_page",
"title": "Show the per-month figure next to the yearly charge",
"reason": "Your yearly plan starts with a free trial: next to a trial, a per-month figure reads as the charge after the trial."
}
],
"next_action": {
"type": "apply_suggestion",
"message": "Optional. Pick a suggestion, apply suggestion.apply.content exactly where apply.where says…",
"operation_id": "retrieveCompliancePlan",
"mcp_tool": "get_compliance_plan"
},
"disclaimer": "Optional suggestions to improve conversion and retention…"
}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.