openapi: 3.2.0 info: title: V12 Documents API version: 2.0.0 description: Findings, runs and context documents of one V12 organization. Every path but /me sits under /orgs/{org}, where {org} is the organization's slug (GET /me returns it); a token reaches only its own organization, and any other slug answers 404. servers: - url: https://v12.sh/api/v2 tags: - name: Documents paths: /orgs/{org}/documents/uploads: post: operationId: requestDocumentUpload summary: Request a document upload slot description: 'Get a URL to PUT a file to (up to 50 MiB, valid 10 minutes), then call create_document with the slot id. Types: PDF, Markdown, text, JSON, DOCX, CSV.' tags: - Documents security: - bearer: [] - oauth2: - runs:write x-mcp-tool: request_document_upload parameters: - name: org in: path required: true description: Organization slug; must be the token's organization. schema: type: string requestBody: required: true content: application/json: schema: type: object additionalProperties: false properties: filename: type: string minLength: 1 maxLength: 255 contentType: type: string minLength: 1 maxLength: 255 description: MIME type of the file. required: - filename - contentType responses: '201': description: Request a document upload slot content: application/json: schema: type: object properties: upload: type: object properties: id: type: string url: type: string method: type: string const: PUT headers: type: object properties: Content-Type: type: string required: - Content-Type additionalProperties: false expiresAt: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ maxBytes: type: number const: 52428800 required: - id - url - method - headers - expiresAt - maxBytes additionalProperties: false required: - upload additionalProperties: false '400': description: The request is invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '401': description: Missing or invalid bearer token content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '403': description: The token lacks a scope, or its user lacks a permission content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '404': description: Not found in the token organization content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '409': description: The request conflicts with the current state content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '413': description: The body exceeds 1 MiB content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '415': description: The body is not application/json content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '429': description: Rate limited; see Retry-After content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '503': description: Temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' /orgs/{org}/documents: post: operationId: createDocument summary: Create a context document description: 'Add a context document runs can read: an uploaded file ({ upload }) or a text note ({ note }). Identical content returns the existing document with its original title (created: false); if that document was archived, this restores it (restored: true). An upload slot works once.' tags: - Documents security: - bearer: [] - oauth2: - runs:write x-mcp-tool: create_document parameters: - name: org in: path required: true description: Organization slug; must be the token's organization. schema: type: string requestBody: required: true content: application/json: schema: type: object additionalProperties: false properties: upload: type: object properties: id: type: string format: uuid pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$ title: type: string minLength: 1 maxLength: 200 required: - id - title additionalProperties: false note: type: object properties: title: type: string minLength: 1 maxLength: 200 text: type: string minLength: 1 required: - title - text additionalProperties: false required: [] responses: '201': description: Create a context document content: application/json: schema: type: object properties: document: type: object properties: id: type: string title: type: string kind: type: string enum: - upload - note contentType: type: string extension: type: string bytes: type: integer minimum: 0 maximum: 9007199254740991 createdAt: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ archived: type: boolean usedInRuns: type: integer minimum: 0 maximum: 9007199254740991 recommended: type: boolean createdBy: anyOf: - type: object properties: username: anyOf: - type: string - type: 'null' email: anyOf: - type: string - type: 'null' required: - username - email additionalProperties: false - type: 'null' required: - id - title - kind - contentType - extension - bytes - createdAt - archived - usedInRuns - recommended - createdBy additionalProperties: false created: type: boolean description: 'False when identical content already existed: that document comes back with its original title.' restored: type: boolean description: True when that existing document was archived and is now restored. required: - document - created - restored additionalProperties: false '400': description: The request is invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '401': description: Missing or invalid bearer token content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '403': description: The token lacks a scope, or its user lacks a permission content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '404': description: Not found in the token organization content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '409': description: The request conflicts with the current state content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '413': description: The body exceeds 1 MiB content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '415': description: The body is not application/json content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '429': description: Rate limited; see Retry-After content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '503': description: Temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' get: operationId: listDocuments summary: List context documents description: 'Context documents of the organization, newest first. With repository, documents used by earlier runs on that repository come first and have recommended: true; it ranks, it does not filter.' tags: - Documents security: - bearer: [] - oauth2: - runs:read x-mcp-tool: list_documents parameters: - name: org in: path required: true description: Organization slug; must be the token's organization. schema: type: string - name: repository in: query required: false schema: type: string pattern: ^[^/\s]+\/[^/\s]+$ description: Repository slug or full name, "owner/name". - name: archived in: query required: false schema: default: false type: boolean - name: limit in: query required: false schema: default: 50 type: integer minimum: 1 maximum: 100 - name: cursor in: query required: false schema: type: string minLength: 1 maxLength: 2048 description: '`nextCursor` from the previous page.' responses: '200': description: List context documents content: application/json: schema: type: object properties: nextCursor: anyOf: - type: string - type: 'null' items: type: array items: type: object properties: id: type: string title: type: string kind: type: string enum: - upload - note contentType: type: string extension: type: string bytes: type: integer minimum: 0 maximum: 9007199254740991 createdAt: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ archived: type: boolean usedInRuns: type: integer minimum: 0 maximum: 9007199254740991 recommended: type: boolean createdBy: anyOf: - type: object properties: username: anyOf: - type: string - type: 'null' email: anyOf: - type: string - type: 'null' required: - username - email additionalProperties: false - type: 'null' required: - id - title - kind - contentType - extension - bytes - createdAt - archived - usedInRuns - recommended - createdBy additionalProperties: false required: - nextCursor - items additionalProperties: false '400': description: The request is invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '401': description: Missing or invalid bearer token content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '403': description: The token lacks a scope, or its user lacks a permission content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '404': description: Not found in the token organization content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '409': description: The request conflicts with the current state content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '429': description: Rate limited; see Retry-After content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '503': description: Temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' /orgs/{org}/documents/{document}: get: operationId: getDocument summary: Get a context document description: One context document by id. tags: - Documents security: - bearer: [] - oauth2: - runs:read parameters: - name: org in: path required: true description: Organization slug; must be the token's organization. schema: type: string - name: document in: path required: true schema: type: string format: uuid pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$ description: Context document id. responses: '200': description: Get a context document content: application/json: schema: type: object properties: document: type: object properties: id: type: string title: type: string kind: type: string enum: - upload - note contentType: type: string extension: type: string bytes: type: integer minimum: 0 maximum: 9007199254740991 createdAt: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ archived: type: boolean usedInRuns: type: integer minimum: 0 maximum: 9007199254740991 recommended: type: boolean createdBy: anyOf: - type: object properties: username: anyOf: - type: string - type: 'null' email: anyOf: - type: string - type: 'null' required: - username - email additionalProperties: false - type: 'null' required: - id - title - kind - contentType - extension - bytes - createdAt - archived - usedInRuns - recommended - createdBy additionalProperties: false required: - document additionalProperties: false '400': description: The request is invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '401': description: Missing or invalid bearer token content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '403': description: The token lacks a scope, or its user lacks a permission content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '404': description: Not found in the token organization content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '409': description: The request conflicts with the current state content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '429': description: Rate limited; see Retry-After content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '503': description: Temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' delete: operationId: archiveDocument summary: Archive a context document description: Archive a document so new runs refuse it (estimate_run and start_run answer conflict). Creating identical content again restores it. Only its creator or an owner may archive it. tags: - Documents security: - bearer: [] - oauth2: - runs:write x-mcp-tool: archive_document parameters: - name: org in: path required: true description: Organization slug; must be the token's organization. schema: type: string - name: document in: path required: true schema: type: string format: uuid pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$ description: Context document id. responses: '200': description: Archive a context document content: application/json: schema: type: object properties: document: type: object properties: id: type: string title: type: string kind: type: string enum: - upload - note contentType: type: string extension: type: string bytes: type: integer minimum: 0 maximum: 9007199254740991 createdAt: type: string format: date-time pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$ archived: type: boolean usedInRuns: type: integer minimum: 0 maximum: 9007199254740991 recommended: type: boolean createdBy: anyOf: - type: object properties: username: anyOf: - type: string - type: 'null' email: anyOf: - type: string - type: 'null' required: - username - email additionalProperties: false - type: 'null' required: - id - title - kind - contentType - extension - bytes - createdAt - archived - usedInRuns - recommended - createdBy additionalProperties: false required: - document additionalProperties: false '400': description: The request is invalid content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '401': description: Missing or invalid bearer token content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '403': description: The token lacks a scope, or its user lacks a permission content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '404': description: Not found in the token organization content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '409': description: The request conflicts with the current state content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '429': description: Rate limited; see Retry-After content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' '503': description: Temporarily unavailable content: application/json: schema: $ref: '#/components/schemas/ApiErrorEnvelope' components: schemas: ApiErrorEnvelope: type: object properties: error: type: object properties: code: type: string enum: - invalid_request - repository_required - unauthenticated - insufficient_credits - spend_cap_reached - insufficient_scope - forbidden - not_found - repository_not_visible - repository_not_added - method_not_allowed - position_unavailable - decision_active - conflict - price_exceeds_max - quote_stale - change_refused - nothing_to_review - repository_not_runnable - idempotency_key_reused - api_version_retired - payload_too_large - unsupported_media_type - rate_limited - internal_error - upstream_error - platform_unavailable - repository_access_unavailable - rate_limit_unavailable - public_api_disabled message: type: string details: type: object propertyNames: type: string additionalProperties: {} required: - code - message additionalProperties: false requestId: type: string required: - error - requestId additionalProperties: false securitySchemes: bearer: type: http scheme: bearer description: A personal access token (v12p_…) or an OAuth access token (v12a_…). oauth2: type: oauth2 flows: authorizationCode: authorizationUrl: https://v12.sh/oauth/authorize tokenUrl: https://v12.sh/api/oauth/token refreshUrl: https://v12.sh/api/oauth/token scopes: user:read: 'The member directory: usernames, emails and roles. Any key reads its own account, organization and credit balance without it.' repos:read: Repositories, branches, pull requests, tags and Steer instructions. repos:write: Add public repositories to the workspace; owners can also add private repositories granted by GitHub, create repositories V12 hosts and push code to them. steers:write: Create, edit, archive and restore Steers. Archiving detaches them from Autopilot rules; finding tags and run history are kept. runs:read: Runs, their progress and context documents. runs:write: Estimate and start runs; add or archive context documents. runs:manage: Cancel runs. runs:share: Create, change and revoke guest links that open a run to people outside the organization. findings:read: 'The inbox: findings, their status, reports and comments.' findings:write: Change status, comment and update triage decisions.