TypeScript SDK
@zksecurity/zkao-sdk is a typed client for the zkao API.
Its types are generated from the OpenAPI spec, so every request and response is checked at compile time.
It runs on Node 18 or later and in any runtime with fetch.
npm install @zksecurity/zkao-sdkCreate a client
Section titled “Create a client”import { ZkaoClient } from "@zksecurity/zkao-sdk";
const zkao = new ZkaoClient({ token: process.env.ZKAO_API_TOKEN!, projectId: process.env.ZKAO_PROJECT_ID!,});A client is bound to one project. Every call is scoped to it.
| Option | Type | Meaning |
|---|---|---|
token |
string |
Project API token, zkao_proj_<keyId>_<secret>. Required. |
projectId |
string |
Id of the project the token belongs to. Required. |
baseUrl |
string |
API base URL, used exactly as given. Optional. |
fetch |
typeof fetch |
Custom fetch, for tests or proxies. Optional. |
Base URL
Section titled “Base URL”The client picks its base URL in this order:
- The
baseUrloption, used verbatim. - The
ZKAO_URLenvironment variable, normalized. - Production,
https://zkao.io/api/v1(exported asDEFAULT_BASE_URL).
ZKAO_URL accepts a bare host, an origin, or a full API URL.
A bare host gets https://, except localhost, which gets http://.
/api/v1 is appended unless the value already ends in /api/v<n>.
So staging.zkao.io becomes https://staging.zkao.io/api/v1.
A plain http:// URL to a non-local host logs a warning, since the token would travel unencrypted.
Two helpers expose this logic:
| Function | Meaning |
|---|---|
normalizeBaseUrl(value: string): string |
Turn a host, origin, or URL into a full API base URL. Throws on an empty or invalid value. |
resolveBaseUrlFromEnv(env?): string | undefined |
Read and normalize ZKAO_URL, from env or process.env. Returns undefined when unset. |
Methods
Section titled “Methods”Every method returns a promise. A non-2xx response rejects with ZkaoApiError.
The required token scope is noted where a method needs more than read.
Each method links to its endpoint in the API reference.
| Method | Returns | Meaning |
|---|---|---|
getTokenInfo() |
TokenInfo |
The token’s scopes, repository allowlist, expiry, spend limit, and its project and organization. API |
The standalone getTokenInfo({ token, baseUrl?, fetch? }) does the same without a project id.
Use it to find which project a token belongs to.
Repositories
Section titled “Repositories”| Method | Returns | Meaning |
|---|---|---|
listRepositories() |
Repository[] |
The project’s repositories, or the token’s allowlisted subset. API |
waitForRepositoryReady(repositoryId, opts?) |
Repository |
Block until the repository’s readiness is ready. See Polling helpers. |
Guidance
Section titled “Guidance”| Method | Returns | Meaning |
|---|---|---|
getRepositoryGuidance(repositoryId) |
RepositoryGuidance |
Read a repository’s guidance. API |
setRepositoryGuidance(repositoryId, content, opts?) |
SetGuidanceResult |
Set guidance, or clear it with null. Needs guidance:write. API |
setRepositoryGuidance takes { expectedContent?: string | null }.
Pass the content you last read, or null if it was cleared.
The write then fails with 409 conflict if someone changed it in between.
Writing the content already stored is a no-op that returns unchanged: true.
const current = await zkao.getRepositoryGuidance(repoId);await zkao.setRepositoryGuidance(repoId, `${current.content ?? ""}\nNew note.`, { expectedContent: current.content,});Audit areas
Section titled “Audit areas”| Method | Returns | Meaning |
|---|---|---|
listAuditAreas(repositoryId, opts?) |
AuditAreaList |
A repository’s audit areas. opts.branch picks the branch whose map gives sizes. API |
createAuditArea(repositoryId, name, description?) |
AuditArea |
Add a custom area. The key is derived from the name. Needs guidance:write. API |
deleteAuditArea(repositoryId, areaKey) |
DeleteAuditAreaResult |
Delete a custom area. An area a scan’s map named is refused with 409. Needs guidance:write. API |
| Method | Returns | Meaning |
|---|---|---|
listScans(opts?) |
Paginated<Scan> |
Scans, most recent first. opts takes page and limit (max 100). API |
getScan(scanId) |
ScanDetail |
One scan’s status and detail. API |
launchScan(body) |
LaunchScanResult |
Launch a scan. Needs scans:launch. API |
waitForScan(scanId, opts?) |
ScanDetail |
Block until the scan is COMPLETED, FAILED, or CANCELLED. See Polling helpers. |
cancelScan(scanId) |
CancelScanResult |
Cancel a running or queued scan and release its unspent credits. Needs scans:launch. API |
publishScan(scanId, opts?) |
PublishArtifactResult |
Publish a completed scan as a public page. opts.withPassword adds a generated password. Needs publish. API |
launchScan takes a LaunchScanRequest:
| Field | Meaning |
|---|---|
repositoryId |
Repository to scan. Required. |
creditBudget |
Maximum budget in credits. Omit it to use the budget zkao recommends. |
presetRef |
Preset ref from listScanPresets(). Defaults to the first active preset. |
branch |
Branch to scan. Ignored when commitHash is set. |
commitHash |
Commit to scan. |
commitMessage |
Commit message to record. |
baseCommit |
Base commit, branch, or tag of a diff scan. Required by a diff preset, refused by others. |
auditAreaKeys |
Area keys to scope the scan to. Omit to scan the whole repository. |
guidance |
Guidance for this scan only, replacing the repository’s. |
It resolves to { scanId, queued, creditBudget }.
See Scans and Diff scans.
Findings
Section titled “Findings”findingId accepts the full id or the ZK- label shown on the finding page.
| Method | Returns | Meaning |
|---|---|---|
listFindings(opts?) |
Paginated<Finding> |
Findings across the project. opts takes scanId, page, and limit. API |
getFinding(findingId) |
FindingDetail |
Full detail, including the proof of concept and notes. API |
addFindingNote(findingId, content) |
{ noteId, findingId } |
Add a comment. Needs findings:write. API |
pinFindingNote(findingId, noteId, kind?) |
{ findingId, noteId } |
Pin a note as the finding’s resolution note. kind is "resolution". Needs findings:write. API |
setFindingSeverity(findingId, severity) |
{ findingId, userSeverity, effectiveSeverity } |
Override severity, or clear the override with null. Needs findings:write. API |
setFindingResolution(findingId, status, opts?) |
{ findingId, resolutionStatus } |
Change the resolution status. Needs findings:write. API |
publishFinding(findingId, opts?) |
PublishArtifactResult |
Publish a finding as a public page. opts takes noteId and withPassword. Needs publish. API |
setFindingResolution takes { note?: ChangeNote; reason?: ResolutionReason }.
note is { content } for a new comment or { existingNoteId } to reuse one.
reason is a catalog code valid for the status. note wins when both are given.
Both are ignored for NOT_STARTED and IN_PROGRESS.
See Triage findings for the codes.
await zkao.setFindingResolution(findingId, "WONT_FIX", { reason: "risk_accepted" });Presets
Section titled “Presets”| Method | Returns | Meaning |
|---|---|---|
listScanPresets() |
ScanPreset[] |
Presets the project can launch. Pass a ref as presetRef. API |
Billing
Section titled “Billing”The balance belongs to the project’s organization and is shared by all its projects. Usage and the monthly summary count only movements attributed to this project. See Credits.
| Method | Returns | Meaning |
|---|---|---|
getBillingBalance() |
BillingBalance |
balanceCredits, reservedCredits held by active scans, and availableCredits for new scans. API |
getBillingUsage(opts?) |
BillingUsage |
Ledger movements with signed credits. opts takes from, to, and limit. Defaults to the last 30 days. API |
getBillingSummary(opts?) |
UsageMonthSummary[] |
Credits spent and purchased per UTC month, newest first. opts.months sets how many. API |
Polling helpers
Section titled “Polling helpers”Scans take minutes, and a tight polling loop is rejected with 429.
The helpers back off exponentially with jitter, honor the server’s Retry-After, and treat a 429 as a signal to slow down.
const { scanId } = await zkao.launchScan({ repositoryId, presetRef });const scan = await zkao.waitForScan(scanId, { onPoll: (s) => console.log(s.status),});if (scan.status !== "COMPLETED") throw new Error(`Scan ended ${scan.status}`);waitForScan(scanId, opts) resolves with the final detail whatever the final status is.
| Option | Default | Meaning |
|---|---|---|
intervalMs |
5000 |
First delay between polls. Grows by 1.5x each poll. |
maxIntervalMs |
30000 |
Cap on the delay. |
timeoutMs |
1 hour | Give up and throw after this long. |
signal |
none | AbortSignal that stops the wait. Rejects with the abort reason. |
onPoll |
none | Called with the latest ScanDetail on each poll that is not final. |
waitForRepositoryReady(repositoryId, opts) takes the same options except onPoll, with a default timeout of 30 minutes.
It throws if the repository is not in the project or the token’s allowlist.
Call it between adding a repository and launching its first scan.
isTerminalScanStatus(status) and TERMINAL_SCAN_STATUSES tell whether a status is final, for your own loops.
Errors
Section titled “Errors”Every non-2xx response throws ZkaoApiError.
| Property | Meaning |
|---|---|
status |
HTTP status. |
code |
Machine-readable error code from the response, such as insufficient_credits. |
message |
Human-readable message. |
Branch on code, not on the message.
import { ZkaoApiError } from "@zksecurity/zkao-sdk";
try { await zkao.launchScan({ repositoryId, presetRef });} catch (err) { if (err instanceof ZkaoApiError && err.code === "repository_initializing") { await zkao.waitForRepositoryReady(repositoryId); } else if (err instanceof ZkaoApiError && err.code === "insufficient_credits") { console.error("Not enough credits for this budget."); } else { throw err; }}The full list of codes is in API conventions.
Timeouts and aborts in the polling helpers throw a plain Error, not ZkaoApiError.
The package exports a named type for each API object.
| Type | Meaning |
|---|---|
Repository, RepositoryGuidance, SetGuidanceResult |
Repositories and their guidance. |
Scan, ScanDetail, ScanStatus, ScanPreset |
Scans, their status, and presets. |
LaunchScanRequest, LaunchScanResult, CancelScanResult |
Launch and cancel bodies and results. |
Finding, FindingDetail, FindingNote, ChangeNote |
Findings and their notes. |
Severity, ResolutionStatus, ResolutionReason, TriageStatus |
Finding enums. |
PublishArtifactResult |
Result of publishing a scan or finding. |
TokenInfo |
The calling token and its project. |
BillingBalance, BillingUsage, UsageEvent, UsageEventType, BillingSummary, UsageMonthSummary |
Credit balance and ledger. |
Paginated<T> |
{ items, page, limit, total } for list endpoints. |
ZkaoClientOptions, WaitForScanOptions, WaitForRepositoryReadyOptions |
Option objects. |
The raw generated types are exported as components and paths.
Any schema without a named export is available as components["schemas"]["<Name>"], for example components["schemas"]["AuditArea"].

