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.
- Connecting an IDE or agent → MCP server
- Calling from scripts or CI → REST API
- Full schema →
/api/v1/openapi.json
Authentication
Authenticated API requests take a Bearer token in the Authorization header:
curl -H 'Authorization: Bearer <token>' https://v12.sh/api/v1/meTwo 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:
-
Read the metadata from
GET /.well-known/oauth-authorization-server. -
Register at
POST /api/oauth/register(Dynamic Client Registration, RFC 7591). -
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 -
Exchange the returned code at
POST /api/oauth/token(grant_type=authorization_code). -
Refresh with
grant_type=refresh_tokenonly if the client registered with the explicitrefresh_tokengrant. 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
Per-user buckets. Hitting a limit returns 429 Too Many Requests with a Retry-After header.
| Bucket | Limit | Window |
|---|---|---|
Writes (runs:write) | 20 | 1 hour |
Management (runs:manage) | 30 | 1 hour |
Finding writes (findings:write) | 60 | 1 hour |
| Reads | 300 | 1 minute |
| MCP protocol requests | 120 | 1 minute |