Skip to content
These docs describe staging.zkao.io and the @zksecurity/zkao-cli@next release. For production, see docs.zkao.io.

Launch a scan

POST
/projects/{projectId}/scans
curl --request POST \
--url https://zkao.io/api/v1/projects/example/scans \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "repositoryId": "example", "creditBudget": 1, "presetRef": "example", "branch": "example", "commitHash": "example", "commitMessage": "example", "baseCommit": "example", "auditAreaKeys": [ "example" ], "guidance": "example" }'

Requires scope: scans:launch. Reserves creditBudget credits from the project balance. The repo must be in the token’s allowlist (when set) and ACTIVE. Discover valid presetRef values via /scan-presets. Each scan type runs a fixed set of flows. Per-token spend limits are enforced, and the project must have enough prepaid credits to cover the budget (otherwise 402).

A repository added moments ago may still be analyzing, in which case this returns 409 repository_initializing. Wait for its readiness to be ready in GET /repositories and launch again.

A diff scan preset audits only the change from baseCommit to the scanned commit, and requires baseCommit. Every other preset refuses it. A malformed, unknown, or misplaced base is a 400 with code diff_base_required, diff_base_not_allowed, or diff_base_invalid. A diff scan also needs a change to audit (otherwise 422).

projectId
required
string
Media typeapplication/json
object
repositoryId
required
string
creditBudget

Max budget for the scan, in credits. Reserved at launch. Omit it to launch at the budget zkao recommends for this scan type and scope on this repository: sized from what past scans of it spent, half again the last budget when that scan ran short of it, or the scan type’s minimum on the first.

integer
>= 1
presetRef

A preset ref from /scan-presets. Defaults to the first active preset.

string
branch

Branch to scan (resolved to its head commit server-side). Ignored if commitHash is set.

string | null
commitHash

Pin a specific commit SHA (7-40 hex chars).

string | null
commitMessage
string | null
baseCommit

What a diff scan’s change is measured from: a commit SHA, branch, or tag. Required by a diff scan preset and refused by every other. The scan records the merge base of this and the scanned commit.

string | null
auditAreaKeys

Area keys from /audit-areas to scope this scan to. Omit or send an empty array to scan the whole repository. A key the repository’s current map no longer names fails the launch rather than being dropped, so a scan budgeted for one subsystem never silently runs against everything.

Array<string>
guidance

Guidance for this scan only, replacing the repository’s configured guidance layer (it is still layered over any committed zkao.md). Omit the field to inherit the repository’s guidance; send null to scan with no guidance layer.

string | null
<= 100000 characters
Examplegenerated
{
"repositoryId": "example",
"creditBudget": 1,
"presetRef": "example",
"branch": "example",
"commitHash": "example",
"commitMessage": "example",
"baseCommit": "example",
"auditAreaKeys": [
"example"
],
"guidance": "example"
}

Scan accepted (queued)

Media typeapplication/json
object
scanId
required
string
queued
required
boolean
creditBudget
required

The budget the scan was launched with, in credits.

integer
Examplegenerated
{
"scanId": "example",
"queued": true,
"creditBudget": 1
}

Invalid request

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

Missing, malformed, expired, or revoked token

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

The project does not have enough prepaid credits to cover the scan budget. Top up credits and retry. (code insufficient_credits)

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

The token lacks the required scope

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

Resource not in this token’s project or repo allowlist

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

The repository is still being analyzed and cannot be scanned yet. The same request succeeds once GET /repositories reports its readiness as ready. (code repository_initializing)

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

The diff scan has nothing to audit. Code diff_empty: the base and the scanned commit have no change between them.

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}

Rate limited. Either the token’s spend limit for the current period is reached (on launch), or the token is sending too many requests. Wait the number of seconds in the Retry-After header before retrying.

Media typeapplication/json
object
error
required
object
code
required
string
Allowed values: unauthorized forbidden not_found bad_request conflict insufficient_credits repository_initializing diff_base_required diff_base_not_allowed diff_base_invalid diff_empty rate_limited internal
message
required
string
Example
{
"error": {
"code": "unauthorized"
}
}
Retry-After
integer

Seconds to wait before retrying.