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

Authentication

View .md

Every call to the zkao API uses a project API token. A token belongs to exactly one project. It carries a set of scopes and can be narrowed further to some repositories, an expiry date, and a spend limit.

There are two ways to get one: approve the CLI in your browser, or create a token by hand.

Terminal window
zkao login

The CLI starts a device authorization flow:

  1. It prints a URL and a short code, and opens the URL in your browser.
  2. On the Authorize a CLI page, you confirm that the code matches the one in your terminal.
  3. You pick a project, review the requested scopes, and approve. You can also set a repository allowlist, an expiry, and a spend limit there.
  4. The CLI receives the token and saves it to ~/.zkao/config.json.

Only approve a login you started yourself. Approving mints a real token for the project you select.

By default the CLI requests read, scans:launch, and findings:write. The approval page pre-ticks them, and the approver can change them. To request other scopes, pass --scope:

Terminal window
zkao login --scope read guidance:write

zkao login --project <projectId> preselects a project on the approval page. You can approve several projects in one login. Each gets its own saved token, and the first becomes the active project.

Use --no-browser to print the URL without opening a browser.

A bare zkao login blocks until someone approves in the browser. That can take minutes and trip a command timeout. Non-interactive callers split it in two:

Terminal window
zkao login --no-wait --no-browser # prints the URL and code, then exits
# a person opens the URL and approves
zkao login --resume # polls once and exits

Repeat zkao login --resume until it prints Authorized. Still waiting for approval means nobody has approved yet. --resume --timeout <seconds> waits up to that long instead of polling once.

Several logins can be pending at once. --resume finishes whichever is approved first and keeps the rest. A pending login expires after a while. Start a new one when --resume reports that it expired.

A project admin can create a token under Project Settings → Integrations in the zkao app. Choose a name, the scopes, and optionally a repository allowlist, an expiry, and a spend limit.

The token is shown once, together with the project id. It looks like this:

zkao_proj_<keyId>_<secret>

Store it as a secret. zkao cannot show it again.

Hand it to the CLI or SDK through environment variables:

Terminal window
export ZKAO_API_TOKEN=zkao_proj_...
export ZKAO_PROJECT_ID=<projectId>

Or save it to the config file:

Terminal window
zkao config set --token zkao_proj_... --project <projectId>

A token carries a subset of these scopes:

Scope Allows
read List and read repositories, scans, findings, presets, and billing.
findings:write Comment on findings, change severity and resolution, pin a note.
guidance:write Update a repository’s guidance and manage its audit areas.
scans:launch Launch and cancel scans.
publish Publish a finding or a scan as a public page.

A call that needs a scope the token lacks returns 403 forbidden.

  • Repository allowlist. The token only sees the listed repositories. An empty list means every repository in the project.
  • Expiry. The token stops working after this date.
  • Spend limit. The most credits the token may commit to scans in the current billing period. A launch past the limit returns 429.

zkao whoami (or GET /token) returns the token’s project, organization, scopes, allowlist, expiry, and spend limit. Any valid token can call it, whatever its scopes.

Status Meaning
401 unauthorized The token is missing, malformed, expired, or revoked. The response does not say which.
403 forbidden The token is valid but lacks the scope this call needs.
404 not_found The resource is outside the token’s project or repository allowlist. zkao does not confirm that it exists.

A token used against another project’s id gets a 404 whose message names the token’s own project.

Send the token only in the Authorization: Bearer header. A token passed in the query string is rejected with 400.

The CLI writes ~/.zkao/config.json with owner-only permissions. It keeps one token per project, so logging in to a second project does not drop the first.

Terminal window
zkao config show # active settings and every saved project (tokens masked)
zkao config use <projectId> # switch the active project

Settings resolve in this order, highest first:

  1. Flags: --token, --project, --base-url.
  2. Environment: ZKAO_API_TOKEN, ZKAO_PROJECT_ID, ZKAO_URL.
  3. The saved config file.

Revoke a token under Project Settings → Integrations. It stops working at once. A token also stops working when its project or organization is archived.