# Elements API

> Checkbox Elements: the drop-in <checkbox-disclosure> web component (and React wrapper) that shows the locked automatic-renewal disclosure above the pay button with an unchecked consent checkbox, and the consent records it creates.

| Operation | Endpoint |
|---|---|
| [Load the Elements browser bundle](#getElementsBundle) | `GET /v1/elements.js` |
| [List Elements bundle versions and SRI hashes](#getElementsManifest) | `GET /v1/elements/manifest.json` |
| [Load a pinned Elements bundle version](#getElementsBundleVersion) | `GET /v1/elements/{version}/elements.js` |
| [Create a locked disclosure for a site](#createDisclosure) | `POST /v1/disclosures` |
| [Retrieve a disclosure](#retrieveDisclosure) | `GET /v1/disclosures/{disclosure}` |
| [List consents](#listConsents) | `GET /v1/consents` |
| [Record a consent](#createConsent) | `POST /v1/consents` |
| [Retrieve a consent](#retrieveConsent) | `GET /v1/consents/{consent}` |
| [Attach a customer reference to a consent](#updateConsent) | `POST /v1/consents/{consent}` |

## The Disclosure object

Locked automatic-renewal disclosure + consent wording for a site, rendered by <checkbox-disclosure disclosure="disc_…">.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique identifier of the disclosure (disc_…). |
| `object` | enum | String representing the object's type. Always "disclosure". |
| `livemode` | boolean | true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). |
| `created` | integer | Creation time. Unix timestamp in seconds. |
| `site` | string | Site. |
| `terms` | object | Terms stated (DisclosureTerms). |
| `text` | string | Locked disclosure text. |
| `consent_label` | string | Locked consent checkbox label. |
| `texts_sha256` | string | sha256 of text + "\n" + consent_label. |
| `rules_version` | string | Rules version that generated and verified the wording. |
| `verification` | object \| null | Rules-engine verification of the element on your checkout (secret-key responses only). |
| `verification.passes` | boolean | Every targeted sign-up check passes on the modelled checkout. |
| `verification.modelled` | string | from_capture (your scanned checkout) or synthetic. |
| `verification.remaining` | array of strings | Checks that would still not pass. |
| `verification.checks` | array of objects | Per-check before / after. |
| `element_html` | string | Markup to paste directly above your pay button. |
| `script_tag` | string | <script> tag (pinned version, SRI) for the page <head>. |
| `publishable_key` | string | The publishable key for this mode (safe to embed in pages). |
| `next_action` | NextAction | What the caller (often an AI agent) should do next. |

## Load the Elements browser bundle {#getElementsBundle}

`GET /v1/elements.js`

The current elements.js (registers <checkbox-disclosure>). For production pin a version with SRI: use the script_tag from getElementsManifest or createDisclosure.

**No API key** (public) · **Operation** `getElementsBundle`

SDK: `checkbox.elements.retrieveBundle()` (Node) · `checkbox.elements.retrieve_bundle()` (Python). MCP / agents: operation `getElementsBundle`.

#### Returns

Returns the file (`application/javascript`).

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/elements.js
```
```node
import Checkbox from '@checkbox-site/cli';

const checkbox = new Checkbox();

const file = await checkbox.elements.retrieveBundle();
console.log(file);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox()

element = checkbox.elements.retrieve_bundle()
print(element)
```

## List Elements bundle versions and SRI hashes {#getElementsManifest}

`GET /v1/elements/manifest.json`

Released elements.js versions with their immutable URLs and Subresource Integrity hashes, plus a ready-to-paste script tag for the latest one.

**No API key** (public) · **Operation** `getElementsManifest`

SDK: `checkbox.elements.retrieveManifest()` (Node) · `checkbox.elements.retrieve_manifest()` (Python). MCP / agents: operation `getElementsManifest`.

#### Returns

Returns an `ElementsManifest` 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/elements/manifest.json
```
```node
import Checkbox from '@checkbox-site/cli';

const checkbox = new Checkbox();

const element = await checkbox.elements.retrieveManifest();
console.log(element);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox()

element = checkbox.elements.retrieve_manifest()
print(element)
```

```json title="Response"
{
  "object": "elements_manifest",
  "latest": {
    "version": "1.0.0",
    "url": "https://app.checkbox.site/v1/elements/1.0.0/elements.js",
    "integrity": "sha384-…",
    "size": 33000
  },
  "versions": [
    {
      "version": "1.0.0",
      "url": "https://app.checkbox.site/v1/elements/1.0.0/elements.js",
      "integrity": "sha384-…",
      "size": 33000
    }
  ],
  "script_tag": "<script src=\"…\" integrity=\"sha384-…\" crossorigin=\"anonymous\" defer></script>",
  "element_tag": "checkbox-disclosure",
  "docs_url": "https://checkbox.site/docs/elements"
}
```

## Load a pinned Elements bundle version {#getElementsBundleVersion}

`GET /v1/elements/{version}/elements.js`

An immutable elements.js release (cached for a year). Its integrity hash is in getElementsManifest.

**No API key** (public) · **Operation** `getElementsBundleVersion`

SDK: `checkbox.elements.retrieveBundleVersion()` (Node) · `checkbox.elements.retrieve_bundle_version()` (Python). MCP / agents: operation `getElementsBundleVersion`.

#### Parameters

| Parameter | In | Type | Description |
|---|---|---|---|
| `version` **required** | path | string | Semver, e.g. 1.0.0. |

#### Returns

Returns the file (`application/javascript`).

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/elements/1.0.0/elements.js
```
```node
import Checkbox from '@checkbox-site/cli';

const checkbox = new Checkbox();

const file = await checkbox.elements.retrieveBundleVersion('1.0.0');
console.log(file);
```
```python
import os
from checkbox import Checkbox

checkbox = Checkbox()

element = checkbox.elements.retrieve_bundle_version("1.0.0")
print(element)
```

## Create a locked disclosure for a site {#createDisclosure}

`POST /v1/disclosures`

Generates the locked automatic-renewal disclosure and consent label for the site's terms (from the billing connection, the given terms, or both), verifies with the rules engine that the element passes the sign-up checks on your checkout, and returns the markup to paste above your pay button. Next: put script_tag in <head> and element_html directly above the pay button, then call listConsents after a test sign-up.

**Scope** `consents:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `createDisclosure`

SDK: `checkbox.disclosures.create()` (Node) · `checkbox.disclosures.create()` (Python). MCP / agents: operation `createDisclosure`.

#### Body

| Field | Type | Description |
|---|---|---|
| `site` **required** | string | site_… the disclosure is for. |
| `plan` | string | Price / plan id from the site's billing connection (Stripe price_…) when it offers several. |
| `terms` | DisclosureTerms | Terms to state. Omitted values come from the billing connection; cancel_url defaults to the hosted cancellation page. |
| `terms.merchant_name` | string | Brand shown to subscribers. |
| `terms.amount` | integer | Recurring charge in minor units (1999 = $19.99). |
| `terms.currency` | string | Three-letter ISO currency code. |
| `terms.interval` | enum | Billing interval. One of `day`, `week`, `month`, `year`. |
| `terms.interval_count` | integer | Intervals per charge (default 1). |
| `terms.trial_days` | integer | Free-trial length in days (0 or absent: no trial). |
| `terms.cancel_url` | string | https address where subscribers cancel online. |
| `terms.cancel_timing` | enum | When a cancellation takes effect (default period_end). One of `period_end`, `immediately`. |

#### Returns

Returns a [Disclosure](https://checkbox.site/docs/api/elements#the-disclosure-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/disclosures \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "trial_days": 14,
    "cancel_url": "https://app.checkbox.site/cancel/joybox",
    "cancel_timing": "period_end"
  }
}'
```
```node
import Checkbox from '@checkbox-site/cli';

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

const disclosure = await checkbox.disclosures.create({
  site: 'site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b',
  terms: {
    merchant_name: 'Joybox',
    amount: 1999,
    currency: 'usd',
    interval: 'month',
    interval_count: 1,
    trial_days: 14,
    cancel_url: 'https://app.checkbox.site/cancel/joybox',
    cancel_timing: 'period_end',
  },
});
console.log(disclosure);
```
```python
import os
from checkbox import Checkbox

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

disclosure = checkbox.disclosures.create(
    site="site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    terms={
        "merchant_name": "Joybox",
        "amount": 1999,
        "currency": "usd",
        "interval": "month",
        "interval_count": 1,
        "trial_days": 14,
        "cancel_url": "https://app.checkbox.site/cancel/joybox",
        "cancel_timing": "period_end",
    },
)
print(disclosure)
```

```json title="Response"
{
  "id": "disc_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "disclosure",
  "livemode": false,
  "created": 1793318400,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month"
  },
  "text": "Your Joybox subscription automatically renews every month at $19.99 …",
  "consent_label": "I agree that my Joybox subscription renews automatically …",
  "texts_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "rules_version": "2026.10.30",
  "verification": {
    "passes": true,
    "modelled": "synthetic",
    "remaining": [],
    "checks": []
  },
  "element_html": "<checkbox-disclosure publishable-key=\"pk_test_…\" disclosure=\"disc_…\"></checkbox-disclosure>",
  "script_tag": "<script src=\"https://app.checkbox.site/v1/elements/1.0.0/elements.js\" integrity=\"sha384-…\" crossorigin=\"anonymous\" defer></script>",
  "publishable_key": "pk_test_…",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  }
}
```

## Retrieve a disclosure {#retrieveDisclosure}

`GET /v1/disclosures/{disclosure}`

The locked disclosure text, consent label and terms. Works with the publishable key from the site's own pages (this is how <checkbox-disclosure disclosure="disc_…"> loads its text).

**Key** publishable (`pk_…`) or secret · **Operation** `retrieveDisclosure`

SDK: `checkbox.disclosures.retrieve()` (Node) · `checkbox.disclosures.retrieve()` (Python). MCP / agents: operation `retrieveDisclosure`.

#### Parameters

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

#### Returns

Returns a [Disclosure](https://checkbox.site/docs/api/elements#the-disclosure-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/disclosures/disc_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:"
```
```node
import Checkbox from '@checkbox-site/cli';

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

const disclosure = await checkbox.disclosures.retrieve('disc_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(disclosure);
```
```python
import os
from checkbox import Checkbox

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

disclosure = checkbox.disclosures.retrieve("disc_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(disclosure)
```

```json title="Response"
{
  "id": "disc_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "disclosure",
  "livemode": false,
  "created": 1793318400,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month"
  },
  "text": "Your Joybox subscription automatically renews every month at $19.99 …",
  "consent_label": "I agree that my Joybox subscription renews automatically …",
  "texts_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "rules_version": "2026.10.30",
  "verification": {
    "passes": true,
    "modelled": "synthetic",
    "remaining": [],
    "checks": []
  },
  "element_html": "<checkbox-disclosure publishable-key=\"pk_test_…\" disclosure=\"disc_…\"></checkbox-disclosure>",
  "script_tag": "<script src=\"https://app.checkbox.site/v1/elements/1.0.0/elements.js\" integrity=\"sha384-…\" crossorigin=\"anonymous\" defer></script>",
  "publishable_key": "pk_test_…",
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  }
}
```

## List consents {#listConsents}

`GET /v1/consents`

Consents, newest first. Filter by site, customer_reference (e.g. find the consent behind a disputed Stripe subscription), disclosure or creation time.

**Scope** `consents:read` · **Operation** `listConsents`

SDK: `checkbox.consents.list()` (Node) · `checkbox.consents.list()` (Python). MCP / agents: operation `listConsents`.

#### 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). |
| `site` | query | string | Only this site's consents. |
| `customer_reference` | query | string | Only consents with this customer reference. |
| `disclosure` | query | string | Only consents to this disclosure. |
| `created_gte` | query | integer \| null | Created at or after (unix seconds). |
| `created_lte` | query | integer \| null | Created at or before (unix seconds). |

#### Returns

Returns a list (`{ object: "list", data, has_more, url }`) of `Consent` 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/consents \
  -u "$CHECKBOX_SECRET_KEY:" \
  -d limit=3
```
```node
import Checkbox from '@checkbox-site/cli';

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

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

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

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

```json title="Response"
{
  "object": "list",
  "data": [
    {
      "id": "cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
      "object": "consent",
      "livemode": false,
      "created": 1793318400,
      "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
      "disclosure": {
        "id": null,
        "text": "Your Joybox subscription automatically renews every month …",
        "consent_label": "I agree that my Joybox subscription renews automatically …",
        "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        "texts_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
        "matches_locked_text": true
      },
      "terms": {
        "merchant_name": "Joybox",
        "amount": 1999,
        "currency": "usd",
        "interval": "month"
      },
      "checkbox": {
        "checked": true,
        "initially_checked": false,
        "required": true
      },
      "page_url": "https://joybox.example/checkout",
      "origin": "https://joybox.example",
      "user_agent_sha256": null,
      "customer_reference": "cs_test_a1b2c3",
      "client_reference": null,
      "source": "elements",
      "element_version": "1.0.0",
      "client_timestamp": null,
      "presentation": {
        "violations": [],
        "fallback_applied": false,
        "font_size_px": 16,
        "contrast_ratio": 16.1,
        "above_submit": true,
        "gap_px": 12,
        "boxed": true,
        "visible": true
      },
      "metadata": {},
      "evidence": {
        "id": "ev_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
        "sha256": null,
        "chain_hash": null
      },
      "corroborating_capture": null,
      "next_action": {
        "type": "verify_domain",
        "message": "Verify your site domain to turn on live mode.",
        "operation_id": "createDomainVerification",
        "mcp_tool": "call_api",
        "url": "https://checkbox.site/docs/api/activation"
      }
    }
  ],
  "has_more": false,
  "url": "/v1/sites"
}
```

## Record a consent {#createConsent}

`POST /v1/consents`

Records that a subscriber ticked the consent checkbox for the exact disclosure shown: stored with the text, its hashes, the terms, the page, a hash of the user agent and your customer reference, written to the site's hash-chained evidence vault, and fed to the compliance evaluation as corroborating evidence. <checkbox-disclosure> calls this with the publishable key (Origin-checked); servers may call it with a secret key and site. Next: attach the returned cons_… id to the subscription (metadata.checkbox_consent) or call updateConsent.

**Key** publishable (`pk_…`) or secret · **Idempotent** (send `Idempotency-Key`) · **Operation** `createConsent`

SDK: `checkbox.consents.create()` (Node) · `checkbox.consents.create()` (Python). MCP / agents: operation `createConsent`.

#### Body

| Field | Type | Description |
|---|---|---|
| `site` | string | site_… the consent belongs to. Optional with a publishable key (resolved from the page Origin); required with a secret key. |
| `disclosure` | string | disc_… of the server-issued disclosure that was shown, if any. |
| `terms` **required** | DisclosureTerms | Terms to state. Omitted values come from the billing connection; cancel_url defaults to the hosted cancellation page. |
| `terms.merchant_name` **required** | string | Brand shown to subscribers. |
| `terms.amount` **required** | integer | Recurring charge in minor units (1999 = $19.99). |
| `terms.currency` **required** | string | Three-letter ISO currency code. |
| `terms.interval` **required** | enum | Billing interval. One of `day`, `week`, `month`, `year`. |
| `terms.interval_count` | integer | Intervals per charge (default 1). |
| `terms.trial_days` | integer | Free-trial length in days (0 or absent: no trial). |
| `terms.cancel_url` **required** | string | https address where subscribers cancel online. |
| `terms.cancel_timing` | enum | When a cancellation takes effect (default period_end). One of `period_end`, `immediately`. |
| `disclosure_text` **required** | string | The exact disclosure text the subscriber saw. |
| `consent_label` **required** | string | The exact label of the consent checkbox. |
| `checkbox` **required** | object | Checkbox state. |
| `checkbox.checked` **required** | boolean | The box was ticked when the consent was recorded (must be true). |
| `checkbox.initially_checked` | boolean | The box was ticked before the subscriber touched it (default false). |
| `checkbox.required` | boolean | Ticking the box was required to subscribe (default true). |
| `page_url` | string | Page the consent was given on (fragment removed). |
| `customer_reference` | string | Your id for the subscriber: Stripe customer / Checkout Session / subscription id. Not an email address: no raw personal data is needed. |
| `client_timestamp` | integer | Unix seconds on the subscriber's device (informational; `created` is the server time). |
| `element_version` | string | elements.js version that rendered the disclosure. |
| `presentation` | ConsentPresentationInput | What <checkbox-disclosure> measured on screen (sent by the element). |
| `metadata` | object | Up to 20 key/value string pairs you can attach to the object. |

#### Returns

Returns a `Consent` 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/consents \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "trial_days": 14,
    "cancel_url": "https://app.checkbox.site/cancel/joybox",
    "cancel_timing": "period_end"
  },
  "disclosure_text": "Your Joybox subscription automatically renews every month at $19.99 (plus applicable taxes) until you cancel. …",
  "consent_label": "I agree that my Joybox subscription renews automatically every month at $19.99 …",
  "checkbox": {
    "checked": true,
    "initially_checked": false,
    "required": true
  },
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b"
}'
```
```node
import Checkbox from '@checkbox-site/cli';

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

const consent = await checkbox.consents.create({
  terms: {
    merchant_name: 'Joybox',
    amount: 1999,
    currency: 'usd',
    interval: 'month',
    interval_count: 1,
    trial_days: 14,
    cancel_url: 'https://app.checkbox.site/cancel/joybox',
    cancel_timing: 'period_end',
  },
  disclosure_text: 'Your Joybox subscription automatically renews every month at $19.99 (plus applicable taxes) until you cancel. …',
  consent_label: 'I agree that my Joybox subscription renews automatically every month at $19.99 …',
  checkbox: { checked: true, initially_checked: false, required: true },
  site: 'site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b',
});
console.log(consent);
```
```python
import os
from checkbox import Checkbox

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

consent = checkbox.consents.create(
    terms={
        "merchant_name": "Joybox",
        "amount": 1999,
        "currency": "usd",
        "interval": "month",
        "interval_count": 1,
        "trial_days": 14,
        "cancel_url": "https://app.checkbox.site/cancel/joybox",
        "cancel_timing": "period_end",
    },
    disclosure_text="Your Joybox subscription automatically renews every month at $19.99 (plus applicable taxes) until you cancel. …",
    consent_label="I agree that my Joybox subscription renews automatically every month at $19.99 …",
    checkbox={
        "checked": True,
        "initially_checked": False,
        "required": True,
    },
    site="site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
)
print(consent)
```

```json title="Response"
{
  "id": "cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "consent",
  "livemode": false,
  "created": 1793318400,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "disclosure": {
    "id": null,
    "text": "Your Joybox subscription automatically renews every month …",
    "consent_label": "I agree that my Joybox subscription renews automatically …",
    "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "texts_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "matches_locked_text": true
  },
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month"
  },
  "checkbox": {
    "checked": true,
    "initially_checked": false,
    "required": true
  },
  "page_url": "https://joybox.example/checkout",
  "origin": "https://joybox.example",
  "user_agent_sha256": null,
  "customer_reference": "cs_test_a1b2c3",
  "client_reference": null,
  "source": "elements",
  "element_version": "1.0.0",
  "client_timestamp": null,
  "presentation": {
    "violations": [],
    "fallback_applied": false,
    "font_size_px": 16,
    "contrast_ratio": 16.1,
    "above_submit": true,
    "gap_px": 12,
    "boxed": true,
    "visible": true
  },
  "metadata": {},
  "evidence": {
    "id": "ev_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "sha256": null,
    "chain_hash": null
  },
  "corroborating_capture": null,
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  }
}
```

## Retrieve a consent {#retrieveConsent}

`GET /v1/consents/{consent}`

A consent record: what the subscriber saw and agreed to, when, where, and its evidence record. Use it to answer a chargeback or a regulator: the evidence id verifies against the site's hash chain (verifyEvidenceChain) and downloads with downloadEvidenceContent.

**Scope** `consents:read` · **Operation** `retrieveConsent`

SDK: `checkbox.consents.retrieve()` (Node) · `checkbox.consents.retrieve()` (Python). MCP / agents: operation `retrieveConsent`.

#### Parameters

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

#### Returns

Returns a `Consent` 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/consents/cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:"
```
```node
import Checkbox from '@checkbox-site/cli';

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

const consent = await checkbox.consents.retrieve('cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(consent);
```
```python
import os
from checkbox import Checkbox

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

consent = checkbox.consents.retrieve("cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(consent)
```

```json title="Response"
{
  "id": "cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "consent",
  "livemode": false,
  "created": 1793318400,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "disclosure": {
    "id": null,
    "text": "Your Joybox subscription automatically renews every month …",
    "consent_label": "I agree that my Joybox subscription renews automatically …",
    "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "texts_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "matches_locked_text": true
  },
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month"
  },
  "checkbox": {
    "checked": true,
    "initially_checked": false,
    "required": true
  },
  "page_url": "https://joybox.example/checkout",
  "origin": "https://joybox.example",
  "user_agent_sha256": null,
  "customer_reference": "cs_test_a1b2c3",
  "client_reference": null,
  "source": "elements",
  "element_version": "1.0.0",
  "client_timestamp": null,
  "presentation": {
    "violations": [],
    "fallback_applied": false,
    "font_size_px": 16,
    "contrast_ratio": 16.1,
    "above_submit": true,
    "gap_px": 12,
    "boxed": true,
    "visible": true
  },
  "metadata": {},
  "evidence": {
    "id": "ev_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "sha256": null,
    "chain_hash": null
  },
  "corroborating_capture": null,
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  }
}
```

## Attach a customer reference to a consent {#updateConsent}

`POST /v1/consents/{consent}`

Sets customer_reference once (e.g. the Stripe subscription id created after the consent) and merges metadata. A different reference on a consent that already has one answers 409 consent_reference_locked. The change is appended to the evidence chain.

**Scope** `consents:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `updateConsent`

SDK: `checkbox.consents.update()` (Node) · `checkbox.consents.update()` (Python). MCP / agents: operation `updateConsent`.

#### Parameters

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

#### Body

| Field | Type | Description |
|---|---|---|
| `customer_reference` | string | Attach your subscriber reference (only while none is set). |
| `metadata` | object | Up to 20 key/value string pairs you can attach to the object. |

#### Returns

Returns a `Consent` 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/consents/cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "customer_reference": "sub_1Q2w3E"
}'
```
```node
import Checkbox from '@checkbox-site/cli';

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

const consent = await checkbox.consents.update('cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', { customer_reference: 'sub_1Q2w3E' });
console.log(consent);
```
```python
import os
from checkbox import Checkbox

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

consent = checkbox.consents.update("cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", customer_reference="sub_1Q2w3E")
print(consent)
```

```json title="Response"
{
  "id": "cons_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "consent",
  "livemode": false,
  "created": 1793318400,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "disclosure": {
    "id": null,
    "text": "Your Joybox subscription automatically renews every month …",
    "consent_label": "I agree that my Joybox subscription renews automatically …",
    "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "texts_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    "matches_locked_text": true
  },
  "terms": {
    "merchant_name": "Joybox",
    "amount": 1999,
    "currency": "usd",
    "interval": "month"
  },
  "checkbox": {
    "checked": true,
    "initially_checked": false,
    "required": true
  },
  "page_url": "https://joybox.example/checkout",
  "origin": "https://joybox.example",
  "user_agent_sha256": null,
  "customer_reference": "cs_test_a1b2c3",
  "client_reference": null,
  "source": "elements",
  "element_version": "1.0.0",
  "client_timestamp": null,
  "presentation": {
    "violations": [],
    "fallback_applied": false,
    "font_size_px": 16,
    "contrast_ratio": 16.1,
    "above_submit": true,
    "gap_px": 12,
    "boxed": true,
    "visible": true
  },
  "metadata": {},
  "evidence": {
    "id": "ev_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
    "sha256": null,
    "chain_hash": null
  },
  "corroborating_capture": null,
  "next_action": {
    "type": "verify_domain",
    "message": "Verify your site domain to turn on live mode.",
    "operation_id": "createDomainVerification",
    "mcp_tool": "call_api",
    "url": "https://checkbox.site/docs/api/activation"
  }
}
```
