V12 Docs
Public API

Public API

Authenticate with personal access tokens or OAuth, and connect to V12's REST API or MCP server.

V12 exposes a REST API at /api/v1/* and a remote MCP server at /api/mcp so you can run audits, read findings, and triage results from your own tools and scripts.

Authentication

Authenticated API requests take a Bearer token in the Authorization header:

curl -H 'Authorization: Bearer <token>' https://v12.sh/api/v1/me

Two token kinds work on authenticated endpoints:

  • Personal access tokens (v12p_*) — created at Settings → Developer for the currently selected organization. Shown once on creation. PATs do not expire by default.
  • OAuth access tokens (v12a_*) — issued via the OAuth flow. Access tokens last 1 hour; refresh tokens (when issued) last 30 days. The consent flow binds them to the organization you had selected when you approved the client.

Each token operates inside exactly one account context. If you need access to two orgs, create two PATs or authorize the OAuth client once per org.

OAuth

Use OAuth when a third-party tool needs to act on your behalf. Paste the V12 server URL into the tool and complete the sign-in prompt — the tool handles the token exchange itself. Claude Desktop, Cursor, Codex, VS Code, and Windsurf are known to work end-to-end. Manage authorized apps at Settings → Developer.

Implementing your own OAuth client

If you're building the client side yourself:

  1. Read the metadata from GET /.well-known/oauth-authorization-server.

  2. Register at POST /api/oauth/register (Dynamic Client Registration, RFC 7591).

  3. Send the user to /oauth/authorize:

    /oauth/authorize
      ?response_type=code
      &client_id=<client_id>
      &redirect_uri=<redirect_uri>
      &state=<random>
      &code_challenge=<S256(verifier)>
      &code_challenge_method=S256
      &scope=runs:read+runs:write
  4. Exchange the returned code at POST /api/oauth/token (grant_type=authorization_code).

  5. Refresh with grant_type=refresh_token only if the client registered with the explicit refresh_token grant. DCR clients default to authorization-code-only access.

Scopes

ScopeLabelDescription
runs:readView runsList runs, read reports and findings.
runs:writeCreate runsStart new audit runs and upload source archives. Consumes credits.
runs:manageManage runsCancel runs you own through the public API and MCP.
findings:writeEdit findingsChange finding status, add comments, and update triage decisions.
repos:readView repositoriesList GitHub repositories connected to V12 for your account.
user:readView profileRead your account information and credit balance.

New tokens default to runs:read, user:read, and repos:read. Writes (runs:write, runs:manage, findings:write) are opt-in via the scope picker in Settings → Developer.

Vocabulary

Severity (severity filter values, PATCH payloads, finding fields): critical, high, medium, low, info, qa.

Validity (validity filter values, PATCH payloads, finding fields): valid, invalid (false positive), unreviewed, acknowledged (real but accepted).

Run states (state field on run objects): queued, running, completed, failed, cancelled. Terminal states (no further transitions): completed, failed, cancelled.

Rate limits

Per-user buckets. Hitting a limit returns 429 Too Many Requests with a Retry-After header.

BucketLimitWindow
Writes (runs:write)201 hour
Management (runs:manage)301 hour
Finding writes (findings:write)601 hour
Reads3001 minute
MCP protocol requests1201 minute