# Sites API

> The subscription businesses Checkbox monitors, how to install the snippet, and domain verification (which activates live mode).

| Operation | Endpoint |
|---|---|
| [List sites](#listSites) | `GET /v1/sites` |
| [Create a site](#createSite) | `POST /v1/sites` |
| [Retrieve a site](#retrieveSite) | `GET /v1/sites/{site}` |
| [Update a site](#updateSite) | `POST /v1/sites/{site}` |
| [Archive a site](#deleteSite) | `DELETE /v1/sites/{site}` |
| [Restore an archived site](#restoreSite) | `POST /v1/sites/{site}/restore` |
| [Connect a billing platform](#connectBillingPlatform) | `POST /v1/sites/{site}/integrations` |
| [Retrieve domain verification](#retrieveDomainVerification) | `GET /v1/sites/{site}/domain_verification` |
| [Start domain verification](#createDomainVerification) | `POST /v1/sites/{site}/domain_verification` |
| [Check domain verification now](#checkDomainVerification) | `POST /v1/sites/{site}/domain_verification/check` |
| [Re-sync Stripe settings](#resyncBilling) | `POST /v1/sites/{site}/billing/resync` |

## The Site object

A subscription business Checkbox monitors.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique identifier of the site (site_…). |
| `object` | enum | String representing the object's type. Always "site". |
| `livemode` | boolean | true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). |
| `name` | string | Display name. |
| `url` | string | Base URL. |
| `platform` | enum | Billing platform. One of `stripe`, `shopify`, `recharge`, `chargebee`, `recurly`, `paddle`, `woocommerce`, `custom`. |
| `jurisdictions` | array of enum | Evaluated jurisdictions (empty = all). |
| `facts` | SiteFacts | Business facts that decide which legal requirements apply. |
| `checkout` | object | Synthetic-shopper configuration (secrets are never returned). |
| `checkout.url` | string | Checkout entry page. |
| `checkout.regions` | array of enum | States scanned from. |
| `checkout.devices` | array of enum | Devices scanned. |
| `checkout.checkout_steps` | integer | Number of configured checkout steps. |
| `checkout.completes_purchase` | boolean | A synthetic sign-up is configured. |
| `checkout.has_test_account` | boolean | A test account for the cancellation test is configured. |
| `checkout.test_account` | object \| null | The test account as configured (the password is write-only and never returned). |
| `checkout.cancel_steps` | integer | Number of explicit cancellation steps. |
| `checkout.account_url` | string \| null | Public account / cancellation page visited on every scan. |
| `checkout.terms_url` | string \| null | Terms of service page read on every scan. |
| `checkout.homepage_as_checkout` | boolean | The checkout page is the home page (checkout_url was omitted or set to the site root). Sign-up checks then judge the home page: set checkout_url to the page with the subscribe button unless the home page really has it. |
| `monitoring` | SiteMonitoring | Scheduled monitoring. |
| `protection_level` | enum | Which requirement tiers Checkbox shows (minimum: required only; balanced: + recommended suggestions; maximum: + extras). Only required items affect compliance. One of `minimum`, `balanced`, `maximum`. |
| `retention` | SiteRetention | The retention in effect for the site. |
| `legal_hold` | LegalHold | Account-wide legal hold: while active, nothing of this mode's data is deleted. |
| `compliance` | SiteCompliance \| null | Latest verdict; null until the first evaluation. |
| `install` | SiteInstall | What to install on the merchant site. |
| `archived` | boolean | Archived (soft-deleted); evidence is retained. |
| `created` | integer | When the site was created. Unix timestamp in seconds. |
| `latest_scan` | Scan | Most recent scan (only with expand[]=latest_scan). |
| `unverified_scan` | UnverifiedScan \| null | While the domain is not verified: the newest read-only scan of the site's own public pages (labeled "unverified scan": no checkout submitted, not evidence, replaced by the full scan after verification). Null otherwise. |
| `domain_verification` | DomainVerification | Domain verification (only with expand[]=domain_verification). |

## List sites {#listSites}

`GET /v1/sites`

Returns the sites of the account in the current mode, newest first. Archived sites are included only with archived=true.

**Scope** `sites:read` · **Operation** `listSites`

SDK: `checkbox.sites.list()` (Node) · `checkbox.sites.list()` (Python). MCP / agents: operation `listSites`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `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). |
| `archived` | query | enum | true lists only archived sites. One of `true`, `false`. |

#### Returns

Returns a list (`{ object: "list", data, has_more, url }`) of [Site](https://checkbox.site/docs/api/sites#the-site-object) objects.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl -G https://app.checkbox.site/v1/sites \
  -u "$CHECKBOX_SECRET_KEY:" \
  -d limit=3
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const sites = await checkbox.sites.list({ limit: 3 });
console.log(sites.data);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

sites = checkbox.sites.list(limit=3)
print(sites.data)
```

```json title="Response"
{
  "object": "list",
  "data": [
    {
      "id": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
      "object": "site",
      "livemode": false,
      "name": "Acme Coffee Club",
      "url": "https://acme.example",
      "platform": "stripe",
      "jurisdictions": [],
      "facts": {
        "has_free_trial": true,
        "trial_days": 14,
        "term_months": 1,
        "online_signup": true,
        "sells_goods": false,
        "notice_channel_email": true,
        "price_increase_consent_or_refund": false,
        "plan_price_id": "price_1Pabc",
        "payment_methods": [
          "card"
        ],
        "checkout_type": "payment_link"
      },
      "checkout": {
        "url": "https://acme.example/pricing",
        "regions": [
          "US-CA"
        ],
        "devices": [
          "desktop"
        ],
        "checkout_steps": 0,
        "completes_purchase": false,
        "has_test_account": false,
        "test_account": {
          "login_url": "https://acme.example/login",
          "email": "test-subscriber@acme.example"
        },
        "cancel_steps": 0,
        "account_url": "https://acme.example/account",
        "terms_url": "https://acme.example/terms",
        "homepage_as_checkout": false
      },
      "monitoring": {
        "enabled": true,
        "interval_minutes": 1440,
        "held_for_activation": false,
        "last_scanned": 1793318400,
        "held_for_domain_verification": false,
        "verify_domains": []
      },
      "protection_level": "balanced",
      "retention": {
        "records_years": 7,
        "superseded_results_days": 30,
        "good_practice_years": 7,
        "problem_history_days": 30
      },
      "legal_hold": {
        "active": false,
        "scope": null,
        "set": null,
        "reason": null
      },
      "compliance": {
        "evaluated": 1793318400,
        "open_findings": 2,
        "needs_review": 1,
        "status": "compliant",
        "label": "Compliant · 2 live checks pending",
        "rollup": {
          "status": "compliant",
          "label": "Compliant · 2 live checks pending",
          "counts": {
            "needs_fix": 0,
            "your_call": 0,
            "pending_live_check": 2,
            "verified_live": 3,
            "compliant": 9,
            "not_applicable": 6,
            "not_set_up": 0,
            "not_checked": 0
          },
          "pending_live_checks": [
            {
              "what": "Your acknowledgment email, seen sent for a real sign-up",
              "completes": "Run a proof, or BCC your real acknowledgment emails to your Checkbox inbound address.",
              "action": "bcc_real_sends",
              "due": "2026-11-20"
            }
          ],
          "suggestions": 1,
          "checkouts": [
            {
              "name": "Annual",
              "kind": "payment_link",
              "plan": "Annual",
              "status": "pending_live_check",
              "label": "Needs a fix",
              "open": []
            }
          ]
        }
      },
      "install": {
        "script_tag": "<script async src=\"https://app.checkbox.site/s.js\" data-key=\"ab12…\"></script>",
        "snippet_key": "ab12cd34ef56",
        "inbound_email": "ab12cd34ef56@in.checkbox.site",
        "webhook_urls": {
          "stripe": "https://app.checkbox.site/webhooks/stripe/…"
        }
      },
      "archived": false,
      "created": 1793318400,
      "latest_scan": {
        "id": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "object": "scan",
        "livemode": false,
        "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "status": "completed",
        "trigger": "api",
        "regions": [
          "US-CA"
        ],
        "error": null,
        "warnings": [],
        "evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "compliance": {
          "status": "needs_fix",
          "label": "2 fixes needed"
        },
        "started": 1793318400,
        "finished": 1793318400,
        "created": 1793318400
      },
      "unverified_scan": {
        "id": "uscan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "object": "unverified_scan",
        "unverified": true,
        "label": "unverified scan",
        "status": "completed",
        "created": 1793318400,
        "finished": 1793318400,
        "pages": [],
        "findings": [],
        "counts": {
          "pages_captured": 6,
          "pages_skipped": 1,
          "failing": 2,
          "needs_review": 1,
          "passing": 9
        },
        "error": null,
        "note": "Unverified scan: Checkbox only loaded public pages of this site…"
      },
      "domain_verification": {
        "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "object": "domain_verification",
        "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "domain": "acme.example",
        "status": "pending",
        "method": null,
        "verified_at": 1793318400,
        "last_checked": 1793318400,
        "last_error": "TXT record not found",
        "dns_record": {
          "type": "TXT",
          "name": "_checkbox-verify.acme.example",
          "value": "checkbox-verify=Xy…"
        },
        "file": {
          "url": "https://acme.example/.well-known/checkbox-verify.txt",
          "contents": "Xy…"
        },
        "meta_tag": {
          "url": "https://acme.example/",
          "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
        },
        "scan_target_problems": [],
        "account_activated": false,
        "next_action": {
          "type": "publish_dns_record",
          "message": "Publish the TXT record, then call checkDomainVerification.",
          "operation_id": "checkDomainVerification",
          "mcp_tool": "call_api",
          "endpoint": "POST /v1/sites/{site}/domain_verification/check"
        }
      }
    }
  ],
  "has_more": false,
  "url": "/v1/sites"
}
```

## Create a site {#createSite}

`POST /v1/sites`

Registers a subscription business. Only `url` is required; Checkbox derives the name and uses the URL as the checkout entry page. The response includes `install` (snippet tag, inbound email, platform webhook URLs). Next: install the snippet, then run createScan (or let `checkbox init` do both). In live mode before activation, monitoring is held until a domain is verified; in test mode, monitoring of a host that is not localhost or a domain the account verified is held the same way, and on-demand scans of such hosts are limited to a few a day.

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `createSite`

SDK: `checkbox.sites.create()` (Node) · `checkbox.sites.create()` (Python). MCP / agents: operation `createSite`.

#### Body

| Field | Type | Description |
|---|---|---|
| `name` | string | Display name. |
| `url` **required** | string | Base URL of the business website. |
| `platform` | enum | Billing platform. One of `stripe`, `shopify`, `recharge`, `chargebee`, `recurly`, `paddle`, `woocommerce`, `custom`. |
| `jurisdictions` | array of enum | Jurisdictions to evaluate (empty = all US laws). |
| `facts` | SiteFacts | Business facts that decide which legal requirements apply. |
| `checkout_url` | string | Page with the subscribe button (defaults to url). Not a Stripe-hosted session link. |
| `account_url` | string \| null | Public account or cancellation page. Visited on every scan, even without a test account, so offline-only cancellation instructions are seen. null clears it. |
| `terms_url` | string \| null | Terms of service page. Checkbox reads it on every scan (rendering JavaScript, so single-page apps work) and checks its renewal and cancellation terms. null clears it. |
| `checkout_steps` | array of ScanSteps | Steps to reach the final pre-payment screen. |
| `purchase` | SitePurchase | How the synthetic shopper completes a real (free) sign-up. |
| `test_account` | SiteTestAccount | A test customer account the synthetic shopper uses to try cancelling online. |
| `cancel_steps` | array of ScanSteps | Explicit cancellation steps (otherwise auto-discovered). |
| `regions` | array of enum | States the synthetic shopper visits from. |
| `devices` | array of enum | Devices to emulate. |
| `monitoring_interval_minutes` | integer | Scheduled re-scan interval (0 = off, minimum 60). Default 1440 in live mode, 0 in test mode. |
| `protection_level` | enum | Which requirement tiers Checkbox shows. minimum: the legal floor only (required items). balanced (default): required items plus recommended suggestions (consent receipts, a cancellation confirmation email…), collapsed and never blocking "compliant". maximum: everything, including extra protections (a separate checkbox per term, a pre-purchase summary). Only required items can make a site not compliant, at every level. One of `minimum`, `balanced`, `maximum`. |

#### Returns

Returns a [Site](https://checkbox.site/docs/api/sites#the-site-object) object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://acme.example"
}'
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const site = await checkbox.sites.create({ url: 'https://acme.example' });
console.log(site);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

site = checkbox.sites.create(url="https://acme.example")
print(site)
```

```json title="Response"
{
  "id": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "site",
  "livemode": false,
  "name": "Acme Coffee Club",
  "url": "https://acme.example",
  "platform": "stripe",
  "jurisdictions": [],
  "facts": {
    "has_free_trial": true,
    "trial_days": 14,
    "term_months": 1,
    "online_signup": true,
    "sells_goods": false,
    "notice_channel_email": true,
    "price_increase_consent_or_refund": false,
    "plan_price_id": "price_1Pabc",
    "payment_methods": [
      "card"
    ],
    "checkout_type": "payment_link"
  },
  "checkout": {
    "url": "https://acme.example/pricing",
    "regions": [
      "US-CA"
    ],
    "devices": [
      "desktop"
    ],
    "checkout_steps": 0,
    "completes_purchase": false,
    "has_test_account": false,
    "test_account": {
      "login_url": "https://acme.example/login",
      "email": "test-subscriber@acme.example"
    },
    "cancel_steps": 0,
    "account_url": "https://acme.example/account",
    "terms_url": "https://acme.example/terms",
    "homepage_as_checkout": false
  },
  "monitoring": {
    "enabled": true,
    "interval_minutes": 1440,
    "held_for_activation": false,
    "last_scanned": 1793318400,
    "held_for_domain_verification": false,
    "verify_domains": []
  },
  "protection_level": "balanced",
  "retention": {
    "records_years": 7,
    "superseded_results_days": 30,
    "good_practice_years": 7,
    "problem_history_days": 30,
    "inherited": true
  },
  "legal_hold": {
    "active": false,
    "scope": null,
    "set": null,
    "reason": null
  },
  "compliance": {
    "evaluated": 1793318400,
    "open_findings": 2,
    "needs_review": 1,
    "status": "compliant",
    "label": "Compliant · 2 live checks pending",
    "rollup": {
      "status": "compliant",
      "label": "Compliant · 2 live checks pending",
      "counts": {
        "needs_fix": 0,
        "your_call": 0,
        "pending_live_check": 2,
        "verified_live": 3,
        "compliant": 9,
        "not_applicable": 6,
        "not_set_up": 0,
        "not_checked": 0
      },
      "pending_live_checks": [
        {
          "what": "Your acknowledgment email, seen sent for a real sign-up",
          "completes": "Run a proof, or BCC your real acknowledgment emails to your Checkbox inbound address.",
          "action": "bcc_real_sends",
          "due": "2026-11-20"
        }
      ],
      "suggestions": 1,
      "checkouts": [
        {
          "name": "Annual",
          "kind": "payment_link",
          "plan": "Annual",
          "status": "pending_live_check",
          "label": "Needs a fix",
          "open": [
            {
              "check_id": "signup.disclosure.price",
              "title": "recurring charge is stated",
              "status": "pending_live_check"
            }
          ]
        }
      ]
    }
  },
  "install": {
    "script_tag": "<script async src=\"https://app.checkbox.site/s.js\" data-key=\"ab12…\"></script>",
    "snippet_key": "ab12cd34ef56",
    "inbound_email": "ab12cd34ef56@in.checkbox.site",
    "webhook_urls": {
      "stripe": "https://app.checkbox.site/webhooks/stripe/…"
    }
  },
  "archived": false,
  "created": 1793318400,
  "latest_scan": {
    "id": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "scan",
    "livemode": false,
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "status": "completed",
    "trigger": "api",
    "regions": [
      "US-CA"
    ],
    "error": null,
    "warnings": [],
    "evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "compliance": {
      "status": "needs_fix",
      "label": "2 fixes needed"
    },
    "started": 1793318400,
    "finished": 1793318400,
    "created": 1793318400
  },
  "unverified_scan": {
    "id": "uscan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "unverified_scan",
    "unverified": true,
    "label": "unverified scan",
    "status": "completed",
    "created": 1793318400,
    "finished": 1793318400,
    "pages": [],
    "findings": [],
    "counts": {
      "pages_captured": 6,
      "pages_skipped": 1,
      "failing": 2,
      "needs_review": 1,
      "passing": 9
    },
    "error": null,
    "note": "Unverified scan: Checkbox only loaded public pages of this site…"
  },
  "domain_verification": {
    "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "domain_verification",
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "domain": "acme.example",
    "status": "pending",
    "method": null,
    "verified_at": 1793318400,
    "last_checked": 1793318400,
    "last_error": "TXT record not found",
    "dns_record": {
      "type": "TXT",
      "name": "_checkbox-verify.acme.example",
      "value": "checkbox-verify=Xy…"
    },
    "file": {
      "url": "https://acme.example/.well-known/checkbox-verify.txt",
      "contents": "Xy…"
    },
    "meta_tag": {
      "url": "https://acme.example/",
      "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
    },
    "scan_target_problems": [],
    "account_activated": false,
    "next_action": {
      "type": "publish_dns_record",
      "message": "Publish the TXT record, then call checkDomainVerification.",
      "operation_id": "checkDomainVerification",
      "mcp_tool": "call_api",
      "endpoint": "POST /v1/sites/{site}/domain_verification/check"
    }
  }
}
```

## Retrieve a site {#retrieveSite}

`GET /v1/sites/{site}`

Returns a site with its latest compliance status (label and counts) and install details.

**Scope** `sites:read` · **Operation** `retrieveSite`

SDK: `checkbox.sites.retrieve()` (Node) · `checkbox.sites.retrieve()` (Python). MCP / agents: operation `retrieveSite`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |
| `expand[]` | query | array of enum | Related objects to include inline: latest_scan, domain_verification. Pass as expand[]=name. |

#### Returns

Returns a [Site](https://checkbox.site/docs/api/sites#the-site-object) object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:"
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const site = await checkbox.sites.retrieve('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(site);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

site = checkbox.sites.retrieve("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(site)
```

```json title="Response"
{
  "id": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "site",
  "livemode": false,
  "name": "Acme Coffee Club",
  "url": "https://acme.example",
  "platform": "stripe",
  "jurisdictions": [],
  "facts": {
    "has_free_trial": true,
    "trial_days": 14,
    "term_months": 1,
    "online_signup": true,
    "sells_goods": false,
    "notice_channel_email": true,
    "price_increase_consent_or_refund": false,
    "plan_price_id": "price_1Pabc",
    "payment_methods": [
      "card"
    ],
    "checkout_type": "payment_link"
  },
  "checkout": {
    "url": "https://acme.example/pricing",
    "regions": [
      "US-CA"
    ],
    "devices": [
      "desktop"
    ],
    "checkout_steps": 0,
    "completes_purchase": false,
    "has_test_account": false,
    "test_account": {
      "login_url": "https://acme.example/login",
      "email": "test-subscriber@acme.example"
    },
    "cancel_steps": 0,
    "account_url": "https://acme.example/account",
    "terms_url": "https://acme.example/terms",
    "homepage_as_checkout": false
  },
  "monitoring": {
    "enabled": true,
    "interval_minutes": 1440,
    "held_for_activation": false,
    "last_scanned": 1793318400,
    "held_for_domain_verification": false,
    "verify_domains": []
  },
  "protection_level": "balanced",
  "retention": {
    "records_years": 7,
    "superseded_results_days": 30,
    "good_practice_years": 7,
    "problem_history_days": 30,
    "inherited": true
  },
  "legal_hold": {
    "active": false,
    "scope": null,
    "set": null,
    "reason": null
  },
  "compliance": {
    "evaluated": 1793318400,
    "open_findings": 2,
    "needs_review": 1,
    "status": "compliant",
    "label": "Compliant · 2 live checks pending",
    "rollup": {
      "status": "compliant",
      "label": "Compliant · 2 live checks pending",
      "counts": {
        "needs_fix": 0,
        "your_call": 0,
        "pending_live_check": 2,
        "verified_live": 3,
        "compliant": 9,
        "not_applicable": 6,
        "not_set_up": 0,
        "not_checked": 0
      },
      "pending_live_checks": [
        {
          "what": "Your acknowledgment email, seen sent for a real sign-up",
          "completes": "Run a proof, or BCC your real acknowledgment emails to your Checkbox inbound address.",
          "action": "bcc_real_sends",
          "due": "2026-11-20"
        }
      ],
      "suggestions": 1,
      "checkouts": [
        {
          "name": "Annual",
          "kind": "payment_link",
          "plan": "Annual",
          "status": "pending_live_check",
          "label": "Needs a fix",
          "open": [
            {
              "check_id": "signup.disclosure.price",
              "title": "recurring charge is stated",
              "status": "pending_live_check"
            }
          ]
        }
      ]
    }
  },
  "install": {
    "script_tag": "<script async src=\"https://app.checkbox.site/s.js\" data-key=\"ab12…\"></script>",
    "snippet_key": "ab12cd34ef56",
    "inbound_email": "ab12cd34ef56@in.checkbox.site",
    "webhook_urls": {
      "stripe": "https://app.checkbox.site/webhooks/stripe/…"
    }
  },
  "archived": false,
  "created": 1793318400,
  "latest_scan": {
    "id": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "scan",
    "livemode": false,
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "status": "completed",
    "trigger": "api",
    "regions": [
      "US-CA"
    ],
    "error": null,
    "warnings": [],
    "evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "compliance": {
      "status": "needs_fix",
      "label": "2 fixes needed"
    },
    "started": 1793318400,
    "finished": 1793318400,
    "created": 1793318400
  },
  "unverified_scan": {
    "id": "uscan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "unverified_scan",
    "unverified": true,
    "label": "unverified scan",
    "status": "completed",
    "created": 1793318400,
    "finished": 1793318400,
    "pages": [],
    "findings": [],
    "counts": {
      "pages_captured": 6,
      "pages_skipped": 1,
      "failing": 2,
      "needs_review": 1,
      "passing": 9
    },
    "error": null,
    "note": "Unverified scan: Checkbox only loaded public pages of this site…"
  },
  "domain_verification": {
    "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "domain_verification",
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "domain": "acme.example",
    "status": "pending",
    "method": null,
    "verified_at": 1793318400,
    "last_checked": 1793318400,
    "last_error": "TXT record not found",
    "dns_record": {
      "type": "TXT",
      "name": "_checkbox-verify.acme.example",
      "value": "checkbox-verify=Xy…"
    },
    "file": {
      "url": "https://acme.example/.well-known/checkbox-verify.txt",
      "contents": "Xy…"
    },
    "meta_tag": {
      "url": "https://acme.example/",
      "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
    },
    "scan_target_problems": [],
    "account_activated": false,
    "next_action": {
      "type": "publish_dns_record",
      "message": "Publish the TXT record, then call checkDomainVerification.",
      "operation_id": "checkDomainVerification",
      "mcp_tool": "call_api",
      "endpoint": "POST /v1/sites/{site}/domain_verification/check"
    }
  }
}
```

## Update a site {#updateSite}

`POST /v1/sites/{site}`

Updates the given fields; omitted fields keep their values. Changing `url` to another domain forgets the domain verification and ends the active certificate.

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `updateSite`

SDK: `checkbox.sites.update()` (Node) · `checkbox.sites.update()` (Python). MCP / agents: operation `updateSite`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Body

| Field | Type | Description |
|---|---|---|
| `name` | string | Display name. |
| `url` | string | Base URL of the business website. |
| `platform` | enum | Billing platform. One of `stripe`, `shopify`, `recharge`, `chargebee`, `recurly`, `paddle`, `woocommerce`, `custom`. |
| `jurisdictions` | array of enum | Jurisdictions to evaluate (empty = all US laws). |
| `facts` | SiteFacts | Business facts that decide which legal requirements apply. |
| `checkout_url` | string | Page with the subscribe button (defaults to url). Not a Stripe-hosted session link. |
| `account_url` | string \| null | Public account or cancellation page. Visited on every scan, even without a test account, so offline-only cancellation instructions are seen. null clears it. |
| `terms_url` | string \| null | Terms of service page. Checkbox reads it on every scan (rendering JavaScript, so single-page apps work) and checks its renewal and cancellation terms. null clears it. |
| `checkout_steps` | array of ScanSteps | Steps to reach the final pre-payment screen. |
| `purchase` | SitePurchase | How the synthetic shopper completes a real (free) sign-up. |
| `test_account` | SiteTestAccount | A test customer account the synthetic shopper uses to try cancelling online. |
| `cancel_steps` | array of ScanSteps | Explicit cancellation steps (otherwise auto-discovered). |
| `regions` | array of enum | States the synthetic shopper visits from. |
| `devices` | array of enum | Devices to emulate. |
| `monitoring_interval_minutes` | integer | Scheduled re-scan interval (0 = off, minimum 60). Default 1440 in live mode, 0 in test mode. |
| `protection_level` | enum | Which requirement tiers Checkbox shows. minimum: the legal floor only (required items). balanced (default): required items plus recommended suggestions (consent receipts, a cancellation confirmation email…), collapsed and never blocking "compliant". maximum: everything, including extra protections (a separate checkbox per term, a pre-purchase summary). Only required items can make a site not compliant, at every level. One of `minimum`, `balanced`, `maximum`. |
| `checkout` | object | The URLs nested as the site object returns them (checkout.url, checkout.account_url, checkout.terms_url); the flat fields win when both are given. |
| `checkout.url` | string | Same as checkout_url. |
| `checkout.account_url` | string \| null | Same as account_url. |
| `checkout.terms_url` | string \| null | Same as terms_url. |
| `retention` | RetentionParams | Default retention for every site without its own setting. A longer period for superseded check results keeps a fuller timeline of changes to your site. |
| `retention.records_years` | integer \| null | Years records are kept (1-10). On a site, null returns to the account default. |
| `retention.superseded_results_days` | integer \| null | Days superseded check results are kept (7-730). On a site, null returns to the account default. |
| `retention.good_practice_years` | integer \| null | Deprecated: use records_years. |
| `retention.problem_history_days` | integer \| null | Deprecated: use superseded_results_days. |
| `legal_hold` | LegalHoldParams | Account-wide legal hold: suspends every deletion of the account's records until turned off. |
| `legal_hold.active` **required** | boolean | true turns the hold on, false turns it off. |
| `legal_hold.reason` | string | Note stored with the hold (who asked, matter). |

#### Returns

Returns a [Site](https://checkbox.site/docs/api/sites#the-site-object) object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Acme Coffee Club"
}'
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const site = await checkbox.sites.update('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', { name: 'Acme Coffee Club' });
console.log(site);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

site = checkbox.sites.update("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", name="Acme Coffee Club")
print(site)
```

```json title="Response"
{
  "id": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "site",
  "livemode": false,
  "name": "Acme Coffee Club",
  "url": "https://acme.example",
  "platform": "stripe",
  "jurisdictions": [],
  "facts": {
    "has_free_trial": true,
    "trial_days": 14,
    "term_months": 1,
    "online_signup": true,
    "sells_goods": false,
    "notice_channel_email": true,
    "price_increase_consent_or_refund": false,
    "plan_price_id": "price_1Pabc",
    "payment_methods": [
      "card"
    ],
    "checkout_type": "payment_link"
  },
  "checkout": {
    "url": "https://acme.example/pricing",
    "regions": [
      "US-CA"
    ],
    "devices": [
      "desktop"
    ],
    "checkout_steps": 0,
    "completes_purchase": false,
    "has_test_account": false,
    "test_account": {
      "login_url": "https://acme.example/login",
      "email": "test-subscriber@acme.example"
    },
    "cancel_steps": 0,
    "account_url": "https://acme.example/account",
    "terms_url": "https://acme.example/terms",
    "homepage_as_checkout": false
  },
  "monitoring": {
    "enabled": true,
    "interval_minutes": 1440,
    "held_for_activation": false,
    "last_scanned": 1793318400,
    "held_for_domain_verification": false,
    "verify_domains": []
  },
  "protection_level": "balanced",
  "retention": {
    "records_years": 7,
    "superseded_results_days": 30,
    "good_practice_years": 7,
    "problem_history_days": 30,
    "inherited": true
  },
  "legal_hold": {
    "active": false,
    "scope": null,
    "set": null,
    "reason": null
  },
  "compliance": {
    "evaluated": 1793318400,
    "open_findings": 2,
    "needs_review": 1,
    "status": "compliant",
    "label": "Compliant · 2 live checks pending",
    "rollup": {
      "status": "compliant",
      "label": "Compliant · 2 live checks pending",
      "counts": {
        "needs_fix": 0,
        "your_call": 0,
        "pending_live_check": 2,
        "verified_live": 3,
        "compliant": 9,
        "not_applicable": 6,
        "not_set_up": 0,
        "not_checked": 0
      },
      "pending_live_checks": [
        {
          "what": "Your acknowledgment email, seen sent for a real sign-up",
          "completes": "Run a proof, or BCC your real acknowledgment emails to your Checkbox inbound address.",
          "action": "bcc_real_sends",
          "due": "2026-11-20"
        }
      ],
      "suggestions": 1,
      "checkouts": [
        {
          "name": "Annual",
          "kind": "payment_link",
          "plan": "Annual",
          "status": "pending_live_check",
          "label": "Needs a fix",
          "open": [
            {
              "check_id": "signup.disclosure.price",
              "title": "recurring charge is stated",
              "status": "pending_live_check"
            }
          ]
        }
      ]
    }
  },
  "install": {
    "script_tag": "<script async src=\"https://app.checkbox.site/s.js\" data-key=\"ab12…\"></script>",
    "snippet_key": "ab12cd34ef56",
    "inbound_email": "ab12cd34ef56@in.checkbox.site",
    "webhook_urls": {
      "stripe": "https://app.checkbox.site/webhooks/stripe/…"
    }
  },
  "archived": false,
  "created": 1793318400,
  "latest_scan": {
    "id": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "scan",
    "livemode": false,
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "status": "completed",
    "trigger": "api",
    "regions": [
      "US-CA"
    ],
    "error": null,
    "warnings": [],
    "evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "compliance": {
      "status": "needs_fix",
      "label": "2 fixes needed"
    },
    "started": 1793318400,
    "finished": 1793318400,
    "created": 1793318400
  },
  "unverified_scan": {
    "id": "uscan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "unverified_scan",
    "unverified": true,
    "label": "unverified scan",
    "status": "completed",
    "created": 1793318400,
    "finished": 1793318400,
    "pages": [],
    "findings": [],
    "counts": {
      "pages_captured": 6,
      "pages_skipped": 1,
      "failing": 2,
      "needs_review": 1,
      "passing": 9
    },
    "error": null,
    "note": "Unverified scan: Checkbox only loaded public pages of this site…"
  },
  "domain_verification": {
    "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "domain_verification",
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "domain": "acme.example",
    "status": "pending",
    "method": null,
    "verified_at": 1793318400,
    "last_checked": 1793318400,
    "last_error": "TXT record not found",
    "dns_record": {
      "type": "TXT",
      "name": "_checkbox-verify.acme.example",
      "value": "checkbox-verify=Xy…"
    },
    "file": {
      "url": "https://acme.example/.well-known/checkbox-verify.txt",
      "contents": "Xy…"
    },
    "meta_tag": {
      "url": "https://acme.example/",
      "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
    },
    "scan_target_problems": [],
    "account_activated": false,
    "next_action": {
      "type": "publish_dns_record",
      "message": "Publish the TXT record, then call checkDomainVerification.",
      "operation_id": "checkDomainVerification",
      "mcp_tool": "call_api",
      "endpoint": "POST /v1/sites/{site}/domain_verification/check"
    }
  }
}
```

## Archive a site {#deleteSite}

`DELETE /v1/sites/{site}`

Archives (soft-deletes) the site: monitoring stops and it disappears from lists, but evidence and findings are retained. Undo with restoreSite.

**Scope** `sites:write` · **Operation** `deleteSite`

SDK: `checkbox.sites.del()` (Node) · `checkbox.sites.delete()` (Python). MCP / agents: operation `deleteSite`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Returns

Returns a [Site](https://checkbox.site/docs/api/sites#the-site-object) object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:" \
  -X DELETE
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const site = await checkbox.sites.del('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(site);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

site = checkbox.sites.delete("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(site)
```

```json title="Response"
{
  "id": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "site",
  "livemode": false,
  "name": "Acme Coffee Club",
  "url": "https://acme.example",
  "platform": "stripe",
  "jurisdictions": [],
  "facts": {
    "has_free_trial": true,
    "trial_days": 14,
    "term_months": 1,
    "online_signup": true,
    "sells_goods": false,
    "notice_channel_email": true,
    "price_increase_consent_or_refund": false,
    "plan_price_id": "price_1Pabc",
    "payment_methods": [
      "card"
    ],
    "checkout_type": "payment_link"
  },
  "checkout": {
    "url": "https://acme.example/pricing",
    "regions": [
      "US-CA"
    ],
    "devices": [
      "desktop"
    ],
    "checkout_steps": 0,
    "completes_purchase": false,
    "has_test_account": false,
    "test_account": {
      "login_url": "https://acme.example/login",
      "email": "test-subscriber@acme.example"
    },
    "cancel_steps": 0,
    "account_url": "https://acme.example/account",
    "terms_url": "https://acme.example/terms",
    "homepage_as_checkout": false
  },
  "monitoring": {
    "enabled": true,
    "interval_minutes": 1440,
    "held_for_activation": false,
    "last_scanned": 1793318400,
    "held_for_domain_verification": false,
    "verify_domains": []
  },
  "protection_level": "balanced",
  "retention": {
    "records_years": 7,
    "superseded_results_days": 30,
    "good_practice_years": 7,
    "problem_history_days": 30,
    "inherited": true
  },
  "legal_hold": {
    "active": false,
    "scope": null,
    "set": null,
    "reason": null
  },
  "compliance": {
    "evaluated": 1793318400,
    "open_findings": 2,
    "needs_review": 1,
    "status": "compliant",
    "label": "Compliant · 2 live checks pending",
    "rollup": {
      "status": "compliant",
      "label": "Compliant · 2 live checks pending",
      "counts": {
        "needs_fix": 0,
        "your_call": 0,
        "pending_live_check": 2,
        "verified_live": 3,
        "compliant": 9,
        "not_applicable": 6,
        "not_set_up": 0,
        "not_checked": 0
      },
      "pending_live_checks": [
        {
          "what": "Your acknowledgment email, seen sent for a real sign-up",
          "completes": "Run a proof, or BCC your real acknowledgment emails to your Checkbox inbound address.",
          "action": "bcc_real_sends",
          "due": "2026-11-20"
        }
      ],
      "suggestions": 1,
      "checkouts": [
        {
          "name": "Annual",
          "kind": "payment_link",
          "plan": "Annual",
          "status": "pending_live_check",
          "label": "Needs a fix",
          "open": [
            {
              "check_id": "signup.disclosure.price",
              "title": "recurring charge is stated",
              "status": "pending_live_check"
            }
          ]
        }
      ]
    }
  },
  "install": {
    "script_tag": "<script async src=\"https://app.checkbox.site/s.js\" data-key=\"ab12…\"></script>",
    "snippet_key": "ab12cd34ef56",
    "inbound_email": "ab12cd34ef56@in.checkbox.site",
    "webhook_urls": {
      "stripe": "https://app.checkbox.site/webhooks/stripe/…"
    }
  },
  "archived": false,
  "created": 1793318400,
  "latest_scan": {
    "id": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "scan",
    "livemode": false,
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "status": "completed",
    "trigger": "api",
    "regions": [
      "US-CA"
    ],
    "error": null,
    "warnings": [],
    "evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "compliance": {
      "status": "needs_fix",
      "label": "2 fixes needed"
    },
    "started": 1793318400,
    "finished": 1793318400,
    "created": 1793318400
  },
  "unverified_scan": {
    "id": "uscan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "unverified_scan",
    "unverified": true,
    "label": "unverified scan",
    "status": "completed",
    "created": 1793318400,
    "finished": 1793318400,
    "pages": [],
    "findings": [],
    "counts": {
      "pages_captured": 6,
      "pages_skipped": 1,
      "failing": 2,
      "needs_review": 1,
      "passing": 9
    },
    "error": null,
    "note": "Unverified scan: Checkbox only loaded public pages of this site…"
  },
  "domain_verification": {
    "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "domain_verification",
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "domain": "acme.example",
    "status": "pending",
    "method": null,
    "verified_at": 1793318400,
    "last_checked": 1793318400,
    "last_error": "TXT record not found",
    "dns_record": {
      "type": "TXT",
      "name": "_checkbox-verify.acme.example",
      "value": "checkbox-verify=Xy…"
    },
    "file": {
      "url": "https://acme.example/.well-known/checkbox-verify.txt",
      "contents": "Xy…"
    },
    "meta_tag": {
      "url": "https://acme.example/",
      "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
    },
    "scan_target_problems": [],
    "account_activated": false,
    "next_action": {
      "type": "publish_dns_record",
      "message": "Publish the TXT record, then call checkDomainVerification.",
      "operation_id": "checkDomainVerification",
      "mcp_tool": "call_api",
      "endpoint": "POST /v1/sites/{site}/domain_verification/check"
    }
  }
}
```

## Restore an archived site {#restoreSite}

`POST /v1/sites/{site}/restore`

Un-archives a site (counts against the fair-use site limit again).

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `restoreSite`

SDK: `checkbox.sites.restore()` (Node) · `checkbox.sites.restore()` (Python). MCP / agents: operation `restoreSite`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Returns

Returns a [Site](https://checkbox.site/docs/api/sites#the-site-object) object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/restore \
  -u "$CHECKBOX_SECRET_KEY:" \
  -X POST
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const site = await checkbox.sites.restore('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(site);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

site = checkbox.sites.restore("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(site)
```

```json title="Response"
{
  "id": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "site",
  "livemode": false,
  "name": "Acme Coffee Club",
  "url": "https://acme.example",
  "platform": "stripe",
  "jurisdictions": [],
  "facts": {
    "has_free_trial": true,
    "trial_days": 14,
    "term_months": 1,
    "online_signup": true,
    "sells_goods": false,
    "notice_channel_email": true,
    "price_increase_consent_or_refund": false,
    "plan_price_id": "price_1Pabc",
    "payment_methods": [
      "card"
    ],
    "checkout_type": "payment_link"
  },
  "checkout": {
    "url": "https://acme.example/pricing",
    "regions": [
      "US-CA"
    ],
    "devices": [
      "desktop"
    ],
    "checkout_steps": 0,
    "completes_purchase": false,
    "has_test_account": false,
    "test_account": {
      "login_url": "https://acme.example/login",
      "email": "test-subscriber@acme.example"
    },
    "cancel_steps": 0,
    "account_url": "https://acme.example/account",
    "terms_url": "https://acme.example/terms",
    "homepage_as_checkout": false
  },
  "monitoring": {
    "enabled": true,
    "interval_minutes": 1440,
    "held_for_activation": false,
    "last_scanned": 1793318400,
    "held_for_domain_verification": false,
    "verify_domains": []
  },
  "protection_level": "balanced",
  "retention": {
    "records_years": 7,
    "superseded_results_days": 30,
    "good_practice_years": 7,
    "problem_history_days": 30,
    "inherited": true
  },
  "legal_hold": {
    "active": false,
    "scope": null,
    "set": null,
    "reason": null
  },
  "compliance": {
    "evaluated": 1793318400,
    "open_findings": 2,
    "needs_review": 1,
    "status": "compliant",
    "label": "Compliant · 2 live checks pending",
    "rollup": {
      "status": "compliant",
      "label": "Compliant · 2 live checks pending",
      "counts": {
        "needs_fix": 0,
        "your_call": 0,
        "pending_live_check": 2,
        "verified_live": 3,
        "compliant": 9,
        "not_applicable": 6,
        "not_set_up": 0,
        "not_checked": 0
      },
      "pending_live_checks": [
        {
          "what": "Your acknowledgment email, seen sent for a real sign-up",
          "completes": "Run a proof, or BCC your real acknowledgment emails to your Checkbox inbound address.",
          "action": "bcc_real_sends",
          "due": "2026-11-20"
        }
      ],
      "suggestions": 1,
      "checkouts": [
        {
          "name": "Annual",
          "kind": "payment_link",
          "plan": "Annual",
          "status": "pending_live_check",
          "label": "Needs a fix",
          "open": [
            {
              "check_id": "signup.disclosure.price",
              "title": "recurring charge is stated",
              "status": "pending_live_check"
            }
          ]
        }
      ]
    }
  },
  "install": {
    "script_tag": "<script async src=\"https://app.checkbox.site/s.js\" data-key=\"ab12…\"></script>",
    "snippet_key": "ab12cd34ef56",
    "inbound_email": "ab12cd34ef56@in.checkbox.site",
    "webhook_urls": {
      "stripe": "https://app.checkbox.site/webhooks/stripe/…"
    }
  },
  "archived": false,
  "created": 1793318400,
  "latest_scan": {
    "id": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "scan",
    "livemode": false,
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "status": "completed",
    "trigger": "api",
    "regions": [
      "US-CA"
    ],
    "error": null,
    "warnings": [],
    "evaluation": "eval_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "compliance": {
      "status": "needs_fix",
      "label": "2 fixes needed"
    },
    "started": 1793318400,
    "finished": 1793318400,
    "created": 1793318400
  },
  "unverified_scan": {
    "id": "uscan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "unverified_scan",
    "unverified": true,
    "label": "unverified scan",
    "status": "completed",
    "created": 1793318400,
    "finished": 1793318400,
    "pages": [],
    "findings": [],
    "counts": {
      "pages_captured": 6,
      "pages_skipped": 1,
      "failing": 2,
      "needs_review": 1,
      "passing": 9
    },
    "error": null,
    "note": "Unverified scan: Checkbox only loaded public pages of this site…"
  },
  "domain_verification": {
    "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "object": "domain_verification",
    "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "domain": "acme.example",
    "status": "pending",
    "method": null,
    "verified_at": 1793318400,
    "last_checked": 1793318400,
    "last_error": "TXT record not found",
    "dns_record": {
      "type": "TXT",
      "name": "_checkbox-verify.acme.example",
      "value": "checkbox-verify=Xy…"
    },
    "file": {
      "url": "https://acme.example/.well-known/checkbox-verify.txt",
      "contents": "Xy…"
    },
    "meta_tag": {
      "url": "https://acme.example/",
      "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
    },
    "scan_target_problems": [],
    "account_activated": false,
    "next_action": {
      "type": "publish_dns_record",
      "message": "Publish the TXT record, then call checkDomainVerification.",
      "operation_id": "checkDomainVerification",
      "mcp_tool": "call_api",
      "endpoint": "POST /v1/sites/{site}/domain_verification/check"
    }
  }
}
```

## Connect a billing platform {#connectBillingPlatform}

`POST /v1/sites/{site}/integrations`

Connects the site's billing platform with read-only credentials (a Stripe restricted key, a Recharge token or a Shopify Admin API token), so Checkbox reads the customer-portal and reminder settings. Works for test-mode sites too (use an rk_test_ key). The credentials are validated by reading the settings once and stored encrypted.

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `connectBillingPlatform`

SDK: `checkbox.sites.connectBillingPlatform()` (Node) · `checkbox.sites.connect_billing_platform()` (Python). MCP / agents: operation `connectBillingPlatform`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Body

| Field | Type | Description |
|---|---|---|
| `platform` **required** | enum | Billing platform. One of `stripe`, `recharge`, `shopify`. |
| `credentials` **required** | object | Read-only credentials. Stripe: { "secretKey": "rk_test_…" } (a restricted key with read access; rk_test_ in test mode). Recharge: { "apiToken": "…" }. Shopify: { "shop": "store.myshopify.com", "accessToken": "shpat_…" }. |

#### Returns

Returns an `Integration` object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/integrations \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "platform": "stripe",
  "credentials": {
    "secretKey": "rk_test_51H…"
  }
}'
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const site = await checkbox.sites.connectBillingPlatform('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', {
  platform: 'stripe',
  credentials: { secretKey: 'rk_test_51H…' },
});
console.log(site);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

site = checkbox.sites.connect_billing_platform("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", platform="stripe", credentials={"secretKey": "rk_test_51H…"})
print(site)
```

```json title="Response"
{
  "object": "integration",
  "livemode": false,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "platform": "stripe",
  "status": "connected",
  "last_synced": 1793318400,
  "warning": null
}
```

## Retrieve domain verification {#retrieveDomainVerification}

`GET /v1/sites/{site}/domain_verification`

Status of the site domain verification, with the DNS record / file to publish.

**Scope** `sites:read` · **Operation** `retrieveDomainVerification`

SDK: `checkbox.domainVerifications.retrieve()` (Node) · `checkbox.domain_verifications.retrieve()` (Python). MCP / agents: operation `retrieveDomainVerification`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Returns

Returns a `DomainVerification` object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/domain_verification \
  -u "$CHECKBOX_SECRET_KEY:"
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const domainVerification = await checkbox.domainVerifications.retrieve('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(domainVerification);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

domain_verification = checkbox.domain_verifications.retrieve("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(domain_verification)
```

```json title="Response"
{
  "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "domain_verification",
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "domain": "acme.example",
  "status": "pending",
  "method": null,
  "verified_at": 1793318400,
  "last_checked": 1793318400,
  "last_error": "TXT record not found",
  "dns_record": {
    "type": "TXT",
    "name": "_checkbox-verify.acme.example",
    "value": "checkbox-verify=Xy…"
  },
  "file": {
    "url": "https://acme.example/.well-known/checkbox-verify.txt",
    "contents": "Xy…"
  },
  "meta_tag": {
    "url": "https://acme.example/",
    "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
  },
  "scan_target_problems": [],
  "account_activated": false,
  "next_action": {
    "type": "publish_dns_record",
    "message": "Publish the TXT record, then call checkDomainVerification.",
    "operation_id": "checkDomainVerification",
    "mcp_tool": "call_api",
    "endpoint": "POST /v1/sites/{site}/domain_verification/check"
  }
}
```

## Start domain verification {#createDomainVerification}

`POST /v1/sites/{site}/domain_verification`

Starts verification of the site domain and returns a DNS TXT record and a /.well-known file; publishing either proves control. Then call checkDomainVerification. Verifying a live-mode site activates live mode for the account (instant, self-serve).

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `createDomainVerification`

SDK: `checkbox.domainVerifications.create()` (Node) · `checkbox.domain_verifications.create()` (Python). MCP / agents: operation `createDomainVerification`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Body

| Field | Type | Description |
|---|---|---|
| `rotate` | boolean | Issue a new token (invalidates the old one). |

#### Returns

Returns a `DomainVerification` object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/domain_verification \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{}'
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const domainVerification = await checkbox.domainVerifications.create('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(domainVerification);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

domain_verification = checkbox.domain_verifications.create("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(domain_verification)
```

```json title="Response"
{
  "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "domain_verification",
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "domain": "acme.example",
  "status": "pending",
  "method": null,
  "verified_at": 1793318400,
  "last_checked": 1793318400,
  "last_error": "TXT record not found",
  "dns_record": {
    "type": "TXT",
    "name": "_checkbox-verify.acme.example",
    "value": "checkbox-verify=Xy…"
  },
  "file": {
    "url": "https://acme.example/.well-known/checkbox-verify.txt",
    "contents": "Xy…"
  },
  "meta_tag": {
    "url": "https://acme.example/",
    "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
  },
  "scan_target_problems": [],
  "account_activated": false,
  "next_action": {
    "type": "publish_dns_record",
    "message": "Publish the TXT record, then call checkDomainVerification.",
    "operation_id": "checkDomainVerification",
    "mcp_tool": "call_api",
    "endpoint": "POST /v1/sites/{site}/domain_verification/check"
  }
}
```

## Check domain verification now {#checkDomainVerification}

`POST /v1/sites/{site}/domain_verification/check`

Looks for the DNS TXT record, the /.well-known file, and the site's Checkbox snippet or the checkbox-verify meta tag on https://<domain>/ now. On success in live mode, the account is activated and held monitoring starts.

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `checkDomainVerification`

SDK: `checkbox.domainVerifications.check()` (Node) · `checkbox.domain_verifications.check()` (Python). MCP / agents: operation `checkDomainVerification`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Returns

Returns a `DomainVerification` object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/domain_verification/check \
  -u "$CHECKBOX_SECRET_KEY:" \
  -X POST
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const domainVerification = await checkbox.domainVerifications.check('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(domainVerification);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

domain_verification = checkbox.domain_verifications.check("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(domain_verification)
```

```json title="Response"
{
  "id": "dv_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "domain_verification",
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "domain": "acme.example",
  "status": "pending",
  "method": null,
  "verified_at": 1793318400,
  "last_checked": 1793318400,
  "last_error": "TXT record not found",
  "dns_record": {
    "type": "TXT",
    "name": "_checkbox-verify.acme.example",
    "value": "checkbox-verify=Xy…"
  },
  "file": {
    "url": "https://acme.example/.well-known/checkbox-verify.txt",
    "contents": "Xy…"
  },
  "meta_tag": {
    "url": "https://acme.example/",
    "html": "<meta name=\"checkbox-verify\" content=\"Xy…\">"
  },
  "scan_target_problems": [],
  "account_activated": false,
  "next_action": {
    "type": "publish_dns_record",
    "message": "Publish the TXT record, then call checkDomainVerification.",
    "operation_id": "checkDomainVerification",
    "mcp_tool": "call_api",
    "endpoint": "POST /v1/sites/{site}/domain_verification/check"
  }
}
```

## Re-sync Stripe settings {#resyncBilling}

`POST /v1/sites/{site}/billing/resync`

Re-reads the site's billing-platform settings now (Stripe customer-portal cancellation, trial-ending emails, plans) and re-evaluates the site, so a setting you just changed in Stripe shows up without waiting for the next scan. Every scan also re-reads them. Then poll retrieveLatestEvaluation (or listFindings) after about a minute.

**Scope** `sites:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `resyncBilling`

SDK: `checkbox.billings.resync()` (Node) · `checkbox.billings.resync()` (Python). MCP / agents: operation `resyncBilling`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `site` **required** | path | string | Unique identifier of the site (site_…). |

#### Returns

Returns a `BillingSync` object.

Errors use the [standard envelope](https://checkbox.site/docs/api/errors) with a stable `code` and, where useful, `next_action`.

```curl
curl https://app.checkbox.site/v1/sites/site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b/billing/resync \
  -u "$CHECKBOX_SECRET_KEY:" \
  -X POST
```
```node
import Checkbox from '@checkbox-site/node';

const checkbox = new Checkbox(process.env.CHECKBOX_SECRET_KEY);

const billing = await checkbox.billings.resync('site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(billing);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox(os.environ["CHECKBOX_SECRET_KEY"])

billing = checkbox.billings.resync("site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(billing)
```

```json title="Response"
{
  "object": "billing_sync",
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "platforms": [
    {
      "platform": "stripe",
      "status": "queued",
      "last_synced": 1793318400,
      "last_error": null
    }
  ],
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "endpoint": "POST /v1/sites/{site}/domain_verification",
    "url": "https://checkbox.site/docs/concepts/activation#verify"
  }
}
```
