Book a call Start a run

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:

Terminal window
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 don’t 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.

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

Scope Label Description
runs:read View runs List runs, read reports and findings
runs:write Create runs Start new audit runs and upload source archives. Consumes credits.
runs:manage Manage runs Cancel runs you own through the public API and MCP
findings:write Edit findings Change finding status, add comments, and update triage decisions
repos:read View repositories List GitHub repositories connected to V12 for your account
user:read View profile Read 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

Most limits are per-user buckets: one budget per account, shared across REST, MCP and the CLI, and independent of which organization your token is bound to. The MCP transport adds one per-IP bucket that is charged before authentication, so callers behind a shared egress IP—an office NAT, a CI runner—share that budget with each other.

Hitting a limit returns 429 Too Many Requests with a Retry-After header in seconds.

Bucket Limit Window Keyed by Charged by
reads 1200 1 minute user Metadata reads: profile, run list and detail, findings list, comments, context documents, export status, and the equivalent MCP tools and resources
reads:artifact 300 1 minute user Stored artifacts: run report, report.md, finding detail, PoC, and fix
reads:github 300 1 minute user Repository listing (GET /api/v1/repos, v12_repos), which runs on your own GitHub REST budget
findings:write 120 1 minute user Triage updates and finding comments
runs:manage 60 1 minute user Cancelling and sharing runs
runs:write 20 1 hour user Run creation, ZIP and context uploads, archiving context documents
runs:estimate 30 1 hour user Cost estimates
exports:create 100 1 hour user Finding-export creation
mcp:protocol 1500 1 minute user Every /api/mcp request that passes the browser-origin check and authenticates, on top of any tool or resource bucket the request goes on to dispatch. A rejected origin or an invalid token exits before this counter
mcp:protocol:ip 3000 1 minute client IP Every /api/mcp request, before the origin check and before authentication. The one bucket no account is exempt from

Reads are split by what they cost us, not by which endpoint you called: reads covers work our own database answers, while reads:artifact and reads:github cover reads that pull bytes out of object storage or fan out to GitHub. Nothing got tighter in the split—those two keep the ceiling that used to apply to all reads.

Type to search.