Compliance plans API
The agent-to-agent fix loop: an ordered, machine-readable plan of changes (requirement + citation, where, the exact patch / copy / Stripe params, how to verify), verification of each change, and questions for the human where a machine cannot decide.
| Operation | Endpoint |
|---|---|
| Get the compliance plan for a site | GET /v1/sites/{site}/plan |
| Get one task of a compliance plan | GET /v1/tasks/{task} |
| Claim, decline or reopen a task | POST /v1/tasks/{task} |
| Record the human answer to a manual task | POST /v1/tasks/{task}/answer |
| Verify a task after applying its change | POST /v1/tasks/{task}/verify |
| Re-check the whole site now | POST /v1/sites/{site}/verify |
| Get a verification (long-poll with ?wait=30) | GET /v1/verifications/{verification} |
| List verifications of a site | GET /v1/sites/{site}/verifications |
The CompliancePlan object
The ordered, machine-readable list of changes that makes a site compliant, recomputed from its latest evaluation.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the compliance plan (plan_…). |
object | enum | String representing the object's type. Always "compliance_plan". |
livemode | boolean | true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). |
site | string | The site. |
status | enum | action_required (an agent can apply open tasks now), verifying (changes applied; waiting for confirming observations), compliant (every applicable check Checkbox could observe passes — an automated assessment, not a legal determination; see coverage for what was not observed), blocked (only human answers or declined critical tasks remain). One of action_required, verifying, compliant, blocked. |
score | integer | null | Compliance score 0-100 of the latest evaluation. |
insurable | boolean | null | Preview flag the planned Checkbox Warranty will key on (no checks failing at high severity). No warranty or insurance is offered yet; this is not an underwriting decision. |
evaluation | string | null | The evaluation the plan was built from (null before the first check). |
evaluated | integer | null | When that evaluation ran. Unix timestamp in seconds. |
summary | string | Two or three sentences for an LLM: where the site stands and what comes next. |
counts | object | Tasks per status. |
counts.open | integer | Open tasks. |
counts.in_progress | integer | Claimed tasks. |
counts.verifying | integer | Tasks waiting for a confirming observation. |
counts.manual | integer | Tasks waiting for a human answer. |
counts.done | integer | Done tasks. |
counts.wont_fix | integer | Declined tasks. |
tasks | array of Tasks | Tasks in the order to do them (done tasks last). |
coverage | object | What the assessment rests on. Tell the human about not_observed and attested items; never call the site "compliant" without them. |
coverage.observed | array of strings | Lifecycle stages Checkbox observed (signup, acknowledgment_email, reminders, cancellation, policies, billing_settings). |
coverage.not_observed | array of strings | Stages Checkbox has no observation of: their checks cannot fail, so passing says nothing about them. |
coverage.attested | array of strings | Task keys resting on a human confirmation instead of an observation. |
coverage.billing_connected | boolean | A billing platform is connected (dashboard). |
next_action | PlanNextAction | What the caller (usually an AI coding agent) should do next. |
rules_version | string | null | Rules / catalog version of the evaluation. |
disclaimer | string | Automated assessment; not legal advice. |
generated | integer | When the plan was computed. Unix timestamp in seconds. |
Get the compliance plan for a site
GET /v1/sites/{site}/plan
Ordered tasks that make the site compliant, recomputed from its latest evaluation: each with the requirement and citation, where to change (file / URL / selector / Stripe object), the exact change (unified-diff template with machine-applicable edits, copy, or Stripe params) and how to verify it. Do plan.next_action: apply the first open task, call verifyTask, repeat until status is compliant. Tasks with status manual hold a question for the human (answerTask); they never block the others.
Scope compliance_plans:read · Operation retrieveCompliancePlan
SDK: checkbox.plans.retrieve() (Node) · checkbox.plans.retrieve() (Python). MCP / agents: operation retrieveCompliancePlan.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
site required | path | string | Unique identifier of the site (site_…). |
Returns
Returns a CompliancePlan object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/plan \
-u "$CHECKBOX_SECRET_KEY:"import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const plan = await checkbox.plans.retrieve('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(plan);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
plan = checkbox.plans.retrieve("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(plan){
"id": "plan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "compliance_plan",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"status": "action_required",
"score": 62,
"insurable": false,
"evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"evaluated": 1793318400,
"summary": "StreamMax fails 4 critical checks…",
"counts": {
"open": 3,
"in_progress": 0,
"verifying": 1,
"manual": 1,
"done": 2,
"wont_fix": 0
},
"tasks": [
{
"id": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "task",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"key": "signup_disclosure",
"title": "Show the renewal terms and an unchecked consent box above the Subscribe button",
"status": "open",
"priority": "critical",
"order": 1,
"check_ids": [
"signup.disclosure.autorenew_language"
],
"findings": [],
"requirement": {
"jurisdictions": [
"US-FED"
],
"citation": "15 U.S.C. § 8403(1); Cal. Bus. & Prof. Code § 17602(a)(1)",
"citations": [
{
"id": "US-CA.17602.a.1",
"jurisdiction": "US-CA",
"citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
"source_url": "https://leginfo.legislature.ca.gov/"
}
],
"plain_language": "Before the purchase, state clearly that the subscription renews automatically until canceled, the price and frequency, and how to cancel."
},
"why": "The checkout in US-CA shows no renewal terms near \"Start now\"; the consent checkbox is pre-checked.",
"where": {
"kind": "code",
"file_hint": "app/checkout/page.tsx",
"url": "https://shop.example/checkout",
"selector": "#subscribe-button",
"stripe_object": "checkout.session"
},
"change": {
"type": "patch",
"content": "--- a/app/checkout/page.tsx\n+++ b/app/checkout/page.tsx\n@@ …",
"language": "html",
"explanation": "Insert directly above the purchase button; never pre-check the box.",
"edits": [
{
"op": "insert_before",
"target": {},
"content": "<div class=\"checkbox-renewal-terms\">…</div>",
"attribute": "checked"
}
],
"engine_verified": true,
"operation_id": "updateSite",
"endpoint": "POST /v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"verify": {
"method": "page_fetch",
"how": "POST /v1/tasks/task_…/verify",
"expected": "Every listed check passes (layout checks may stay needs_review on a static fetch until the confirming scan)."
},
"blocked_on": null,
"closed_reason": null,
"depends_on": [],
"blocked_by": [],
"question": {
"text": "Did your subscribers choose email as the channel for account notices?",
"options": [
"yes"
],
"why": "New York requires notices in the manner the subscriber selected; no page or email shows that choice.",
"effect": "yes records the attestation (site fact notice_channel_email) and re-evaluates."
},
"answer": {
"value": "yes",
"note": null,
"answered": 1793318400,
"confirmed_by_human": false,
"pending_confirmation_url": null
},
"decision": {
"status": "wont_fix",
"reason": "Annual plan retired; no subscribers left."
},
"last_verification": {
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"status": "failed",
"created": 1793318400
},
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"first_seen": 1793318400,
"done_at": 1793318400
}
],
"coverage": {
"observed": [
"signup"
],
"not_observed": [
"cancellation"
],
"attested": [],
"billing_connected": false
},
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"rules_version": "1.2.0",
"disclaimer": "Checkbox checks against its legal catalog; it is not legal advice.",
"generated": 1793318400
}Get one task of a compliance plan
GET /v1/tasks/{task}
The task as in the current plan (recomputed): the change to apply, how to verify, its last verification and next_action.
Scope compliance_plans:read · Operation retrieveTask
SDK: checkbox.tasks.retrieve() (Node) · checkbox.tasks.retrieve() (Python). MCP / agents: operation retrieveTask.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
task required | path | string | Unique identifier of the task (task_…). |
Returns
Returns a Task object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
-u "$CHECKBOX_SECRET_KEY:"import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const task = await checkbox.tasks.retrieve('task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(task);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
task = checkbox.tasks.retrieve("task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(task){
"id": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "task",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"key": "signup_disclosure",
"title": "Show the renewal terms and an unchecked consent box above the Subscribe button",
"status": "open",
"priority": "critical",
"order": 1,
"check_ids": [
"signup.disclosure.autorenew_language",
"signup.consent.affirmative"
],
"findings": [],
"requirement": {
"jurisdictions": [
"US-FED"
],
"citation": "15 U.S.C. § 8403(1); Cal. Bus. & Prof. Code § 17602(a)(1)",
"citations": [
{
"id": "US-CA.17602.a.1",
"jurisdiction": "US-CA",
"citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
"source_url": "https://leginfo.legislature.ca.gov/"
}
],
"plain_language": "Before the purchase, state clearly that the subscription renews automatically until canceled, the price and frequency, and how to cancel."
},
"why": "The checkout in US-CA shows no renewal terms near \"Start now\"; the consent checkbox is pre-checked.",
"where": {
"kind": "code",
"file_hint": "app/checkout/page.tsx",
"url": "https://shop.example/checkout",
"selector": "#subscribe-button",
"stripe_object": "checkout.session"
},
"change": {
"type": "patch",
"content": "--- a/app/checkout/page.tsx\n+++ b/app/checkout/page.tsx\n@@ …",
"language": "html",
"explanation": "Insert directly above the purchase button; never pre-check the box.",
"edits": [
{
"op": "insert_before",
"target": {
"selector": "#subscribe-button",
"text": "Start now",
"tag": "button"
},
"content": "<div class=\"checkbox-renewal-terms\">…</div>",
"attribute": "checked"
}
],
"engine_verified": true,
"operation_id": "updateSite",
"endpoint": "POST /v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"verify": {
"method": "page_fetch",
"how": "POST /v1/tasks/task_…/verify",
"expected": "Every listed check passes (layout checks may stay needs_review on a static fetch until the confirming scan)."
},
"blocked_on": null,
"closed_reason": null,
"depends_on": [],
"blocked_by": [],
"question": {
"text": "Did your subscribers choose email as the channel for account notices?",
"options": [
"yes"
],
"why": "New York requires notices in the manner the subscriber selected; no page or email shows that choice.",
"effect": "yes records the attestation (site fact notice_channel_email) and re-evaluates."
},
"answer": {
"value": "yes",
"note": null,
"answered": 1793318400,
"confirmed_by_human": false,
"pending_confirmation_url": null
},
"decision": {
"status": "wont_fix",
"reason": "Annual plan retired; no subscribers left."
},
"last_verification": {
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"status": "failed",
"created": 1793318400
},
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"first_seen": 1793318400,
"done_at": 1793318400
}Claim, decline or reopen a task
POST /v1/tasks/{task}
status in_progress claims the task (shown to other agents and the dashboard); wont_fix declines it with a reason (the merchant's decision, recorded; a declined critical or high task keeps the plan blocked); open clears the decision. Applying a change does not need this call: call verifyTask.
Scope compliance_plans:write · Idempotent (send Idempotency-Key) · Operation updateTask
SDK: checkbox.tasks.update() (Node) · checkbox.tasks.update() (Python). MCP / agents: operation updateTask.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
task required | path | string | Unique identifier of the task (task_…). |
Body
| Field | Type | Description |
|---|---|---|
status required | enum | in_progress claims the task (other agents see it), wont_fix declines it (needs reason; a declined critical/high task keeps the plan from being compliant), open clears either. One of open, in_progress, wont_fix. |
reason | string | Why (required for wont_fix). |
Returns
Returns a Task object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
-u "$CHECKBOX_SECRET_KEY:" \
-H "Content-Type: application/json" \
-d '{
"status": "in_progress"
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const task = await checkbox.tasks.update('task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', { status: 'in_progress' });
console.log(task);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
task = checkbox.tasks.update("task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", status="in_progress")
print(task){
"id": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "task",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"key": "signup_disclosure",
"title": "Show the renewal terms and an unchecked consent box above the Subscribe button",
"status": "open",
"priority": "critical",
"order": 1,
"check_ids": [
"signup.disclosure.autorenew_language",
"signup.consent.affirmative"
],
"findings": [],
"requirement": {
"jurisdictions": [
"US-FED"
],
"citation": "15 U.S.C. § 8403(1); Cal. Bus. & Prof. Code § 17602(a)(1)",
"citations": [
{
"id": "US-CA.17602.a.1",
"jurisdiction": "US-CA",
"citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
"source_url": "https://leginfo.legislature.ca.gov/"
}
],
"plain_language": "Before the purchase, state clearly that the subscription renews automatically until canceled, the price and frequency, and how to cancel."
},
"why": "The checkout in US-CA shows no renewal terms near \"Start now\"; the consent checkbox is pre-checked.",
"where": {
"kind": "code",
"file_hint": "app/checkout/page.tsx",
"url": "https://shop.example/checkout",
"selector": "#subscribe-button",
"stripe_object": "checkout.session"
},
"change": {
"type": "patch",
"content": "--- a/app/checkout/page.tsx\n+++ b/app/checkout/page.tsx\n@@ …",
"language": "html",
"explanation": "Insert directly above the purchase button; never pre-check the box.",
"edits": [
{
"op": "insert_before",
"target": {
"selector": "#subscribe-button",
"text": "Start now",
"tag": "button"
},
"content": "<div class=\"checkbox-renewal-terms\">…</div>",
"attribute": "checked"
}
],
"engine_verified": true,
"operation_id": "updateSite",
"endpoint": "POST /v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"verify": {
"method": "page_fetch",
"how": "POST /v1/tasks/task_…/verify",
"expected": "Every listed check passes (layout checks may stay needs_review on a static fetch until the confirming scan)."
},
"blocked_on": null,
"closed_reason": null,
"depends_on": [],
"blocked_by": [],
"question": {
"text": "Did your subscribers choose email as the channel for account notices?",
"options": [
"yes"
],
"why": "New York requires notices in the manner the subscriber selected; no page or email shows that choice.",
"effect": "yes records the attestation (site fact notice_channel_email) and re-evaluates."
},
"answer": {
"value": "yes",
"note": null,
"answered": 1793318400,
"confirmed_by_human": false,
"pending_confirmation_url": null
},
"decision": {
"status": "wont_fix",
"reason": "Annual plan retired; no subscribers left."
},
"last_verification": {
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"status": "failed",
"created": 1793318400
},
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"first_seen": 1793318400,
"done_at": 1793318400
}Record the human answer to a manual task
POST /v1/tasks/{task}/answer
For tasks with status manual: record the human's answer to task.question (ask them; never answer on their behalf). Answers that assert a legal fact (yes, confirmed) are stored as a proposal and return next_action.type "ask_human_to_confirm" with a link the human opens while signed in to Checkbox; only their confirmation writes the attestation, sets the site fact and re-evaluates. no / needs_change turn the task into a change for the agent; done (after a dashboard-only step) re-checks at once. Every answer is stored in the evidence vault.
Scope compliance_plans:write · Idempotent (send Idempotency-Key) · Operation answerTask
SDK: checkbox.tasks.answer() (Node) · checkbox.tasks.answer() (Python). MCP / agents: operation answerTask.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
task required | path | string | Unique identifier of the task (task_…). |
Body
| Field | Type | Description |
|---|---|---|
answer required | string | One of the task's question.options (yes / no, or confirmed / needs_change). |
note | string | Context from the human (stored with the attestation). |
Returns
Returns a Task object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/answer \
-u "$CHECKBOX_SECRET_KEY:" \
-H "Content-Type: application/json" \
-d '{
"answer": "yes"
}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const task = await checkbox.tasks.answer('task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', { answer: 'yes' });
console.log(task);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
task = checkbox.tasks.answer("task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", answer="yes")
print(task){
"id": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "task",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"key": "signup_disclosure",
"title": "Show the renewal terms and an unchecked consent box above the Subscribe button",
"status": "open",
"priority": "critical",
"order": 1,
"check_ids": [
"signup.disclosure.autorenew_language",
"signup.consent.affirmative"
],
"findings": [],
"requirement": {
"jurisdictions": [
"US-FED"
],
"citation": "15 U.S.C. § 8403(1); Cal. Bus. & Prof. Code § 17602(a)(1)",
"citations": [
{
"id": "US-CA.17602.a.1",
"jurisdiction": "US-CA",
"citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
"source_url": "https://leginfo.legislature.ca.gov/"
}
],
"plain_language": "Before the purchase, state clearly that the subscription renews automatically until canceled, the price and frequency, and how to cancel."
},
"why": "The checkout in US-CA shows no renewal terms near \"Start now\"; the consent checkbox is pre-checked.",
"where": {
"kind": "code",
"file_hint": "app/checkout/page.tsx",
"url": "https://shop.example/checkout",
"selector": "#subscribe-button",
"stripe_object": "checkout.session"
},
"change": {
"type": "patch",
"content": "--- a/app/checkout/page.tsx\n+++ b/app/checkout/page.tsx\n@@ …",
"language": "html",
"explanation": "Insert directly above the purchase button; never pre-check the box.",
"edits": [
{
"op": "insert_before",
"target": {
"selector": "#subscribe-button",
"text": "Start now",
"tag": "button"
},
"content": "<div class=\"checkbox-renewal-terms\">…</div>",
"attribute": "checked"
}
],
"engine_verified": true,
"operation_id": "updateSite",
"endpoint": "POST /v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"verify": {
"method": "page_fetch",
"how": "POST /v1/tasks/task_…/verify",
"expected": "Every listed check passes (layout checks may stay needs_review on a static fetch until the confirming scan)."
},
"blocked_on": null,
"closed_reason": null,
"depends_on": [],
"blocked_by": [],
"question": {
"text": "Did your subscribers choose email as the channel for account notices?",
"options": [
"yes"
],
"why": "New York requires notices in the manner the subscriber selected; no page or email shows that choice.",
"effect": "yes records the attestation (site fact notice_channel_email) and re-evaluates."
},
"answer": {
"value": "yes",
"note": null,
"answered": 1793318400,
"confirmed_by_human": false,
"pending_confirmation_url": null
},
"decision": {
"status": "wont_fix",
"reason": "Annual plan retired; no subscribers left."
},
"last_verification": {
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"status": "failed",
"created": 1793318400
},
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"first_seen": 1793318400,
"done_at": 1793318400
}Verify a task after applying its change
POST /v1/tasks/{task}/verify
Runs the fastest re-check that can confirm the task (static fetch of the live checkout or the html you send, the Stripe params you send, the email copy you send, a re-fetch of the Terms) and queues the confirming observation (a scan, a billing-platform sync, the next email). A failing pre-check fails the verification at once with a diff. Pass ?wait=30 to long-poll; otherwise poll retrieveVerification or wait for the task.verified webhook. Then follow next_action.
Scope compliance_plans:write · Idempotent (send Idempotency-Key) · Operation verifyTask
SDK: checkbox.tasks.verify() (Node) · checkbox.tasks.verify() (Python). MCP / agents: operation verifyTask.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
task required | path | string | Unique identifier of the task (task_…). |
wait | query | integer | null | Long-poll: wait up to this many seconds (0-30) for the verification to resolve before answering. |
Body
| Field | Type | Description |
|---|---|---|
html | string | page_fetch tasks: the rendered page HTML before you deploy, at most ~900 KB (request bodies are limited to 1 MB). Pre-check only; the confirming scan runs on the live page. |
stripe_checkout_session | object | stripe_params tasks: exactly what your code now passes to stripe.checkout.sessions.create. |
email | object | email_copy tasks: the new email template (pre-check; the real email confirms). |
email.kind | enum | Email kind (default: from the task). One of acknowledgment, trial_reminder, renewal_reminder, price_change, annual_terms, charge_notice, cancellation_confirmation. |
email.subject required | string | Subject. |
email.text | string | Plain-text body. |
email.html | string | HTML body. |
Returns
Returns a Verification object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify \
-u "$CHECKBOX_SECRET_KEY:" \
-H "Content-Type: application/json" \
-d '{}'import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const task = await checkbox.tasks.verify('task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(task);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
task = checkbox.tasks.verify("task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(task){
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "verification",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"scope": "task",
"status": "pending",
"method": "page_fetch",
"precheck": {
"source": "static_fetch",
"verdict": "pass",
"url": "https://shop.example/checkout",
"note": "Static fetch: text checks are exact; layout is estimated until the confirming scan."
},
"scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"checks": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"diff": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"plan_status": "action_required",
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"created": 1793318400,
"completed": 1793318400,
"expires": 1793318400
}Re-check the whole site now
POST /v1/sites/{site}/verify
Re-fetches the registered policies, pre-checks the checkout, re-evaluates and queues a scan. Use it for the first check after setup, or after applying several tasks. Pass ?wait=30 to long-poll; then get the plan (retrieveCompliancePlan).
Scope compliance_plans:write · Idempotent (send Idempotency-Key) · Operation verifySite
SDK: checkbox.sites.verify() (Node) · checkbox.sites.verify() (Python). MCP / agents: operation verifySite.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
site required | path | string | Unique identifier of the site (site_…). |
wait | query | integer | null | Long-poll: wait up to this many seconds (0-30) for the verification to resolve before answering. |
Returns
Returns a Verification object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify \
-u "$CHECKBOX_SECRET_KEY:" \
-X POSTimport Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const site = await checkbox.sites.verify('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(site);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
site = checkbox.sites.verify("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(site){
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "verification",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"scope": "task",
"status": "pending",
"method": "page_fetch",
"precheck": {
"source": "static_fetch",
"verdict": "pass",
"url": "https://shop.example/checkout",
"note": "Static fetch: text checks are exact; layout is estimated until the confirming scan."
},
"scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"checks": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"diff": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"plan_status": "action_required",
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"created": 1793318400,
"completed": 1793318400,
"expires": 1793318400
}Get a verification (long-poll with ?wait=30)
GET /v1/verifications/{verification}
The verification's status (pending, passed, failed), expected vs observed per check, the diff and next_action. ?wait=N (≤ 30) holds the request until it resolves or N seconds pass.
Scope compliance_plans:read · Operation retrieveVerification
SDK: checkbox.verifications.retrieve() (Node) · checkbox.verifications.retrieve() (Python). MCP / agents: operation retrieveVerification.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
verification required | path | string | Unique identifier of the verification (ver_…). |
wait | query | integer | null | Long-poll: wait up to this many seconds (0-30) for the verification to resolve before answering. |
Returns
Returns a Verification object.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl https://app.checkbox.site/v1/verifications/ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
-u "$CHECKBOX_SECRET_KEY:"import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const verification = await checkbox.verifications.retrieve('ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(verification);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
verification = checkbox.verifications.retrieve("ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(verification){
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "verification",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"scope": "task",
"status": "pending",
"method": "page_fetch",
"precheck": {
"source": "static_fetch",
"verdict": "pass",
"url": "https://shop.example/checkout",
"note": "Static fetch: text checks are exact; layout is estimated until the confirming scan."
},
"scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"checks": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"diff": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"plan_status": "action_required",
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"created": 1793318400,
"completed": 1793318400,
"expires": 1793318400
}List verifications of a site
GET /v1/sites/{site}/verifications
Verifications newest first (optionally for one task).
Scope compliance_plans:read · Operation listVerifications
SDK: checkbox.verifications.list() (Node) · checkbox.verifications.list() (Python). MCP / agents: operation listVerifications.
Parameters
| Parameter | In | Type | Description |
|---|---|---|---|
site required | path | string | Unique identifier of the site (site_…). |
limit | query | integer | Number of objects to return, 1-100 (default 10). |
starting_after | query | string | Cursor: an object id; returns the objects after it (older). |
ending_before | query | string | Cursor: an object id; returns the objects before it (newer). |
task | query | string | Only this task (task_…). |
Returns
Returns a list ({ object: "list", data, has_more, url }) of Verification objects.
Errors use the standard envelope with a stable code and, where useful, next_action.
curl -G https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verifications \
-u "$CHECKBOX_SECRET_KEY:" \
-d limit=3import Checkbox from '@checkbox-site/cli';
const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);
const verifications = await checkbox.verifications.list('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', { limit: 3 });
console.log(verifications.data);import os
from checkbox import Checkbox
checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])
verifications = checkbox.verifications.list("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", limit=3)
print(verifications.data){
"object": "list",
"data": [
{
"id": "ver_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"object": "verification",
"livemode": false,
"site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"scope": "task",
"status": "pending",
"method": "page_fetch",
"precheck": {
"source": "static_fetch",
"verdict": "pass",
"url": "https://shop.example/checkout",
"note": "Static fetch: text checks are exact; layout is estimated until the confirming scan."
},
"scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"checks": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"diff": [
{
"check_id": "signup.disclosure.price",
"expected": "pass",
"observed": "fail",
"source": "static_fetch",
"detail": "No recurring price near the purchase button."
}
],
"plan_status": "action_required",
"next_action": {
"type": "apply_task",
"description": "Apply task_… (add the renewal terms above the Subscribe button in app/checkout/page.tsx), then call verifyTask.",
"task": "task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
"operation_id": "verifyTask",
"mcp_tool": "verify_task",
"endpoint": "POST /v1/tasks/task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/verify",
"command": "checkbox fix task_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
},
"created": 1793318400,
"completed": 1793318400,
"expires": 1793318400
}
],
"has_more": false,
"url": "/v1/sites"
}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.