# Findings API

> The latest result of each legal check for a site, with citations, evidence references and remediation.

| Operation | Endpoint |
|---|---|
| [List findings](#listFindings) | `GET /v1/findings` |
| [Retrieve a finding](#retrieveFinding) | `GET /v1/findings/{finding}` |
| [Triage a finding](#updateFinding) | `POST /v1/findings/{finding}` |

## The Finding object

The latest result of one legal check for a site.

| Field | Type | Description |
|---|---|---|
| `id` | string | Unique identifier of the finding (fnd_…). |
| `object` | enum | String representing the object's type. Always "finding". |
| `livemode` | boolean | true for live-mode objects, false for test mode (ck_test_ keys act on an isolated sandbox). |
| `site` | string | The site. |
| `check_id` | string | Stable id of the legal check. |
| `title` | string | Short title. |
| `detail` | string | What was observed. |
| `stage` | enum | Lifecycle stage. One of `signup`, `confirmation`, `reminder`, `cancellation`, `config`. |
| `severity` | enum | Strictest severity among the applicable requirements. One of `critical`, `high`, `medium`, `low`. |
| `status` | enum | Latest check result. One of `pass`, `fail`, `needs_review`, `not_applicable`. |
| `state` | enum | Triage state. One of `open`, `acknowledged`, `resolved`, `accepted_risk`. |
| `note` | string \| null | Triage note. |
| `jurisdictions` | array of enum | Jurisdictions whose laws this check applies. |
| `requirements` | array of RequirementRefs | The legal requirements behind the check, with citations. |
| `remediation` | Remediation \| null | How to fix the finding (see also the fixes resource and compliance plans). |
| `confidence` | number | Confidence 0-1 of the check result. |
| `evidence_refs` | array of strings | Ids of the captures / emails / evidence records supporting the result. |
| `details` | object | Check-specific details (failing regions/devices/URLs, measurements, quotes). |
| `scan` | string \| null | Scan that produced the latest result. |
| `first_seen` | integer | First time the check was evaluated. Unix timestamp in seconds. |
| `last_seen` | integer | Latest evaluation. Unix timestamp in seconds. |
| `resolved_at` | integer \| null | When it was resolved. Unix timestamp in seconds. |

## List findings {#listFindings}

`GET /v1/findings`

Findings ordered by urgency (failing first, then by severity). Filter by site, status (fail, needs_review, pass, not_applicable) and state (open, acknowledged, resolved, accepted_risk). Fix the open `fail` findings to become compliant.

**Scope** `findings:read` · **Operation** `listFindings`

SDK: `checkbox.findings.list()` (Node) · `checkbox.findings.list()` (Python). MCP / agents: operation `listFindings`.

#### 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 objects of this site (site_…). |
| `status` | query | enum | Only this check status. One of `pass`, `fail`, `needs_review`, `not_applicable`. |
| `state` | query | enum | Only this triage state. One of `open`, `acknowledged`, `resolved`, `accepted_risk`. |

#### Returns

Returns a list (`{ object: "list", data, has_more, url }`) of [Finding](https://checkbox.site/docs/api/findings#the-finding-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/findings \
  -u "$CHECKBOX_SECRET_KEY:" \
  -d limit=3
```
```node
import Checkbox from '@checkbox-site/cli';

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

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

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

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

```json title="Response"
{
  "object": "list",
  "data": [
    {
      "id": "fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
      "object": "finding",
      "livemode": false,
      "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
      "check_id": "signup.disclosure_clear_conspicuous",
      "title": "Auto-renewal terms are not shown before purchase",
      "detail": "The checkout page in US-CA (mobile) shows no renewal terms near the subscribe button.",
      "stage": "signup",
      "severity": "high",
      "status": "fail",
      "state": "open",
      "note": null,
      "jurisdictions": [
        "US-CA"
      ],
      "requirements": [
        {
          "id": "US-CA.17602.a.1",
          "jurisdiction": "US-CA",
          "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
          "title": "Clear and conspicuous auto-renewal terms before purchase",
          "source_url": "https://leginfo.legislature.ca.gov/…"
        }
      ],
      "remediation": {
        "summary": "Show the auto-renewal terms next to the subscribe button.",
        "steps": [
          "Add the disclosure above the button"
        ],
        "platform": "stripe",
        "suggested_copy": "Your subscription renews automatically every month at $9.99 until you cancel.",
        "snippet": {
          "language": "html",
          "code": "<p class=\"renewal-terms\">…</p>"
        }
      },
      "confidence": 0.9,
      "evidence_refs": [],
      "details": {
        "failingRegions": [
          "US-CA"
        ]
      },
      "scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
      "first_seen": 1793318400,
      "last_seen": 1793318400,
      "resolved_at": 1793318400
    }
  ],
  "has_more": false,
  "url": "/v1/sites"
}
```

## Retrieve a finding {#retrieveFinding}

`GET /v1/findings/{finding}`

One finding with its legal requirements (citations), evidence references and remediation.

**Scope** `findings:read` · **Operation** `retrieveFinding`

SDK: `checkbox.findings.retrieve()` (Node) · `checkbox.findings.retrieve()` (Python). MCP / agents: operation `retrieveFinding`.

#### Parameters

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

#### Returns

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

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

const finding = await checkbox.findings.retrieve('fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b');
console.log(finding);
```
```python
import os
from checkbox import Checkbox

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

finding = checkbox.findings.retrieve("fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b")
print(finding)
```

```json title="Response"
{
  "id": "fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "finding",
  "livemode": false,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "check_id": "signup.disclosure_clear_conspicuous",
  "title": "Auto-renewal terms are not shown before purchase",
  "detail": "The checkout page in US-CA (mobile) shows no renewal terms near the subscribe button.",
  "stage": "signup",
  "severity": "high",
  "status": "fail",
  "state": "open",
  "note": null,
  "jurisdictions": [
    "US-CA",
    "US-NY"
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous auto-renewal terms before purchase",
      "source_url": "https://leginfo.legislature.ca.gov/…"
    }
  ],
  "remediation": {
    "summary": "Show the auto-renewal terms next to the subscribe button.",
    "steps": [
      "Add the disclosure above the button"
    ],
    "platform": "stripe",
    "suggested_copy": "Your subscription renews automatically every month at $9.99 until you cancel.",
    "snippet": {
      "language": "html",
      "code": "<p class=\"renewal-terms\">…</p>"
    }
  },
  "confidence": 0.9,
  "evidence_refs": [],
  "details": {
    "failingRegions": [
      "US-CA"
    ]
  },
  "scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "first_seen": 1793318400,
  "last_seen": 1793318400,
  "resolved_at": 1793318400
}
```

## Triage a finding {#updateFinding}

`POST /v1/findings/{finding}`

Sets the triage state (open, acknowledged, accepted_risk, resolved) and an optional note. Triage does not change the check result; fixing the issue and re-scanning does.

**Scope** `findings:write` · **Idempotent** (send `Idempotency-Key`) · **Operation** `updateFinding`

SDK: `checkbox.findings.update()` (Node) · `checkbox.findings.update()` (Python). MCP / agents: operation `updateFinding`.

#### Parameters

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

#### Body

| Field | Type | Description |
|---|---|---|
| `state` **required** | enum | New triage state. One of `open`, `acknowledged`, `resolved`, `accepted_risk`. |
| `note` | string | Why (kept with the finding). |

#### Returns

Returns a [Finding](https://checkbox.site/docs/api/findings#the-finding-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/findings/fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b \
  -u "$CHECKBOX_SECRET_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
  "state": "acknowledged"
}'
```
```node
import Checkbox from '@checkbox-site/cli';

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

const finding = await checkbox.findings.update('fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b', { state: 'acknowledged' });
console.log(finding);
```
```python
import os
from checkbox import Checkbox

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

finding = checkbox.findings.update("fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b", state="acknowledged")
print(finding)
```

```json title="Response"
{
  "id": "fnd_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "object": "finding",
  "livemode": false,
  "site": "site_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "check_id": "signup.disclosure_clear_conspicuous",
  "title": "Auto-renewal terms are not shown before purchase",
  "detail": "The checkout page in US-CA (mobile) shows no renewal terms near the subscribe button.",
  "stage": "signup",
  "severity": "high",
  "status": "fail",
  "state": "open",
  "note": null,
  "jurisdictions": [
    "US-CA",
    "US-NY"
  ],
  "requirements": [
    {
      "id": "US-CA.17602.a.1",
      "jurisdiction": "US-CA",
      "citation": "Cal. Bus. & Prof. Code § 17602(a)(1)",
      "title": "Clear and conspicuous auto-renewal terms before purchase",
      "source_url": "https://leginfo.legislature.ca.gov/…"
    }
  ],
  "remediation": {
    "summary": "Show the auto-renewal terms next to the subscribe button.",
    "steps": [
      "Add the disclosure above the button"
    ],
    "platform": "stripe",
    "suggested_copy": "Your subscription renews automatically every month at $9.99 until you cancel.",
    "snippet": {
      "language": "html",
      "code": "<p class=\"renewal-terms\">…</p>"
    }
  },
  "confidence": 0.9,
  "evidence_refs": [],
  "details": {
    "failingRegions": [
      "US-CA"
    ]
  },
  "scan": "scan_3f9a1c2e7b4d4e0f9a8b7c6d5e4f3a2b",
  "first_seen": 1793318400,
  "last_seen": 1793318400,
  "resolved_at": 1793318400
}
```
