{
  "openapi": "3.1.0",
  "info": {
    "title": "VersoDocs API",
    "version": "1.0.0",
    "summary": "Read approved (published) documents; on Team, review proposals; on Pro, propose, revise, publish approved proposals and manage docs & folders.",
    "description": "The VersoDocs v1 REST API. Every response is JSON with `Cache-Control: private`. Only published versions are ever returned by document reads; drafts never leave VersoDocs. Plan gating: each operation carries `x-min-plan` (free | team | pro) and `x-scope` (the API-key scope it needs). A call outside the organization's plan answers 403 `plan_feature`; a key without the scope answers 403 `forbidden`. Agent verdicts are advisory: they never count toward required approvals. Human-readable reference: https://versodocs.com/docs/api and https://versodocs.com/docs/agents",
    "contact": { "name": "VersoDocs", "url": "https://versodocs.com/docs" }
  },
  "externalDocs": { "description": "Developer docs", "url": "https://versodocs.com/docs/api" },
  "servers": [{ "url": "https://versodocs.com/api/v1/orgs/{orgSlug}", "variables": { "orgSlug": { "default": "acme", "description": "Your organization slug: the segment after /org/ in VersoDocs URLs." } } }],
  "security": [{ "apiKey": [] }],
  "tags": [
    { "name": "Documents", "description": "Read published documents (all plans)." },
    { "name": "History", "description": "Versions and diffs (Team+)." },
    { "name": "Discovery", "description": "Search and tree (Team+)." },
    { "name": "Attachments", "description": "Files embedded in published versions (Team+). Upload images and files to embed in proposals (Pro, docs:propose or docs:write)." },
    { "name": "CI", "description": "Current-version stamps for spec drift checks (Team+)." },
    { "name": "Proposals", "description": "Propose changes for human review (Pro, docs:propose); revise or withdraw the key's own proposals (Pro); publish approved proposals (Pro, proposals:publish)." },
    { "name": "Review", "description": "List and read proposals, comment, resolve threads, submit advisory verdicts (Team+, proposals:review). Comment threads on published documents: read with docs:read, comment and resolve with proposals:review (Team+)." },
    { "name": "Manage", "description": "Create, rename, move and delete documents and folders (Pro, docs:write). Deletes are guarded: unpublished documents / empty folders only, with confirm_title." },
    { "name": "Automations", "description": "Webhook subscriptions for Zapier, n8n and other automation tools (all plans; Free: 3 key review events)." },
    { "name": "Context", "description": "Every Current document in one response for AI agents: context pack and private llms.txt (Team+)." },
    { "name": "Issues", "description": "Jira and Linear issues linked to documents and proposals (Team+)." }
  ],
  "paths": {
    "/docs": {
      "get": {
        "operationId": "listDocs",
        "tags": ["Documents"],
        "summary": "List published documents",
        "description": "Published, non-archived documents the key can see, newest-updated first. Keyset-paginated: pass `next_cursor` back as `cursor` until it is null. `q` requires Team.",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "parameters": [
          { "name": "folder", "in": "query", "description": "`<workspace>` or `<workspace>/<folders…>`: that subtree only.", "schema": { "type": "string" }, "example": "eng/apis" },
          { "name": "updated_since", "in": "query", "description": "ISO 8601 timestamp; documents updated at or after it.", "schema": { "type": "string", "format": "date-time" } },
          { "name": "q", "in": "query", "description": "Full-text filter (Team+).", "schema": { "type": "string" } },
          { "name": "cursor", "in": "query", "description": "Opaque cursor from `next_cursor`.", "schema": { "type": "string" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 200 } }
        ],
        "responses": {
          "200": { "description": "A page of documents.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocList" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "post": {
        "operationId": "createDoc",
        "tags": ["Manage"],
        "summary": "Create a document",
        "description": "Creates an empty document as the key's creator (who needs edit rights in the workspace). Nothing is published: with `content_markdown` the text opens a first proposal (\"Initial version\") for review, which also needs the `docs:propose` scope.",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [{ "apiKey": ["docs:write"] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocCreateInput" } } } },
        "responses": {
          "201": { "description": "Document created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocCreated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "402": { "$ref": "#/components/responses/PlanLimit" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}": {
      "get": {
        "operationId": "getDoc",
        "tags": ["Documents"],
        "summary": "Read one document",
        "description": "The document and one published version. Current by default; `version` (Team+) reads history. Also returns the legacy `document` object and legacy `version` keys for backward compatibility.",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "parameters": [
          { "$ref": "#/components/parameters/DocumentId" },
          { "$ref": "#/components/parameters/Format" },
          { "$ref": "#/components/parameters/Version" },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "responses": {
          "200": {
            "description": "The document.",
            "headers": { "ETag": { "$ref": "#/components/headers/ETag" } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocResponseLegacy" } } }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "patch": {
        "operationId": "updateDoc",
        "tags": ["Manage"],
        "summary": "Rename or move a document",
        "description": "Rename (`title`; the URL slug follows) and/or move to another folder of the same workspace (`folder_id` or `folder_path`; null / \"\" = workspace root). Content and versions are untouched.",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [{ "apiKey": ["docs:write"] }],
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocUpdateInput" } } } },
        "responses": {
          "200": { "description": "Updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocUpdated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "delete": {
        "operationId": "deleteDoc",
        "tags": ["Manage"],
        "summary": "Delete an unpublished document",
        "description": "PERMANENTLY deletes a document with NO published version, with its drafts and proposals. A document that has a published (approved) version answers 409 `published_document`; a person deletes those in VersoDocs. `confirm_title` must repeat the exact title (case- and whitespace-insensitive), else 400 `confirm_title_mismatch`.",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [{ "apiKey": ["docs:write"] }],
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }, { "$ref": "#/components/parameters/ConfirmTitle" }],
        "responses": {
          "200": { "description": "Deleted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocDeleted" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/by-path": {
      "get": {
        "operationId": "getDocByPath",
        "tags": ["Documents"],
        "summary": "Read a document by its path",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "parameters": [
          { "$ref": "#/components/parameters/Path" },
          { "$ref": "#/components/parameters/Format" },
          { "$ref": "#/components/parameters/Version" },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "responses": {
          "200": {
            "description": "The document.",
            "headers": { "ETag": { "$ref": "#/components/headers/ETag" } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocResponse" } } }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/versions": {
      "get": {
        "operationId": "listVersions",
        "tags": ["History"],
        "summary": "List published versions",
        "description": "Every published version, newest first (up to 500).",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }, { "$ref": "#/components/parameters/IfNoneMatch" }],
        "responses": {
          "200": {
            "description": "Version history.",
            "headers": { "ETag": { "$ref": "#/components/headers/ETag" } },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["document", "versions"],
                  "properties": {
                    "document": { "$ref": "#/components/schemas/DocSummary" },
                    "versions": { "type": "array", "items": { "$ref": "#/components/schemas/VersionListItem" } }
                  }
                }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/diff": {
      "get": {
        "operationId": "diffVersions",
        "tags": ["History"],
        "summary": "Diff two published versions",
        "description": "Unified diff of the two versions' Markdown plus block/line counts.",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [
          { "$ref": "#/components/parameters/DocumentId" },
          { "name": "from", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1 } },
          { "name": "to", "in": "query", "description": "Default: Current.", "schema": { "type": "integer", "minimum": 1 } },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "responses": {
          "200": {
            "description": "The diff.",
            "headers": { "ETag": { "$ref": "#/components/headers/ETag" } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Diff" } } }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/search": {
      "get": {
        "operationId": "search",
        "tags": ["Discovery"],
        "summary": "Full-text search",
        "description": "Ranked full-text search over published documents; the last word is prefix-matched.",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [
          { "name": "q", "in": "query", "required": true, "schema": { "type": "string", "minLength": 2, "maxLength": 200 } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 20 } }
        ],
        "responses": {
          "200": {
            "description": "Ranked results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["query", "results"],
                  "properties": {
                    "query": { "type": "string" },
                    "results": {
                      "type": "array",
                      "items": { "allOf": [{ "$ref": "#/components/schemas/DocSummary" }, { "type": "object", "required": ["rank"], "properties": { "rank": { "type": "number" } } }] }
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/tree": {
      "get": {
        "operationId": "tree",
        "tags": ["Discovery"],
        "summary": "Workspace → folder → document tree",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [{ "name": "workspace", "in": "query", "description": "Limit to one workspace slug.", "schema": { "type": "string" } }],
        "responses": {
          "200": {
            "description": "The tree (published, non-archived documents only).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["workspaces"],
                  "properties": { "workspaces": { "type": "array", "items": { "$ref": "#/components/schemas/TreeWorkspace" } } }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/attachments": {
      "get": {
        "operationId": "listAttachments",
        "tags": ["Attachments"],
        "summary": "List attachments of a version",
        "description": "Files embedded in a published version (Current unless `version`).",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }, { "$ref": "#/components/parameters/Version" }, { "$ref": "#/components/parameters/IfNoneMatch" }],
        "responses": {
          "200": {
            "description": "Attachments.",
            "headers": { "ETag": { "$ref": "#/components/headers/ETag" } },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["document_id", "version", "attachments"],
                  "properties": {
                    "document_id": { "type": "string", "format": "uuid" },
                    "version": { "type": "integer" },
                    "attachments": { "type": "array", "items": { "$ref": "#/components/schemas/Attachment" } }
                  }
                }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "post": {
        "operationId": "uploadAttachment",
        "tags": ["Attachments"],
        "summary": "Upload an image or file to embed in a proposal",
        "description": "Two flows. Direct (up to 5 MB): multipart form data with `file` (+ optional `alt`), or JSON with `data_base64`; answers the stored attachment. Presigned (images up to 10 MB, files up to 25 MB): JSON with `size`; answers a signed PUT URL, the exact headers to send and a `confirm_url` to POST once the bytes are up. Put the returned `markdown` in a proposal's `content_markdown` (or an edit) to embed it; uploads no proposal references are removed after a day. Needs `docs:propose` or `docs:write` (Pro; on Team, a member's one-click OAuth connection). The credential's user must be able to edit the document, and the bytes count toward the plan's storage.",
        "x-min-plan": "pro",
        "x-scope": "docs:propose",
        "security": [{ "apiKey": ["docs:propose"] }, { "apiKey": ["docs:write"] }],
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/AttachmentUploadInput" } },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["file"],
                "properties": {
                  "file": { "type": "string", "format": "binary" },
                  "alt": { "type": "string", "maxLength": 500 },
                  "filename": { "type": "string", "description": "Overrides the part's file name." },
                  "content_type": { "type": "string", "description": "Overrides the part's Content-Type." }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Stored (direct) or ready to PUT (presigned).",
            "content": { "application/json": { "schema": { "oneOf": [{ "$ref": "#/components/schemas/UploadedAttachment" }, { "$ref": "#/components/schemas/PresignedUpload" }] } } }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "description": "Scope, plan, edit access, or `storage_quota` (the plan's storage is full).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "$ref": "#/components/responses/NotFound" },
          "413": { "description": "`file_too_large`: over the direct (5 MB) or per-type cap.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "415": { "description": "`unsupported_type`, or `content_mismatch` (an image whose bytes are not the declared type).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/attachments/{attachmentId}/confirm": {
      "post": {
        "operationId": "confirmAttachmentUpload",
        "tags": ["Attachments"],
        "summary": "Confirm a presigned upload",
        "description": "Call after the PUT to the presigned URL succeeds. Checks the bytes landed and, for an image, that they really are the declared type (a mismatch is deleted). Answers the attachment with its `markdown`.",
        "x-min-plan": "pro",
        "x-scope": "docs:propose",
        "security": [{ "apiKey": ["docs:propose"] }, { "apiKey": ["docs:write"] }],
        "parameters": [
          { "$ref": "#/components/parameters/DocumentId" },
          { "name": "attachmentId", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[0-9a-f]{32}$" } }
        ],
        "requestBody": {
          "required": false,
          "content": { "application/json": { "schema": { "type": "object", "properties": { "alt": { "type": "string", "maxLength": 500 } } } } }
        },
        "responses": {
          "200": { "description": "Upload confirmed.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UploadedAttachment" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "description": "`upload_not_found`: nothing was PUT under this id (or the URL expired).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "415": { "description": "`content_mismatch`: the image bytes are not the declared type; the upload was deleted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/attachments/{attachmentId}": {
      "get": {
        "operationId": "downloadAttachment",
        "tags": ["Attachments"],
        "summary": "Download an attachment (302)",
        "description": "Redirects to a signed download URL valid for 5 minutes. Only files referenced by the published version are reachable.",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [
          { "$ref": "#/components/parameters/DocumentId" },
          { "name": "attachmentId", "in": "path", "required": true, "schema": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,64}$" } },
          { "$ref": "#/components/parameters/Version" }
        ],
        "responses": {
          "302": { "description": "Redirect to the signed URL.", "headers": { "Location": { "schema": { "type": "string", "format": "uri" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/current": {
      "get": {
        "operationId": "getDocCurrent",
        "tags": ["CI"],
        "summary": "Current version stamp (CI check)",
        "description": "Current version number/label/date, URLs and the canonical reference, without content. Shape frozen (used by the GitHub spec drift action).",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }],
        "responses": {
          "200": { "description": "The stamp.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocStatus" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/current": {
      "get": {
        "operationId": "getDocCurrentByPath",
        "tags": ["CI"],
        "summary": "Current version stamp by path (CI check)",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "parameters": [{ "$ref": "#/components/parameters/Path" }],
        "responses": {
          "200": { "description": "The stamp.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocStatus" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/proposals": {
      "post": {
        "operationId": "createProposal",
        "tags": ["Proposals"],
        "summary": "Propose a change for review",
        "description": "Opens a proposal in review, authored by the key's creator. Send EITHER `content_markdown` (the whole new document) OR `edits` (`[{ find, replace }]` applied in order to the Current Markdown; each `find` must match exactly once, else 422 `edit_failed` and nothing is written). It follows the normal review → publish workflow; this call never publishes.",
        "x-min-plan": "pro",
        "x-scope": "docs:propose",
        "security": [{ "apiKey": ["docs:propose"] }],
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalInput" } } }
        },
        "responses": {
          "201": { "description": "Proposal opened.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalCreated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "422": { "$ref": "#/components/responses/Unprocessable" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals": {
      "get": {
        "operationId": "listProposals",
        "tags": ["Review"],
        "summary": "List proposals",
        "description": "Proposals on documents the key can see, newest-updated first. Default `status=open` (in review, changes requested, approved). Drafts are private to their author and never listed.",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [
          { "name": "status", "in": "query", "schema": { "type": "string", "enum": ["open", "all", "in_review", "changes_requested", "approved", "published", "closed"], "default": "open" } },
          { "name": "document_id", "in": "query", "description": "Only proposals on this document.", "schema": { "type": "string", "format": "uuid" } },
          { "name": "limit", "in": "query", "schema": { "type": "integer", "minimum": 1, "maximum": 200, "default": 50 } }
        ],
        "responses": {
          "200": { "description": "Proposals.", "content": { "application/json": { "schema": { "type": "object", "required": ["proposals"], "properties": { "proposals": { "type": "array", "items": { "$ref": "#/components/schemas/ProposalSummary" } } } } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals/{proposalId}": {
      "get": {
        "operationId": "getProposal",
        "tags": ["Review"],
        "summary": "Read a proposal (diff, reviewers, comments)",
        "description": "The proposal's Markdown, the diff against the version it forked from, human reviewers and their verdicts, advisory agent reviews and the comment threads.",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }],
        "responses": {
          "200": { "description": "The proposal.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalDetail" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "patch": {
        "operationId": "updateProposal",
        "tags": ["Proposals"],
        "summary": "Revise the agent’s own open proposal",
        "description": "Only a proposal opened by THIS key (else 403 `not_agent_proposal`). Any of `title`, `description`, and content as `content_markdown` XOR `edits` (applied to the proposal's current text). A content change after approval dismisses the approvals, exactly like an edit in the app.",
        "x-min-plan": "pro",
        "x-scope": "docs:propose",
        "security": [{ "apiKey": ["docs:propose"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalUpdateInput" } } } },
        "responses": {
          "200": { "description": "Updated.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalUpdated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/Unprocessable" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals/{proposalId}/comments": {
      "post": {
        "operationId": "commentOnProposal",
        "tags": ["Review"],
        "summary": "Comment or reply on a proposal",
        "description": "Written as the key's creator, labeled \"via <key name>\". `quote` (exact text from one paragraph of the proposal) anchors an inline comment (422 `quote_not_found` otherwise); `parent_id` replies in a thread; neither posts to the conversation. @mention members by email.",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentInput" } } } },
        "responses": {
          "201": { "description": "Comment posted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CommentCreated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/Unprocessable" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals/{proposalId}/comments/{commentId}": {
      "patch": {
        "operationId": "resolveProposalComment",
        "tags": ["Review"],
        "summary": "Resolve or reopen a comment thread",
        "description": "Any comment of the thread works; the whole thread flips.",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }, { "name": "commentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["resolved"], "properties": { "resolved": { "type": "boolean" } } } } } },
        "responses": {
          "200": { "description": "Thread updated.", "content": { "application/json": { "schema": { "type": "object", "required": ["thread_root_id", "resolved", "updated"], "properties": { "thread_root_id": { "type": "string", "format": "uuid" }, "resolved": { "type": "boolean" }, "updated": { "type": "integer", "description": "Comments changed." } } } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/comments": {
      "get": {
        "operationId": "listDocComments",
        "tags": ["Review"],
        "summary": "Comment threads on a published version",
        "description": "Threads on the Current version (or `version`), oldest first, including threads written on an older version and carried forward. Each comment carries its `anchor_version` (id + number). Open threads only unless `include_resolved=true`. Proposal review comments are on GET /proposals/{proposalId}.",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "security": [{ "apiKey": ["docs:read"] }],
        "parameters": [
          { "$ref": "#/components/parameters/DocumentId" },
          { "name": "version", "in": "query", "description": "Published version number or version id (default: Current).", "schema": { "type": "string" } },
          { "name": "include_resolved", "in": "query", "schema": { "type": "boolean", "default": false } }
        ],
        "responses": {
          "200": { "description": "Threads.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocCommentList" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "post": {
        "operationId": "commentOnDoc",
        "tags": ["Review"],
        "summary": "Comment or reply on a document",
        "description": "Written as the key's creator, labeled \"via <key name>\". `quote` (exact text from one paragraph of `version`, default Current) starts an inline thread (422 `quote_not_found` otherwise); `parent_id` replies in a thread. @mention members by email.",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocCommentInput" } } } },
        "responses": {
          "201": { "description": "Comment posted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DocCommentCreated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "422": { "$ref": "#/components/responses/Unprocessable" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/docs/{documentId}/comments/{commentId}": {
      "patch": {
        "operationId": "resolveDocComment",
        "tags": ["Review"],
        "summary": "Resolve or reopen a document comment thread",
        "description": "Any comment of the thread works; the whole thread flips.",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [{ "$ref": "#/components/parameters/DocumentId" }, { "name": "commentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": ["resolved"], "properties": { "resolved": { "type": "boolean" } } } } } },
        "responses": {
          "200": { "description": "Thread updated.", "content": { "application/json": { "schema": { "type": "object", "required": ["thread_root_id", "resolved", "updated"], "properties": { "thread_root_id": { "type": "string", "format": "uuid" }, "resolved": { "type": "boolean" }, "updated": { "type": "integer", "description": "Comments changed." } } } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals/{proposalId}/reviews": {
      "post": {
        "operationId": "submitReview",
        "tags": ["Review"],
        "summary": "Submit an advisory verdict",
        "description": "Shown to reviewers as an AI review. ADVISORY: it never counts toward required approvals, never marks the proposal approved and never auto-publishes. `body` is required for `request_changes` and `comment`. Open proposals only (409 `proposal_closed`).",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [{ "apiKey": ["proposals:review"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerdictInput" } } } },
        "responses": {
          "201": { "description": "Verdict recorded.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerdictRecorded" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals/{proposalId}/close": {
      "post": {
        "operationId": "closeProposal",
        "tags": ["Proposals"],
        "summary": "Withdraw the agent’s own proposal",
        "description": "Closes, without publishing, a proposal opened by THIS key (else 403 `not_agent_proposal`). Participants are notified.",
        "x-min-plan": "pro",
        "x-scope": "docs:propose",
        "security": [{ "apiKey": ["docs:propose"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }],
        "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "reason": { "type": "string", "maxLength": 500 } } } } } },
        "responses": {
          "200": { "description": "Closed.", "content": { "application/json": { "schema": { "type": "object", "required": ["proposal_id", "status"], "properties": { "proposal_id": { "type": "string", "format": "uuid" }, "status": { "const": "closed" } } } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/proposals/{proposalId}/publish": {
      "post": {
        "operationId": "publishProposal",
        "tags": ["Proposals"],
        "summary": "Publish an approved proposal",
        "description": "Same gates as Publish in the app (author or workspace admin, edit access, up to date with Current, workspace publish rules), plus: status must be `approved` by humans (409 `not_approved`), never an override, and a workspace requiring a re-authenticated e-signature answers 403 `requires_e_signature`, since an agent can never sign. Stale → 409 `stale`; other rule → 409 `publish_blocked`.",
        "x-min-plan": "pro",
        "x-scope": "proposals:publish",
        "security": [{ "apiKey": ["proposals:publish"] }],
        "parameters": [{ "$ref": "#/components/parameters/ProposalId" }],
        "responses": {
          "200": { "description": "Published.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ProposalPublished" } } } },
          "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" }, "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/folders": {
      "post": {
        "operationId": "createFolder",
        "tags": ["Manage"],
        "summary": "Create a folder",
        "description": "At the workspace root, or inside `parent_id` / `parent_path`. The key's creator must be a member of the workspace with edit rights.",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [{ "apiKey": ["docs:write"] }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderCreateInput" } } } },
        "responses": {
          "201": { "description": "Folder created.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderCreated" } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/folders/{folderId}": {
      "patch": {
        "operationId": "updateFolder",
        "tags": ["Manage"],
        "summary": "Rename or move a folder",
        "description": "Rename (`name`) and/or move (`parent_id` / `parent_path`; null / \"\" = workspace root) within its workspace.",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [{ "apiKey": ["docs:write"] }],
        "parameters": [{ "$ref": "#/components/parameters/FolderId" }],
        "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FolderUpdateInput" } } } },
        "responses": {
          "200": { "description": "Updated.", "content": { "application/json": { "schema": { "type": "object", "required": ["folder_id", "name", "slug"], "properties": { "folder_id": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "slug": { "type": "string" } } } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "delete": {
        "operationId": "deleteFolder",
        "tags": ["Manage"],
        "summary": "Delete an empty folder",
        "description": "Only an EMPTY folder (409 `folder_not_empty` while it holds documents or subfolders). `confirm_title` must repeat the folder name, else 400 `confirm_title_mismatch`.",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [{ "apiKey": ["docs:write"] }],
        "parameters": [{ "$ref": "#/components/parameters/FolderId" }, { "$ref": "#/components/parameters/ConfirmTitle" }],
        "responses": {
          "200": { "description": "Deleted.", "content": { "application/json": { "schema": { "type": "object", "required": ["folder_id", "deleted"], "properties": { "folder_id": { "type": "string", "format": "uuid" }, "deleted": { "const": true } } } } } },
          "400": { "$ref": "#/components/responses/BadRequest" }, "401": { "$ref": "#/components/responses/Unauthorized" }, "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" }, "409": { "$ref": "#/components/responses/Conflict" }, "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listAutomationHooks",
        "tags": [
          "Automations"
        ],
        "summary": "List automation subscriptions",
        "description": "Subscriptions this credential created, in its workspaces.",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Subscriptions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "createAutomationHook",
        "tags": [
          "Automations"
        ],
        "summary": "Subscribe a URL to events",
        "description": "Deliveries POST `{ event, created_at, data }` to target_url, signed (x-versodocs-signature-v2 = v2=hex(HMAC-SHA256(secret, `<timestamp>.<body>`))). Free: proposal.opened, proposal.verdict_submitted, version.published; Team+: every event (402 with locked_events otherwise). The secret is returned only here. `workspace` is required when the key sees several workspaces (400 workspace_required lists them). The key owner needs edit access to the workspace (403 forbidden otherwise).",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target_url",
                  "events"
                ],
                "properties": {
                  "target_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "workspace": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscribed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "target_url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "workspace": {
                      "type": "object"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PlanLimit"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/webhooks/{webhookId}": {
      "delete": {
        "operationId": "deleteAutomationHook",
        "tags": [
          "Automations"
        ],
        "summary": "Unsubscribe",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Removed."
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/samples": {
      "get": {
        "operationId": "automationSamples",
        "tags": [
          "Automations"
        ],
        "summary": "Sample deliveries for an event",
        "description": "Up to 3 recent deliveries to automation subscriptions for `event`, or one example (Zapier performList, n8n test).",
        "x-min-plan": "free",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Envelopes.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/context-pack": {
      "get": {
        "operationId": "getContextPack",
        "tags": [
          "Context"
        ],
        "summary": "All Current docs in one Markdown / JSON pack",
        "description": "Every non-archived document's Current version in scope, ordered by path: an index, then one section per document (path, version, approvers, publish date, link). Cut at max_chars with a notice listing the documents left out (headers x-versodocs-pack-documents, x-versodocs-pack-truncated). ETag over the (document, version) set: If-None-Match answers 304.",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "workspace",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Workspace slug."
          },
          {
            "name": "folder",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "`<workspace>/<…folders>`; that subtree only."
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "md",
                "json"
              ],
              "default": "md"
            }
          },
          {
            "name": "max_chars",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 2000,
              "maximum": 2000000,
              "default": 200000
            }
          },
          {
            "$ref": "#/components/parameters/IfNoneMatch"
          }
        ],
        "responses": {
          "200": {
            "description": "The pack.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "304": {
            "$ref": "#/components/responses/NotModified"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "operationId": "getLlmsTxt",
        "tags": [
          "Context"
        ],
        "summary": "Private llms.txt index of Current docs",
        "description": "llmstxt.org-style index of the organization's Current documents, grouped by workspace, each linking its Markdown through this API (same key).",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The index.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/docs/{documentId}/issue-links": {
      "get": {
        "operationId": "listDocIssueLinks",
        "tags": [
          "Issues"
        ],
        "summary": "Issues linked to a document",
        "description": "Jira / Linear issues linked to the document.",
        "x-min-plan": "team",
        "x-scope": "docs:read",
        "security": [
          {
            "apiKey": [
              "docs:read"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Links.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string",
                            "enum": [
                              "jira",
                              "linear"
                            ]
                          },
                          "key": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_at": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "linkDocIssue",
        "tags": [
          "Issues"
        ],
        "summary": "Link an issue to a document",
        "description": "Body `{ url }`: a Jira Cloud (`https://<site>.atlassian.net/browse/KEY-1`) or Linear (`https://linear.app/<team>/issue/KEY-1`) issue URL. Title and status are filled when the organization connected Jira / Linear. 409 already_linked / issue_link_limit (20 per target).",
        "x-min-plan": "pro",
        "x-scope": "docs:write",
        "security": [
          {
            "apiKey": [
              "docs:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/DocumentId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Linked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "link": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "provider": {
                          "type": "string",
                          "enum": [
                            "jira",
                            "linear"
                          ]
                        },
                        "key": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "title": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/proposals/{proposalId}/issue-links": {
      "get": {
        "operationId": "listProposalIssueLinks",
        "tags": [
          "Issues"
        ],
        "summary": "Issues linked to a proposal",
        "description": "Jira / Linear issues linked to the proposal (never drafts).",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [
          {
            "apiKey": [
              "proposals:review"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProposalId"
          }
        ],
        "responses": {
          "200": {
            "description": "Links.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string",
                            "enum": [
                              "jira",
                              "linear"
                            ]
                          },
                          "key": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "title": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "status": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_at": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "linkProposalIssue",
        "tags": [
          "Issues"
        ],
        "summary": "Link an issue to a proposal",
        "description": "Body `{ url }`: a Jira Cloud (`https://<site>.atlassian.net/browse/KEY-1`) or Linear (`https://linear.app/<team>/issue/KEY-1`) issue URL. Title and status are filled when the organization connected Jira / Linear. 409 already_linked / issue_link_limit (20 per target).",
        "x-min-plan": "team",
        "x-scope": "proposals:review",
        "security": [
          {
            "apiKey": [
              "proposals:review"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ProposalId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Linked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "link": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "provider": {
                          "type": "string",
                          "enum": [
                            "jira",
                            "linear"
                          ]
                        },
                        "key": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "title": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "created_at": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "vsd_…",
        "description": "API key from Organization settings → Developer. A key holds scopes (operations list the one they need in `security` / `x-scope`): `docs:read` (always; all plans), `proposals:review` (Team+: list/read proposals, comment, resolve, advisory verdicts), `docs:propose` (Pro for keys: open, revise and withdraw the key's own proposals), `docs:write` (Pro: create / rename / move / delete docs and folders) and `proposals:publish` (Pro: publish approved proposals). `docs:write` and `proposals:publish` are opt-in. OAuth access tokens (vsd_at_…) are only valid on the MCP endpoint (/api/mcp) and are rejected here."
      }
    },
    "parameters": {
      "DocumentId": { "name": "documentId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
      "Path": { "name": "path", "in": "query", "required": true, "description": "`<workspace>/<folders…>/<doc-slug>`: what follows /org/<orgSlug>/ in the document URL.", "schema": { "type": "string" }, "example": "eng/apis/payments-api" },
      "Format": { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["json", "md", "html"], "default": "json" }, "description": "json = Tiptap JSON, md = Markdown, html = HTML." },
      "Version": { "name": "version", "in": "query", "description": "Published version number (history: Team+ on document reads).", "schema": { "type": "integer", "minimum": 1 } },
      "IfNoneMatch": { "name": "If-None-Match", "in": "header", "description": "ETag from a previous response; answers 304 when unchanged.", "schema": { "type": "string" } },
      "ProposalId": { "name": "proposalId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
      "FolderId": { "name": "folderId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } },
      "ConfirmTitle": { "name": "confirm_title", "in": "query", "required": true, "description": "The exact title / folder name (case- and whitespace-insensitive). Guards against deleting the wrong thing.", "schema": { "type": "string" } }
    },
    "headers": {
      "ETag": { "description": "Identifies this exact representation.", "schema": { "type": "string" } }
    },
    "responses": {
      "NotModified": { "description": "Not modified (ETag matched)." },
      "BadRequest": { "description": "Invalid parameter or body.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Unauthorized": { "description": "Missing, unknown, revoked or expired token, or an OAuth token used on the REST API.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Forbidden": {
        "description": "`plan_feature` (endpoint or parameter outside the org's plan), `forbidden` (missing scope / key creator can't do this), `agent_proposal_quota`, `not_agent_proposal` (revise / close a proposal this key didn't open) or `requires_e_signature` (publish in a workspace that requires an interactive e-signature).",
        "content": { "application/json": { "schema": { "oneOf": [{ "$ref": "#/components/schemas/PlanFeatureError" }, { "$ref": "#/components/schemas/Error" }] } } }
      },
      "NotFound": { "description": "Unknown, archived, unpublished, outside the key's workspaces, or another org.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Conflict": {
        "description": "`choose_active_workspace` (Free org with several workspaces and none active), `proposal_limit`, `key_owner_missing`, `proposal_closed`, `not_approved`, `stale`, `publish_blocked`, `published_document` or `folder_not_empty`.",
        "content": { "application/json": { "schema": { "oneOf": [{ "$ref": "#/components/schemas/ChooseWorkspaceError" }, { "$ref": "#/components/schemas/Error" }] } } }
      },
      "PlanLimit": { "description": "`plan_limit`: the org's plan document cap is reached.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
      "Unprocessable": {
        "description": "`edit_failed` (an `edits[i].find` is missing or matches more than once; nothing is written) or `quote_not_found` (comment `quote` not in the proposal).",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
      },
      "RateLimited": {
        "description": "Per-key rate limit exceeded.",
        "headers": { "Retry-After": { "description": "Seconds to wait.", "schema": { "type": "integer" } } },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": ["error", "message", "limit_per_min"],
              "properties": { "error": { "const": "rate_limited" }, "message": { "type": "string" }, "limit_per_min": { "type": "integer" } }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "bad_request", "unauthorized", "forbidden", "not_found", "proposal_limit", "key_owner_missing", "agent_proposal_quota",
              "edit_failed", "quote_not_found", "proposal_closed", "not_agent_proposal", "not_approved", "stale", "publish_blocked",
              "requires_e_signature", "published_document", "folder_not_empty", "confirm_title_mismatch", "plan_limit"
            ]
          },
          "message": { "type": "string" }
        }
      },
      "PlanFeatureError": {
        "type": "object",
        "required": ["error", "code", "feature", "required_plan", "upgrade_url"],
        "properties": {
          "error": { "type": "string", "description": "Human-readable explanation." },
          "code": { "const": "plan_feature" },
          "feature": { "type": "string", "enum": ["currentRead", "history", "diff", "search", "tree", "attachments", "ciCheck", "propose", "review", "proposalUpdate", "write", "publish", "auditApiUsage", "workspaceScopedKeys"] },
          "required_plan": { "type": "string", "enum": ["free", "team", "pro"] },
          "upgrade_url": { "type": "string", "format": "uri" }
        }
      },
      "ChooseWorkspaceError": {
        "type": "object",
        "required": ["error", "code", "upgrade_url"],
        "properties": {
          "error": { "type": "string" },
          "code": { "const": "choose_active_workspace" },
          "upgrade_url": { "type": "string", "format": "uri" }
        }
      },
      "VersionSummary": {
        "type": "object",
        "required": ["number", "label", "published_at"],
        "properties": {
          "number": { "type": "integer" },
          "label": { "type": ["string", "null"] },
          "published_at": { "type": "string", "format": "date-time" }
        }
      },
      "DocSummary": {
        "type": "object",
        "required": ["id", "title", "slug", "workspace_slug", "path", "url", "updated_at", "current_version", "reference"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "slug": { "type": "string" },
          "workspace_slug": { "type": "string" },
          "path": { "type": "string", "examples": ["eng/apis/payments-api"] },
          "url": { "type": "string", "format": "uri" },
          "updated_at": { "type": "string", "format": "date-time" },
          "current_version": { "oneOf": [{ "$ref": "#/components/schemas/VersionSummary" }, { "type": "null" }] },
          "reference": { "type": ["string", "null"], "description": "Canonical spec reference `versodocs:<org>/<id>@v<N>`.", "examples": ["versodocs:acme/0b6c2d8e-1f2a-4b3c-9d4e-5f6a7b8c9d0e@v13"] }
        }
      },
      "DocList": {
        "type": "object",
        "required": ["documents", "next_cursor"],
        "properties": {
          "documents": { "type": "array", "items": { "$ref": "#/components/schemas/DocSummary" } },
          "next_cursor": { "type": ["string", "null"] }
        }
      },
      "Author": {
        "type": ["object", "null"],
        "properties": { "name": { "type": ["string", "null"] }, "email": { "type": ["string", "null"] } }
      },
      "VersionListItem": {
        "type": "object",
        "required": ["id", "number", "label", "published_at", "is_current", "reference", "url", "author"],
        "properties": {
          "id": { "type": "string" },
          "number": { "type": "integer" },
          "label": { "type": ["string", "null"] },
          "published_at": { "type": "string", "format": "date-time" },
          "is_current": { "type": "boolean" },
          "reference": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "author": { "$ref": "#/components/schemas/Author" }
        }
      },
      "DocVersion": {
        "allOf": [
          { "$ref": "#/components/schemas/VersionListItem" },
          { "type": "object", "required": ["slug"], "properties": { "slug": { "type": "string" } } }
        ]
      },
      "DocResponse": {
        "allOf": [
          { "$ref": "#/components/schemas/DocSummary" },
          {
            "type": "object",
            "required": ["version", "format", "content"],
            "properties": {
              "version": { "$ref": "#/components/schemas/DocVersion" },
              "format": { "type": "string", "enum": ["json", "md", "html"] },
              "content": { "description": "Markdown or HTML string, or Tiptap JSON object (format=json)." }
            }
          }
        ]
      },
      "DocResponseLegacy": {
        "allOf": [
          { "$ref": "#/components/schemas/DocResponse" },
          {
            "type": "object",
            "properties": {
              "document": {
                "type": "object",
                "deprecated": true,
                "properties": {
                  "id": { "type": "string" },
                  "title": { "type": "string" },
                  "slug": { "type": "string" },
                  "workspace_slug": { "type": "string" },
                  "org_slug": { "type": "string" }
                }
              },
              "version": {
                "type": "object",
                "description": "Also carries deprecated `version_number`, `created_at`, `format` and `content` / `content_html` / `content_markdown`.",
                "properties": {
                  "version_number": { "type": "integer", "deprecated": true },
                  "created_at": { "type": "string", "format": "date-time", "deprecated": true },
                  "content": { "deprecated": true },
                  "content_html": { "type": "string", "deprecated": true },
                  "content_markdown": { "type": "string", "deprecated": true }
                }
              }
            }
          }
        ]
      },
      "Diff": {
        "type": "object",
        "required": ["document", "from", "to", "summary", "format", "diff"],
        "properties": {
          "document": { "$ref": "#/components/schemas/DocSummary" },
          "from": { "$ref": "#/components/schemas/VersionSummary" },
          "to": { "$ref": "#/components/schemas/VersionSummary" },
          "summary": {
            "type": "object",
            "required": ["blocks_added", "blocks_removed", "blocks_changed", "blocks_unchanged", "lines_added", "lines_removed"],
            "properties": {
              "blocks_added": { "type": "integer" },
              "blocks_removed": { "type": "integer" },
              "blocks_changed": { "type": "integer" },
              "blocks_unchanged": { "type": "integer" },
              "lines_added": { "type": "integer" },
              "lines_removed": { "type": "integer" }
            }
          },
          "format": { "const": "unified" },
          "diff": { "type": "string", "description": "Unified diff of the two versions' Markdown." }
        }
      },
      "TreeDoc": {
        "type": "object",
        "required": ["id", "title", "slug", "path", "current_version_number"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "slug": { "type": "string" },
          "path": { "type": "string" },
          "current_version_number": { "type": ["integer", "null"] }
        }
      },
      "TreeFolder": {
        "type": "object",
        "required": ["id", "name", "slug", "path", "folders", "documents"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "path": { "type": "string" },
          "folders": { "type": "array", "items": { "$ref": "#/components/schemas/TreeFolder" } },
          "documents": { "type": "array", "items": { "$ref": "#/components/schemas/TreeDoc" } }
        }
      },
      "TreeWorkspace": {
        "type": "object",
        "required": ["id", "name", "slug", "folders", "documents"],
        "properties": {
          "id": { "type": "string" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "folders": { "type": "array", "items": { "$ref": "#/components/schemas/TreeFolder" } },
          "documents": { "type": "array", "items": { "$ref": "#/components/schemas/TreeDoc" } }
        }
      },
      "Attachment": {
        "type": "object",
        "required": ["id", "type", "name", "mime", "size", "download_url"],
        "properties": {
          "id": { "type": "string" },
          "type": { "type": "string", "enum": ["image", "file"], "description": "image: an uploaded image embedded in the doc; file: an attachment chip." },
          "name": { "type": "string" },
          "mime": { "type": "string" },
          "size": { "type": "integer", "description": "Bytes; 0 when unknown (images)." },
          "download_url": { "type": "string", "format": "uri", "description": "This API's download endpoint (302 to a 5-minute signed URL)." }
        }
      },
      "AttachmentUploadInput": {
        "type": "object",
        "required": ["filename", "content_type"],
        "description": "Send `data_base64` (direct upload, up to 5 MB decoded) OR `size` (presigned upload: images up to 10 MB, files up to 25 MB), not both. Images: PNG, JPEG, GIF, WebP (no SVG). Files: PDF, Word, Excel, PowerPoint, CSV, text, Markdown, JSON, ZIP.",
        "oneOf": [{ "required": ["data_base64"] }, { "required": ["size"] }],
        "properties": {
          "filename": { "type": "string", "minLength": 1, "maxLength": 255 },
          "content_type": { "type": "string", "examples": ["image/png", "application/pdf"] },
          "data_base64": { "type": "string", "contentEncoding": "base64", "description": "The file bytes (a `data:…;base64,` prefix is accepted)." },
          "size": { "type": "integer", "minimum": 1, "description": "Exact byte length of the file you will PUT." },
          "alt": { "type": "string", "maxLength": 500, "description": "Images: alt text." }
        }
      },
      "UploadedAttachment": {
        "type": "object",
        "required": ["id", "kind", "name", "mime", "size", "url", "markdown"],
        "properties": {
          "id": { "type": "string", "pattern": "^[0-9a-f]{32}$" },
          "kind": { "type": "string", "enum": ["image", "file"], "description": "`image` embeds inline; `file` is an attachment chip." },
          "name": { "type": "string" },
          "mime": { "type": "string" },
          "size": { "type": "integer", "description": "Bytes (for a presigned upload: the declared size until confirmed)." },
          "url": { "type": "string", "format": "uri", "description": "Public URL of the stored object." },
          "markdown": { "type": "string", "description": "Paste into `content_markdown` (or an edit) of a proposal: `![alt](url)` for an image, `[📎 name](url)` for a file." }
        }
      },
      "PresignedUpload": {
        "type": "object",
        "required": ["attachment", "upload", "confirm_url"],
        "properties": {
          "attachment": { "$ref": "#/components/schemas/UploadedAttachment" },
          "upload": {
            "type": "object",
            "required": ["url", "method", "headers", "expires_in"],
            "properties": {
              "url": { "type": "string", "format": "uri", "description": "Signed R2 URL." },
              "method": { "type": "string", "const": "PUT" },
              "headers": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Send exactly these headers with the PUT (Content-Type, Content-Length and, for files, Content-Disposition are signed)." },
              "expires_in": { "type": "integer", "description": "Seconds until the URL expires." }
            }
          },
          "confirm_url": { "type": "string", "format": "uri", "description": "POST here after the PUT succeeds." }
        }
      },
      "DocStatus": {
        "type": "object",
        "required": ["document", "current_version", "reference"],
        "properties": {
          "document": {
            "type": "object",
            "required": ["id", "title", "slug", "org_slug", "workspace_slug", "url", "history_url"],
            "properties": {
              "id": { "type": "string", "format": "uuid" },
              "title": { "type": "string" },
              "slug": { "type": "string" },
              "org_slug": { "type": "string" },
              "workspace_slug": { "type": "string" },
              "url": { "type": "string", "format": "uri" },
              "history_url": { "type": "string", "format": "uri" }
            }
          },
          "current_version": {
            "type": "object",
            "required": ["number", "label", "published_at", "url", "change_url"],
            "properties": {
              "number": { "type": "integer" },
              "label": { "type": ["string", "null"] },
              "published_at": { "type": "string", "format": "date-time" },
              "url": { "type": "string", "format": "uri" },
              "change_url": { "type": ["string", "null"], "format": "uri", "description": "The proposal that produced Current; null after a direct publish or restore." }
            }
          },
          "reference": { "type": "string" }
        }
      },
      "ContentMarkdown": { "type": "string", "minLength": 1, "maxLength": 500000, "description": "The complete new document in Markdown. `![alt](https://…)` embeds an image by URL; to add a new image or file, upload it with POST docs/{documentId}/attachments and paste the `markdown` it returns (`[📎 name](url)` becomes an attachment). Images and attachments kept from the current text are preserved." },
      "TextEdits": {
        "type": "array",
        "minItems": 1,
        "maxItems": 100,
        "description": "Applied in order, all or nothing. Each `find` is literal, case-sensitive, and must occur exactly once in the text at that point (line endings normalized). `replace` may be empty (a deletion).",
        "items": {
          "type": "object",
          "required": ["find", "replace"],
          "properties": { "find": { "type": "string", "minLength": 1, "maxLength": 100000 }, "replace": { "type": "string", "maxLength": 100000 } }
        }
      },
      "ProposalInput": {
        "type": "object",
        "required": ["title"],
        "description": "Send `content_markdown` OR `edits`, not both.",
        "oneOf": [{ "required": ["content_markdown"] }, { "required": ["edits"] }],
        "properties": {
          "title": { "type": "string", "minLength": 1, "maxLength": 200 },
          "description": { "type": "string", "description": "Context for reviewers; truncated to 10,000 characters." },
          "content_markdown": { "$ref": "#/components/schemas/ContentMarkdown" },
          "edits": { "$ref": "#/components/schemas/TextEdits" },
          "request_review": { "type": "array", "maxItems": 20, "items": { "type": "string", "format": "email" } }
        }
      },
      "ProposalCreated": {
        "type": "object",
        "required": ["proposal_id", "url", "status", "document_id", "reviewers_requested", "unmatched_reviewers"],
        "properties": {
          "proposal_id": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "status": { "const": "in_review" },
          "document_id": { "type": "string", "format": "uuid" },
          "reviewers_requested": { "type": "array", "items": { "type": "string" } },
          "unmatched_reviewers": { "type": "array", "items": { "type": "string" } }
        }
      },
      "ProposalSummary": {
        "type": "object",
        "required": ["id", "title", "status", "url", "document", "author", "opened_via_agent", "stale", "opened_at", "updated_at"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "status": { "type": "string", "enum": ["in_review", "changes_requested", "approved", "published", "closed"] },
          "url": { "type": "string", "format": "uri" },
          "document": { "type": "object", "required": ["id", "title", "workspace"], "properties": { "id": { "type": "string", "format": "uuid" }, "title": { "type": "string" }, "workspace": { "type": "string" } } },
          "author": { "$ref": "#/components/schemas/Author" },
          "opened_via_agent": { "type": "boolean", "description": "Opened through an API key or MCP connection." },
          "stale": { "type": "boolean", "description": "Current moved on since this proposal forked; it must be updated before it can publish." },
          "opened_at": { "type": ["string", "null"], "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ProposalDetail": {
        "allOf": [
          { "$ref": "#/components/schemas/ProposalSummary" },
          {
            "type": "object",
            "required": ["description", "base_version", "content_markdown", "diff", "reviewers", "agent_reviews", "comments"],
            "properties": {
              "description": { "type": ["string", "null"] },
              "base_version": { "type": ["integer", "null"], "description": "Published version the proposal forked from; null = new document." },
              "content_markdown": { "type": "string" },
              "diff": { "type": "object", "required": ["summary", "unified"], "properties": { "summary": { "$ref": "#/components/schemas/Diff/properties/summary" }, "unified": { "type": "string" } } },
              "reviewers": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": { "name": { "type": ["string", "null"] }, "email": { "type": ["string", "null"] }, "guest": { "type": "boolean" }, "state": { "type": "string" }, "note": { "type": ["string", "null"] }, "responded_at": { "type": ["string", "null"], "format": "date-time" } }
                }
              },
              "agent_reviews": {
                "type": "array",
                "description": "Advisory agent verdicts (latest per credential), never counted toward required approvals.",
                "items": { "type": "object", "properties": { "via": { "type": "string" }, "verdict": { "type": "string", "enum": ["approved", "changes_requested", "commented"] }, "note": { "type": ["string", "null"] }, "created_at": { "type": "string", "format": "date-time" } } }
              },
              "comments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "string", "format": "uuid" },
                    "parent_id": { "type": ["string", "null"] },
                    "author": { "type": "string" },
                    "via": { "type": ["string", "null"], "description": "\"via API key “X”\" / \"via <app>\" for agent comments; null for people." },
                    "quote": { "type": ["string", "null"] },
                    "body": { "type": "string" },
                    "resolved": { "type": "boolean" },
                    "created_at": { "type": "string", "format": "date-time" }
                  }
                }
              }
            }
          }
        ]
      },
      "ProposalUpdateInput": {
        "type": "object",
        "description": "At least one field. `content_markdown` XOR `edits` (edits apply to the proposal's current text).",
        "properties": {
          "title": { "type": "string", "minLength": 1, "maxLength": 200 },
          "description": { "type": ["string", "null"] },
          "content_markdown": { "$ref": "#/components/schemas/ContentMarkdown" },
          "edits": { "$ref": "#/components/schemas/TextEdits" }
        }
      },
      "ProposalUpdated": {
        "type": "object",
        "required": ["proposal_id", "status", "approvals_dismissed", "url"],
        "properties": {
          "proposal_id": { "type": "string", "format": "uuid" },
          "status": { "type": "string" },
          "approvals_dismissed": { "type": "boolean", "description": "A content change after approval resets the verdicts; reviewers must look again." },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "ProposalPublished": {
        "type": "object",
        "required": ["proposal_id", "status", "version", "document_id", "url"],
        "properties": {
          "proposal_id": { "type": "string", "format": "uuid" },
          "status": { "const": "published" },
          "version": { "type": "integer", "description": "The new Current version number." },
          "document_id": { "type": "string", "format": "uuid" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "CommentInput": {
        "type": "object",
        "required": ["body"],
        "description": "`parent_id` or `quote`, not both (a reply inherits its thread's anchor).",
        "properties": {
          "body": { "type": "string", "minLength": 1, "maxLength": 10000 },
          "parent_id": { "type": "string", "format": "uuid" },
          "quote": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Exact text from one paragraph of the proposal." }
        }
      },
      "CommentCreated": {
        "type": "object",
        "required": ["comment_id", "parent_id", "url", "unresolved_mentions"],
        "properties": {
          "comment_id": { "type": "string", "format": "uuid" },
          "parent_id": { "type": ["string", "null"] },
          "url": { "type": "string", "format": "uri" },
          "unresolved_mentions": { "type": "array", "items": { "type": "string" } }
        }
      },
      "VersionSelector": {
        "description": "A published version: its number (12, \"v12\"), its version id, or \"current\" (default).",
        "oneOf": [{ "type": "integer", "minimum": 1 }, { "type": "string" }]
      },
      "DocCommentInput": {
        "type": "object",
        "required": ["body"],
        "description": "A new thread needs `quote`; a reply sends `parent_id` (it joins its thread's version and anchor). `parent_id` or `quote`, not both; `version` only with `quote`.",
        "properties": {
          "body": { "type": "string", "minLength": 1, "maxLength": 10000 },
          "parent_id": { "type": "string", "format": "uuid" },
          "quote": { "type": "string", "minLength": 1, "maxLength": 5000, "description": "Exact text from one paragraph of the version." },
          "version": { "$ref": "#/components/schemas/VersionSelector" }
        }
      },
      "DocCommentCreated": {
        "type": "object",
        "required": ["comment_id", "parent_id", "version", "url", "unresolved_mentions"],
        "properties": {
          "comment_id": { "type": "string", "format": "uuid" },
          "parent_id": { "type": ["string", "null"] },
          "version": { "type": "object", "required": ["id", "number"], "properties": { "id": { "type": "string", "format": "uuid" }, "number": { "type": ["integer", "null"] } } },
          "url": { "type": "string", "format": "uri" },
          "unresolved_mentions": { "type": "array", "items": { "type": "string" } }
        }
      },
      "DocComment": {
        "type": "object",
        "required": ["id", "parent_id", "author", "guest", "guest_name", "via", "quote", "body", "resolved", "outdated", "anchor_version", "carried_forward", "created_at"],
        "properties": {
          "id": { "type": "string", "format": "uuid" },
          "parent_id": { "type": ["string", "null"] },
          "author": { "type": "string", "description": "Member name or email, or the guest's name." },
          "guest": { "type": "boolean", "description": "Written by a share-link guest (no account)." },
          "guest_name": { "type": ["string", "null"] },
          "via": { "type": ["string", "null"], "description": "Agent / AI reviewer label; null for people." },
          "quote": { "type": ["string", "null"] },
          "body": { "type": "string" },
          "resolved": { "type": "boolean" },
          "outdated": { "type": "boolean", "description": "Superseded: its quoted text is gone or its AI reviewer re-ran." },
          "anchor_version": { "type": "object", "required": ["id", "number"], "description": "The published version the comment was written on.", "properties": { "id": { "type": "string", "format": "uuid" }, "number": { "type": ["integer", "null"] } } },
          "carried_forward": { "type": "boolean", "description": "Written on an older version and carried forward onto the listed one." },
          "created_at": { "type": "string", "format": "date-time" }
        }
      },
      "DocCommentList": {
        "type": "object",
        "required": ["document", "version", "include_resolved", "comments"],
        "properties": {
          "document": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "title": { "type": "string" }, "url": { "type": "string", "format": "uri" } } },
          "version": { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "number": { "type": "integer" }, "is_current": { "type": "boolean" } } },
          "include_resolved": { "type": "boolean" },
          "comments": { "type": "array", "items": { "$ref": "#/components/schemas/DocComment" } }
        }
      },
      "VerdictInput": {
        "type": "object",
        "required": ["verdict"],
        "properties": {
          "verdict": { "type": "string", "enum": ["approve", "request_changes", "comment"] },
          "body": { "type": "string", "maxLength": 5000, "description": "Required for request_changes and comment." }
        }
      },
      "VerdictRecorded": {
        "type": "object",
        "required": ["verdict", "advisory", "counts_toward_approval", "proposal_status", "url"],
        "properties": {
          "verdict": { "type": "string", "enum": ["approved", "changes_requested", "commented"] },
          "advisory": { "const": true },
          "counts_toward_approval": { "const": false },
          "proposal_status": { "type": "string" },
          "url": { "type": "string", "format": "uri" }
        }
      },
      "FolderTarget": {
        "type": "object",
        "description": "Where in the workspace: `folder_id` (uuid) or `folder_path` (\"apis/v2\"), not both; null / \"\" = workspace root.",
        "properties": { "folder_id": { "type": ["string", "null"], "format": "uuid" }, "folder_path": { "type": ["string", "null"], "maxLength": 1000 } }
      },
      "DocCreateInput": {
        "allOf": [
          { "$ref": "#/components/schemas/FolderTarget" },
          {
            "type": "object",
            "required": ["workspace", "title"],
            "properties": {
              "workspace": { "type": "string", "description": "Workspace slug, e.g. \"eng\"." },
              "title": { "type": "string", "minLength": 1, "maxLength": 200 },
              "content_markdown": { "$ref": "#/components/schemas/ContentMarkdown", "description": "Optional first draft, opened as an \"Initial version\" proposal (needs docs:propose)." }
            }
          }
        ]
      },
      "DocCreated": {
        "type": "object",
        "required": ["document_id", "title", "slug", "workspace", "url", "proposal"],
        "properties": {
          "document_id": { "type": "string", "format": "uuid" },
          "title": { "type": "string" },
          "slug": { "type": "string" },
          "workspace": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "proposal": { "oneOf": [{ "$ref": "#/components/schemas/ProposalCreated" }, { "type": "null" }] }
        }
      },
      "DocUpdateInput": {
        "allOf": [{ "$ref": "#/components/schemas/FolderTarget" }, { "type": "object", "properties": { "title": { "type": "string", "minLength": 1, "maxLength": 200 } } }],
        "description": "`title` and/or a folder target."
      },
      "DocUpdated": {
        "type": "object",
        "required": ["document_id", "title", "slug", "url"],
        "properties": { "document_id": { "type": "string", "format": "uuid" }, "title": { "type": "string" }, "slug": { "type": "string" }, "url": { "type": "string", "format": "uri" } }
      },
      "DocDeleted": {
        "type": "object",
        "required": ["document_id", "deleted"],
        "properties": { "document_id": { "type": "string", "format": "uuid" }, "deleted": { "const": true } }
      },
      "FolderCreateInput": {
        "type": "object",
        "required": ["workspace", "name"],
        "description": "`parent_id` or `parent_path`, not both; none = workspace root.",
        "properties": {
          "workspace": { "type": "string" },
          "name": { "type": "string", "minLength": 1, "maxLength": 200 },
          "parent_id": { "type": ["string", "null"], "format": "uuid" },
          "parent_path": { "type": ["string", "null"], "maxLength": 1000 }
        }
      },
      "FolderCreated": {
        "type": "object",
        "required": ["folder_id", "name", "slug", "workspace", "parent_id"],
        "properties": {
          "folder_id": { "type": "string", "format": "uuid" },
          "name": { "type": "string" },
          "slug": { "type": "string" },
          "workspace": { "type": "string" },
          "parent_id": { "type": ["string", "null"] }
        }
      },
      "FolderUpdateInput": {
        "type": "object",
        "description": "`name` and/or `parent_id` | `parent_path` (null / \"\" = workspace root).",
        "properties": {
          "name": { "type": "string", "minLength": 1, "maxLength": 200 },
          "parent_id": { "type": ["string", "null"], "format": "uuid" },
          "parent_path": { "type": ["string", "null"], "maxLength": 1000 }
        }
      }
    }
  }
}
