# Reference

Every Lockpick API operation, its permission, inputs and answer, generated from the API itself. Version 1, in beta.

{/* Generated by scripts/docs-generate.mts. Do not edit; run `pnpm docs:generate`. */}

Version 1, in beta. Every path starts with `/api/cli/v1`, every request carries a key as a bearer token, and every answer is `{ data, error }`. The whole description is also [OpenAPI 3.1](/openapi.json).

## Agent API

The server operations behind the hosted MCP tools. New integrations should use these. `lockpick_wait_for_scan` polls `GET /agent/scans/{scanId}`; `lockpick_evaluate_scan` reads that same scan and applies the assessment policy in the client. These two composed tools have no separate HTTP endpoint. Scripts can poll the scan status and evaluate its completion time, coverage and open finding counts against their policy.

### GET /agent/me

The person, workspace, scopes and expiry of this credential, and what it can start.

* Permission: `read`
* MCP tool: [`lockpick_whoami`](/docs/mcp/tools#lockpick_whoami)

**data**

| Field          | Type   | Always there |
| -------------- | ------ | ------------ |
| `user`         | object | Yes          |
| `workspace`    | object | Yes          |
| `credential`   | object | Yes          |
| `capabilities` | object | Yes          |

### GET /agent/allowance

Free scans left this month, their reset dates and credits.

* Permission: `read`
* MCP tool: [`lockpick_get_allowance`](/docs/mcp/tools#lockpick_get_allowance)

**data**

| Field               | Type                                                                             | Always there |
| ------------------- | -------------------------------------------------------------------------------- | ------------ |
| `accessSource`      | `community`, `stripe` (legacy billing value), `pilot` (legacy, internal), `none` | Yes          |
| `accountingMode`    | `pilot` (legacy, internal), `credits` (legacy, internal), `unmetered`            | Yes          |
| `pulse`             | object                                                                           | Yes          |
| `deep`              | object                                                                           | Yes          |
| `creditBalance`     | integer or null                                                                  | Yes          |
| `freeSiteId`        | string or null                                                                   | Yes          |
| `freeSiteVisible`   | boolean                                                                          | Yes          |
| `canSwitchFreeSite` | boolean                                                                          | Yes          |

### GET /agent/monitor

Browse current security intelligence and explain matches for authorized sites.

* Permission: `read`
* MCP tool: [`lockpick_monitor`](/docs/mcp/tools#lockpick_monitor)

**Query**

| Field        | Type                                                  | Required |
| ------------ | ----------------------------------------------------- | -------- |
| `view`       | `latest`, `sites`, `exploited`, `following`           | No       |
| `kind`       | `all`, `vulnerability`, `malicious_package`           | No       |
| `q`          | string                                                | No       |
| `ecosystem`  | `all`, `npm`, `pypi`, `composer`, `wordpress`         | No       |
| `severity`   | `all`, `critical`, `high`, `medium`, `low`, `unknown` | No       |
| `days`       | number                                                | No       |
| `cursor`     | string                                                | No       |
| `limit`      | integer                                               | No       |
| `siteId`     | string                                                | No       |
| `advisoryId` | string                                                | No       |

**data**

| Field         | Type           | Always there |
| ------------- | -------------- | ------------ |
| `items`       | list of object | Yes          |
| `nextCursor`  | string or null | Yes          |
| `limitations` | list of string | Yes          |

**Each item**

| Field         | Type                                           | Always there |
| ------------- | ---------------------------------------------- | ------------ |
| `id`          | string                                         | Yes          |
| `title`       | string                                         | Yes          |
| `source`      | string                                         | Yes          |
| `kind`        | `vulnerability`, `malicious_package`           | Yes          |
| `severity`    | `critical`, `high`, `medium`, `low`, `unknown` | Yes          |
| `provenance`  | list of object                                 | Yes          |
| `withdrawnAt` | string or null                                 | No           |
| `publishedAt` | string                                         | Yes          |
| `exploited`   | boolean                                        | Yes          |
| `ids`         | list of string                                 | Yes          |
| `tech`        | list of object                                 | Yes          |
| `epss`        | object or null                                 | No           |
| `cvss`        | object or null                                 | No           |
| `attribution` | string or null                                 | Yes          |
| `references`  | list of string                                 | Yes          |
| `packages`    | list of object                                 | Yes          |
| `sites`       | list of object                                 | Yes          |

### GET /agent/sites

A page of sites with their latest scans.

* Permission: `read`
* MCP tool: [`lockpick_list_sites`](/docs/mcp/tools#lockpick_list_sites)

**Query**

| Field    | Type    | Required |
| -------- | ------- | -------- |
| `limit`  | integer | No       |
| `cursor` | string  | No       |

**data**

| Field        | Type           | Always there |
| ------------ | -------------- | ------------ |
| `items`      | list of object | Yes          |
| `nextCursor` | string or null | Yes          |

**Each item**

| Field         | Type           | Always there |
| ------------- | -------------- | ------------ |
| `id`          | string         | Yes          |
| `name`        | string         | Yes          |
| `status`      | string         | Yes          |
| `baseDomain`  | string or null | Yes          |
| `latestPulse` | object or null | Yes          |
| `latestDeep`  | object or null | Yes          |
| `latestBox`   | object or null | Yes          |
| `webPath`     | string         | Yes          |
| `webUrl`      | string         | Yes          |

### POST /agent/sites

Add a site, or return the one with that address.

* Permission: `sites`
* MCP tool: [`lockpick_add_site`](/docs/mcp/tools#lockpick_add_site)

**Body**

| Field            | Type   | Required |
| ---------------- | ------ | -------- |
| `url`            | string | Yes      |
| `name`           | string | No       |
| `idempotencyKey` | string | Yes      |

**data**

| Field     | Type    | Always there |
| --------- | ------- | ------------ |
| `site`    | object  | Yes          |
| `created` | boolean | Yes          |

### GET /agent/sites/\{siteId}/status

One site's standing: its latest scans and what to do next.

* Permission: `read`
* MCP tool: [`lockpick_site_status`](/docs/mcp/tools#lockpick_site_status)

**data**

| Field            | Type           | Always there |
| ---------------- | -------------- | ------------ |
| `site`           | object         | Yes          |
| `latestPulse`    | object or null | Yes          |
| `latestDeep`     | object or null | Yes          |
| `latestBox`      | object or null | Yes          |
| `lastComparison` | object or null | Yes          |
| `caveats`        | list of string | Yes          |
| `relevant`       | list of object | No           |
| `relevantTotal`  | integer        | No           |

### POST /agent/sites/\{siteId}/dependencies

Send the package names and exact versions a site pins, never code, and read which advisories affect them.

* Permission: `sites`
* MCP tool: [`lockpick_send_dependencies`](/docs/mcp/tools#lockpick_send_dependencies)

**Body**

| Field            | Type                                                                                                                 | Required |
| ---------------- | -------------------------------------------------------------------------------------------------------------------- | -------- |
| `inventory`      | object                                                                                                               | No       |
| `packages`       | list of object                                                                                                       | Yes      |
| `sources`        | list of `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `requirements.txt`, `poetry.lock` | Yes      |
| `idempotencyKey` | string                                                                                                               | Yes      |

**data**

| Field             | Type                                                                                                                 | Always there |
| ----------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ |
| `siteId`          | string                                                                                                               | Yes          |
| `receivedAt`      | string or null                                                                                                       | Yes          |
| `sources`         | list of `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `requirements.txt`, `poetry.lock` | Yes          |
| `packageCount`    | integer                                                                                                              | Yes          |
| `affectsYouCount` | integer                                                                                                              | Yes          |
| `affectsYou`      | list of object                                                                                                       | Yes          |
| `webUrl`          | string                                                                                                               | Yes          |

### POST /agent/sites/\{siteId}/pulse

Start a Pulse on a site.

* Permission: `pulse`
* MCP tool: [`lockpick_start_pulse`](/docs/mcp/tools#lockpick_start_pulse)

**Body**

| Field            | Type   | Required |
| ---------------- | ------ | -------- |
| `idempotencyKey` | string | Yes      |
| `baselineScanId` | string | No       |

**data**

| Field       | Type    | Always there |
| ----------- | ------- | ------------ |
| `scan`      | object  | Yes          |
| `charged`   | object  | Yes          |
| `allowance` | object  | Yes          |
| `replayed`  | boolean | Yes          |

### POST /agent/sites/\{siteId}/deep-verifications

Issue a DNS or file ownership proof before a Deep scan.

* Permission: `deep`
* MCP tool: [`lockpick_start_deep_verification`](/docs/mcp/tools#lockpick_start_deep_verification)

**Body**

| Field            | Type                  | Required |
| ---------------- | --------------------- | -------- |
| `method`         | `dns`, `file`, `meta` | Yes      |
| `idempotencyKey` | string                | Yes      |

**data**

| Field               | Type                                                     | Always there |
| ------------------- | -------------------------------------------------------- | ------------ |
| `verificationId`    | string                                                   | Yes          |
| `siteId`            | string                                                   | Yes          |
| `origin`            | string                                                   | Yes          |
| `method`            | `dns`, `file`, `meta`                                    | Yes          |
| `state`             | `pending`, `verified`, `expired`, `exhausted`, `revoked` | Yes          |
| `expiresAt`         | string                                                   | Yes          |
| `verifiedUntil`     | string or null                                           | Yes          |
| `attemptsRemaining` | integer                                                  | Yes          |
| `retryAfterSeconds` | integer or null                                          | Yes          |
| `value`             | string                                                   | Yes          |
| `location`          | string                                                   | Yes          |

### POST /agent/sites/\{siteId}/deep-verifications/\{verificationId}/verify

Check a published ownership proof. Each check uses one of its attempts.

* Permission: `deep`
* MCP tool: [`lockpick_check_deep_verification`](/docs/mcp/tools#lockpick_check_deep_verification)

**data**

| Field               | Type                                                     | Always there |
| ------------------- | -------------------------------------------------------- | ------------ |
| `verificationId`    | string                                                   | Yes          |
| `siteId`            | string                                                   | Yes          |
| `origin`            | string                                                   | Yes          |
| `method`            | `dns`, `file`, `meta`                                    | Yes          |
| `state`             | `pending`, `verified`, `expired`, `exhausted`, `revoked` | Yes          |
| `expiresAt`         | string                                                   | Yes          |
| `verifiedUntil`     | string or null                                           | Yes          |
| `attemptsRemaining` | integer                                                  | Yes          |
| `retryAfterSeconds` | integer or null                                          | Yes          |

### POST /agent/sites/\{siteId}/deep-operations

Prepare a Deep scan and get the link where the person approves it.

* Permission: `deep`
* MCP tool: [`lockpick_prepare_deep`](/docs/mcp/tools#lockpick_prepare_deep)

**Body**

| Field            | Type   | Required |
| ---------------- | ------ | -------- |
| `verificationId` | string | Yes      |
| `idempotencyKey` | string | Yes      |

**data**

| Field             | Type                                       | Always there |
| ----------------- | ------------------------------------------ | ------------ |
| `operationId`     | string                                     | Yes          |
| `siteId`          | string                                     | Yes          |
| `origin`          | string                                     | Yes          |
| `assessmentLevel` | string                                     | Yes          |
| `verificationId`  | string                                     | Yes          |
| `cost`            | object                                     | Yes          |
| `allowance`       | object                                     | Yes          |
| `approvalState`   | `pending`, `approved`, `expired`, `denied` | Yes          |
| `approvalUrl`     | string                                     | Yes          |
| `expiresAt`       | string                                     | Yes          |

### POST /agent/deep-operations/\{operationId}/start

Start a Deep scan the person approved.

* Permission: `deep`
* MCP tool: [`lockpick_start_deep`](/docs/mcp/tools#lockpick_start_deep)

**data**

| Field       | Type    | Always there |
| ----------- | ------- | ------------ |
| `scan`      | object  | Yes          |
| `charged`   | object  | Yes          |
| `allowance` | object  | Yes          |
| `replayed`  | boolean | Yes          |

### POST /agent/free-site-switch

Remove a site so this month's free Pulse can move to another.

* Permission: `sites` and `pulse`
* MCP tool: [`lockpick_switch_free_site`](/docs/mcp/tools#lockpick_switch_free_site)

**Body**

| Field            | Type    | Required |
| ---------------- | ------- | -------- |
| `removeSiteId`   | string  | Yes      |
| `checkId`        | string  | No       |
| `idempotencyKey` | string  | Yes      |
| `confirmRemoval` | boolean | Yes      |

**data**

| Field               | Type           | Always there |
| ------------------- | -------------- | ------------ |
| `removedSiteId`     | string         | Yes          |
| `removedSiteHost`   | string         | Yes          |
| `replacementSiteId` | string or null | Yes          |
| `allowance`         | object         | Yes          |
| `restoreUrl`        | string         | Yes          |
| `startedScanId`     | string or null | Yes          |
| `charged`           | object         | Yes          |
| `replayed`          | boolean        | Yes          |

### GET /agent/scans

A page of scans, newest first, with filters.

* Permission: `read`
* MCP tool: [`lockpick_list_scans`](/docs/mcp/tools#lockpick_list_scans)

**Query**

| Field             | Type                                                                                | Required |
| ----------------- | ----------------------------------------------------------------------------------- | -------- |
| `siteId`          | string                                                                              | No       |
| `kind`            | `pulse`, `box` (Deep, legacy name)                                                  | No       |
| `assessmentLevel` | `pulse`, `standard`, `deep`                                                         | No       |
| `status`          | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | No       |
| `limit`           | integer                                                                             | No       |
| `cursor`          | string                                                                              | No       |

**data**

| Field        | Type           | Always there |
| ------------ | -------------- | ------------ |
| `items`      | list of object | Yes          |
| `nextCursor` | string or null | Yes          |

**Each item**

| Field                       | Type                                                                                | Always there |
| --------------------------- | ----------------------------------------------------------------------------------- | ------------ |
| `id`                        | string                                                                              | Yes          |
| `kind`                      | `pulse`, `box` (Deep, legacy name)                                                  | Yes          |
| `projectId`                 | string                                                                              | Yes          |
| `target`                    | string                                                                              | Yes          |
| `status`                    | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | Yes          |
| `mode`                      | `autonomous`, `authenticated`, `active` or null                                     | Yes          |
| `createdAt`                 | string or null                                                                      | Yes          |
| `finishedAt`                | string or null                                                                      | Yes          |
| `webPath`                   | string                                                                              | Yes          |
| `assessmentLevel`           | `pulse`, `standard`, `deep` or null                                                 | Yes          |
| `headline`                  | object                                                                              | Yes          |
| `webUrl`                    | string                                                                              | Yes          |
| `suggestedPollAfterSeconds` | integer or null                                                                     | Yes          |

### GET /agent/scans/\{scanId}

One scan with its status and headline.

* Permission: `read`
* MCP tool: [`lockpick_get_scan`](/docs/mcp/tools#lockpick_get_scan)

**data**

| Field                       | Type                                                                                | Always there |
| --------------------------- | ----------------------------------------------------------------------------------- | ------------ |
| `id`                        | string                                                                              | Yes          |
| `kind`                      | `pulse`, `box` (Deep, legacy name)                                                  | Yes          |
| `projectId`                 | string                                                                              | Yes          |
| `target`                    | string                                                                              | Yes          |
| `status`                    | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | Yes          |
| `mode`                      | `autonomous`, `authenticated`, `active` or null                                     | Yes          |
| `createdAt`                 | string or null                                                                      | Yes          |
| `finishedAt`                | string or null                                                                      | Yes          |
| `webPath`                   | string                                                                              | Yes          |
| `assessmentLevel`           | `pulse`, `standard`, `deep` or null                                                 | Yes          |
| `headline`                  | object                                                                              | Yes          |
| `webUrl`                    | string                                                                              | Yes          |
| `suggestedPollAfterSeconds` | integer or null                                                                     | Yes          |
| `baselineRunId`             | string or null                                                                      | Yes          |
| `open`                      | object                                                                              | Yes          |
| `findingCount`              | integer                                                                             | Yes          |
| `progress`                  | object or null                                                                      | Yes          |
| `coverage`                  | object                                                                              | Yes          |
| `caveats`                   | list of string                                                                      | Yes          |
| `outcome`                   | object or null                                                                      | Yes          |
| `exposureCheck`             | object                                                                              | No           |

### GET /agent/scans/\{scanId}/findings

A page of findings of a scan.

* Permission: `read`
* MCP tool: [`lockpick_list_findings`](/docs/mcp/tools#lockpick_list_findings)
* Send `x-lockpick-agent-features: finding-code` to receive each finding's `code` (`LP-` and six characters, as the web report shows it). Without the header the answer has no `code`, the shape older clients expect.

**Query**

| Field      | Type                                          | Required |
| ---------- | --------------------------------------------- | -------- |
| `state`    | `attention`, `information`, `unknown`, `pass` | No       |
| `severity` | `critical`, `high`, `medium`, `low`, `info`   | No       |
| `all`      | boolean or `true`, `false`                    | No       |
| `limit`    | integer                                       | No       |
| `cursor`   | string                                        | No       |

**data**

| Field        | Type           | Always there |
| ------------ | -------------- | ------------ |
| `items`      | list of object | Yes          |
| `nextCursor` | string or null | Yes          |

**Each item**

| Field               | Type                                                  | Always there |
| ------------------- | ----------------------------------------------------- | ------------ |
| `id`                | string                                                | Yes          |
| `code`              | string                                                | No           |
| `runId`             | string                                                | Yes          |
| `kind`              | `pulse`, `box` (Deep, legacy name)                    | Yes          |
| `severity`          | `critical`, `high`, `medium`, `low`, `info`           | Yes          |
| `state`             | `attention`, `information`, `unknown`, `pass`         | Yes          |
| `category`          | string                                                | Yes          |
| `title`             | string                                                | Yes          |
| `meaning`           | string                                                | Yes          |
| `fix`               | string or null                                        | Yes          |
| `confidence`        | string                                                | Yes          |
| `evidence`          | list of string                                        | Yes          |
| `sources`           | list of string                                        | Yes          |
| `steps`             | list of string                                        | Yes          |
| `webPath`           | string                                                | Yes          |
| `webUrl`            | string                                                | Yes          |
| `evidenceTrust`     | string                                                | Yes          |
| `evidenceTruncated` | boolean                                               | Yes          |
| `verdict`           | `confirmed`, `needs_review`, `not_actionable` or null | No           |
| `certainty`         | `high`, `medium`, `low` or null                       | No           |
| `exploitability`    | `direct`, `conditional`, `hygiene`, `none` or null    | No           |
| `proof`             | object or null                                        | No           |
| `proofGap`          | string or null                                        | No           |
| `urgency`           | `now`, `week`, `later`, `none`                        | No           |
| `howSure`           | `confirmed`, `likely`, `possible` or null             | No           |

### GET /agent/scans/\{scanId}/findings/\{findingId}

One finding with its redacted evidence.

* Permission: `read`
* MCP tool: [`lockpick_get_finding`](/docs/mcp/tools#lockpick_get_finding)
* Send `x-lockpick-agent-features: finding-code` to receive each finding's `code` (`LP-` and six characters, as the web report shows it). Without the header the answer has no `code`, the shape older clients expect.

**data**

| Field               | Type                                                  | Always there |
| ------------------- | ----------------------------------------------------- | ------------ |
| `id`                | string                                                | Yes          |
| `code`              | string                                                | No           |
| `runId`             | string                                                | Yes          |
| `kind`              | `pulse`, `box` (Deep, legacy name)                    | Yes          |
| `severity`          | `critical`, `high`, `medium`, `low`, `info`           | Yes          |
| `state`             | `attention`, `information`, `unknown`, `pass`         | Yes          |
| `category`          | string                                                | Yes          |
| `title`             | string                                                | Yes          |
| `meaning`           | string                                                | Yes          |
| `fix`               | string or null                                        | Yes          |
| `confidence`        | string                                                | Yes          |
| `evidence`          | list of string                                        | Yes          |
| `sources`           | list of string                                        | Yes          |
| `steps`             | list of string                                        | Yes          |
| `webPath`           | string                                                | Yes          |
| `webUrl`            | string                                                | Yes          |
| `evidenceTrust`     | string                                                | Yes          |
| `evidenceTruncated` | boolean                                               | Yes          |
| `verdict`           | `confirmed`, `needs_review`, `not_actionable` or null | No           |
| `certainty`         | `high`, `medium`, `low` or null                       | No           |
| `exploitability`    | `direct`, `conditional`, `hygiene`, `none` or null    | No           |
| `proof`             | object or null                                        | No           |
| `proofGap`          | string or null                                        | No           |
| `urgency`           | `now`, `week`, `later`, `none`                        | No           |
| `howSure`           | `confirmed`, `likely`, `possible` or null             | No           |

### GET /agent/scans/\{scanId}/repair-brief

One part of a scan's repair brief.

* Permission: `read`
* MCP tool: [`lockpick_get_repair_brief`](/docs/mcp/tools#lockpick_get_repair_brief)

**Query**

| Field       | Type                                                                                      | Required |
| ----------- | ----------------------------------------------------------------------------------------- | -------- |
| `findingId` | string                                                                                    | No       |
| `agent`     | `claude-code`, `codex`, `cursor`, `vscode`, `opencode`, `lovable`, `bolt`, `replit`, `v0` | No       |
| `cursor`    | string                                                                                    | No       |

**data**

| Field        | Type           | Always there |
| ------------ | -------------- | ------------ |
| `scanId`     | string         | Yes          |
| `findingIds` | list of string | Yes          |
| `saved`      | boolean        | Yes          |
| `markdown`   | string         | Yes          |
| `nextCursor` | string or null | Yes          |
| `complete`   | boolean        | Yes          |
| `webUrl`     | string         | Yes          |

### GET /agent/scans/\{scanId}/comparison

What changed between a scan and the one it rechecks.

* Permission: `read`
* MCP tool: [`lockpick_compare_scans`](/docs/mcp/tools#lockpick_compare_scans)
* Send `x-lockpick-agent-features: finding-code` to receive each finding's `code` (`LP-` and six characters, as the web report shows it). Without the header the answer has no `code`, the shape older clients expect.

**data**

| Field           | Type           | Always there |
| --------------- | -------------- | ------------ |
| `runId`         | string         | Yes          |
| `baselineRunId` | string         | Yes          |
| `error`         | string or null | Yes          |
| `changes`       | list of object | Yes          |
| `webUrl`        | string         | Yes          |

### POST /agent/scans/\{scanId}/dns-rechecks

Run the free DNS check again for a scan. Sends nothing to the site.

* Permission: `pulse`
* MCP tool: [`lockpick_recheck_dns`](/docs/mcp/tools#lockpick_recheck_dns)

**Body**

| Field            | Type   | Required |
| ---------------- | ------ | -------- |
| `findingId`      | string | Yes      |
| `idempotencyKey` | string | Yes      |

**data**

| Field                    | Type           | Always there |
| ------------------------ | -------------- | ------------ |
| `scanId`                 | string         | Yes          |
| `findingIds`             | list of string | Yes          |
| `pending`                | object or null | Yes          |
| `checkedAt`              | string or null | Yes          |
| `outcomes`               | list of object | Yes          |
| `nextAllowedAt`          | string or null | Yes          |
| `failedAt`               | string or null | Yes          |
| `originalGradeUnchanged` | boolean        | Yes          |

### GET /agent/scans/\{scanId}/dns-rechecks/latest

A scan's latest DNS check again.

* Permission: `read`
* MCP tool: [`lockpick_get_dns_recheck`](/docs/mcp/tools#lockpick_get_dns_recheck)

**data**

| Field                    | Type           | Always there |
| ------------------------ | -------------- | ------------ |
| `scanId`                 | string         | Yes          |
| `findingIds`             | list of string | Yes          |
| `pending`                | object or null | Yes          |
| `checkedAt`              | string or null | Yes          |
| `outcomes`               | list of object | Yes          |
| `nextAllowedAt`          | string or null | Yes          |
| `failedAt`               | string or null | Yes          |
| `originalGradeUnchanged` | boolean        | Yes          |

### POST /agent/quick-checks

Start a free quick check of a homepage.

* Permission: `pulse`
* MCP tool: [`lockpick_quick_check`](/docs/mcp/tools#lockpick_quick_check)

**Body**

| Field            | Type   | Required |
| ---------------- | ------ | -------- |
| `url`            | string | Yes      |
| `idempotencyKey` | string | Yes      |

**data**

| Field                       | Type                                       | Always there |
| --------------------------- | ------------------------------------------ | ------------ |
| `checkId`                   | string                                     | Yes          |
| `status`                    | `queued`, `running`, `succeeded`, `failed` | Yes          |
| `reused`                    | boolean                                    | Yes          |
| `headline`                  | object                                     | Yes          |
| `summary`                   | string or null                             | Yes          |
| `checks`                    | list of object                             | Yes          |
| `webUrl`                    | string                                     | Yes          |
| `suggestedPollAfterSeconds` | integer or null                            | Yes          |

### POST /agent/repository-checks

Check a public GitHub repository (a skill, plugin, MCP server or app) before installing it.

* Permission: `pulse`
* MCP tool: [`lockpick_check_repository`](/docs/mcp/tools#lockpick_check_repository)

**Body**

| Field            | Type           | Required |
| ---------------- | -------------- | -------- |
| `url`            | string         | Yes      |
| `mode`           | `skill`, `app` | No       |
| `depth`          | `free`, `deep` | No       |
| `idempotencyKey` | string         | Yes      |

**data**

| Field                       | Type                                                                                                                 | Always there |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ |
| `checkId`                   | string                                                                                                               | Yes          |
| `status`                    | `queued`, `running`, `succeeded`, `failed`                                                                           | Yes          |
| `reused`                    | boolean                                                                                                              | Yes          |
| `repository`                | object                                                                                                               | Yes          |
| `mode`                      | `skill`, `app` or null                                                                                               | Yes          |
| `kind`                      | string or null                                                                                                       | Yes          |
| `verdict`                   | `safe`, `caution`, `do_not_install` or null                                                                          | Yes          |
| `appRisk`                   | `low`, `elevated`, `high` or null                                                                                    | Yes          |
| `score`                     | integer or null                                                                                                      | Yes          |
| `summary`                   | string or null                                                                                                       | Yes          |
| `plainSummary`              | string or null                                                                                                       | Yes          |
| `findings`                  | list of object                                                                                                       | Yes          |
| `moreFindings`              | integer                                                                                                              | Yes          |
| `coverage`                  | object or null                                                                                                       | Yes          |
| `failure`                   | `not-found`, `ref-not-found`, `empty`, `too-large`, `rate-limited`, `unavailable`, `timeout`, `engine-error` or null | Yes          |
| `webUrl`                    | string                                                                                                               | Yes          |
| `suggestedPollAfterSeconds` | integer or null                                                                                                      | Yes          |

### GET /agent/repository-checks/\{checkId}

A repository check and its findings.

* Permission: `read`
* MCP tool: [`lockpick_get_repository_check`](/docs/mcp/tools#lockpick_get_repository_check)

**data**

| Field                       | Type                                                                                                                 | Always there |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------ |
| `checkId`                   | string                                                                                                               | Yes          |
| `status`                    | `queued`, `running`, `succeeded`, `failed`                                                                           | Yes          |
| `reused`                    | boolean                                                                                                              | Yes          |
| `repository`                | object                                                                                                               | Yes          |
| `mode`                      | `skill`, `app` or null                                                                                               | Yes          |
| `kind`                      | string or null                                                                                                       | Yes          |
| `verdict`                   | `safe`, `caution`, `do_not_install` or null                                                                          | Yes          |
| `appRisk`                   | `low`, `elevated`, `high` or null                                                                                    | Yes          |
| `score`                     | integer or null                                                                                                      | Yes          |
| `summary`                   | string or null                                                                                                       | Yes          |
| `plainSummary`              | string or null                                                                                                       | Yes          |
| `findings`                  | list of object                                                                                                       | Yes          |
| `moreFindings`              | integer                                                                                                              | Yes          |
| `coverage`                  | object or null                                                                                                       | Yes          |
| `failure`                   | `not-found`, `ref-not-found`, `empty`, `too-large`, `rate-limited`, `unavailable`, `timeout`, `engine-error` or null | Yes          |
| `webUrl`                    | string                                                                                                               | Yes          |
| `suggestedPollAfterSeconds` | integer or null                                                                                                      | Yes          |

### GET /agent/quick-checks/\{checkId}

A quick check and its result.

* Permission: `read`
* MCP tool: [`lockpick_get_quick_check`](/docs/mcp/tools#lockpick_get_quick_check)

**data**

| Field                       | Type                                       | Always there |
| --------------------------- | ------------------------------------------ | ------------ |
| `checkId`                   | string                                     | Yes          |
| `status`                    | `queued`, `running`, `succeeded`, `failed` | Yes          |
| `reused`                    | boolean                                    | Yes          |
| `headline`                  | object                                     | Yes          |
| `summary`                   | string or null                             | Yes          |
| `checks`                    | list of object                             | Yes          |
| `webUrl`                    | string                                     | Yes          |
| `suggestedPollAfterSeconds` | integer or null                            | Yes          |

### GET /agent/docs/search

Search Lockpick's public docs.

* Permission: `read`
* MCP tool: [`lockpick_search_docs`](/docs/mcp/tools#lockpick_search_docs)

**Query**

| Field   | Type    | Required |
| ------- | ------- | -------- |
| `query` | string  | Yes      |
| `limit` | integer | No       |

**data**

| Field     | Type           | Always there |
| --------- | -------------- | ------------ |
| `query`   | string         | Yes          |
| `results` | list of object | Yes          |

### GET /agent/docs/page

One public docs page as Markdown, in parts when it is long.

* Permission: `read`
* MCP tool: [`lockpick_read_doc`](/docs/mcp/tools#lockpick_read_doc)

**Query**

| Field    | Type   | Required |
| -------- | ------ | -------- |
| `path`   | string | No       |
| `cursor` | string | No       |

**data**

| Field         | Type           | Always there |
| ------------- | -------------- | ------------ |
| `path`        | string         | Yes          |
| `title`       | string         | Yes          |
| `description` | string or null | Yes          |
| `url`         | string         | Yes          |
| `markdownUrl` | string         | Yes          |
| `markdown`    | string         | Yes          |
| `nextCursor`  | string or null | Yes          |
| `complete`    | boolean        | Yes          |

## Device sign-in

How `lockpick login` gets a key: it asks for a code, the person approves it in the browser, and polling returns the key.

### POST /device/code

Start a device sign-in and get a code for the person to approve in the browser.

* Permission: none, part of sign-in

**Body**

| Field        | Type                                      | Required |
| ------------ | ----------------------------------------- | -------- |
| `clientName` | string                                    | No       |
| `hostname`   | string                                    | No       |
| `platform`   | string                                    | No       |
| `version`    | string                                    | No       |
| `scopes`     | list of `pulse`, `sites`, `deep`, `local` | No       |

**data**

| Field                     | Type    | Always there |
| ------------------------- | ------- | ------------ |
| `deviceCode`              | string  | Yes          |
| `userCode`                | string  | Yes          |
| `verificationUri`         | string  | Yes          |
| `verificationUriComplete` | string  | Yes          |
| `expiresIn`               | integer | Yes          |
| `interval`                | integer | Yes          |

### POST /device/token

Poll a device sign-in until the person approves it, then receive the key.

* Permission: none, part of sign-in

**Body**

| Field        | Type   | Required |
| ------------ | ------ | -------- |
| `deviceCode` | string | Yes      |

## Legacy

The original CLI routes, which CLI 0.2 uses. They stay as they are, and new integrations should use the Agent API above.

<details>
  <summary>
    Original CLI routes
  </summary>

  **POST /projects/\{projectId}/local-assessments/authorize**

  Authorize a local assessment before repository inspection. No source or results are uploaded.

  * Permission: `local`

  **Body**

  | Field                 | Type                                                                                                                                                                                               | Required |
  | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
  | `cliVersion`          | string                                                                                                                                                                                             | Yes      |
  | `scannerVersion`      | string                                                                                                                                                                                             | Yes      |
  | `rulesetVersion`      | string                                                                                                                                                                                             | Yes      |
  | `reportSchemaVersion` | string                                                                                                                                                                                             | Yes      |
  | `checks`              | list of `tracked-secrets`, `public-environment`, `browser-artifacts`, `supabase-client`, `supabase-migrations`, `git-history`, `docker-files`, `docker-values`, `actions-injection`, `source-maps` | Yes      |

  **data**

  | Field           | Type           | Always there |
  | --------------- | -------------- | ------------ |
  | `admissionId`   | string         | Yes          |
  | `projectId`     | string         | Yes          |
  | `workspaceId`   | string         | Yes          |
  | `policyVersion` | string         | Yes          |
  | `startBy`       | string         | Yes          |
  | `checks`        | list of object | Yes          |

  **GET /me**

  The person, workspace and key behind this credential.

  * Permission: `read`

  **data**

  | Field       | Type   | Always there |
  | ----------- | ------ | ------------ |
  | `user`      | object | Yes          |
  | `workspace` | object | Yes          |
  | `key`       | object | Yes          |

  **DELETE /me**

  Revoke the presented key.

  * Permission: any valid key

  **data**

  | Field     | Type    | Always there |
  | --------- | ------- | ------------ |
  | `revoked` | boolean | Yes          |

  **GET /projects**

  Sites (projects) with their latest Pulse and Deep scans.

  * Permission: `read`

  **Each item in data**

  | Field         | Type           | Always there |
  | ------------- | -------------- | ------------ |
  | `id`          | string         | Yes          |
  | `name`        | string         | Yes          |
  | `status`      | string         | Yes          |
  | `baseDomain`  | string or null | Yes          |
  | `latestPulse` | object or null | Yes          |
  | `latestDeep`  | object or null | No           |
  | `latestBox`   | object or null | Yes          |
  | `webPath`     | string         | Yes          |
  | `webUrl`      | string         | No           |

  **GET /projects/\{projectId}/status**

  One site's latest results and what changed.

  * Permission: `read`

  **data**

  | Field            | Type           | Always there |
  | ---------------- | -------------- | ------------ |
  | `project`        | object         | Yes          |
  | `latestPulse`    | object or null | Yes          |
  | `latestDeep`     | object or null | No           |
  | `latestBox`      | object or null | Yes          |
  | `lastComparison` | object or null | Yes          |
  | `caveats`        | list of string | Yes          |

  **POST /projects/\{projectId}/pulse**

  Start a Pulse on a site, or a recheck of its latest one.

  * Permission: `pulse`
  * Answers 201 when it works

  **Body**

  | Field            | Type   | Required |
  | ---------------- | ------ | -------- |
  | `idempotencyKey` | string | Yes      |

  **data**

  | Field                       | Type                                                                                | Always there |
  | --------------------------- | ----------------------------------------------------------------------------------- | ------------ |
  | `id`                        | string                                                                              | Yes          |
  | `kind`                      | `pulse`, `box` (Deep, legacy name)                                                  | Yes          |
  | `projectId`                 | string                                                                              | Yes          |
  | `target`                    | string                                                                              | Yes          |
  | `status`                    | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | Yes          |
  | `mode`                      | `autonomous`, `authenticated`, `active` or null                                     | Yes          |
  | `createdAt`                 | string or null                                                                      | Yes          |
  | `finishedAt`                | string or null                                                                      | Yes          |
  | `webPath`                   | string                                                                              | Yes          |
  | `assessmentLevel`           | `pulse`, `standard`, `deep` or null                                                 | No           |
  | `headline`                  | object                                                                              | No           |
  | `webUrl`                    | string                                                                              | No           |
  | `suggestedPollAfterSeconds` | integer or null                                                                     | No           |
  | `baselineRunId`             | string or null                                                                      | Yes          |
  | `open`                      | object                                                                              | Yes          |
  | `findingCount`              | integer                                                                             | Yes          |
  | `progress`                  | object or null                                                                      | Yes          |
  | `coverage`                  | object                                                                              | Yes          |
  | `caveats`                   | list of string                                                                      | Yes          |
  | `outcome`                   | object or null                                                                      | No           |
  | `exposureCheck`             | object or null                                                                      | No           |

  **POST /projects/\{projectId}/deep**

  Start a release's Deep scan with a CI key made for this site with Deep allowed.

  * Permission: `deep`
  * Answers 201 when it works

  **Body**

  | Field            | Type   | Required |
  | ---------------- | ------ | -------- |
  | `idempotencyKey` | string | Yes      |

  **data**

  | Field                       | Type                                                                                | Always there |
  | --------------------------- | ----------------------------------------------------------------------------------- | ------------ |
  | `id`                        | string                                                                              | Yes          |
  | `kind`                      | `pulse`, `box` (Deep, legacy name)                                                  | Yes          |
  | `projectId`                 | string                                                                              | Yes          |
  | `target`                    | string                                                                              | Yes          |
  | `status`                    | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | Yes          |
  | `mode`                      | `autonomous`, `authenticated`, `active` or null                                     | Yes          |
  | `createdAt`                 | string or null                                                                      | Yes          |
  | `finishedAt`                | string or null                                                                      | Yes          |
  | `webPath`                   | string                                                                              | Yes          |
  | `assessmentLevel`           | `pulse`, `standard`, `deep` or null                                                 | No           |
  | `headline`                  | object                                                                              | No           |
  | `webUrl`                    | string                                                                              | No           |
  | `suggestedPollAfterSeconds` | integer or null                                                                     | No           |
  | `baselineRunId`             | string or null                                                                      | Yes          |
  | `open`                      | object                                                                              | Yes          |
  | `findingCount`              | integer                                                                             | Yes          |
  | `progress`                  | object or null                                                                      | Yes          |
  | `coverage`                  | object                                                                              | Yes          |
  | `caveats`                   | list of string                                                                      | Yes          |
  | `outcome`                   | object or null                                                                      | No           |
  | `exposureCheck`             | object or null                                                                      | No           |

  **GET /runs**

  Pulse and Deep scans, newest first.

  * Permission: `read`

  **Query**

  | Field             | Type                                                                                | Required |
  | ----------------- | ----------------------------------------------------------------------------------- | -------- |
  | `projectId`       | string                                                                              | No       |
  | `kind`            | `pulse`, `box` (Deep, legacy name)                                                  | No       |
  | `assessmentLevel` | `pulse`, `standard`, `deep`                                                         | No       |
  | `status`          | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | No       |
  | `limit`           | integer                                                                             | No       |

  **Each item in data**

  | Field                       | Type                                                                                | Always there |
  | --------------------------- | ----------------------------------------------------------------------------------- | ------------ |
  | `id`                        | string                                                                              | Yes          |
  | `kind`                      | `pulse`, `box` (Deep, legacy name)                                                  | Yes          |
  | `projectId`                 | string                                                                              | Yes          |
  | `target`                    | string                                                                              | Yes          |
  | `status`                    | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | Yes          |
  | `mode`                      | `autonomous`, `authenticated`, `active` or null                                     | Yes          |
  | `createdAt`                 | string or null                                                                      | Yes          |
  | `finishedAt`                | string or null                                                                      | Yes          |
  | `webPath`                   | string                                                                              | Yes          |
  | `assessmentLevel`           | `pulse`, `standard`, `deep` or null                                                 | No           |
  | `headline`                  | object                                                                              | No           |
  | `webUrl`                    | string                                                                              | No           |
  | `suggestedPollAfterSeconds` | integer or null                                                                     | No           |

  **GET /runs/\{runId}**

  One run with its headline and counts.

  * Permission: `read`

  **data**

  | Field                       | Type                                                                                | Always there |
  | --------------------------- | ----------------------------------------------------------------------------------- | ------------ |
  | `id`                        | string                                                                              | Yes          |
  | `kind`                      | `pulse`, `box` (Deep, legacy name)                                                  | Yes          |
  | `projectId`                 | string                                                                              | Yes          |
  | `target`                    | string                                                                              | Yes          |
  | `status`                    | `queued`, `running`, `cancelling`, `succeeded`, `incomplete`, `failed`, `cancelled` | Yes          |
  | `mode`                      | `autonomous`, `authenticated`, `active` or null                                     | Yes          |
  | `createdAt`                 | string or null                                                                      | Yes          |
  | `finishedAt`                | string or null                                                                      | Yes          |
  | `webPath`                   | string                                                                              | Yes          |
  | `assessmentLevel`           | `pulse`, `standard`, `deep` or null                                                 | No           |
  | `headline`                  | object                                                                              | No           |
  | `webUrl`                    | string                                                                              | No           |
  | `suggestedPollAfterSeconds` | integer or null                                                                     | No           |
  | `baselineRunId`             | string or null                                                                      | Yes          |
  | `open`                      | object                                                                              | Yes          |
  | `findingCount`              | integer                                                                             | Yes          |
  | `progress`                  | object or null                                                                      | Yes          |
  | `coverage`                  | object                                                                              | Yes          |
  | `caveats`                   | list of string                                                                      | Yes          |
  | `outcome`                   | object or null                                                                      | No           |
  | `exposureCheck`             | object or null                                                                      | No           |

  **GET /runs/\{runId}/findings**

  Findings of a run.

  * Permission: `read`

  **Query**

  | Field      | Type                                          | Required |
  | ---------- | --------------------------------------------- | -------- |
  | `severity` | `critical`, `high`, `medium`, `low`, `info`   | No       |
  | `state`    | `attention`, `information`, `unknown`, `pass` | No       |
  | `all`      | `true`, `false`                               | No       |

  **Each item in data**

  | Field            | Type                                                  | Always there |
  | ---------------- | ----------------------------------------------------- | ------------ |
  | `id`             | string                                                | Yes          |
  | `code`           | string                                                | No           |
  | `runId`          | string                                                | Yes          |
  | `kind`           | `pulse`, `box` (Deep, legacy name)                    | Yes          |
  | `severity`       | `critical`, `high`, `medium`, `low`, `info`           | Yes          |
  | `state`          | `attention`, `information`, `unknown`, `pass`         | Yes          |
  | `category`       | string                                                | Yes          |
  | `title`          | string                                                | Yes          |
  | `meaning`        | string                                                | Yes          |
  | `fix`            | string or null                                        | Yes          |
  | `confidence`     | string                                                | Yes          |
  | `evidence`       | list of string                                        | Yes          |
  | `sources`        | list of string                                        | Yes          |
  | `steps`          | list of string                                        | Yes          |
  | `webPath`        | string                                                | Yes          |
  | `webUrl`         | string                                                | No           |
  | `verdict`        | `confirmed`, `needs_review`, `not_actionable` or null | No           |
  | `certainty`      | `high`, `medium`, `low` or null                       | No           |
  | `exploitability` | `direct`, `conditional`, `hygiene`, `none` or null    | No           |
  | `proof`          | object or null                                        | No           |
  | `proofGap`       | string or null                                        | No           |
  | `urgency`        | `now`, `week`, `later`, `none`                        | No           |
  | `howSure`        | `confirmed`, `likely`, `possible` or null             | No           |

  **GET /runs/\{runId}/findings/\{findingId}**

  One finding with its redacted evidence.

  * Permission: `read`

  **data**

  | Field            | Type                                                  | Always there |
  | ---------------- | ----------------------------------------------------- | ------------ |
  | `id`             | string                                                | Yes          |
  | `code`           | string                                                | No           |
  | `runId`          | string                                                | Yes          |
  | `kind`           | `pulse`, `box` (Deep, legacy name)                    | Yes          |
  | `severity`       | `critical`, `high`, `medium`, `low`, `info`           | Yes          |
  | `state`          | `attention`, `information`, `unknown`, `pass`         | Yes          |
  | `category`       | string                                                | Yes          |
  | `title`          | string                                                | Yes          |
  | `meaning`        | string                                                | Yes          |
  | `fix`            | string or null                                        | Yes          |
  | `confidence`     | string                                                | Yes          |
  | `evidence`       | list of string                                        | Yes          |
  | `sources`        | list of string                                        | Yes          |
  | `steps`          | list of string                                        | Yes          |
  | `webPath`        | string                                                | Yes          |
  | `webUrl`         | string                                                | No           |
  | `verdict`        | `confirmed`, `needs_review`, `not_actionable` or null | No           |
  | `certainty`      | `high`, `medium`, `low` or null                       | No           |
  | `exploitability` | `direct`, `conditional`, `hygiene`, `none` or null    | No           |
  | `proof`          | object or null                                        | No           |
  | `proofGap`       | string or null                                        | No           |
  | `urgency`        | `now`, `week`, `later`, `none`                        | No           |
  | `howSure`        | `confirmed`, `likely`, `possible` or null             | No           |

  **GET /runs/\{runId}/repair-brief**

  A run's fixes as one Markdown brief.

  * Permission: `read`

  **Query**

  | Field       | Type                                                                                      | Required |
  | ----------- | ----------------------------------------------------------------------------------------- | -------- |
  | `findingId` | string                                                                                    | No       |
  | `agent`     | `claude-code`, `codex`, `cursor`, `vscode`, `opencode`, `lovable`, `bolt`, `replit`, `v0` | No       |

  **data**

  | Field        | Type           | Always there |
  | ------------ | -------------- | ------------ |
  | `runId`      | string         | Yes          |
  | `findingIds` | list of string | Yes          |
  | `saved`      | boolean        | Yes          |
  | `markdown`   | string         | Yes          |
  | `webUrl`     | string         | No           |

  **GET /runs/\{runId}/comparison**

  What changed between a run and the one before it.

  * Permission: `read`

  **data**

  | Field           | Type           | Always there |
  | --------------- | -------------- | ------------ |
  | `runId`         | string         | Yes          |
  | `baselineRunId` | string         | Yes          |
  | `error`         | string or null | Yes          |
  | `changes`       | list of object | Yes          |
  | `webUrl`        | string         | No           |
</details>