API overview
REST, MCP and the CLI over one API: what they cover and the rules they share.
V12's API has three ways in: REST for scripts and services, an MCP server for AI assistants, and the v12 command-line tool. All three cover findings, runs and their guest links, context documents, repositories, Steers and members. REST offers all 31 operations; MCP offers 28 of them as tools.
API quickstart
Create an API key and make a REST call.
Connect an MCP client
Connect an AI assistant to https://v12.sh/api/mcp.
CLI
The v12 command, for terminals and CI.
Recipes
Triage findings and start runs within a price limit.
REST reference
Every endpoint, scope and error.
Authentication
Send Authorization: Bearer <token> on every request, with an API key or OAuth access token. See Authentication and permissions.
Addresses
A token acts on one workspace, an organization or your personal workspace. Every REST endpoint except GET /api/v2/me sits under https://v12.sh/api/v2/orgs/<org>, where <org> is that workspace's slug. Short paths in these docs, such as POST /runs, omit that prefix.
- Get the slug from
organization.sluginGET https://v12.sh/api/v2/me, open to any valid token, or the app's address bar:v12.sh/<org>/…. - Another workspace's slug gets 404
not_found, even for an organization you belong to. So does a path without/orgs/<org>. - A slug from before the workspace was renamed still works.
- MCP takes no slug: a connection acts on its token's workspace.
Address things as the app shows them:
- Finding: key
F-42or number42. - Run: number in the workspace,
12. - Repository: slug or full name
owner/name,acme/api. A repository V12 hosts goes by its slug,v12/api. - Assignee:
me,none, or a member's email or username. - Steer: slug,
auth. - Context document: id, a UUID.
- Guest link: number within its run, from 1.
PATCH /runs/12/links/2changes link 2 of run 12.
Responses use the same addresses, and findings, runs, repositories and Steers carry a webUrl that opens them in the app.
Positions
Operations that read code state take an optional at, default when left out:
at | Position |
|---|---|
default | Head of the default branch V12 uses for the repository |
branch:<name> | Head of a branch |
pr:<number> | Head of a pull request |
commit:<sha> | A commit, by its full 40-character SHA |
Responses report the evaluated commit in position.at, pinned to its SHA: branch:main@<sha>. Send it back to stay on that commit after the branch moves.
An unresolvable position gets 409 position_unavailable, with details.reason such as unknown-branch or unknown-pull-request.
Pagination
Lists return items and nextCursor. For the next page, repeat the request with the same filters and cursor set to nextCursor, until it is null. A cursor sent with different filters gets 400 invalid_request.
Where a list takes limit, it sets the page size: 1 to 100, default 50.
Safe retries
Run starts and comments take an idempotency key, Idempotency-Key in REST or requestId in MCP. A retry with the same key and request returns the original result. A replayed start adds replayed: true, shows the run as it was when it started, and doesn't count toward the run-start limit. Reusing a key for a different request gets 409 idempotency_key_reused. POST /runs needs a key or an estimate's quote. The CLI sends a key for you.
Finding changes and repository adds are safe to repeat without a key: they leave findings already in the requested state unchanged and list them in skipped, and return an existing repository with added: false.
Errors and limits
Every error has the same JSON body, with a requestId matching the X-Request-Id header. See the error reference.
Per-user request budgets appear in X-RateLimit-* headers on every response. See Rate limits.
/api/v1 is retired and answers 410 api_version_retired. Use /api/v2 and CLI version 1.0.