{
  "openapi": "3.0.3",
  "info": {
    "title": "GC AI External API",
    "version": "1.0.0",
    "description": "The GC AI External API allows programmatic access to GC AI's chat capabilities. It's designed for integration with workflow automation tools like Zapier, Make, n8n, or custom applications.\n\n## Authentication\n\nAll API requests must include an API key in the `Authorization` header:\n\n```\nAuthorization: gcai_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n```\n\nAPI keys can be created in the GC AI app under **Settings → API**.\n\n## Multi-turn Conversations\n\nConversations can span multiple turns: pass the `chat_id` returned by a completion back on your next request to continue the same chat. See [Multi-turn Conversations](https://docs.gc.ai/api-reference/concepts/multi-turn).\n\n## Current Limitations\n\nThe following is not yet available via API:\n\n- **Interactive clarification**: the model cannot pause to ask the caller a follow-up question; the `askUserQuestions` tool is disabled on the API surface\n\n## Usage\n\nUsage is tracked and viewable in the GC AI app under **Settings → API → View Usage**.\n\n## Support\n\nFor API support, contact [support@gc.ai](mailto:support@gc.ai) or reach out to your account representative.",
    "contact": {
      "email": "support@gc.ai"
    }
  },
  "servers": [
    {
      "url": "https://app.gc.ai/api/external/v1",
      "description": "Production server"
    }
  ],
  "tags": [
    {
      "name": "Async Jobs",
      "description": "Poll the status and result of asynchronous API jobs"
    },
    {
      "name": "Chat",
      "description": "AI chat completion endpoints"
    },
    {
      "name": "Chats",
      "description": "Chat management, message history, and sharing endpoints"
    },
    {
      "name": "Contract Intelligence",
      "description": "Vault discovery and document ingestion endpoints for Contract Intelligence"
    },
    {
      "name": "Files",
      "description": "File upload and management endpoints"
    },
    {
      "name": "Folders",
      "description": "Folder management endpoints"
    },
    {
      "name": "Playbooks",
      "description": "Playbook review endpoints"
    },
    {
      "name": "Profiles",
      "description": "Personal and company profile endpoints"
    },
    {
      "name": "Projects",
      "description": "Project management endpoints"
    },
    {
      "name": "Skills",
      "description": "Skill management endpoints"
    },
    {
      "name": "Utility",
      "description": "Health check and connectivity endpoints"
    },
    {
      "name": "Usage",
      "description": "Usage and credit/billing reporting endpoints"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "API key for authentication. Format: `gcai_xxxxxxxxx`\n\nCreate API keys in the GC AI app under Settings → API."
      }
    },
    "schemas": {
      "ChatCompletionResponse": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "description": "Async job identifier"
          },
          "kind": {
            "type": "string",
            "enum": [
              "chat/completions"
            ],
            "description": "Stable job kind for this endpoint"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "succeeded",
              "failed",
              "canceled"
            ],
            "description": "Current job status"
          },
          "result": {
            "$ref": "#/components/schemas/ChatCompletionResult"
          },
          "error": {
            "type": "object",
            "nullable": true,
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ],
            "description": "Failure payload when the job has failed"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "completed_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 completion timestamp, or null when not terminal"
          }
        },
        "required": [
          "job_id",
          "kind",
          "status",
          "result",
          "error",
          "created_at",
          "completed_at"
        ]
      },
      "ChatCompletionResult": {
        "type": "object",
        "nullable": true,
        "properties": {
          "result": {
            "type": "string",
            "description": "The AI-generated response text",
            "example": "When reviewing a software license agreement, key terms to examine include:\n\n1. **License Grant** - Understand the scope of rights granted..."
          },
          "chat_id": {
            "type": "string",
            "format": "uuid",
            "description": "The chat ID. API chats stay out of chat history until you materialize them. Pass `materialize: true` on the request to surface the chat in the same call, or pass this ID to `POST /chat/{id}/materialize` afterwards. See [Chat Visibility](https://docs.gc.ai/api-reference/concepts/chat-visibility)."
          },
          "chat_url": {
            "type": "string",
            "format": "uri",
            "description": "Deep link that opens the chat in the GC AI web app. Present only when the request set `materialize: true` and the chat was surfaced, so its absence means the chat is still headless.",
            "example": "https://app.gc.ai/chat/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiDocument"
            },
            "description": "Documents produced during this completion: either edits of an attached file (the document editing tool) or newly generated files (the document or slide generation tools). Present only when at least one document was produced. Each entry exposes a new `file_id` and a signed download URL; edits also reference the preserved original via `original_file_id`."
          },
          "emails": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiEmail"
            },
            "description": "Email drafts produced during this completion by the email drafting tool. Present only when at least one email was drafted. Each entry is a structured draft (`to`, `subject`, `body`, …) ready to send via your own mail client or provider."
          },
          "diagrams": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiDiagram"
            },
            "description": "Diagrams produced during this completion by the diagram tool. Present only when at least one diagram was produced. Each entry exposes validated Mermaid source (`mermaid`) you can render with any Mermaid-compatible renderer."
          },
          "judge_approved_steps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "GC AI actions, by tool name, that the safety check approved during this completion. Present only when `auto_accept` was set and the check approved at least one step.",
            "example": [
              "projects_update"
            ]
          },
          "skipped_steps": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "GC AI actions, by tool name, that needed a person to approve them and did not run. Present only when at least one step was skipped.",
            "example": [
              "projects_create"
            ]
          }
        },
        "required": [
          "result",
          "chat_id"
        ],
        "description": "Completion payload when the job has succeeded"
      },
      "ApiDocument": {
        "type": "object",
        "properties": {
          "file_id": {
            "type": "string",
            "format": "uuid",
            "description": "The new uploaded file ID for the produced document. Use it with `POST /chat/completions` `file_ids` to apply further edits to this version. Download via `signed_url` for the finished file."
          },
          "original_file_id": {
            "type": "string",
            "format": "uuid",
            "description": "The `file_id` the changes were applied to (edits only). The original file is preserved unchanged. Omitted for newly generated documents."
          },
          "filename": {
            "type": "string",
            "description": "Filename of the produced document (edits are prefixed with `edited_`)."
          },
          "original_filename": {
            "type": "string",
            "description": "Filename of the source file the changes were applied to (edits only). Omitted for newly generated documents."
          },
          "signed_url": {
            "type": "string",
            "format": "uri",
            "description": "Time-limited direct download URL (no login required). Valid for 7 days from job completion. Download promptly; the URL is not re-minted, so re-fetching the job after expiry returns the same expired URL. For a link you intend to store or email, use `download_url` instead."
          },
          "download_url": {
            "type": "string",
            "format": "uri",
            "description": "Permanent, login-gated download link for the produced document. Unlike `signed_url` it never expires: it points at a GC AI web page that mints a fresh download for a signed-in user with access to the file, and redirects to GC AI login otherwise. Use this for links you store or email. The produced document inherits the source document's access, so it opens for whoever can already see the source: a document uploaded to the organization is org-visible, one in a project is visible to that project's members, and one in personal files stays private to the uploader. Recipients still need a GC AI login."
          }
        },
        "required": [
          "file_id",
          "filename",
          "signed_url",
          "download_url"
        ]
      },
      "ApiEmail": {
        "type": "object",
        "properties": {
          "to": {
            "type": "string",
            "description": "Recipient email address(es), comma-separated. May be an empty string when the prompt named no recipient; fill it in before sending."
          },
          "cc": {
            "type": "string",
            "description": "CC recipient email address(es), comma-separated."
          },
          "bcc": {
            "type": "string",
            "description": "BCC recipient email address(es), comma-separated."
          },
          "subject": {
            "type": "string",
            "description": "Email subject line. Always present, inferred from context when the prompt did not specify one."
          },
          "body": {
            "type": "string",
            "description": "Email body in markdown."
          },
          "plaintext_body": {
            "type": "string",
            "description": "Email body with markdown stripped, for plain-text clients."
          }
        },
        "required": [
          "to",
          "subject",
          "body",
          "plaintext_body"
        ]
      },
      "ApiDiagram": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "A short descriptive title for the diagram."
          },
          "diagram_type": {
            "type": "string",
            "description": "The semantic type of diagram, e.g. orgChart, dealStructure, workflow, timeline, sequence, entityRelationship, or general."
          },
          "mermaid": {
            "type": "string",
            "description": "The diagram source as validated Mermaid syntax. Render it with any Mermaid-compatible renderer."
          }
        },
        "required": [
          "title",
          "diagram_type",
          "mermaid"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message"
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code present on some errors (e.g. `RATE_LIMITED`, `INSUFFICIENT_CREDITS`, `TRIAL_NOT_STARTED`, `BILLING_NOT_CONFIGURED`). Branch on this rather than the human-readable `error` string."
          },
          "message": {
            "type": "string",
            "description": "Additional error details"
          },
          "details": {
            "type": "object",
            "additionalProperties": {
              "nullable": true
            },
            "description": "Validation error details (for 400 errors)"
          }
        },
        "required": [
          "error"
        ]
      },
      "ChatCompletionRequest": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "minLength": 1,
            "description": "The user's message or prompt",
            "example": "What are the key terms to look for in a software license agreement?"
          },
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Optional uploaded file IDs to attach as context for this completion. Upload files first via `POST /files`.",
            "example": [
              "123e4567-e89b-12d3-a456-426614174000"
            ]
          },
          "playbook_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "maxItems": 20,
            "description": "Optional playbook IDs to ground the completion in (up to 20). The model uses each playbook's checks and guidance to structure its review of the attached files. Discover playbooks via `GET /playbooks`.\n\nOrg-scoped keys can use org-visible and official playbooks.",
            "example": [
              "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
            ]
          },
          "playbook_id": {
            "type": "string",
            "description": "Deprecated and no longer accepted. Use `playbook_ids` (an array) instead. Requests that include this field are rejected with a 400 so the playbook is never silently dropped.",
            "deprecated": true
          },
          "skill_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Optional skill IDs to run on the first turn. Each skill's instructions are injected as context for this completion. Discover skills via `GET /skills`.\n\nOnly valid when starting a new chat; omit them when continuing with `chat_id`.",
            "example": [
              "b2c3d4e5-f6a7-4890-bcde-f12345678901"
            ]
          },
          "blocked_tools": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            },
            "maxItems": 200,
            "description": "Optional GC AI actions to leave out of this completion, by tool name. This can only remove actions the user who owns the key allows. It never adds one.",
            "example": [
              "projects_delete"
            ]
          },
          "auto_accept": {
            "type": "boolean",
            "description": "Set to `true` to let a safety check approve GC AI actions that would otherwise need a person, one call at a time. It works only when the user who owns the key has turned on the safety check. It never approves actions that delete, share or send. When the check says no, that step is skipped and listed in `skipped_steps`.",
            "example": false
          },
          "chat_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional chat ID to continue an existing conversation, from the `chat_id` of a prior completion. Omit to start a new chat.\n\nConversation state is held server-side, so send only your new `message` (plus any new `file_ids`); do **not** re-send prior turns or previously returned documents/emails/diagrams. Only one turn may be in flight per chat at a time. See [Multi-turn Conversations](https://docs.gc.ai/api-reference/concepts/multi-turn).",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional project to file the chat into. Requires write access to the project. Discover projects via `GET /projects`.\n\nThis does two things: it grounds the completion in the project's files, and it files the chat under that project. Filing alone does not make the chat visible to people, because API chats stay out of chat history until they are materialized. Pass `materialize: true` (or call `POST /chat/{id}/materialize` afterwards) for the chat to appear under `GET /projects/{id}/chats` and in the GC AI web app. See [Chat Visibility](https://docs.gc.ai/api-reference/concepts/chat-visibility).",
            "example": "d4c3b2a1-f6e5-0987-dcba-fedcba098765"
          },
          "materialize": {
            "type": "boolean",
            "description": "Surface this chat into chat history as part of the same call, instead of making a second request to `POST /chat/{id}/materialize`. Defaults to `false`, which keeps the chat headless.\n\nSet this when a person is meant to open the chat. An organization-scoped key shares the materialized chat with the whole organization, so any member can open it and keep chatting in it. A user-scoped key keeps the chat owned by the caller.\n\nOn success the response includes `chat_url`. If that field is absent, materialization did not happen and the chat is still headless; retry with `POST /chat/{id}/materialize` using the returned `chat_id`. Continuing an already-materialized chat is a no-op. See [Chat Visibility](https://docs.gc.ai/api-reference/concepts/chat-visibility).",
            "example": true
          },
          "company_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional company profile to ground the completion in, so the model has that company's context (industry, jurisdiction, regulations, risk posture). Discover company profiles via `GET /company-profiles`.\n\nThe company is fixed for the life of a chat. On a new chat, supply this to target a specific company (the only way to ground against a particular one in a multi-company organization); when omitted, a company is auto-resolved: user-scoped keys use the caller's active (default) company, and org-scoped keys use the organization's sole company, or none when there are several.\n\nWhen continuing a chat with `chat_id`, omit this to reuse the chat's company. You may echo the same `company_id`, but a different one is rejected with `409` (start a new chat to use a different company).",
            "example": "d4c3b2a1-f6e5-0987-dcba-fedcba098765"
          },
          "vault_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional Contract Intelligence vault to ground the completion in, so the model can query that vault's documents and fields. Copy the vault ID from the GC AI web app.\n\n**Authorization:** User-scoped keys need the Vault Chat permission, Contract Intelligence access, and view access to the vault. Organization-scoped keys need the organization to have Contract Intelligence entitlement; they can attach any vault in the organization because organization keys have no user identity for per-vault access checks.\n\nThe vault is fixed for the life of a chat. When continuing with `chat_id`, omit this to reuse the chat's vault. You may echo the same `vault_id`, but a different one is rejected with `409` (start a new chat to use a different vault).\n\nWhen also filing into a project (`project_id`) that is linked to a vault, `vault_id` must match that vault. A different one is rejected with `409`; omit `vault_id` to use the project's vault.",
            "example": "e5d4c3b2-a1f6-7890-bcde-f1234567890a"
          }
        },
        "required": [
          "message"
        ]
      },
      "MaterializeChatResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The chat ID"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "The chat title, if generated"
          },
          "chat_url": {
            "type": "string",
            "format": "uri",
            "description": "Deep link to open the chat in the GC AI web UI"
          },
          "materialized_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the chat was materialized"
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Project the chat is filed under, or null if unfiled"
          }
        },
        "required": [
          "id",
          "title",
          "chat_url",
          "materialized_at",
          "project_id"
        ]
      },
      "MaterializeChatRequest": {
        "type": "object",
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "File the chat into this project while materializing it. Requires write access to the project. Omit to leave the chat unfiled."
          }
        }
      },
      "ChatSearchResponse": {
        "type": "object",
        "properties": {
          "chats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatSearchResult"
            },
            "description": "Chats matching the query. Title-substring matches first, then semantic (vector) matches in relevance order, de-duplicated and capped at `limit`."
          },
          "soft_threshold_fallback": {
            "type": "boolean",
            "description": "True when no semantic match cleared the relevance cutoff and the response includes the closest below-threshold candidates instead of omitting them."
          }
        },
        "required": [
          "chats",
          "soft_threshold_fallback"
        ]
      },
      "ChatSearchResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique chat identifier"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Chat title, or null if untitled"
          },
          "summary": {
            "type": "string",
            "nullable": true,
            "description": "AI-generated summary of the chat, if any"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "title",
          "summary",
          "updated_at"
        ]
      },
      "ChatListResponse": {
        "type": "object",
        "properties": {
          "chats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "chats",
          "pagination"
        ]
      },
      "ChatResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique chat identifier"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Chat title, or null if untitled"
          },
          "summary": {
            "type": "string",
            "nullable": true,
            "description": "AI-generated summary, or null"
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Associated project ID, or null"
          },
          "is_public": {
            "type": "boolean",
            "description": "Whether the chat has a public share link"
          },
          "is_access_controlled": {
            "type": "boolean",
            "description": "When true, only the creator and explicitly granted users can see the chat"
          },
          "source": {
            "type": "string",
            "nullable": true,
            "description": "Origin of the chat (web, api, microsoft-word)"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "title",
          "summary",
          "project_id",
          "is_public",
          "is_access_controlled",
          "source",
          "created_at",
          "updated_at"
        ]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "number",
            "description": "Page size"
          },
          "offset": {
            "type": "number",
            "description": "Current offset"
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether more results exist"
          }
        },
        "required": [
          "limit",
          "offset",
          "has_more"
        ]
      },
      "UpdateChatRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "New chat title"
          },
          "summary": {
            "type": "string",
            "nullable": true,
            "description": "New chat summary"
          },
          "project_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Move to a project (UUID) or remove from project (null)"
          }
        }
      },
      "DuplicateResponse": {
        "type": "object",
        "properties": {
          "chat": {
            "$ref": "#/components/schemas/ChatResponse"
          }
        },
        "required": [
          "chat"
        ]
      },
      "DuplicateChatRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "description": "Title for the duplicate (defaults to source title with \"Copy of\" prefix)"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Place the duplicate in a different project"
          }
        }
      },
      "MessageListResponse": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "messages",
          "pagination"
        ]
      },
      "MessageResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique message identifier"
          },
          "role": {
            "type": "string",
            "description": "Message role (user, assistant, system, tool)"
          },
          "content": {
            "type": "string",
            "nullable": true,
            "description": "Plain text content of the message"
          },
          "parts": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "additionalProperties": {
                "nullable": true
              }
            },
            "description": "Structured message parts (text, tool invocations, file references)"
          },
          "parent_id": {
            "type": "string",
            "nullable": true,
            "description": "Parent message ID for branching conversations"
          },
          "version": {
            "type": "number",
            "description": "Message version number"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "role",
          "content",
          "parts",
          "parent_id",
          "version",
          "created_at"
        ]
      },
      "ShareResponse": {
        "type": "object",
        "properties": {
          "share_url": {
            "type": "string",
            "description": "Public share URL"
          },
          "is_public": {
            "type": "boolean",
            "description": "Always true on success"
          },
          "expires_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 expiry, or null when the link never expires."
          }
        },
        "required": [
          "share_url",
          "is_public",
          "expires_at"
        ]
      },
      "ShareRequest": {
        "type": "object",
        "properties": {
          "expires_in": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Link lifetime in seconds from now."
          },
          "expires_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Absolute ISO 8601 expiry. Explicit null means the link never expires."
          }
        }
      },
      "FileResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique file identifier"
          },
          "name": {
            "type": "string",
            "description": "Original filename"
          },
          "size": {
            "type": "number",
            "description": "File size in bytes"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the file",
            "example": "application/pdf"
          },
          "status": {
            "type": "string",
            "enum": [
              "extracting",
              "embedding",
              "ready",
              "failed"
            ],
            "description": "Current processing status of the file"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "folder_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Folder the file belongs to"
          },
          "extraction_error": {
            "type": "string",
            "description": "Error message if extraction failed"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project the file is linked to, if uploaded with project_id"
          },
          "warning": {
            "type": "string",
            "description": "Present when the file was uploaded successfully but a secondary operation (e.g. project linking) failed"
          }
        },
        "required": [
          "id",
          "name",
          "size",
          "content_type",
          "status",
          "created_at"
        ]
      },
      "FileUploadRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "The file to upload"
          },
          "folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "Target folder ID. Defaults to the user's \"My Files\" folder. Mutually exclusive with `project_id` and `scope`."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Upload the file into a project. The file is placed in the project's upload folder and linked to the project. Mutually exclusive with `folder_id` and `scope`."
          },
          "scope": {
            "type": "string",
            "enum": [
              "my-files",
              "organization"
            ],
            "description": "Upload to the root of a meta-collection (\"my-files\" or \"organization\"). Mutually exclusive with `folder_id` and `project_id`. `shared-with-me` is not valid for upload.",
            "example": "my-files"
          }
        },
        "required": [
          "file"
        ]
      },
      "FileSearchResponse": {
        "type": "object",
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchedFile"
            },
            "description": "Files matching the query, ranked by hybrid (vector + keyword) relevance. At most 100 results."
          }
        },
        "required": [
          "files"
        ]
      },
      "SearchedFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique file identifier"
          },
          "name": {
            "type": "string",
            "description": "Original filename"
          },
          "size": {
            "type": "number",
            "description": "File size in bytes"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the file"
          },
          "status": {
            "type": "string",
            "enum": [
              "extracting",
              "embedding",
              "ready",
              "failed"
            ],
            "description": "Current processing status"
          },
          "folder_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Parent folder ID, or null if the file is at the root"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "size",
          "content_type",
          "status",
          "folder_id",
          "created_at"
        ]
      },
      "UpdateFileRequest": {
        "type": "object",
        "properties": {
          "folder_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Target folder ID to move the file to. Pass null to move to the root."
          }
        },
        "required": [
          "folder_id"
        ]
      },
      "InitiateUploadResponse": {
        "type": "object",
        "properties": {
          "upload_id": {
            "type": "string",
            "format": "uuid",
            "description": "Opaque identifier for this upload session. Use it in the part and complete requests."
          },
          "part_size": {
            "type": "number",
            "description": "Recommended part size in bytes. Split the file into parts no larger than this for reliable transfers."
          },
          "max_parts": {
            "type": "number",
            "description": "Maximum number of parts allowed for this session. Part numbers run from 1 to this value."
          },
          "expires_at": {
            "type": "string",
            "description": "ISO 8601 timestamp after which the session expires. Upload all parts and call complete before this."
          }
        },
        "required": [
          "upload_id",
          "part_size",
          "max_parts",
          "expires_at"
        ]
      },
      "InitiateUploadRequest": {
        "type": "object",
        "properties": {
          "file_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Original filename, including extension.",
            "example": "msa-2026.pdf"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the file. When omitted, it is derived from the filename extension.",
            "example": "application/pdf"
          },
          "size": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "Total size of the complete file in bytes. Validated up front against the file-size limit so oversized uploads fail before any parts are sent.",
            "example": 12582912
          },
          "folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "Target folder ID. Defaults to the user's \"My Files\" folder. Mutually exclusive with `project_id` and `scope`."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Upload the file into a project. The file is placed in the project's upload folder and linked to the project. Mutually exclusive with `folder_id` and `scope`."
          },
          "scope": {
            "type": "string",
            "enum": [
              "my-files",
              "organization"
            ],
            "description": "Upload to the root of a meta-collection (\"my-files\" or \"organization\"). Mutually exclusive with `folder_id` and `project_id`. User-scoped keys only.",
            "example": "my-files"
          }
        },
        "required": [
          "file_name",
          "size"
        ]
      },
      "UploadPartResponse": {
        "type": "object",
        "properties": {
          "upload_id": {
            "type": "string",
            "format": "uuid"
          },
          "part_number": {
            "type": "number",
            "description": "The part just stored."
          },
          "size": {
            "type": "number",
            "description": "Bytes received for this part."
          }
        },
        "required": [
          "upload_id",
          "part_number",
          "size"
        ]
      },
      "CompleteUploadRequest": {
        "type": "object",
        "properties": {
          "part_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 32,
            "description": "The total number of parts you uploaded. Parts must be a contiguous run from 1 to this value; completion fails if any are missing.",
            "example": 3
          }
        },
        "required": [
          "part_count"
        ]
      },
      "AbortUploadResponse": {
        "type": "object",
        "properties": {
          "upload_id": {
            "type": "string",
            "format": "uuid"
          },
          "aborted": {
            "type": "boolean",
            "enum": [
              true
            ]
          }
        },
        "required": [
          "upload_id",
          "aborted"
        ]
      },
      "FolderListResponse": {
        "type": "object",
        "properties": {
          "folders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Folder"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "folders",
          "pagination"
        ]
      },
      "Folder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique folder identifier"
          },
          "name": {
            "type": "string",
            "description": "Folder name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Folder description, or null if unset"
          },
          "path": {
            "type": "string",
            "description": "Path through ancestors visible to the requester. Inaccessible ancestors are skipped, so this may not reflect absolute depth. Use `parent_folder_id` to traverse hierarchy.",
            "example": "/My Files/Contracts"
          },
          "parent_folder_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Parent folder ID, or null for root"
          },
          "folder_type": {
            "type": "string",
            "description": "Folder type (custom, my-files, etc.)"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "path",
          "parent_folder_id",
          "folder_type",
          "created_at"
        ]
      },
      "CreateFolderRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "description": "Folder name (min 2 characters)",
            "example": "Q4 Contracts"
          },
          "description": {
            "type": "string",
            "description": "Optional description"
          },
          "parent_folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "Parent folder ID. Mutually exclusive with `scope`. If both are omitted, creates a top-level folder."
          },
          "scope": {
            "type": "string",
            "enum": [
              "my-files",
              "organization"
            ],
            "description": "Create the folder at the root of a meta-collection. Mutually exclusive with `parent_folder_id`. `shared-with-me` is not valid for create.",
            "example": "my-files"
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateFolderRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 2,
            "description": "New folder name (minimum 2 characters)"
          },
          "description": {
            "type": "string",
            "description": "New folder description"
          },
          "parent_folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "Target parent folder ID. The destination must not be the folder itself or one of its descendants."
          },
          "is_access_controlled": {
            "type": "boolean",
            "description": "Whether the folder requires explicit access grants"
          }
        }
      },
      "FolderChildrenResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FolderChild"
            },
            "description": "Direct children of the folder. Subfolders first (alphabetical), then files (alphabetical)."
          }
        },
        "required": [
          "items"
        ]
      },
      "FolderChild": {
        "oneOf": [
          {
            "allOf": [
              {
                "$ref": "#/components/schemas/Folder"
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "folder"
                    ]
                  }
                },
                "required": [
                  "type"
                ]
              }
            ]
          },
          {
            "allOf": [
              {
                "$ref": "#/components/schemas/File"
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "file"
                    ]
                  }
                },
                "required": [
                  "type"
                ]
              }
            ]
          }
        ]
      },
      "File": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique file identifier"
          },
          "name": {
            "type": "string",
            "description": "Original filename"
          },
          "size": {
            "type": "number",
            "description": "File size in bytes"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the file"
          },
          "status": {
            "type": "string",
            "enum": [
              "extracting",
              "embedding",
              "ready",
              "failed"
            ],
            "description": "Current processing status"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "size",
          "content_type",
          "status",
          "created_at"
        ]
      },
      "ProjectListResponse": {
        "type": "object",
        "properties": {
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "projects",
          "pagination"
        ]
      },
      "ProjectResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique project identifier"
          },
          "name": {
            "type": "string",
            "description": "Project name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Project description, or null if unset"
          },
          "custom_instructions": {
            "type": "string",
            "nullable": true,
            "description": "Custom instructions injected into chats opened in this project"
          },
          "is_access_controlled": {
            "type": "boolean",
            "description": "When true, only the creator and explicitly granted users can see the project. When false, any member of the organization can see it."
          },
          "my_access_level": {
            "type": "string",
            "nullable": true,
            "enum": [
              "read",
              "write",
              "admin",
              null
            ],
            "description": "Caller's access level on this project: `admin` (creator or explicitly granted admin), `write`, `read`, or `null` if the caller has no recorded grant. `null` is also returned for org-scoped keys, which carry no user identity."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "custom_instructions",
          "is_access_controlled",
          "my_access_level",
          "created_at",
          "updated_at"
        ]
      },
      "CreateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Project name (required, non-empty after trim)",
            "example": "Vendor: Acme MSA"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Optional project description"
          },
          "custom_instructions": {
            "type": "string",
            "nullable": true,
            "description": "Optional custom instructions for chats in this project"
          },
          "is_access_controlled": {
            "type": "boolean",
            "description": "When true (default), the project is visible only to the creator and explicitly granted users. When false, any member of the organization can see it."
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "New project name (non-empty after trim)",
            "example": "Vendor: Acme MSA (renamed)"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "New project description, or null to clear it"
          },
          "custom_instructions": {
            "type": "string",
            "nullable": true,
            "description": "New custom instructions for chats in this project, or null to clear them"
          }
        }
      },
      "AttachFileRequest": {
        "type": "object",
        "properties": {
          "file_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of an already-uploaded file to attach to the project"
          }
        },
        "required": [
          "file_id"
        ]
      },
      "ProjectFileListResponse": {
        "type": "object",
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectFile"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "files",
          "pagination"
        ]
      },
      "ProjectFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique file identifier"
          },
          "name": {
            "type": "string",
            "description": "Original filename"
          },
          "size": {
            "type": "number",
            "description": "File size in bytes"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the file"
          },
          "status": {
            "type": "string",
            "enum": [
              "extracting",
              "embedding",
              "ready",
              "failed"
            ],
            "description": "Current processing status"
          },
          "folder_id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Folder the file is stored in, or null"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "size",
          "content_type",
          "status",
          "folder_id",
          "created_at"
        ]
      },
      "ProjectFolderListResponse": {
        "type": "object",
        "properties": {
          "folders": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectFolder"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "folders",
          "pagination"
        ]
      },
      "ProjectFolder": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique folder identifier"
          },
          "name": {
            "type": "string",
            "description": "Folder name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Folder description, or null if unset"
          },
          "folder_type": {
            "type": "string",
            "description": "Folder type (custom, my-files, etc.)"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "folder_type"
        ]
      },
      "AttachFolderRequest": {
        "type": "object",
        "properties": {
          "folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the folder to attach. All files in the folder become available as project context."
          }
        },
        "required": [
          "folder_id"
        ]
      },
      "ProjectChatListResponse": {
        "type": "object",
        "properties": {
          "chats": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectChat"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "chats",
          "pagination"
        ]
      },
      "ProjectChat": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique chat identifier"
          },
          "title": {
            "type": "string",
            "nullable": true,
            "description": "Chat title, or null if untitled"
          },
          "summary": {
            "type": "string",
            "nullable": true,
            "description": "AI-generated summary of the chat, if any"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "title",
          "summary",
          "created_at",
          "updated_at"
        ]
      },
      "AttachChatRequest": {
        "type": "object",
        "properties": {
          "chat_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of an existing chat to file into the project"
          }
        },
        "required": [
          "chat_id"
        ]
      },
      "PlaybookListResponse": {
        "type": "object",
        "properties": {
          "playbooks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaybookSummary"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "playbooks",
          "pagination"
        ]
      },
      "PlaybookSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique playbook identifier"
          },
          "title": {
            "type": "string",
            "description": "Playbook title"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Playbook description, or null if unset"
          },
          "is_official": {
            "type": "boolean",
            "description": "Whether this is an official GC AI playbook"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "processing",
              "completed",
              "failed"
            ],
            "description": "Playbook processing status"
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "is_official",
          "status",
          "created_at"
        ]
      },
      "Playbook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique playbook identifier"
          },
          "title": {
            "type": "string",
            "description": "Playbook title"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Playbook description, or null if unset"
          },
          "guide": {
            "type": "string",
            "nullable": true,
            "description": "Free-text guidance applied across the whole playbook when it runs, or null if unset."
          },
          "is_official": {
            "type": "boolean",
            "description": "Whether this is an official GC AI playbook"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "processing",
              "completed",
              "failed"
            ],
            "description": "Playbook processing status"
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "guide",
          "is_official",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "CreatePlaybookRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "Playbook title (required, non-empty).",
            "example": "Vendor NDA review"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Optional human-facing description."
          },
          "guide": {
            "type": "string",
            "nullable": true,
            "description": "Optional free-text guidance applied across the whole playbook when it runs."
          }
        },
        "required": [
          "title"
        ]
      },
      "UpdatePlaybookRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "New title (non-empty)."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "New description, or null to clear."
          },
          "guide": {
            "type": "string",
            "nullable": true,
            "description": "New guide text, or null to clear."
          }
        }
      },
      "DeletePlaybookResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "RunPlaybookResponse": {
        "type": "object",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "description": "Async job identifier"
          },
          "kind": {
            "type": "string",
            "enum": [
              "playbooks/run"
            ],
            "description": "Stable job kind for this endpoint"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "succeeded",
              "failed",
              "canceled"
            ],
            "description": "Current job status"
          },
          "result": {
            "$ref": "#/components/schemas/RunPlaybookResult"
          },
          "error": {
            "type": "object",
            "nullable": true,
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ],
            "description": "Failure payload when the job has failed"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "completed_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 completion timestamp, or null when not terminal"
          }
        },
        "required": [
          "job_id",
          "kind",
          "status",
          "result",
          "error",
          "created_at",
          "completed_at"
        ]
      },
      "RunPlaybookResult": {
        "type": "object",
        "nullable": true,
        "properties": {
          "playbookTitle": {
            "type": "string"
          },
          "totalChecks": {
            "type": "number"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaybookCheckResult"
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "flags": {
                "type": "number"
              },
              "fallbacks": {
                "type": "number"
              },
              "passes": {
                "type": "number"
              },
              "errors": {
                "type": "number"
              }
            },
            "required": [
              "flags",
              "fallbacks",
              "passes",
              "errors"
            ]
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiDocument"
            },
            "description": "Redlined documents produced from the review's suggested revisions, applied as tracked changes. Present only when a single DOCX file was reviewed and at least one revision applied. Works with either a user-scoped or an org-scoped key. The original file is preserved; each entry exposes a new `file_id` and a signed download URL."
          }
        },
        "required": [
          "playbookTitle",
          "totalChecks",
          "results",
          "summary"
        ],
        "description": "Playbook review payload when the job has succeeded"
      },
      "PlaybookCheckResult": {
        "type": "object",
        "properties": {
          "checkId": {
            "type": "string",
            "format": "uuid"
          },
          "checkTitle": {
            "type": "string"
          },
          "evaluationResult": {
            "type": "string",
            "description": "Evaluation outcome. One of `Pass`, `Flag`, `Fallback`, or `Error`."
          },
          "documentPosition": {
            "type": "number",
            "nullable": true,
            "description": "Position in the document where the matched language was found, or null if not anchored."
          }
        },
        "required": [
          "checkId",
          "checkTitle",
          "evaluationResult",
          "documentPosition"
        ],
        "additionalProperties": {
          "nullable": true
        },
        "description": "Per-check evaluation result. Additional fields (e.g. `analysis`, `revisions`) may appear depending on the check type."
      },
      "RunPlaybookRequest": {
        "type": "object",
        "properties": {
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "description": "IDs of uploaded files to review. Files must be in `ready` status. At least one file is required."
          },
          "review_mode": {
            "type": "string",
            "enum": [
              "first-party",
              "third-party"
            ],
            "default": "third-party",
            "description": "Whose perspective the review takes. `third-party` reviews a counterparty document (default); `first-party` reviews your own."
          },
          "representing_party": {
            "type": "string",
            "default": "our company",
            "description": "Name of the party the review represents (default: \"our company\")."
          },
          "check_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "description": "Optional subset of check IDs to evaluate. Omit to run every check in the playbook."
          },
          "company_id": {
            "type": "string",
            "format": "uuid",
            "description": "Optional company profile to ground the review in, so the checks have that company's context (industry, jurisdiction, regulations, risk posture). Discover company profiles via `GET /company-profiles`.\n\nOpt-in: supply this to ground the review against a specific company. When omitted, the review runs with no company profile. This is separate from `representing_party`, which stays free text."
          }
        },
        "required": [
          "file_ids"
        ]
      },
      "CallerIdentityResponse": {
        "type": "object",
        "properties": {
          "token_type": {
            "type": "string",
            "enum": [
              "user",
              "organization"
            ],
            "description": "Scope of the API key making the request. `user` for personal keys (`u:gcai_...`), `organization` for org keys (`gcai_...`)."
          },
          "api_key_id": {
            "type": "string",
            "description": "Identifier of the API key used to authenticate the request"
          },
          "organization": {
            "$ref": "#/components/schemas/CallerOrganization"
          },
          "user": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "integer",
                "description": "Calling user identifier"
              },
              "email": {
                "type": "string",
                "nullable": true,
                "description": "Calling user email, or null if unset"
              }
            },
            "required": [
              "id",
              "email"
            ],
            "description": "The authenticated user, or null for org-scoped keys (which carry no user identity)."
          }
        },
        "required": [
          "token_type",
          "api_key_id",
          "organization",
          "user"
        ]
      },
      "CallerOrganization": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Organization the key belongs to"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Organization display name, or null if unset"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "PersonalProfileResponse": {
        "type": "object",
        "properties": {
          "preferred_name": {
            "type": "string",
            "nullable": true,
            "description": "Preferred name to use in chats, or null if unset"
          },
          "use_name_in_chats": {
            "type": "boolean",
            "description": "Whether the AI should address the user by name"
          },
          "role_title": {
            "type": "string",
            "nullable": true,
            "description": "Job title or role (e.g. \"General Counsel\"), or null"
          },
          "jurisdiction_focus": {
            "type": "string",
            "nullable": true,
            "description": "Primary jurisdiction the user practices in, or null"
          },
          "practice_areas": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Practice areas the user focuses on (may be empty)"
          },
          "custom_instructions": {
            "type": "string",
            "nullable": true,
            "description": "Custom instructions injected into every chat, or null"
          },
          "privilege_marking_enabled": {
            "type": "boolean",
            "description": "Whether AI responses include an attorney-client privilege disclaimer"
          },
          "privilege_marking_text": {
            "type": "string",
            "nullable": true,
            "description": "The privilege disclaimer text, or null if unset"
          },
          "enter_to_submit": {
            "type": "boolean",
            "description": "Whether the chat composer submits on Enter instead of Cmd/Ctrl+Enter"
          },
          "document_author_name": {
            "type": "string",
            "nullable": true,
            "description": "Name stamped on tracked changes when AI edits are applied, or null"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the personal profile is active and applied to chats"
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp, or null if never saved"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-update timestamp, or null if never saved"
          }
        },
        "required": [
          "preferred_name",
          "use_name_in_chats",
          "role_title",
          "jurisdiction_focus",
          "practice_areas",
          "custom_instructions",
          "privilege_marking_enabled",
          "privilege_marking_text",
          "enter_to_submit",
          "document_author_name",
          "enabled",
          "created_at",
          "updated_at"
        ]
      },
      "UpdatePersonalProfileRequest": {
        "type": "object",
        "properties": {
          "preferred_name": {
            "type": "string",
            "nullable": true,
            "maxLength": 100,
            "description": "Preferred name to use in chats. Send null to clear."
          },
          "use_name_in_chats": {
            "type": "boolean",
            "description": "Whether the AI should address the user by name"
          },
          "role_title": {
            "type": "string",
            "nullable": true,
            "maxLength": 200,
            "description": "Job title or role. Send null to clear."
          },
          "jurisdiction_focus": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Primary jurisdiction. Send null to clear."
          },
          "practice_areas": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string",
              "maxLength": 100
            },
            "maxItems": 20,
            "description": "Practice areas (max 20). Send null or [] to clear."
          },
          "custom_instructions": {
            "type": "string",
            "nullable": true,
            "maxLength": 4000,
            "description": "Custom instructions for every chat. Send null to clear."
          },
          "privilege_marking_enabled": {
            "type": "boolean",
            "description": "Whether AI responses include an attorney-client privilege disclaimer"
          },
          "privilege_marking_text": {
            "type": "string",
            "nullable": true,
            "maxLength": 200,
            "description": "Privilege disclaimer text. Send null to clear."
          },
          "enter_to_submit": {
            "type": "boolean",
            "description": "Whether the chat composer submits on Enter instead of Cmd/Ctrl+Enter"
          },
          "document_author_name": {
            "type": "string",
            "nullable": true,
            "maxLength": 100,
            "description": "Name stamped on AI tracked changes. Send null to clear."
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the personal profile is active"
          }
        }
      },
      "CompanyProfileResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique company profile identifier"
          },
          "name": {
            "type": "string",
            "description": "Company name"
          },
          "dba_name": {
            "type": "string",
            "nullable": true,
            "description": "Doing-business-as name, or null"
          },
          "industry": {
            "type": "string",
            "nullable": true,
            "description": "Industry sector, or null"
          },
          "size": {
            "type": "string",
            "nullable": true,
            "description": "Company size band (e.g. \"51-200\"), or null"
          },
          "location": {
            "type": "string",
            "nullable": true,
            "description": "Primary office location, or null"
          },
          "incorporation_country": {
            "type": "string",
            "nullable": true,
            "description": "Country of incorporation, or null"
          },
          "incorporation_state": {
            "type": "string",
            "nullable": true,
            "description": "State/province of incorporation, or null"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Short company description, or null"
          },
          "revenue": {
            "type": "string",
            "nullable": true,
            "description": "Annual revenue band, or null"
          },
          "legal_matters": {
            "type": "string",
            "nullable": true,
            "description": "Typical legal matters the company handles, or null"
          },
          "regulations": {
            "type": "string",
            "nullable": true,
            "description": "Key regulations the company must comply with, or null"
          },
          "risk_tolerance": {
            "type": "string",
            "nullable": true,
            "description": "Risk tolerance level (e.g. \"Low\"), or null"
          },
          "additional_info": {
            "type": "string",
            "nullable": true,
            "description": "Free-form additional context for the AI, or null"
          },
          "customer_types": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string"
            },
            "description": "Types of customers the company serves, or null"
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "dba_name",
          "industry",
          "size",
          "location",
          "incorporation_country",
          "incorporation_state",
          "description",
          "revenue",
          "legal_matters",
          "regulations",
          "risk_tolerance",
          "additional_info",
          "customer_types",
          "created_at",
          "updated_at"
        ]
      },
      "UpdateCompanyProfileRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Company name (cannot be cleared, max 255 chars)"
          },
          "dba_name": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Doing-business-as name. Send null to clear."
          },
          "industry": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Industry sector. Send null to clear."
          },
          "size": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Company size band. Send null to clear."
          },
          "location": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Primary office location. Send null to clear."
          },
          "incorporation_country": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Country of incorporation. Send null to clear."
          },
          "incorporation_state": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "State/province of incorporation. Send null to clear."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 5000,
            "description": "Short company description. Send null to clear."
          },
          "revenue": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Annual revenue band. Send null to clear."
          },
          "legal_matters": {
            "type": "string",
            "nullable": true,
            "maxLength": 10000,
            "description": "Typical legal matters. Send null to clear."
          },
          "regulations": {
            "type": "string",
            "nullable": true,
            "maxLength": 10000,
            "description": "Key regulations. Send null to clear."
          },
          "risk_tolerance": {
            "type": "string",
            "nullable": true,
            "maxLength": 255,
            "description": "Risk tolerance level. Send null to clear."
          },
          "additional_info": {
            "type": "string",
            "nullable": true,
            "maxLength": 10000,
            "description": "Free-form additional context. Send null to clear."
          },
          "customer_types": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "string",
              "maxLength": 255
            },
            "maxItems": 100,
            "description": "Types of customers served. Send null or [] to clear."
          }
        }
      },
      "CompanyProfileListResponse": {
        "type": "object",
        "properties": {
          "company_profiles": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CompanyProfileResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "company_profiles",
          "pagination"
        ]
      },
      "SkillListResponse": {
        "type": "object",
        "properties": {
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "skills",
          "pagination"
        ]
      },
      "SkillSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique skill identifier"
          },
          "name": {
            "type": "string",
            "description": "Skill name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Short description of what the skill does, or null if unset"
          },
          "visibility": {
            "type": "string",
            "enum": [
              "private",
              "organization"
            ],
            "description": "`private` (only the creator and users it has been explicitly shared with) or `organization` (visible to everyone in the org). Official skills report `organization`."
          },
          "is_official": {
            "type": "boolean",
            "description": "Whether this is an official GC AI skill. Official skills are read-only and cannot be edited or deleted via the API."
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillFile"
            },
            "description": "Files attached to the skill as reference context"
          },
          "legal_category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "commercial_contracts",
              "privacy_compliance",
              "employment",
              "procurement",
              "governance",
              "product_and_ip_counsel",
              "legal_operations",
              "real_estate_and_insurance",
              "litigation_and_disputes",
              "regulatory_and_compliance",
              "other",
              null
            ],
            "description": "The area of law the skill is grouped under, or null when it is uncategorized"
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-updated timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "visibility",
          "is_official",
          "files",
          "legal_category",
          "created_at",
          "updated_at"
        ]
      },
      "SkillFile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Attached file identifier"
          },
          "name": {
            "type": "string",
            "description": "Attached file name"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "Skill": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique skill identifier"
          },
          "name": {
            "type": "string",
            "description": "Skill name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Short description of what the skill does, or null if unset"
          },
          "content": {
            "type": "string",
            "description": "The skill instructions: the prompt text the model receives when the skill runs"
          },
          "visibility": {
            "type": "string",
            "enum": [
              "private",
              "organization"
            ],
            "description": "`private` (only the creator and users it has been explicitly shared with) or `organization` (visible to everyone in the org). Official skills report `organization`."
          },
          "is_official": {
            "type": "boolean",
            "description": "Whether this is an official GC AI skill. Official skills are read-only and cannot be edited or deleted via the API."
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillFile"
            },
            "description": "Files attached to the skill as reference context"
          },
          "legal_category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "commercial_contracts",
              "privacy_compliance",
              "employment",
              "procurement",
              "governance",
              "product_and_ip_counsel",
              "legal_operations",
              "real_estate_and_insurance",
              "litigation_and_disputes",
              "regulatory_and_compliance",
              "other",
              null
            ],
            "description": "The area of law the skill is grouped under, or null when it is uncategorized"
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-updated timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "content",
          "visibility",
          "is_official",
          "files",
          "legal_category",
          "created_at",
          "updated_at"
        ]
      },
      "CreateSkillRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Skill name (required, 1-255 chars)",
            "example": "NDA Risk Reviewer"
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100000,
            "description": "The skill instructions: the prompt text the model receives when the skill runs (required, 1-100000 chars)",
            "example": "Review the attached NDA and flag any clauses that deviate from our standard positions."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 1000,
            "description": "Optional short description of what the skill does (max 1000 chars)"
          },
          "visibility": {
            "type": "string",
            "enum": [
              "private",
              "organization"
            ],
            "description": "Skill visibility. Defaults to `private` for user-scoped keys. Org-scoped keys always create `organization`-visible skills (they have no owning user)."
          },
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "maxItems": 50,
            "description": "Optional uploaded file IDs to attach as reference context (max 50). Upload files first via `POST /files`."
          },
          "legal_category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "commercial_contracts",
              "privacy_compliance",
              "employment",
              "procurement",
              "governance",
              "product_and_ip_counsel",
              "legal_operations",
              "real_estate_and_insurance",
              "litigation_and_disputes",
              "regulatory_and_compliance",
              "other",
              null
            ],
            "description": "Optional area of law to group the skill under. Omit or pass `null` to leave it uncategorized."
          }
        },
        "required": [
          "name",
          "content"
        ]
      },
      "UpdateSkillRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Updated skill name (1-255 chars)"
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100000,
            "description": "Updated skill instructions (1-100000 chars)"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 1000,
            "description": "Updated description (max 1000 chars). Pass `null` or an empty string to clear it."
          },
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "maxItems": 50,
            "description": "Replacement set of attached file IDs (max 50). When provided, the skill's attachments are reconciled to exactly this list. Omit to leave attachments unchanged."
          },
          "legal_category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "commercial_contracts",
              "privacy_compliance",
              "employment",
              "procurement",
              "governance",
              "product_and_ip_counsel",
              "legal_operations",
              "real_estate_and_insurance",
              "litigation_and_disputes",
              "regulatory_and_compliance",
              "other",
              null
            ],
            "description": "Updated area of law to group the skill under. Pass `null` to clear it. Omit to leave it unchanged."
          }
        }
      },
      "DeleteSkillResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "PlaybookCheckListResponse": {
        "type": "object",
        "properties": {
          "checks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaybookCheck"
            }
          }
        },
        "required": [
          "checks"
        ]
      },
      "PlaybookCheck": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique check identifier"
          },
          "title": {
            "type": "string",
            "description": "Check title"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Optional internal description, or null if unset"
          },
          "importance": {
            "type": "string",
            "nullable": true,
            "enum": [
              "low",
              "medium",
              "high",
              null
            ],
            "description": "Priority of this check within the playbook, or null if unset"
          },
          "positions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaybookCheckPosition"
            },
            "description": "The check's positions: one standard stance plus any fallbacks."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "importance",
          "positions",
          "created_at",
          "updated_at"
        ]
      },
      "PlaybookCheckPosition": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "standard",
              "fallback"
            ],
            "description": "The primary stance (`standard`) or an alternative fallback the reviewer may accept (`fallback`). Each check has exactly one standard position."
          },
          "guidance": {
            "type": "string",
            "nullable": true,
            "description": "The review stance for this position: what to require, accept, or flag. May be null for positions authored in the web app without guidance."
          }
        },
        "required": [
          "type",
          "guidance"
        ]
      },
      "CreatePlaybookCheckRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "Check title (required, non-empty).",
            "example": "Limitation of liability"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Optional internal description."
          },
          "importance": {
            "type": "string",
            "nullable": true,
            "enum": [
              "low",
              "medium",
              "high",
              null
            ],
            "description": "Optional priority within the playbook."
          },
          "positions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaybookCheckPositionInput"
            },
            "minItems": 1,
            "description": "The check's positions: exactly one `standard` position plus any number of `fallback` positions."
          }
        },
        "required": [
          "title",
          "positions"
        ]
      },
      "PlaybookCheckPositionInput": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "standard",
              "fallback"
            ],
            "description": "Use `standard` for the primary stance and `fallback` for an alternative the reviewer may accept."
          },
          "guidance": {
            "type": "string",
            "minLength": 1,
            "description": "The review stance for this position: what to require, accept, or flag.",
            "example": "Require a mutual liability cap at 12 months of fees."
          }
        },
        "required": [
          "type",
          "guidance"
        ]
      },
      "UpdatePlaybookCheckRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "description": "New title (non-empty)."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "New description, or null to clear."
          },
          "importance": {
            "type": "string",
            "nullable": true,
            "enum": [
              "low",
              "medium",
              "high",
              null
            ],
            "description": "New priority, or null to clear."
          },
          "positions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PlaybookCheckPositionInput"
            },
            "minItems": 1,
            "description": "Replacement set of positions (full desired state). Omit to leave positions unchanged."
          }
        }
      },
      "DeletePlaybookCheckResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "ReorderPlaybookChecksResponse": {
        "type": "object",
        "properties": {
          "reordered": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "reordered"
        ]
      },
      "ReorderPlaybookChecksRequest": {
        "type": "object",
        "properties": {
          "check_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "description": "All check IDs of the playbook in the desired order. Checks omitted from the list keep their existing order relative to one another."
          }
        },
        "required": [
          "check_ids"
        ]
      },
      "VaultListResponse": {
        "type": "object",
        "properties": {
          "vaults": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "vaults",
          "pagination"
        ]
      },
      "VaultResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique vault identifier"
          },
          "name": {
            "type": "string",
            "description": "Vault name",
            "example": "Vendor SaaS agreements"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Vault description, or null if unset"
          },
          "my_role": {
            "type": "string",
            "enum": [
              "owner",
              "editor",
              "viewer"
            ],
            "description": "Caller's role in this vault: `owner` (manage members and settings), `editor` (add documents and edit extracted data), or `viewer` (read and annotate). A vault the caller reaches only through organization-wide visibility reports `viewer`. The role is not the whole story for writes: adding documents also needs the organization-level permission to manage vaults, so a caller can hold `editor` here and still receive `403` from `POST /vaults/{id}/documents`."
          },
          "is_access_controlled": {
            "type": "boolean",
            "description": "When true, only vault members can see the vault. When false, any member of the organization with organization-wide vault read can see it."
          },
          "document_count": {
            "type": "number",
            "description": "Documents that have finished scanning in this vault. Documents still being read are not counted yet."
          },
          "setup_completed_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp when guided setup finished, or null while the vault is still in setup. Documents added to a vault in setup are stored but not scanned until setup finishes. Vaults created through `POST /vaults` finish setup immediately, so this is always set for them."
          },
          "archived_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp when the vault was archived, or null while it is live. Archived vaults are hidden from the default list and reject changes until `POST /vaults/{id}/restore` runs."
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "my_role",
          "is_access_controlled",
          "document_count",
          "setup_completed_at",
          "archived_at",
          "created_at",
          "updated_at"
        ]
      },
      "VaultCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Vault name. Omit it and GC AI allocates the next free default name (`New Vault`, `New Vault (2)`, and so on).",
            "example": "Vendor SaaS agreements"
          },
          "description": {
            "type": "string",
            "maxLength": 1000,
            "description": "Optional description shown beside the vault name"
          }
        }
      },
      "VaultUpdateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "New vault name"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 1000,
            "description": "New description. Send `null` to clear it."
          },
          "is_access_controlled": {
            "type": "boolean",
            "description": "When true, only vault members can see the vault. When false, any member of the organization with organization-wide vault read can see it as a viewer. Changing this adds and removes no members: it only opens or closes the organization-wide path."
          }
        }
      },
      "VaultDeleteResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "VaultMemberListResponse": {
        "type": "object",
        "properties": {
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultMember"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "members",
          "pagination"
        ]
      },
      "VaultMember": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "integer",
            "description": "GC AI user ID of the member. This is the same identifier `GET /me` reports for the calling user, so a caller can pick their own row out of the list."
          },
          "email": {
            "type": "string",
            "nullable": true,
            "description": "Member email address, or null when the account has none on file."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Member display name, preferring the name they chose for themselves. Null when the account has no name on file."
          },
          "role": {
            "type": "string",
            "nullable": true,
            "enum": [
              "owner",
              "editor",
              "viewer",
              null
            ],
            "description": "The member's role in this vault: `owner` (manage members and settings), `editor` (add documents and edit extracted data), or `viewer` (read and annotate). Null on the rare stored value GC AI cannot read as a role. Such a grant carries no permissions at all, so remove it and add the person again."
          },
          "added_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp when the member was added, or null for grants written before GC AI recorded that."
          }
        },
        "required": [
          "user_id",
          "email",
          "name",
          "role",
          "added_at"
        ]
      },
      "AddVaultMemberRequest": {
        "type": "object",
        "properties": {
          "user_id": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "description": "GC AI user ID of the person to add, as `user_id` from `GET /vaults/{id}/members` or `id` from `GET /me`. Send this or `email`."
          },
          "email": {
            "type": "string",
            "maxLength": 320,
            "format": "email",
            "description": "Email address of the person to add. It has to belong to someone who is already a member of your organization. Send this or `user_id`.",
            "example": "dana@example.com"
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "editor",
              "viewer"
            ],
            "default": "editor",
            "description": "Role to grant. Defaults to `editor`."
          }
        }
      },
      "UpdateVaultMemberRoleRequest": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "editor",
              "viewer"
            ],
            "description": "The role this member should hold from now on."
          }
        },
        "required": [
          "role"
        ]
      },
      "RemoveVaultMemberResponse": {
        "type": "object",
        "properties": {
          "removed": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "removed"
        ]
      },
      "VaultDocumentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique file identifier for the uploaded document. Poll `GET /files/{id}` until `status` is `ready`."
          },
          "vault_id": {
            "type": "string",
            "format": "uuid",
            "description": "The vault the document was added to"
          },
          "name": {
            "type": "string",
            "description": "Original filename"
          },
          "size": {
            "type": "number",
            "description": "File size in bytes"
          },
          "content_type": {
            "type": "string",
            "description": "MIME type of the document",
            "example": "application/pdf"
          },
          "status": {
            "type": "string",
            "enum": [
              "extracting",
              "embedding",
              "ready",
              "failed"
            ],
            "description": "Text-extraction status of the document"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          }
        },
        "required": [
          "id",
          "vault_id",
          "name",
          "size",
          "content_type",
          "status",
          "created_at"
        ]
      },
      "VaultDocumentUploadRequest": {
        "type": "object",
        "properties": {
          "file": {
            "type": "string",
            "format": "binary",
            "description": "The document to add to the vault. PDF, Word (.doc/.docx), and plain text (.txt) only."
          }
        },
        "required": [
          "file"
        ]
      },
      "VaultDocumentListResponse": {
        "type": "object",
        "properties": {
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultDocumentRow"
            }
          },
          "total": {
            "type": "number",
            "nullable": true,
            "description": "Rows matching the filters across the whole vault, not just this page. Null when the request passed `include_total=false`, which skips the count."
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": [
          "documents",
          "total",
          "pagination"
        ]
      },
      "VaultDocumentRow": {
        "type": "object",
        "properties": {
          "document_id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable identifier for this row. Use it with `GET`, `DELETE`, and `POST .../restore` on this path. One upload can hold several documents (GC AI splits a bundled PDF into the agreements inside it), and each of those is its own row with its own `document_id`. A document stored before GC AI split bundled uploads carries its `file_id` here."
          },
          "file_id": {
            "type": "string",
            "format": "uuid",
            "description": "The upload this row came from: the `id` returned by `POST /vaults/{id}/documents` and the id `GET /files/{id}` takes. Rows that share a `file_id` came from one upload."
          },
          "name": {
            "type": "string",
            "description": "The name shown in the vault: the document title when the vault has named this row, and the upload filename otherwise.",
            "example": "Acme MSA (2024)"
          },
          "file_name": {
            "type": "string",
            "description": "Filename of the upload, unchanged.",
            "example": "acme-msa-2024.pdf"
          },
          "source_name": {
            "type": "string",
            "nullable": true,
            "description": "The vault source this document arrived through, such as the connected folder name. Null for a source with no name."
          },
          "source_provider": {
            "type": "string",
            "nullable": true,
            "description": "The source type, such as `manual_upload`, `google_drive`, or `sharepoint`.",
            "example": "manual_upload"
          },
          "extracted_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp of the most recent value written to this row, or null before the first value lands."
          },
          "is_extraction_active": {
            "type": "boolean",
            "description": "True while a scan of this document is queued or running, so some cells may still be empty or change. Poll the row until it is false."
          },
          "deleted_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp of the soft delete, or null for a live row. Only rows requested with `include_deleted=true` can carry a value."
          },
          "removed_as_duplicate_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp when GC AI removed this row as a copy of another document in the vault, or null. `include_deleted=true` also returns these copies, so this field says why a row with a null `deleted_at` is in that list."
          },
          "values": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/VaultDocumentCell"
            },
            "description": "One entry per column of the vault, keyed by the column `field_key`. Every row of a vault carries the same keys, so the response reads as a table. Read the keys, labels, and types from `GET /vaults/{id}/columns`."
          }
        },
        "required": [
          "document_id",
          "file_id",
          "name",
          "file_name",
          "source_name",
          "source_provider",
          "extracted_at",
          "is_extraction_active",
          "deleted_at",
          "removed_as_duplicate_at",
          "values"
        ]
      },
      "VaultDocumentCell": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "nullable": true,
            "description": "The extracted value, always a string. Structured column types carry JSON in this string: a currency cell holds `{\"amount\",\"currency\"}`, a date range holds `{\"start\",\"end\"}`, a multi-select or list holds a JSON array of strings, and a party list holds a JSON array of `{\"name\",\"entityType\"}`. A date holds `YYYY-MM-DD`. `null` means the scan found no value for this column, so a caller never has to tell an empty answer from an absent one.",
            "example": "Delaware"
          },
          "is_edited": {
            "type": "boolean",
            "description": "True when a person replaced the scanned value by hand. The `value` is theirs, not the scan output."
          },
          "edited_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp of the hand edit, or null."
          },
          "edited_by": {
            "type": "string",
            "nullable": true,
            "description": "Display name of the person who made the edit, or null."
          },
          "edited_by_user_id": {
            "type": "integer",
            "nullable": true,
            "description": "GC AI user ID of the person who made the edit, or null. Matches the `user_id` that `GET /vaults/{id}/members` reports."
          },
          "has_citations": {
            "type": "boolean",
            "description": "True when the scan recorded where in the document it read this value. Read the citations in the app; v1 does not return them."
          }
        },
        "required": [
          "value",
          "is_edited",
          "edited_at",
          "edited_by",
          "edited_by_user_id",
          "has_citations"
        ]
      },
      "VaultDocumentDeleteResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "VaultDocumentRestoreResponse": {
        "type": "object",
        "properties": {
          "restored": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "restored"
        ]
      },
      "VaultDocumentCellResponse": {
        "type": "object",
        "properties": {
          "document_id": {
            "type": "string",
            "format": "uuid",
            "description": "Document the cell belongs to"
          },
          "field_key": {
            "type": "string",
            "description": "Column key for the cell"
          },
          "cell": {
            "allOf": [
              {
                "$ref": "#/components/schemas/VaultDocumentCell"
              },
              {
                "description": "The cell after the write, in the same shape `GET /vaults/{id}/documents` reports under `values`."
              }
            ]
          },
          "extracted_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 timestamp of the last write that set a value on this cell. A revert restores the scanned value without restamping it, so after a revert this is still the time of the edit that was undone, not the time of the original scan."
          }
        },
        "required": [
          "document_id",
          "field_key",
          "cell",
          "extracted_at"
        ]
      },
      "VaultDocumentCellUpdateRequest": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "maxLength": 50000,
            "description": "The value to store. Send an empty string to clear the cell.",
            "example": "Delaware"
          }
        },
        "required": [
          "value"
        ]
      },
      "VaultColumnListResponse": {
        "type": "object",
        "properties": {
          "columns": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultColumnResponse"
            }
          }
        },
        "required": [
          "columns"
        ]
      },
      "VaultColumnResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "format": "uuid",
            "description": "Unique column identifier, or null for a built-in column. A built-in column has no row of its own in this vault, so it has no ID and cannot be changed or deleted."
          },
          "field_key": {
            "type": "string",
            "description": "The stable key extracted values are stored under. It is set once, when the column is created, and never changes, so renaming the column keeps every value already extracted for it.",
            "example": "renewalNotice"
          },
          "label": {
            "type": "string",
            "description": "The column heading shown in the vault table",
            "example": "Renewal notice"
          },
          "instructions": {
            "type": "string",
            "description": "For an `ai` column, the prompt extraction reads each document with. For a `manual`, `import`, or `connector` column, a note to whoever reads the column."
          },
          "field_type": {
            "type": "string",
            "enum": [
              "text",
              "date",
              "date_range",
              "enum",
              "multi_enum",
              "boolean",
              "number",
              "currency",
              "percentage",
              "duration",
              "email",
              "url",
              "list",
              "rich_text",
              "party_list",
              "related_agreement_list"
            ],
            "description": "The shape of the values in this column. Built-in columns can report `party_list` and `related_agreement_list`, which you cannot set yourself."
          },
          "field_meta": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "enum"
                    ]
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "The values extraction can assign to this column."
                  },
                  "legacy_options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "Values that documents extracted under an older version of this option list still hold. They stay readable and filterable, and extraction never assigns them again."
                  }
                },
                "required": [
                  "type",
                  "options"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "multi_enum"
                    ]
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "The values extraction can assign to this column."
                  }
                },
                "required": [
                  "type",
                  "options"
                ]
              },
              {
                "nullable": true
              }
            ],
            "description": "The option list for an `enum` or `multi_enum` column. Null for every other type."
          },
          "extraction_mode": {
            "type": "string",
            "enum": [
              "ai",
              "manual",
              "import",
              "connector"
            ],
            "description": "How the column gets filled. `ai`: extraction reads it out of each document. `manual`: a person types it and no scan ever touches it. `import`: values come from a connected spreadsheet, which owns the column. `connector`: values come from a connected document source, which owns the column. You can create `ai` and `manual` columns. An `import` column is created by connecting a spreadsheet in the app. A `connector` column is created when a source such as Ironclad fills it."
          },
          "kind": {
            "type": "string",
            "enum": [
              "built_in",
              "system",
              "custom"
            ],
            "description": "What this column is. `built_in`: merged into every vault by GC AI, with no ID and no way to change it. `system`: owned by this vault but managed by GC AI (Document Name, Document Status, Document Title), so it has an ID but rejects every change and every delete. `custom`: yours, and the only kind `PATCH` and `DELETE` accept."
          },
          "editable": {
            "type": "boolean",
            "description": "True when this column can be changed with `PATCH /vaults/{id}/columns/{columnId}`. Built-in and system columns report `false`: GC AI owns their name, type, options, and prompt. One exception, on both surfaces: `sort_order` is list position rather than identity, so it can be set on any column that has an ID."
          },
          "sort_order": {
            "type": "number",
            "nullable": true,
            "description": "Placement weight for this column, or null for a built-in one. The table orders columns by `sort_order` first and creation time second."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 creation timestamp, or null for a built-in column"
          },
          "updated_at": {
            "type": "string",
            "nullable": true,
            "description": "ISO 8601 last-update timestamp, or null for a built-in column"
          }
        },
        "required": [
          "id",
          "field_key",
          "label",
          "instructions",
          "field_type",
          "field_meta",
          "extraction_mode",
          "kind",
          "editable",
          "sort_order",
          "created_at",
          "updated_at"
        ]
      },
      "CreateVaultColumnRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The column heading shown in the vault table.",
            "example": "Renewal notice"
          },
          "field_key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "The key extracted values are stored under. Omit it and GC AI builds one from the label (`Renewal notice` becomes `renewalNotice`). Set it when you need the key to match something you already store, because the key is frozen once the column exists: renaming the column later never changes it. Any printable key up to 100 characters works, including one with an underscore or a hyphen; percent-encode it when you address a cell on this column.",
            "example": "renewalNotice"
          },
          "instructions": {
            "type": "string",
            "maxLength": 4000,
            "default": "",
            "description": "Required for an `ai` column: this text is the prompt extraction reads each document with, so say what to look for and what to return. Optional for a `manual` column, where it is only a note to whoever fills the column in.",
            "example": "Extract the number of days notice required to avoid automatic renewal. Return the number of days only."
          },
          "field_type": {
            "type": "string",
            "enum": [
              "text",
              "date",
              "date_range",
              "enum",
              "multi_enum",
              "boolean",
              "number",
              "currency",
              "percentage",
              "duration",
              "email",
              "url",
              "list",
              "rich_text"
            ],
            "default": "text",
            "description": "The shape of the values in this column. `enum` and `multi_enum` need `field_meta`; every other type needs `field_meta: null`."
          },
          "field_meta": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "enum"
                    ]
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "The values this column can hold. Between 2 and 12, all different.",
                    "example": [
                      "Renewal",
                      "New business",
                      "Amendment"
                    ]
                  }
                },
                "required": [
                  "type",
                  "options"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "multi_enum"
                    ]
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "The values this column can hold. Between 2 and 12, all different. A document can carry more than one."
                  }
                },
                "required": [
                  "type",
                  "options"
                ]
              },
              {
                "nullable": true
              }
            ],
            "default": null,
            "description": "The option list for an `enum` or `multi_enum` column. Send `null`, or omit it, for every other type."
          },
          "extraction_mode": {
            "type": "string",
            "enum": [
              "ai",
              "manual"
            ],
            "default": "ai",
            "description": "How the column gets filled. `ai` (the default) has extraction read it out of each document. `manual` keeps it out of every scan so the values stay exactly what a person types."
          },
          "sort_order": {
            "type": "integer",
            "description": "Placement weight, 0 by default. The table orders columns by `sort_order` first and creation time second, so columns added without one keep the order you added them in."
          }
        },
        "required": [
          "label"
        ]
      },
      "VaultColumnUpdateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/VaultColumnResponse"
          },
          {
            "type": "object",
            "properties": {
              "auto_rescan": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "queued"
                        ]
                      },
                      "queued": {
                        "type": "number",
                        "description": "Documents committed to the re-scan. Zero means no document held a value for this column, or every one that did was already queued."
                      },
                      "total_files": {
                        "type": "number",
                        "description": "Documents that hold a value for this column, including any already queued."
                      }
                    },
                    "required": [
                      "status",
                      "queued",
                      "total_files"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "failed"
                        ],
                        "description": "The column was saved and the re-scan could not be queued. Trigger a re-scan from the app when you want fresh values."
                      }
                    },
                    "required": [
                      "status"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "deferred_to_sample"
                        ]
                      },
                      "run_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "The scan review this vault is waiting on. The re-scan runs when that review is approved."
                      }
                    },
                    "required": [
                      "status",
                      "run_id"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "limit_reached"
                        ]
                      },
                      "used_today": {
                        "type": "number",
                        "description": "Re-analysis actions this vault has spent today."
                      },
                      "limit": {
                        "type": "number",
                        "description": "Re-analysis actions this vault gets per day."
                      },
                      "org_blocked": {
                        "type": "boolean",
                        "description": "True when re-analysis is turned off for the whole account, so waiting for tomorrow will not help."
                      }
                    },
                    "required": [
                      "status",
                      "used_today",
                      "limit",
                      "org_blocked"
                    ]
                  },
                  {
                    "nullable": true
                  }
                ],
                "description": "What happened to the re-scan a type change triggered, or null when the change needed none. A non-null value never means the update failed."
              }
            },
            "required": [
              "auto_rescan"
            ]
          }
        ]
      },
      "UpdateVaultColumnRequest": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "New column heading. The `field_key` does not follow a rename, so every value already extracted stays attached."
          },
          "instructions": {
            "type": "string",
            "maxLength": 4000,
            "description": "New instructions."
          },
          "field_type": {
            "type": "string",
            "enum": [
              "text",
              "date",
              "date_range",
              "enum",
              "multi_enum",
              "boolean",
              "number",
              "currency",
              "percentage",
              "duration",
              "email",
              "url",
              "list",
              "rich_text"
            ],
            "description": "New value shape. Send `field_meta` in the same request when the new type needs a different option list."
          },
          "field_meta": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "enum"
                    ]
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "The values this column can hold. Between 2 and 12, all different.",
                    "example": [
                      "Renewal",
                      "New business",
                      "Amendment"
                    ]
                  }
                },
                "required": [
                  "type",
                  "options"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "multi_enum"
                    ]
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200
                    },
                    "description": "The values this column can hold. Between 2 and 12, all different. A document can carry more than one."
                  }
                },
                "required": [
                  "type",
                  "options"
                ]
              },
              {
                "nullable": true
              }
            ],
            "description": "New option list. Send `null` to clear it. Omit it to leave the current one in place."
          },
          "extraction_mode": {
            "type": "string",
            "enum": [
              "ai",
              "manual"
            ],
            "description": "New fill mode. A column a spreadsheet owns cannot move in or out of `import`, and a column a connected source owns cannot move in or out of `connector`, so those columns reject this field."
          },
          "sort_order": {
            "type": "integer",
            "description": "New placement weight."
          }
        }
      },
      "DeleteVaultColumnResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "VaultViewListResponse": {
        "type": "object",
        "properties": {
          "views": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultViewResponse"
            }
          }
        },
        "required": [
          "views"
        ]
      },
      "VaultViewResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique view identifier"
          },
          "vault_id": {
            "type": "string",
            "format": "uuid",
            "description": "Vault this view belongs to"
          },
          "name": {
            "type": "string",
            "description": "View name, as shown on its tab in the app",
            "example": "Renewals this quarter"
          },
          "position": {
            "type": "integer",
            "description": "Zero-based slot this view occupies in the vault view order. Read-only over the API: reordering views is not available here yet."
          },
          "created_by_user_id": {
            "type": "integer",
            "nullable": true,
            "description": "GC AI user ID of whoever created the view, or null when that person has since been removed. Provenance only: a view is shared with the whole vault and is not owned by its creator."
          },
          "view_state": {
            "$ref": "#/components/schemas/VaultViewState"
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "description": "ISO 8601 last-update timestamp"
          }
        },
        "required": [
          "id",
          "vault_id",
          "name",
          "position",
          "created_by_user_id",
          "view_state",
          "created_at",
          "updated_at"
        ]
      },
      "VaultViewState": {
        "type": "object",
        "properties": {
          "hidden_field_keys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Column keys this view hides. This is a hide list, not a show list, so an empty array means the view shows every column in the vault. A column added to the vault after the view was saved is visible in the view until you add its key here."
          },
          "field_order": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Column keys in the order this view shows them, left to right. An empty array means the view uses the vault default order. Keys you leave out keep their default position relative to one another."
          },
          "sort": {
            "$ref": "#/components/schemas/VaultViewSort"
          },
          "filters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultViewFilter"
            },
            "description": "Filter rules this view applies. Rules combine with AND. An empty array means the view shows every document in the vault."
          }
        },
        "required": [
          "hidden_field_keys",
          "field_order",
          "sort",
          "filters"
        ]
      },
      "VaultViewSort": {
        "type": "object",
        "nullable": true,
        "properties": {
          "field": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Column to sort by: a vault column key, or one of `fileName`, `extractedAt`, `sourceName`.",
            "example": "effectiveDate"
          },
          "direction": {
            "type": "string",
            "enum": [
              "asc",
              "desc"
            ],
            "description": "Sort direction."
          }
        },
        "required": [
          "field",
          "direction"
        ],
        "description": "Sort this view applies, or `null` for the vault default order."
      },
      "VaultViewFilter": {
        "type": "object",
        "properties": {
          "field_key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Column the rule applies to. Use a vault column key, or `__notes__` for the any-column notes filter.",
            "example": "governingLaw"
          },
          "operator": {
            "type": "string",
            "enum": [
              "contains",
              "equals",
              "date_range",
              "in",
              "boolean",
              "number_range",
              "party_contains",
              "list_length",
              "equals_only",
              "not_contains",
              "not_equals",
              "is_empty",
              "is_not_empty",
              "is_before",
              "is_after",
              "has_notes",
              "has_no_notes"
            ],
            "description": "Comparison to apply. Operators are typed to column kinds, so an operator the column cannot carry has no effect on the rows the view returns."
          },
          "value": {
            "nullable": true,
            "description": "Operand for the operator, in the shape that operator takes. Omit it for `is_empty`, `is_not_empty`, `has_notes`, and `has_no_notes`."
          }
        },
        "required": [
          "field_key",
          "operator"
        ]
      },
      "VaultViewCreateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "View name. Trimmed before it is stored, and unique within the vault.",
            "example": "Renewals this quarter"
          },
          "view_state": {
            "$ref": "#/components/schemas/VaultViewStateInput"
          }
        },
        "required": [
          "name"
        ]
      },
      "VaultViewStateInput": {
        "type": "object",
        "properties": {
          "hidden_field_keys": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "maxItems": 500,
            "description": "Column keys this view hides. This is a hide list, not a show list, so an empty array means the view shows every column in the vault. A column added to the vault after the view was saved is visible in the view until you add its key here."
          },
          "field_order": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            },
            "maxItems": 500,
            "description": "Column keys in the order this view shows them, left to right. An empty array means the view uses the vault default order. Keys you leave out keep their default position relative to one another."
          },
          "sort": {
            "$ref": "#/components/schemas/VaultViewSort"
          },
          "filters": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VaultViewFilter"
            },
            "maxItems": 200,
            "description": "Filter rules this view applies. Rules combine with AND. An empty array means the view shows every document in the vault."
          }
        },
        "required": [
          "hidden_field_keys",
          "field_order",
          "sort",
          "filters"
        ],
        "description": "Layout, sort, and filters for the view. Omit it for a view that shows every column in the vault default order, unsorted and unfiltered."
      },
      "VaultViewUpdateRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "description": "New view name."
          },
          "view_state": {
            "allOf": [
              {
                "$ref": "#/components/schemas/VaultViewStateInput"
              },
              {
                "description": "Replacement layout, sort, and filters. This is a full replacement of all four fields, so send the whole object."
              }
            ]
          }
        }
      },
      "VaultViewDeleteResponse": {
        "type": "object",
        "properties": {
          "deleted": {
            "type": "boolean",
            "description": "Always `true` on success"
          }
        },
        "required": [
          "deleted"
        ]
      },
      "PingResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pong"
            ],
            "description": "Always `pong`"
          },
          "timestamp": {
            "type": "string",
            "description": "ISO 8601 server timestamp"
          }
        },
        "required": [
          "status",
          "timestamp"
        ]
      },
      "CreditUsageResponse": {
        "type": "object",
        "properties": {
          "start_date": {
            "type": "string",
            "description": "Inclusive range start."
          },
          "end_date": {
            "type": "string",
            "description": "Inclusive range end."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone used for day boundaries."
          },
          "pricing_available": {
            "type": "boolean",
            "description": "Whether rate-card pricing could be resolved for every observed operation. When false, all credit fields are null and only raw request counts are returned."
          },
          "total_credits": {
            "type": "number",
            "nullable": true,
            "description": "Total credits across all operations over the range. Null when pricing is unavailable."
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditUsageLine"
            },
            "description": "Per-operation usage and credit totals over the range."
          },
          "daily": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreditUsageDay"
            },
            "description": "Daily usage buckets across the full range (days with no usage have an empty `usage` object)."
          }
        },
        "required": [
          "start_date",
          "end_date",
          "timezone",
          "pricing_available",
          "total_credits",
          "lines",
          "daily"
        ]
      },
      "CreditUsageLine": {
        "type": "object",
        "properties": {
          "api": {
            "type": "string",
            "description": "The billable operation, e.g. `chat:completions` or `playbook:run`.",
            "example": "chat:completions"
          },
          "requests": {
            "type": "number",
            "description": "Total billable units consumed for this line over the range."
          },
          "unit": {
            "type": "string",
            "nullable": true,
            "description": "Display label for one billable unit (e.g. `request`). Null when pricing is unavailable."
          },
          "credits_per_unit": {
            "type": "number",
            "nullable": true,
            "description": "Credits charged per unit, from the current rate card. Null when pricing is unavailable."
          },
          "credits": {
            "type": "number",
            "nullable": true,
            "description": "Total credits for this line (`requests × credits_per_unit`). Null when pricing is unavailable."
          }
        },
        "required": [
          "api",
          "requests",
          "unit",
          "credits_per_unit",
          "credits"
        ]
      },
      "CreditUsageDay": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "description": "Calendar day (`YYYY-MM-DD`) in the requested timezone.",
            "example": "2026-06-01"
          },
          "usage": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Billable units consumed that day, keyed by billable operation. Operations with no usage are omitted."
          }
        },
        "required": [
          "date",
          "usage"
        ]
      },
      "UsageSummaryResponse": {
        "type": "object",
        "properties": {
          "start_date": {
            "type": "string",
            "description": "Inclusive range start."
          },
          "end_date": {
            "type": "string",
            "description": "Inclusive range end."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone used for day boundaries."
          },
          "web": {
            "$ref": "#/components/schemas/WebUsage"
          },
          "word": {
            "$ref": "#/components/schemas/WordUsage"
          },
          "api": {
            "$ref": "#/components/schemas/ApiUsage"
          }
        },
        "required": [
          "start_date",
          "end_date",
          "timezone",
          "web",
          "word",
          "api"
        ]
      },
      "WebUsage": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "number",
            "description": "Web-app chat messages sent."
          },
          "web_pages_scraped": {
            "type": "number",
            "description": "Web pages read by GC AI to compose answers."
          },
          "files_uploaded": {
            "type": "number",
            "description": "Files uploaded."
          }
        },
        "required": [
          "messages",
          "web_pages_scraped",
          "files_uploaded"
        ],
        "description": "Web-app activity."
      },
      "WordUsage": {
        "type": "object",
        "properties": {
          "messages": {
            "type": "number",
            "description": "Word add-in messages sent."
          },
          "redlines_applied": {
            "type": "number",
            "description": "Redlines applied from the Word add-in."
          },
          "drafts_applied": {
            "type": "number",
            "description": "Drafts applied from the Word add-in."
          }
        },
        "required": [
          "messages",
          "redlines_applied",
          "drafts_applied"
        ],
        "description": "Word add-in activity."
      },
      "ApiUsage": {
        "type": "object",
        "properties": {
          "requests": {
            "type": "number",
            "description": "Total billable API requests across all operations."
          },
          "by_operation": {
            "type": "object",
            "additionalProperties": {
              "type": "number"
            },
            "description": "Billable API requests keyed by operation (e.g. `chat:completions`, `playbook:run`)."
          }
        },
        "required": [
          "requests",
          "by_operation"
        ],
        "description": "API activity."
      },
      "McpCredentialResponse": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "description": "The M2M application's client ID. Stable across rotations; configure it as the OAuth client ID in Salesforce.",
            "example": "client_01HXWKHA5SX0JZYAD037JBE3PT"
          },
          "client_secret": {
            "type": "string",
            "description": "The client secret for the client-credentials grant. Shown only once, here, at creation. Store it securely; it cannot be retrieved again."
          },
          "token_endpoint": {
            "type": "string",
            "format": "uri",
            "description": "The OAuth 2.0 token endpoint to exchange the credential for an access token (`grant_type=client_credentials`).",
            "example": "https://your-org.authkit.app/oauth2/token"
          },
          "resource": {
            "type": "string",
            "format": "uri",
            "description": "The MCP resource URL to send as the `resource` parameter on the token request (OAuth 2.1). Also the MCP endpoint the issued token is used against.",
            "example": "https://app.example.com/api/mcp"
          },
          "grant_type": {
            "type": "string",
            "enum": [
              "client_credentials"
            ],
            "description": "The OAuth 2.0 grant type to use with this credential."
          }
        },
        "required": [
          "client_id",
          "client_secret",
          "token_endpoint",
          "resource",
          "grant_type"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/chat/completions": {
      "post": {
        "summary": "Create chat completion",
        "description": "Send a message to GC AI and receive an AI-generated response.\n\n<Note>\nThis endpoint is asynchronous: it returns a job envelope, and the result is filled in once the job completes. See [Asynchronous Requests](https://docs.gc.ai/api-reference/concepts/async-jobs) for how waiting, polling, and the envelope work.\n</Note>\n\n## Multi-turn conversations\n\nEvery response includes a `chat_id`. Pass it back as `chat_id` on a later request to continue that conversation. Conversation state (prior messages, tool calls, and any returned documents, emails, or diagrams) is held server-side, so each turn sends only the new `message` (plus any new `file_ids`); never re-send prior turns or previously returned outputs.\n\nOnly one turn may be in flight per chat at a time: a request whose `chat_id` already has a turn running is rejected with `409`. Wait for the prior turn to reach a terminal state before sending the next.\n\nContinuing a chat is scoped like [materialization](https://docs.gc.ai/api-reference/concepts/chat-visibility): personal keys continue chats they created; organization keys continue organization chats. See [Multi-turn Conversations](https://docs.gc.ai/api-reference/concepts/multi-turn).\n\n## Server-side tools\n\nThe model can invoke tools automatically while generating a response. Tool calls happen server-side. Only the final assistant text is returned in `result.result`.\n\n| Tool | Description | Key type |\n|---|---|---|\n| Document reading | Read, query, and search within attached files | All |\n| Web search | Search the web for current information | All |\n| Research agent | Multi-step web research with synthesis | All |\n| Case-law lookup | Search case law databases | User-scoped only |\n| Playbook review | Run playbook checks against attached files (requires `playbook_ids`) | All |\n| Document editing | Apply redline edits to an attached DOCX. All proposed revisions are auto-accepted; the edited file is returned via `result.documents`. The original file is preserved. | All |\n| Document generation | Generate a new DOCX from a prompt. The generated file is returned via `result.documents`. | All |\n| Slide generation | Generate a new PowerPoint deck (PPTX) from a prompt. The generated file is returned via `result.documents`. | User-scoped only |\n| Email drafting | Draft a structured email from a prompt. The draft is returned via `result.emails` (`to`, `subject`, `body`, …). | All |\n| Diagrams | Generate a diagram from a prompt. The diagram is returned via `result.diagrams` as validated Mermaid source (`mermaid`) you can render with any Mermaid-compatible renderer. | All |\n| Vault query | Query documents and fields in an attached Contract Intelligence vault (requires `vault_id`) | All (subject to vault authorization) |\n\nThe following tools are **not available** via API (the response is plain text with no channel for rich outputs):\n\n| Tool | Reason unavailable |\n|---|---|\n| Interactive clarification | Requires a back-and-forth channel with the caller |\n\n<Note>\nThis is an inference endpoint and is [rate limited](https://docs.gc.ai/api-reference/concepts/rate-limits): 60 requests/minute per organization (20 per API key). Exceeding the limit returns `429` with a `Retry-After` header.\n</Note>",
        "operationId": "createChatCompletion",
        "tags": [
          "Chat"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "description": "Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.",
              "example": 0
            },
            "required": false,
            "description": "Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.",
            "name": "wait",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.",
              "example": "wait=0"
            },
            "required": false,
            "description": "Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.",
            "name": "Prefer",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatCompletionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job completed within the effective wait window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              }
            }
          },
          "202": {
            "description": "Job accepted but not yet complete, including fire-and-forget requests",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body or invalid/conflicting wait controls",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key, playbook review not enabled for this account, or Contract Intelligence is not enabled for this account (when `vault_id` is set)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "One or more `file_ids`, one or more `playbook_ids`, the `chat_id`, the `company_id`, or the `vault_id` were not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The `chat_id` refers to a non-API chat, a turn is already in progress for that chat, `company_id` / `vault_id` differs from the chat's pinned value (each is fixed for the life of a chat), or `vault_id` conflicts with the vault linked to `project_id`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}": {
      "get": {
        "summary": "Get async job status",
        "description": "Poll an async API job created by endpoints like `POST /chat/completions`.\n\nUse the `job_id` returned by a `202 Accepted` response to check whether the job is still pending or has reached a terminal state.",
        "operationId": "getAsyncJob",
        "tags": [
          "Async Jobs"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The async job ID"
            },
            "required": true,
            "description": "The async job ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "description": "Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.",
              "example": 0
            },
            "required": false,
            "description": "Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.",
            "name": "wait",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.",
              "example": "wait=0"
            },
            "required": false,
            "description": "Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.",
            "name": "Prefer",
            "in": "header"
          }
        ],
        "responses": {
          "200": {
            "description": "Job found and currently in a terminal state",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              }
            }
          },
          "202": {
            "description": "Job found but not yet complete",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatCompletionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid job ID, wait value, or conflicting wait controls",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Job not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chat/{id}/materialize": {
      "post": {
        "summary": "Materialize an API chat",
        "description": "Surface an API-created chat into chat history and return a shareable deep link.\n\nChats created through `POST /chat/completions` stay out of chat history (both the GC AI web app and [chat search](https://docs.gc.ai/api-reference/search-chats)) until you materialize them. Use the `chat_id` from a completed completion response. The endpoint is idempotent. Calling it again on an already-materialized chat returns the same link without side effects.\n\nPass `project_id` to file the chat into a project at the same time, so it is browsable under `GET /projects/{id}/chats`. This requires write access to the project and files a chat that is already materialized.\n\n**Authorization:** User-scoped keys can only materialize chats they created. Organization-scoped keys can only materialize chats created by other organization-scoped keys.\n\n**Who can use the chat afterwards:** An organization-scoped key shares the chat with the whole organization, and every member can continue it in the web app. A user-scoped key keeps the chat owned by that user, so teammates reach it only through the normal sharing rules.\n\nSee [Chat Visibility](https://docs.gc.ai/api-reference/concepts/chat-visibility) for how this works.",
        "operationId": "materializeChat",
        "tags": [
          "Chat"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaterializeChatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Chat materialized (or already materialized)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaterializeChatResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid chat ID or request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Token cannot materialize this chat (wrong ownership scope)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found, or target project not found or not writable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Chat is not an API-created chat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chat/search": {
      "get": {
        "summary": "Search chats",
        "description": "Hybrid search across the caller's chat history that merges two lanes: a case-insensitive title-substring match and a semantic (vector) match over each chat's AI-generated summary. Title matches are returned first (a strong signal the user remembers the chat name), followed by semantic matches in relevance order, de-duplicated and capped at `limit`.\n\n**Authorization:** User-scoped keys (`u:gcai_...`) search the chats that user can access. Organization-scoped keys search every chat shared with the entire organization, regardless of who or what created it. Chats that remain private to an individual user are never returned to an org-scoped key.\n\nAPI-created chats appear here only once they've been [materialized](https://docs.gc.ai/api-reference/concepts/chat-visibility); unmaterialized chats are not in anyone's history and won't match.",
        "operationId": "searchChats",
        "tags": [
          "Chat"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500,
              "description": "Search query (required, 1-500 chars). Natural language is fine.",
              "example": "force majeure carve-out"
            },
            "required": true,
            "description": "Search query (required, 1-500 chars). Natural language is fine.",
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20,
              "description": "Max chats to return (default 20, max 50)"
            },
            "required": false,
            "description": "Max chats to return (default 20, max 50)",
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Chats matching the query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatSearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "User API key does not include Chat access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chats": {
      "get": {
        "summary": "List chats",
        "description": "List chats visible to the calling token with pagination.\n\n- **Org-scoped tokens**: list chats that are visible to the whole organization. This includes chats that are not access-controlled and chats in an org-visible (non-access-controlled) project. Access-controlled chats stay private to their users.\n- **User-scoped tokens**: list chats the user can access (created, shared, or non-access-controlled).",
        "operationId": "listChats",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Filter to chats in a specific project"
            },
            "required": false,
            "description": "Filter to chats in a specific project",
            "name": "project_id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Search by title (case-insensitive substring)"
            },
            "required": false,
            "description": "Search by title (case-insensitive substring)",
            "name": "q",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of chats",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Project access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chats/{id}": {
      "get": {
        "summary": "Get a chat",
        "description": "Retrieve a single chat by ID. Returns metadata only — use `GET /v1/chats/{id}/messages` for the conversation history.",
        "operationId": "getChat",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Chat details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid chat ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a chat",
        "description": "Update a chat's metadata (title, summary, project). Pass `project_id: null` to remove a chat from its project.",
        "operationId": "updateChat",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateChatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated chat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid chat ID or request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — not the chat creator or insufficient project access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a chat",
        "description": "Delete a chat and all its messages. Files attached to the chat are deleted too, unless something else uses them: another chat, My Files or a folder, a project, a skill, an automation, a task, or a vault. Public share links are invalidated.",
        "operationId": "deleteChat",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Chat deleted"
          },
          "400": {
            "description": "Invalid chat ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key, or a user API key deleting a chat its user did not create",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chats/{id}/duplicate": {
      "post": {
        "summary": "Duplicate a chat",
        "description": "Create a full copy of a chat including all messages and attached files. The new chat is a separate, editable conversation.",
        "operationId": "duplicateChat",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DuplicateChatRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Chat duplicated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DuplicateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid chat ID or request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Project access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Failed to load chat messages",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chats/{id}/messages": {
      "get": {
        "summary": "List messages in a chat",
        "description": "Retrieve the message history of a chat with pagination. Returns all messages including branched versions — use `parent_id` to reconstruct the conversation tree.",
        "operationId": "listChatMessages",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "asc",
              "description": "Sort order by creation time (default: asc)"
            },
            "required": false,
            "description": "Sort order by creation time (default: asc)",
            "name": "order",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of messages",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid chat ID or query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chats/{id}/share": {
      "post": {
        "summary": "Create a public share link",
        "description": "Make a chat publicly accessible via a share URL. **Security note**: anyone with the URL can read the chat, even without authenticating. Treat this as a deliberate publishing action. Omit expiry fields to use the default 7-day lifetime (or keep the current expiry when re-sharing a live link). Pass `expires_at: null` for a link that never expires.",
        "operationId": "createChatShareLink",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShareRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Share link created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid chat ID or expiry",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Chat sharing disabled for this organization, or insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Failed to update chat",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Revoke a public share link",
        "description": "Make a previously public chat private again.",
        "operationId": "revokeChatShareLink",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Share link revoked"
          },
          "400": {
            "description": "Invalid chat ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Failed to revoke share link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/chats/{id}/files/{fileId}": {
      "delete": {
        "summary": "Detach a file from a chat",
        "description": "Detach a file from a chat. The file is NOT deleted from the organization — only the chat association is removed.",
        "operationId": "detachFileFromChat",
        "tags": [
          "Chats"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The chat ID"
            },
            "required": true,
            "description": "The chat ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The file ID to detach"
            },
            "required": true,
            "description": "The file ID to detach",
            "name": "fileId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "File detached"
          },
          "400": {
            "description": "Invalid chat or file ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Chat or file attachment not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files": {
      "post": {
        "summary": "Upload a file",
        "description": "Upload a file to GC AI for processing and storage. Files are uploaded as multipart form data and automatically processed (text extraction, summarization, and embedding creation).\n\nWith a user-scoped key, files default to the user's \"My Files\" folder. With an org-scoped key, files default to the \"Organization Files\" folder and the `my-files` scope is not available.\n\nFor PDFs and Word documents, extraction runs asynchronously. Poll `GET /files/{id}` until `status` is `ready`.",
        "operationId": "uploadFile",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/FileUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File uploaded successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (unsupported file type, empty content, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Project access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Search files",
        "description": "Hybrid (vector + keyword) search across accessible files. Results are ranked by relevance and capped at 100.\n\nUser-scoped keys search all files the user can read. Org-scoped keys search all non-access-controlled files in the organization.\n\nPass `scope` (user-scoped keys only) to constrain the search to one of the three top-level meta-collections shown in the GC AI UI:\n- `my-files`: files in the user's personal \"My Files\" tree\n- `shared-with-me`: files explicitly shared with the user (and files inside shared folders)\n- `organization`: files in the organization's \"Organization Files\" tree\n\nPass `project_id` (user- or org-scoped keys) to constrain the search to the files linked to one project, e.g. searching a project of contracts for specific terms. Mutually exclusive with `scope`. To list a project's files without a query, use `GET /projects/{id}/files` instead.",
        "operationId": "searchFiles",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Search query (required)",
              "example": "force majeure"
            },
            "required": true,
            "description": "Search query (required)",
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "my-files",
                "shared-with-me",
                "organization"
              ],
              "description": "Optional scope filter (user-scoped keys only). When omitted, searches all files the user can read. Mutually exclusive with `project_id`.",
              "example": "my-files"
            },
            "required": false,
            "description": "Optional scope filter (user-scoped keys only). When omitted, searches all files the user can read. Mutually exclusive with `project_id`.",
            "name": "scope",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Optional project filter. Constrains the search to files linked to this project. Mutually exclusive with `scope`."
            },
            "required": false,
            "description": "Optional project filter. Constrains the search to files linked to this project. Mutually exclusive with `scope`.",
            "name": "project_id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Files matching the query, ranked by relevance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileSearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid query parameters, scope used with an org-scoped key, or both scope and project_id supplied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found (when project_id is supplied)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files/{id}": {
      "get": {
        "summary": "Get file status",
        "description": "Retrieve the current status and metadata of an uploaded file. Use this to poll for extraction completion after uploading a file.",
        "operationId": "getFileStatus",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The file ID"
            },
            "required": true,
            "description": "The file ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "File metadata and status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "File not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Move a file",
        "description": "Move a file to a different folder by updating its `folder_id`. Org-scoped keys can move non-access-controlled files to non-access-controlled destination folders.",
        "operationId": "updateFile",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The file ID"
            },
            "required": true,
            "description": "The file ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File moved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Destination folder access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "File not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files/uploads": {
      "post": {
        "summary": "Initiate a chunked upload",
        "description": "Start a multipart upload session for a large file. Validates the file type, size, and destination up front, then returns an `upload_id`. Send the file in parts with `PUT /files/uploads/{upload_id}/parts/{part_number}`, then finalize with `POST /files/uploads/{upload_id}/complete`.\n\nUse this instead of `POST /files` when a single request is impractical (large files, or clients with per-request payload limits). The destination options (`folder_id` / `project_id` / `scope`) behave exactly as on `POST /files`.",
        "operationId": "initiateUpload",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitiateUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Upload session created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitiateUploadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (unsupported file type, size over the limit, conflicting destination options)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Project access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Folder or project not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files/uploads/{upload_id}/parts/{part_number}": {
      "put": {
        "summary": "Upload a file part",
        "description": "Upload one part of a chunked upload. The request body is the raw bytes of the part (`application/octet-stream`). Parts may be uploaded in any order; re-sending the same `part_number` overwrites it, so a failed part is safe to retry.",
        "operationId": "uploadPart",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The upload session ID from initiate."
            },
            "required": true,
            "description": "The upload session ID from initiate.",
            "name": "upload_id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 32,
              "description": "Part index, from 1 to 32."
            },
            "required": true,
            "description": "Part index, from 1 to 32.",
            "name": "part_number",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Part stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadPartResponse"
                }
              }
            }
          },
          "400": {
            "description": "Empty part body or part number out of range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Upload session not found or expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files/uploads/{upload_id}/complete": {
      "post": {
        "summary": "Complete a chunked upload",
        "description": "Assemble the uploaded parts into the final file and start processing (text extraction, summarization, embeddings), returning the same file object as `POST /files`. For PDFs and Word documents, extraction runs asynchronously; poll `GET /files/{id}` until `status` is `ready`.",
        "operationId": "completeUpload",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The upload session ID from initiate."
            },
            "required": true,
            "description": "The upload session ID from initiate.",
            "name": "upload_id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompleteUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "File assembled and processing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileResponse"
                }
              }
            }
          },
          "400": {
            "description": "Missing parts, or the assembled file is empty or over the size limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Project access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Upload session not found or expired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/files/uploads/{upload_id}": {
      "delete": {
        "summary": "Abort a chunked upload",
        "description": "Discard an in-flight upload session and delete any parts already uploaded. Idempotent: aborting an unknown or already-finalized session still returns success.",
        "operationId": "abortUpload",
        "tags": [
          "Files"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The upload session ID from initiate."
            },
            "required": true,
            "description": "The upload session ID from initiate.",
            "name": "upload_id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Session aborted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AbortUploadResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/folders": {
      "get": {
        "summary": "List folders",
        "description": "List all folders accessible to the authenticated user, returned as a flat list with full paths.\n\nPass `scope` to filter to one of the three top-level meta-collections shown in the GC AI UI:\n- `my-files`: folders rooted in the user's personal \"My Files\" tree\n- `shared-with-me`: folders explicitly shared with the user by other users\n- `organization`: folders rooted in the organization's \"Organization Files\" tree\n\nFiltering by `scope` requires a user-scoped API key (`u:gcai_...`).",
        "operationId": "listFolders",
        "tags": [
          "Folders"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Case-insensitive substring search on folder name or description. System-owned collection types (my-files, org-files, etc.) are excluded from results. Composes with `scope`.",
              "example": "contracts"
            },
            "required": false,
            "description": "Case-insensitive substring search on folder name or description. System-owned collection types (my-files, org-files, etc.) are excluded from results. Composes with `scope`.",
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "my-files",
                "shared-with-me",
                "organization"
              ],
              "description": "Filter folders to a single meta-collection. Requires a user-scoped API key.",
              "example": "my-files"
            },
            "required": false,
            "description": "Filter folders to a single meta-collection. Requires a user-scoped API key.",
            "name": "scope",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of folders",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid scope parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Scope filter requires a user-scoped API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a folder",
        "description": "Create a new folder for organizing files. Folders can be nested by specifying a `parent_folder_id`.\n\nOrg-scoped keys can create folders under non-access-controlled parents. The `scope` parameter requires a user-scoped key.",
        "operationId": "createFolder",
        "tags": [
          "Folders"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFolderRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Folder created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Folder"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Parent folder access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/folders/{id}": {
      "get": {
        "summary": "Get a folder",
        "description": "Retrieve a single folder by ID.",
        "operationId": "getFolder",
        "tags": [
          "Folders"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The folder ID"
            },
            "required": true,
            "description": "The folder ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Folder details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Folder"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Folder not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a folder",
        "description": "Update a folder's name, description, parent, or access-control flag. At least one field must be provided. System folders cannot be modified.\n\nOrg-scoped keys can update non-access-controlled folders.",
        "operationId": "updateFolder",
        "tags": [
          "Folders"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The folder ID"
            },
            "required": true,
            "description": "The folder ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFolderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Folder updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Folder"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, system folder, or invalid parent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Folder or destination folder not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a folder",
        "description": "Delete a folder. By default, only empty folders can be deleted; pass `?recursive=true` to delete a folder along with all of its subfolders and files. System folders cannot be deleted.\n\nOrg-scoped keys can delete non-access-controlled folders.",
        "operationId": "deleteFolder",
        "tags": [
          "Folders"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The folder ID"
            },
            "required": true,
            "description": "The folder ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "When `true`, recursively delete subfolders and files. Defaults to `false`.",
              "example": "true"
            },
            "required": false,
            "description": "When `true`, recursively delete subfolders and files. Defaults to `false`.",
            "name": "recursive",
            "in": "query"
          }
        ],
        "responses": {
          "204": {
            "description": "Folder deleted successfully"
          },
          "400": {
            "description": "Invalid folder ID or system folder",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Recursive delete blocked by insufficient descendant access or access-controlled descendants",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Folder not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Folder is not empty and `recursive` was not set",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/folders/{id}/children": {
      "get": {
        "summary": "List a folder's children",
        "description": "List the direct children of a folder. The response items are a discriminated union of subfolders and files: subfolders are returned first (alphabetical), then files (alphabetical).",
        "operationId": "listFolderChildren",
        "tags": [
          "Folders"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The folder ID"
            },
            "required": true,
            "description": "The folder ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Direct children of the folder",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderChildrenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Folder not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects": {
      "get": {
        "summary": "List projects",
        "description": "List projects accessible to the caller, optionally filtered by name.\n\nWith a user-scoped key (`u:gcai_...`), the user sees projects they created, projects shared with them, and non-access-controlled projects. With an org-scoped key (`gcai_...`), only non-access-controlled (org-wide) projects are returned.",
        "operationId": "listProjects",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Case-insensitive substring match on project name"
            },
            "required": false,
            "description": "Case-insensitive substring match on project name",
            "name": "search",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of projects",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Result set too large for offset pagination",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project",
        "description": "Create a new project to group files, folders, and chats around a single matter (deal, vendor, or program).\n\nWith a user-scoped key, the caller is recorded as the project creator and granted admin access. With an org-scoped key, `creatorId` is null and the project defaults to non-access-controlled (org-wide).",
        "operationId": "createProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Project access required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}": {
      "get": {
        "summary": "Get a project",
        "description": "Retrieve a single project by ID. Returns the caller's access level alongside the project metadata.",
        "operationId": "getProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a project",
        "description": "Update a project's name, description, or custom instructions. Only the fields you supply are changed; omitted fields are left untouched. Pass `null` for `description` or `custom_instructions` to clear them.\n\nRequires write access to the project. Org-scoped keys can update non-access-controlled projects.",
        "operationId": "updateProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or insufficient write access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a project",
        "description": "Delete a project. Files, folders, and chats linked to the project are detached, not deleted; they remain in the organization and can be reattached elsewhere.\n\nRequires admin access to the project. Org-scoped keys can delete non-access-controlled projects.",
        "operationId": "deleteProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project deleted"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or insufficient access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/files": {
      "post": {
        "summary": "Attach a file to a project",
        "description": "Attach an already-uploaded file to a project. The file remains in its current folder; this only records the project link.\n\nRequires write access to the project and read access to the file. Org-scoped keys can attach non-access-controlled files to non-access-controlled projects.",
        "operationId": "attachFileToProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachFileRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "File attached (idempotent, repeat calls are no-ops)"
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found, file not found, or insufficient write access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List files on a project",
        "description": "List files directly linked to a project. Files reachable only via a linked folder are not included; list those folders separately with `GET /projects/{id}/folders`.",
        "operationId": "listProjectFiles",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of files",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectFileListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/files/{fileId}": {
      "delete": {
        "summary": "Detach a file from a project",
        "description": "Remove the link between a file and a project. The file itself is not deleted; it stays in the organization and can be reattached later. Idempotent: detaching a file that is not attached is a no-op.\n\nRequires write access to the project. Org-scoped keys can detach files from non-access-controlled projects.",
        "operationId": "detachFileFromProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The file ID"
            },
            "required": true,
            "description": "The file ID",
            "name": "fileId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "File detached (idempotent, repeat calls are no-ops)"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or insufficient write access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/folders": {
      "get": {
        "summary": "List folders linked to a project",
        "description": "List folders linked to a project. To enumerate the contents of a folder, call `GET /folders/{id}/children`.",
        "operationId": "listProjectFolders",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of linked folders",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectFolderListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Attach a folder to a project",
        "description": "Link a folder to a project. Once attached, all files in the folder become available as project context. The folder is not moved or copied; only the project link is recorded.\n\nRequires write access to the project and read access to the folder. Idempotent: re-attaching an already-linked folder is a no-op. Org-scoped keys can attach non-access-controlled folders to non-access-controlled projects.",
        "operationId": "attachFolderToProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachFolderRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Folder attached (idempotent, repeat calls are no-ops)"
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found, folder not found, or insufficient write access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/folders/{folderId}": {
      "delete": {
        "summary": "Detach a folder from a project",
        "description": "Remove the link between a folder and a project. The folder itself is not deleted; it stays in the organization. Idempotent: detaching a folder that is not attached is a no-op.\n\nRequires write access to the project. Org-scoped keys can detach folders from non-access-controlled projects.",
        "operationId": "detachFolderFromProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The folder ID"
            },
            "required": true,
            "description": "The folder ID",
            "name": "folderId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Folder detached (idempotent, repeat calls are no-ops)"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or insufficient write access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/pin": {
      "post": {
        "summary": "Pin a project",
        "description": "Pin a project to the calling user's sidebar. Idempotent. Pinning is per-user state (each user has their own pinned set), so it requires a user-scoped key (`u:gcai_...`). Org-scoped keys carry no user identity and receive 422.",
        "operationId": "pinProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project pinned (idempotent, repeat calls are no-ops)"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Pinning requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Unpin a project",
        "description": "Remove a project from the calling user's sidebar pins. Idempotent. Pinning is per-user state (each user has their own pinned set), so it requires a user-scoped key (`u:gcai_...`). Org-scoped keys carry no user identity and receive 422.",
        "operationId": "unpinProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project unpinned (idempotent, repeat calls are no-ops)"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Pinning requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/star": {
      "post": {
        "summary": "Pin a project (legacy star alias)",
        "deprecated": true,
        "description": "Deprecated: use POST /projects/{id}/pin instead. Pin a project to the calling user's sidebar. Idempotent. Pinning is per-user state (each user has their own pinned set), so it requires a user-scoped key (`u:gcai_...`). Org-scoped keys carry no user identity and receive 422.",
        "operationId": "starProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project pinned (idempotent, repeat calls are no-ops)"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Pinning requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Unpin a project (legacy star alias)",
        "deprecated": true,
        "description": "Deprecated: use DELETE /projects/{id}/pin instead. Remove a project from the calling user's sidebar pins. Idempotent. Pinning is per-user state (each user has their own pinned set), so it requires a user-scoped key (`u:gcai_...`). Org-scoped keys carry no user identity and receive 422.",
        "operationId": "unstarProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project unpinned (idempotent, repeat calls are no-ops)"
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Pinning requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{id}/chats": {
      "get": {
        "summary": "List chats in a project",
        "description": "List chats associated with a project. Returns chat metadata only. Per-chat message retrieval is not exposed via the API.",
        "operationId": "listProjectChats",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of chats",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectChatListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "File a chat into a project",
        "description": "File an existing chat into a project so it is browsable under `GET /projects/{id}/chats` alongside the project's files. If the chat already belongs to another project, this moves it.\n\nRequires write access to the project. User-scoped keys can only file chats they created. Org-scoped keys can file non-access-controlled chats into non-access-controlled projects.",
        "operationId": "attachChatToProject",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The project ID"
            },
            "required": true,
            "description": "The project ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachChatRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Chat filed into the project (idempotent)"
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Project not found, chat not found, or insufficient write access",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks": {
      "get": {
        "summary": "List playbooks",
        "description": "List playbooks accessible to the caller.\n\nWith a user-scoped key, returns playbooks the user created, org-visible playbooks, shared playbooks, and official playbooks. With an org-scoped key, returns org-visible and official playbooks.",
        "operationId": "listPlaybooks",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of playbooks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlaybookListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a playbook",
        "description": "Create a new, empty playbook. Add checks to it with the check endpoints, then run it against files.\n\nWith a user-scoped key, the caller is recorded as the creator and the playbook is private to them. With an org-scoped key, the playbook is org-visible (any member of the organization can read and manage it) and has no individual creator.",
        "operationId": "createPlaybook",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlaybookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Playbook created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Playbook"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key or missing Playbooks permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks/{id}": {
      "get": {
        "summary": "Get a playbook",
        "description": "Retrieve a single playbook by ID, including its `guide` text.\n\nUser-scoped keys can read playbooks they created, playbooks shared with them, org-visible playbooks, and official playbooks. Org-scoped keys can read org-visible and official playbooks, but not private ones.",
        "operationId": "getPlaybook",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Playbook details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Playbook"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a playbook",
        "description": "Update a playbook's title, description, or guide. At least one field is required.\n\nUser-scoped keys require write access to the playbook. Org-scoped keys can update org-visible (non-private) playbooks.",
        "operationId": "updatePlaybook",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The playbook ID"
            },
            "required": true,
            "description": "The playbook ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePlaybookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated playbook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Playbook"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found or not writable by the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a playbook",
        "description": "Soft-delete a playbook by ID. The playbook is marked as deleted and will no longer appear in `GET /playbooks` results.\n\nUser-scoped keys require admin access to the playbook. Org-scoped keys can delete org-visible (non-private) playbooks.",
        "operationId": "deletePlaybook",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The playbook ID to delete"
            },
            "required": true,
            "description": "The playbook ID to delete",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Playbook successfully deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletePlaybookResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid playbook ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks/{id}/duplicate": {
      "post": {
        "summary": "Duplicate a playbook",
        "description": "Create a copy of a playbook, including its checks and positions. The copy is private to the caller.\n\nRequires a user-scoped key: the caller is recorded as the new playbook's creator and must be able to read the source. Org-scoped keys cannot duplicate playbooks.",
        "operationId": "duplicatePlaybook",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The playbook ID"
            },
            "required": true,
            "description": "The playbook ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "201": {
            "description": "Duplicated playbook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Playbook"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Duplicating playbooks requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Source playbook not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks/{id}/run": {
      "post": {
        "summary": "Run a playbook against uploaded files",
        "description": "Run a playbook against one or more uploaded files and receive structured check results.\n\n<Note>\nThis endpoint is asynchronous: it returns a job envelope, and the result is filled in once the job completes. See [Asynchronous Requests](https://docs.gc.ai/api-reference/concepts/async-jobs) for how waiting, polling, and the envelope work.\n</Note>\n\nFiles referenced by `file_ids` must be accessible to the caller and in `ready` status. The playbook must be in `completed` status. Org-scoped keys can run org-visible playbooks against non-access-controlled files.\n\n<Note>\nThis is an inference endpoint and is [rate limited](https://docs.gc.ai/api-reference/concepts/rate-limits): 60 requests/minute per organization (20 per API key). Exceeding the limit returns `429` with a `Retry-After` header.\n</Note>",
        "operationId": "runPlaybook",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "description": "Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.",
              "example": 0
            },
            "required": false,
            "description": "Optional long-poll wait time in seconds. Use `0` for fire-and-forget behavior. If both `wait` and `Prefer: wait=...` are supplied, they must match. Values above 90 are clamped.",
            "name": "wait",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.",
              "example": "wait=0"
            },
            "required": false,
            "description": "Optional RFC 7240 wait preference, for example `wait=0`. If both this header and the `wait` query parameter are supplied, they must match.",
            "name": "Prefer",
            "in": "header"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunPlaybookRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Job completed within the effective wait window",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunPlaybookResponse"
                }
              }
            }
          },
          "202": {
            "description": "Job accepted but not yet complete",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunPlaybookResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, playbook not ready, or files still extracting",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found, file IDs not found, or the `company_id` was not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "One or more files have a permanent extraction failure",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "summary": "Identify the caller",
        "description": "Return the identity behind the API key making the request: the organization it belongs to, and, for user-scoped keys, the user it acts as.\n\nWorks with **either** a user-scoped key (`u:gcai_...`) or an org-scoped key (`gcai_...`). Org-scoped keys carry no user identity, so `user` is `null` for them. Use this to confirm which credential and account a request resolves to before calling `/me/profile` or `/company-profile`.",
        "operationId": "getMe",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The caller identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallerIdentityResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/me/profile": {
      "get": {
        "summary": "Get your personal profile",
        "description": "Retrieve the calling user's personal profile: the chat-context fields the web UI exposes under Settings → Profile. A profile that has never been saved is returned with default values.\n\nDisplay name and avatar are managed by your identity provider, not this API, so they are not included.\n\nRequires a **user-scoped** key (`u:gcai_...`); org-scoped keys carry no user identity and receive 403.",
        "operationId": "getMyProfile",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The personal profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalProfileResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key is not user-scoped, or the API key is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update your personal profile",
        "description": "Partially update the calling user's personal profile. Omitted fields are left unchanged; nullable fields accept `null` to clear them. The profile is created on first write.\n\nDisplay name and avatar are managed by your identity provider, not this API.\n\nRequires a **user-scoped** key (`u:gcai_...`); org-scoped keys receive 403.",
        "operationId": "updateMyProfile",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePersonalProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated personal profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonalProfileResponse"
                }
              }
            }
          },
          "400": {
            "description": "No fields provided, or invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key is not user-scoped, or the API key is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/company-profile": {
      "get": {
        "summary": "Get the company profile",
        "description": "Retrieve the organization's company profile: the company context (industry, jurisdiction, regulations, risk posture) the AI uses to ground answers.\n\nReadable with either a user-scoped or org-scoped key. With a user-scoped key, the user's active (default) company is returned when one is set; otherwise the organization's sole company is returned. An organization with multiple companies and no applicable default returns 409.",
        "operationId": "getDefaultCompanyProfile",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The company profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No company profile exists for this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The organization has more than one company profile, so the singular `/company-profile` resource cannot disambiguate. List them via `GET /company-profiles` and address one by id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update the company profile",
        "description": "Partially update the organization's company profile. Omitted fields are left unchanged; nullable fields accept `null` to clear them.\n\nRequires an **org-scoped** key (`gcai_...`): company context is organization-level configuration, so user-scoped keys receive 403. Creating the first company profile is done in the web UI.",
        "operationId": "updateDefaultCompanyProfile",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCompanyProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated company profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileResponse"
                }
              }
            }
          },
          "400": {
            "description": "No fields provided, or invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key is not org-scoped, or the API key is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No company profile exists to update",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The organization has more than one company profile, so the singular `/company-profile` resource cannot disambiguate. List them via `GET /company-profiles` and address one by id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/company-profiles": {
      "get": {
        "summary": "List company profiles",
        "description": "List the company profiles in the organization: the company contexts (industry, jurisdiction, regulations, risk posture) the AI can use to ground answers.\n\nWith a user-scoped key, only the company profiles the user can read are returned. With an org-scoped key, all of the organization's company profiles are returned.\n\nThis is the multi-profile counterpart to the singular `/company-profile`, and the way to discover the `id` a company profile is addressed by elsewhere in the API.",
        "operationId": "listCompanyProfiles",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of company profiles",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/company-profiles/{id}": {
      "get": {
        "summary": "Get a company profile",
        "description": "Fetch a single company profile by ID.\n\nReturns `404` if the company profile does not exist or is not accessible to the caller. User-scoped keys can only read company profiles they have access to; org-scoped keys can read any company profile in the organization.",
        "operationId": "getCompanyProfile",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Company profile ID from `GET /company-profiles`."
            },
            "required": true,
            "description": "Company profile ID from `GET /company-profiles`.",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The company profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid company profile ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Company profile not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a company profile",
        "description": "Partially update a company profile. Omitted fields are left unchanged; nullable fields accept `null` to clear them.\n\nUser-scoped keys require write access to the company profile; org-scoped keys can update any company profile in the organization. Creating the first company profile is done in the web UI.",
        "operationId": "updateCompanyProfile",
        "tags": [
          "Profiles"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Company profile ID from `GET /company-profiles`."
            },
            "required": true,
            "description": "Company profile ID from `GET /company-profiles`.",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCompanyProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated company profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyProfileResponse"
                }
              }
            }
          },
          "400": {
            "description": "No fields provided, or invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Caller has read-only access to the company profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Company profile not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/skills": {
      "get": {
        "summary": "List skills",
        "description": "List skills accessible to the caller.\n\nReturns id, name, description, visibility, files, and timestamps. Instruction bodies are omitted; fetch a skill by id to load `content`.\n\nWith a user-scoped key that has Skills access, returns skills the user created, org-visible skills, skills explicitly shared with the user, and official skills. With an org-scoped key, returns org-visible skills and official skills.",
        "operationId": "listSkills",
        "tags": [
          "Skills"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Optional case-insensitive search over skill name and description"
            },
            "required": false,
            "description": "Optional case-insensitive search over skill name and description",
            "name": "q",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of skills",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a skill",
        "description": "Create a new skill in the caller's organization.\n\nUser-scoped keys own the skill and default it to `private`; org-scoped keys create `organization`-visible skills. Official skills cannot be created via the API.",
        "operationId": "createSkill",
        "tags": [
          "Skills"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSkillRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created skill",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Skill"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key or missing Skills permission",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "One or more `file_ids` were not found in the organization, or `legal_category` was sent while Legal Categories are not available yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/skills/{id}": {
      "get": {
        "summary": "Get a skill",
        "description": "Fetch a single skill by ID, including its instructions and attached files.\n\nReturns `404` if the skill does not exist or is not accessible to the caller. User-scoped keys require Skills access, including for official skills. User skills follow the same visibility rules as `GET /skills`.",
        "operationId": "getSkill",
        "tags": [
          "Skills"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Skill ID from `GET /skills`."
            },
            "required": true,
            "description": "Skill ID from `GET /skills`.",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The skill",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Skill"
                }
              }
            }
          },
          "400": {
            "description": "Invalid skill ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Skill not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a skill",
        "description": "Partially update a skill's name, instructions, description, attached files, or legal category.\n\nRequires write access to the skill. Official skills cannot be edited via the API. Visibility is not editable here; manage skill sharing in the GC AI app.",
        "operationId": "updateSkill",
        "tags": [
          "Skills"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Skill ID from `GET /skills`."
            },
            "required": true,
            "description": "Skill ID from `GET /skills`.",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSkillRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated skill",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Skill"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body or skill ID",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Caller has read-only access to the skill",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Skill not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "One or more `file_ids` were not found in the organization, or `legal_category` was sent while Legal Categories are not available yet",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a skill",
        "description": "Delete a skill. Attached files are detached, not deleted; manage file lifecycle via the files API.\n\nUser-scoped keys require write access to the skill; org-scoped keys can delete org-visible (non-private) skills. Official skills cannot be deleted via the API.",
        "operationId": "deleteSkill",
        "tags": [
          "Skills"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The skill ID to delete"
            },
            "required": true,
            "description": "The skill ID to delete",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Skill successfully deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteSkillResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid skill ID format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Caller has read-only access to the skill",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Skill not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks/{id}/checks": {
      "get": {
        "summary": "List a playbook's checks",
        "description": "List the checks in a playbook, in their configured order.\n\nReadable by any caller who can read the playbook.",
        "operationId": "listPlaybookChecks",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of checks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlaybookCheckListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found or not accessible to the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Add a check to a playbook",
        "description": "Create a check and append it to the playbook.\n\nRequires write access to the playbook. With a user-scoped key the caller is recorded as the check’s creator; with an org-scoped key the check has no individual creator and is org-owned.",
        "operationId": "createPlaybookCheck",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlaybookCheckRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Check created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlaybookCheck"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found or not writable by the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks/{id}/checks/{checkId}": {
      "get": {
        "summary": "Get a check",
        "description": "Retrieve a single check in a playbook by ID.\n\nReadable by any caller who can read the playbook.",
        "operationId": "getPlaybookCheck",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Check ID from `GET /playbooks/{id}/checks`."
            },
            "required": true,
            "description": "Check ID from `GET /playbooks/{id}/checks`.",
            "name": "checkId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Check details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlaybookCheck"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook or check not found, or not accessible",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a check",
        "description": "Update a check's title, description, importance, or positions. At least one field is required. When `positions` is supplied it replaces the check's positions entirely.\n\nRequires a user-scoped key with write access to the playbook. Org-scoped keys cannot update checks.",
        "operationId": "updatePlaybookCheck",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Check ID from `GET /playbooks/{id}/checks`."
            },
            "required": true,
            "description": "Check ID from `GET /playbooks/{id}/checks`.",
            "name": "checkId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePlaybookCheckRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlaybookCheck"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Updating checks requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook or check not found, or not writable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Cannot replace positions on a check whose positions carry clause language or other settings the API can't yet round-trip; omit `positions` to update other fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a check from a playbook",
        "description": "Remove a check from the playbook.\n\nRequires a user-scoped key with write access to the playbook. Org-scoped keys cannot remove checks.",
        "operationId": "deletePlaybookCheck",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Check ID from `GET /playbooks/{id}/checks`."
            },
            "required": true,
            "description": "Check ID from `GET /playbooks/{id}/checks`.",
            "name": "checkId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Check removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletePlaybookCheckResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Removing checks requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook or check not found, or not writable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/playbooks/{id}/checks/reorder": {
      "post": {
        "summary": "Reorder a playbook's checks",
        "description": "Set the order of the playbook's checks. Provide the check IDs in the desired order.\n\nRequires a user-scoped key with write access to the playbook. Org-scoped keys cannot reorder checks.",
        "operationId": "reorderPlaybookChecks",
        "tags": [
          "Playbooks"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Playbook ID from `GET /playbooks`."
            },
            "required": true,
            "description": "Playbook ID from `GET /playbooks`.",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReorderPlaybookChecksRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checks reordered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReorderPlaybookChecksResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Reordering checks requires a user-scoped key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Playbook not found or not writable by the caller",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults": {
      "get": {
        "summary": "List vaults",
        "description": "List the Contract Intelligence vaults the caller can see: vaults they are a member of, plus organization-wide vaults when their role allows.\n\nUse this to discover the `vault_id` for `POST /chat/completions` and `POST /vaults/{id}/documents`. Pass `status=archived` to list the archived vaults the caller owns.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "listVaults",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 200,
              "description": "Case-insensitive substring match on vault name"
            },
            "required": false,
            "description": "Case-insensitive substring match on vault name",
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "archived"
              ],
              "default": "active",
              "description": "Which vaults to list. `active` (the default) returns live vaults. `archived` returns vaults the caller owns that have been archived, newest first, so they can be restored or deleted. Organization-wide visibility does not reach archived vaults, and only an owner can act on one, so the archived list is owner-only."
            },
            "required": false,
            "description": "Which vaults to list. `active` (the default) returns live vaults. `archived` returns vaults the caller owns that have been archived, newest first, so they can be restored or deleted. Organization-wide visibility does not reach archived vaults, and only an owner can act on one, so the archived list is owner-only.",
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of vaults",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a vault",
        "description": "Create a Contract Intelligence vault. The caller becomes its `owner`, and the vault starts access-controlled, so nobody else can see it until you add members or turn access control off.\n\nA vault created here skips guided setup and is ready for documents right away: upload with `POST /vaults/{id}/documents`, add columns with `POST /vaults/{id}/columns`, and read the extracted table from `GET /vaults/{id}/documents`. In the app a vault waits in guided setup, and documents added meanwhile are stored but not scanned. There is no guided setup over the API, so this endpoint finishes setup as it creates the vault and every upload is scanned as it arrives.\n\nCreating a vault needs the organization-level permission to create vaults, which an organization admin grants. Vault names do not have to be unique.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "createVault",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VaultCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot create vaults",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A vault with that name already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}": {
      "get": {
        "summary": "Get a vault",
        "description": "Retrieve a single Contract Intelligence vault by ID, with the caller's role and its scanned-document count.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "getVault",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Vault details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, archived, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a vault",
        "description": "Change a vault name, description, or whether it is access-controlled. Send only the fields you want to change.\n\nTurning access control on hides the vault from everyone who is not a member. Turning it off lets any organization member with organization-wide vault read open it as a viewer. Neither adds nor removes a member: use `/vaults/{id}/members` for that.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "updateVault",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VaultUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, or another vault already has that name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a vault",
        "description": "Permanently delete an archived vault, its columns, its views, its extracted data, and its connector links. This cannot be undone. The documents themselves are removed from storage in the background over the following minutes.\n\nArchive the vault first with `POST /vaults/{id}/archive`. Deleting a live vault returns `409`, so an accidental call cannot destroy an active vault.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "deleteVault",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Vault deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDeleteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Archive the vault before deleting it permanently",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/archive": {
      "post": {
        "summary": "Archive a vault",
        "description": "Archive a vault. It leaves the default `GET /vaults` list, stops accepting changes, and cancels any scan waiting for review. Nothing is deleted: `POST /vaults/{id}/restore` brings it back with its documents and columns intact.\n\nArchiving is idempotent. Archiving a vault that is already archived returns it unchanged.\n\nArchive a vault before deleting it: `DELETE /vaults/{id}` refuses a live vault.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "archiveVault",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The archived vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/restore": {
      "post": {
        "summary": "Restore an archived vault",
        "description": "Bring an archived vault back. It returns to `GET /vaults`, accepts changes again, and anything its connectors synced while it was archived is queued for a catch-up scan.\n\nFind archived vaults with `GET /vaults?status=archived`. Restoring a vault that is already live returns it unchanged. A vault deleted with `DELETE /vaults/{id}` is gone and returns `404`.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "restoreVault",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The restored vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, permanently deleted, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/members": {
      "get": {
        "summary": "List a vault's members",
        "description": "List the people who hold a role in a vault, oldest grant first, with their role and when they were added.\n\nThis is the direct membership list. Someone who can open the vault only through organization-wide visibility is not a member and does not appear here, so a vault that is not access-controlled can be readable by people this list does not name.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "listVaultMembers",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100,
              "description": "Max items to return (default 100, max 500)"
            },
            "required": false,
            "description": "Max items to return (default 100, max 500)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of vault members",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultMemberListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, archived, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Add a member to a vault",
        "description": "Give someone a role in a vault. Name them by `user_id` or by `email`, exactly one of the two.\n\nThe person has to be a member of your organization already. An address that belongs to nobody in the organization returns `400` and nothing is sent, so this endpoint can never invite anyone or add a seat.\n\nAdding someone who already holds a role returns their existing row unchanged, current role included. That keeps a repeated call from quietly demoting an owner to `editor`. To change a role, use `PATCH /vaults/{id}/members/{userId}`.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "addVaultMember",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddVaultMemberRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The vault member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultMember"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, or user is not a member of this organization",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/members/{userId}": {
      "patch": {
        "summary": "Change a member's role",
        "description": "Set a vault member's role.\n\nA vault always keeps at least one owner, so demoting the last one returns `400`. Promote another member first, then demote.\n\nThe person has to hold a role in the vault already. To grant a first role, use `POST /vaults/{id}/members`.\n\nRequires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "updateVaultMemberRole",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true,
              "description": "GC AI user ID of the member, as `user_id` from `GET /vaults/{id}/members`."
            },
            "required": true,
            "description": "GC AI user ID of the member, as `user_id` from `GET /vaults/{id}/members`.",
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateVaultMemberRoleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated vault member",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultMember"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, or A vault needs at least one owner. Promote another member first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, access denied, or user is not a member of this vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a member from a vault",
        "description": "Take away a member's role in a vault. The vault, its documents, and its extracted data are untouched. Only this person's access goes away.\n\nRemoving the last owner returns `400`, so a vault cannot be left ownerless. A user who holds no role in the vault returns `404`, so a mistyped id is visible instead of reading as success.\n\nCallers can remove themselves by passing their own `user_id`, which needs vault membership rather than the `owner` role. Removing anyone else requires the `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "removeVaultMember",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true,
              "description": "GC AI user ID of the member, as `user_id` from `GET /vaults/{id}/members`."
            },
            "required": true,
            "description": "GC AI user ID of the member, as `user_id` from `GET /vaults/{id}/members`.",
            "name": "userId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Member removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RemoveVaultMemberResponse"
                }
              }
            }
          },
          "400": {
            "description": "A vault needs at least one owner. Promote another member first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller is not a vault owner",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, access denied, or user is not a member of this vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/documents": {
      "post": {
        "summary": "Add a document to a vault",
        "description": "Upload one document into a Contract Intelligence vault as multipart form data. The document is stored, its text is extracted, and it is then scanned against the vault's columns, so its extracted fields appear in the vault View a few minutes later.\n\nVaults accept a narrower set of formats than the rest of GC AI: PDF, Word (`.doc`, `.docx`), and plain text (`.txt`). Scanned and image-based PDFs are supported through OCR. Spreadsheets, presentations, standalone images, and email files are rejected.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults; a caller with the role but not the permission gets `403`. A vault that has reached its document capacity or whose organization has no remaining allowance returns `409` with the same message the app shows, and stores nothing. While a vault is still in guided setup, documents are stored and scanned once setup finishes.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "uploadVaultDocument",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/VaultDocumentUploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document added to the vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing file, unsupported file type for a vault, or file too large)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller's vault role cannot add documents",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, or the vault or organization cannot accept more documents right now (capacity or allowance reached); nothing was stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Read a vault's document table",
        "description": "Read the extracted table of a Contract Intelligence vault: one row per document, with every column the vault scans for.\n\nA document appears here once its first scan writes values, which is a few minutes after upload. Until then poll `GET /files/{id}` with the `id` that `POST /vaults/{id}/documents` returned.\n\nFiltering and sorting run in the database over the whole vault, so `total` counts every matching document and not just the page. Both name their target by the column `field_key` that `GET /vaults/{id}/columns` reports. A `sort` or `filter` naming a column the vault does not have returns `400`, and so does a filter whose value does not fit its operator, because a silently dropped rule paired with a confident `total` is worse than a rejected request.\n\nPass `filter` as a URL-encoded JSON array of rules, each `{\"field\",\"operator\",\"value\"}`, where `field` is a column `field_key`. For example `filter=[{\"field\":\"governingLaw\",\"operator\":\"equals\",\"value\":\"Delaware\"}]`. Operators that take no value (`is_empty`, `is_not_empty`) omit it; `number_range` and `date_range` take `{\"from\",\"to\"}` with either side optional; `in` and `equals_only` take an array. Rules combine with AND.\n\nA page holds at most 200 rows. `total` scans the whole filtered vault, so a client paging quickly can pass `include_total=false` and read the count on its own cadence.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "listVaultDocuments",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100,
              "description": "Max rows to return (default 100, max 200)"
            },
            "required": false,
            "description": "Max rows to return (default 100, max 200)",
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "nullable": true,
              "minimum": 0,
              "default": 0,
              "description": "Number of items to skip (default 0)"
            },
            "required": false,
            "description": "Number of items to skip (default 0)",
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 200,
              "description": "Case-insensitive substring match on the document name, the upload filename, or the Document Name column."
            },
            "required": false,
            "description": "Case-insensitive substring match on the document name, the upload filename, or the Document Name column.",
            "name": "search",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 8000,
              "description": "URL-encoded JSON array of filter rules. See the description for the shape and the operators.",
              "example": "[{\"field\":\"governingLaw\",\"operator\":\"equals\",\"value\":\"Delaware\"}]"
            },
            "required": false,
            "description": "URL-encoded JSON array of filter rules. See the description for the shape and the operators.",
            "name": "filter",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 200,
              "description": "Column `field_key` to sort by. Also accepts `fileName` (the upload filename), `extractedAt`, and `sourceName`. Defaults to `fileName`, ascending.",
              "example": "extractedAt"
            },
            "required": false,
            "description": "Column `field_key` to sort by. Also accepts `fileName` (the upload filename), `extractedAt`, and `sourceName`. Defaults to `fileName`, ascending.",
            "name": "sort",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "description": "Sort direction. Defaults to `asc`."
            },
            "required": false,
            "description": "Sort direction. Defaults to `asc`.",
            "name": "sort_direction",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "When `false`, skip the whole-vault count and return `total: null`. Defaults to `true`.",
              "example": "false"
            },
            "required": false,
            "description": "When `false`, skip the whole-vault count and return `total: null`. Defaults to `true`.",
            "name": "include_total",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "When `true`, also return soft-deleted documents and the copies GC AI removed as duplicates. Reading deleted documents needs the same rights as deleting them, so this requires the `editor` or `owner` role plus the organization-level permission to manage vaults. Defaults to `false`.",
              "example": "true"
            },
            "required": false,
            "description": "When `true`, also return soft-deleted documents and the copies GC AI removed as duplicates. Reading deleted documents needs the same rights as deleting them, so this requires the `editor` or `owner` role plus the organization-level permission to manage vaults. Defaults to `false`.",
            "name": "include_deleted",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of the document table",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters, malformed `filter` JSON, or a `filter` or `sort` naming a `field_key` this vault does not have",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or `include_deleted` was used by a caller who cannot remove documents",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, archived, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/documents/{documentId}": {
      "get": {
        "summary": "Get one document row",
        "description": "Read one row of a vault's document table by its `document_id`.\n\nA document appears here once its first scan writes values, which is a few minutes after upload. Until then poll `GET /files/{id}` with the `id` that `POST /vaults/{id}/documents` returned.\n\nThe row is built by the same query that serves the list, so a document reads the same way whichever endpoint returns it. Soft-deleted documents answer `404` unless the request passes `include_deleted=true`.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "getVaultDocument",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The `document_id` of a row from `GET /vaults/{id}/documents`."
            },
            "required": true,
            "description": "The `document_id` of a row from `GET /vaults/{id}/documents`.",
            "name": "documentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ],
              "description": "When `true`, also return soft-deleted documents and the copies GC AI removed as duplicates. Reading deleted documents needs the same rights as deleting them, so this requires the `editor` or `owner` role plus the organization-level permission to manage vaults. Defaults to `false`.",
              "example": "true"
            },
            "required": false,
            "description": "When `true`, also return soft-deleted documents and the copies GC AI removed as duplicates. Reading deleted documents needs the same rights as deleting them, so this requires the `editor` or `owner` role plus the organization-level permission to manage vaults. Defaults to `false`.",
            "name": "include_deleted",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The document row",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentRow"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or `include_deleted` was used by a caller who cannot remove documents",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or document not found, vault archived, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a document from a vault",
        "description": "Remove a document from the vault. The document leaves the table, stops counting toward the vault document limit, and stops being read by chat and playbooks. Nothing is destroyed: `POST /vaults/{id}/documents/{documentId}/restore` brings it back with its extracted values, and a connected source never re-adds it.\n\nRemoval works on the upload, so every row that shares this row's `file_id` goes with it. That matters for a bundled upload GC AI split into several documents: removing one of them removes the whole upload.\n\nRemoving a document that is already removed returns `200`, so a retried call is safe.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "deleteVaultDocument",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The `document_id` of a row from `GET /vaults/{id}/documents`."
            },
            "required": true,
            "description": "The `document_id` of a row from `GET /vaults/{id}/documents`.",
            "name": "documentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Document removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentDeleteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot remove documents from this vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or document not found, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/documents/{documentId}/restore": {
      "post": {
        "summary": "Restore a removed document",
        "description": "Bring a removed document back into the vault table with the values it already had. Find removed documents with `GET /vaults/{id}/documents?include_deleted=true`.\n\nRestoring works on the upload, so every row that shares this row's `file_id` comes back with it.\n\nA restore that would put the vault over its document limit is refused whole with `403`, and nothing comes back. Restoring a document that is already live returns `200`, so a retried call is safe.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "restoreVaultDocument",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The `document_id` of a row from `GET /vaults/{id}/documents`."
            },
            "required": true,
            "description": "The `document_id` of a row from `GET /vaults/{id}/documents`.",
            "name": "documentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Document restored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentRestoreResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., the caller cannot restore documents in this vault, or the restore would put the vault over its document limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or document not found, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/documents/{documentId}/cells/{fieldKey}": {
      "patch": {
        "summary": "Set a cell value by hand",
        "description": "Overwrite one extracted value in a vault with a value of your own. The cell keeps showing your value, and hides the citations and reasoning behind the extracted one, until you put it back with `POST /vaults/{id}/documents/{documentId}/cells/{fieldKey}/revert`.\n\n`value` is always a string, whatever the column holds. Text, enum, email, URL, number, and percentage columns take the value as written. A checkbox column takes `true` or `false`. A date column takes `YYYY-MM-DD`. Multi-select and list columns take a JSON array of strings, for example `[\"Delaware\",\"New York\"]`. Currency, duration, date-range, party, and related-agreement columns take the same JSON the read path returns for that column, so the safest way to build one is to read the cell first and edit what comes back.\n\nAn enum or multi-select value outside the column's configured options returns `400`, and so does any column GC AI writes itself: the folder columns synced from a connected drive, and a Document Name column the vault manages through its naming template.\n\nEditing a cell while its document is still being scanned is allowed. Your value wins: an extraction that lands afterwards does not overwrite it, so there is no need to poll for the scan to finish first.\n\nA document that belongs to another vault returns `404`, even when the caller can reach both vaults, and so does a column key this vault does not have. Read the keys from `GET /vaults/{id}/columns`.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults. An archived vault returns `409`: restore it first. A document that was deleted, or auto-removed as a duplicate copy, also returns `409`, and so does a document stored before GC AI split bundled uploads, which has no cells of its own to write.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "updateVaultDocumentCell",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The `document_id` of a row from `GET /vaults/{id}/documents`."
            },
            "required": true,
            "description": "The `document_id` of a row from `GET /vaults/{id}/documents`.",
            "name": "documentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100,
              "description": "Column key, as the vault reports it for its columns. A key, not a label: `governingLaw`, not `Governing law`. Percent-encode it if it holds a character a URL path reserves.",
              "example": "governingLaw"
            },
            "required": true,
            "description": "Column key, as the vault reports it for its columns. A key, not a label: `governingLaw`, not `Governing law`. Percent-encode it if it holds a character a URL path reserves.",
            "name": "fieldKey",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VaultDocumentCellUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored cell",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentCellResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, a value outside the column's configured options, or a column GC AI writes itself",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller's vault role cannot edit data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or document not found, the document belongs to another vault, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, the document has been deleted or removed as a duplicate, or the document predates bundled-upload splitting and has no cells to write",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/documents/{documentId}/cells/{fieldKey}/revert": {
      "post": {
        "summary": "Restore the extracted value of a cell",
        "description": "Take a hand edit off one cell and put the value the scan extracted back. This does not clear the cell: it restores the AI value, along with the source citations and reasoning the edit had been hiding.\n\nA cell with no hand edit on it returns `404`. So does a cell that was edited and already reverted, and a column that has no value on this document at all. The three are indistinguishable in the response, so treat the `404` as \"there is nothing to put back\" rather than as a missing document.\n\nA manual column returns `400`. Every value in a manual column was typed by a person, so there is no analyzed value to go back to.\n\nA document that belongs to another vault returns `404`, even when the caller can reach both vaults.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults. An archived vault returns `409`: restore it first. A document that was deleted, or auto-removed as a duplicate copy, also returns `409`, and so does a document stored before GC AI split bundled uploads, which has no cells of its own to write.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "revertVaultDocumentCell",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The `document_id` of a row from `GET /vaults/{id}/documents`."
            },
            "required": true,
            "description": "The `document_id` of a row from `GET /vaults/{id}/documents`.",
            "name": "documentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100,
              "description": "Column key, as the vault reports it for its columns. A key, not a label: `governingLaw`, not `Governing law`. Percent-encode it if it holds a character a URL path reserves.",
              "example": "governingLaw"
            },
            "required": true,
            "description": "Column key, as the vault reports it for its columns. A key, not a label: `governingLaw`, not `Governing law`. Percent-encode it if it holds a character a URL path reserves.",
            "name": "fieldKey",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The restored cell",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultDocumentCellResponse"
                }
              }
            }
          },
          "400": {
            "description": "A manual column, or a column GC AI writes itself, has nothing to revert to",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller's vault role cannot edit data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or document not found, the document belongs to another vault, access denied, or no hand edit to revert",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, the document has been deleted or removed as a duplicate, or the document predates bundled-upload splitting and has no cells to write",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/columns": {
      "get": {
        "summary": "List a vault's columns",
        "description": "List every column in a vault's table, in the order the table shows them.\n\nThe list covers both kinds of column. Built-in columns, such as Document Type and Effective Date, come from GC AI and appear in every vault; they report `id: null` and `kind: built_in`, and no endpoint changes them. The rest belong to this vault and carry an ID. Of those, `kind: custom` columns are yours to change, and `kind: system` columns (Document Name, Document Status, Document Title) are managed by GC AI and reject every change.\n\nColumns a member has hidden in the app are listed too: hiding is a display preference, and a hidden column still holds its values and still counts toward the vault's 500 column limit.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "listVaultColumns",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The vault's columns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultColumnListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, archived, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Add a column to a vault",
        "description": "Add a column to a vault's table.\n\nAdding a column scans nothing. Documents already in the vault keep an empty cell for the new column until a re-scan fills it, which you start from the vault in the app. Add the columns you want before you upload, and every document that arrives afterwards is read against all of them.\n\nThe new column starts hidden in every saved view of this vault. A saved view is a sharing boundary, so a column created after the view was saved never joins it on its own; a member of the view reveals it there when they want it.\n\n`field_key` is frozen at creation. Omit it and GC AI builds one from the label. Renaming the column later leaves the key alone, so the values already extracted stay attached to it.\n\nA vault holds at most 500 columns. Column 501 returns `403` with the message the app shows, and you have to delete a column before adding another.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "createVaultColumn",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateVaultColumnRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created column",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultColumnResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, a `field_key` that is reserved, underivable, or holds a control character, an option list that is not 2 to 12 unique values, or an `ai` column with no instructions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., the caller cannot manage this vault's columns, or the vault has reached its 500 column limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, or a column with that `field_key` already exists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/columns/{columnId}": {
      "patch": {
        "summary": "Update a vault column",
        "description": "Change a column's label, instructions, value type, option list, fill mode, or placement. Send only the fields you want to change; everything you leave out keeps its current value. `field_key` is not one of them: it is frozen at creation so the values already extracted stay attached.\n\nChanging the value type of an `ai` column makes the values already extracted for it stale, because they were stored as text read under the old type. GC AI queues a re-scan of the documents that hold one and reports it in `auto_rescan`. The column is saved whatever `auto_rescan` says, so treat that field as news about the re-scan and not as an error. When the vault is waiting on a scan review, the re-scan waits for that approval instead of starting now.\n\nOnly a `custom` column accepts changes. A `system` column (Document Name, Document Status, Document Title) returns `400`, and so does a column a connected spreadsheet owns if you try to move it in or out of `import`.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "updateVaultColumn",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The column ID from `GET /vaults/{id}/columns`. Built-in columns report `id: null` and cannot be addressed here."
            },
            "required": true,
            "description": "The column ID from `GET /vaults/{id}/columns`. Built-in columns report `id: null` and cannot be addressed here.",
            "name": "columnId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateVaultColumnRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated column",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultColumnUpdateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, an option list that is not 2 to 12 unique values, an `ai` column left with no instructions, a column GC AI manages, or a spreadsheet-owned column whose fill mode cannot change",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot manage this vault's columns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or column not found, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a column from a vault",
        "description": "Remove a column from a vault's table.\n\nThe values already extracted under the column's `field_key` stay stored, so a new column created with the same `field_key` shows them again. Nothing is re-scanned either way.\n\nOnly a `custom` column can be removed. A `system` column (Document Name, Document Status, Document Title) returns `400`, and a built-in column has no ID to address. A column a connected spreadsheet owns comes off when you remove the sheet in the app.\n\nRequires the `editor` or `owner` role in the vault and the organization-level permission to manage vaults.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "deleteVaultColumn",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The column ID from `GET /vaults/{id}/columns`. Built-in columns report `id: null` and cannot be addressed here."
            },
            "required": true,
            "description": "The column ID from `GET /vaults/{id}/columns`. Built-in columns report `id: null` and cannot be addressed here.",
            "name": "columnId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Column removed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteVaultColumnResponse"
                }
              }
            }
          },
          "400": {
            "description": "This column is managed by GC AI and cannot be deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot manage this vault's columns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or column not found, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/views": {
      "get": {
        "summary": "List a vault's saved views",
        "description": "List the saved views in a vault. A view stores a column layout, a sort, and a set of filters, and it is shared: every member of the vault sees the same views.\n\nColumn visibility is stored as a hide list. `hidden_field_keys` names the columns a view hides, so an empty list means the view shows every column the vault has. A column added to the vault later appears in the view until you hide it.\n\nViews come back in the order the app shows them.\n\nReadable by any caller who can read the vault.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "listVaultViews",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The vault views",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultViewListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found, archived, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a saved view",
        "description": "Create a saved view in a vault. The view is shared with the whole vault the moment it exists: anyone who can read the vault can open it, and anyone with the Manage Views permission can change or delete it.\n\nColumn visibility is stored as a hide list. `hidden_field_keys` names the columns a view hides, so an empty list means the view shows every column the vault has. A column added to the vault later appears in the view until you hide it.\n\nEvery field key has to exist in the vault. Keys in `hidden_field_keys` and `field_order` can also name a system column (`actions`, `fileName`, `relationships`, `extractedAt`, `sourceName`). `sort.field` takes a vault column or one of `fileName`, `extractedAt`, `sourceName`, because those are the only system columns the table can sort by. A filter `field_key` takes a vault column or `__notes__`, the any-column notes filter. Anything else returns `400` naming the keys it could not place, rather than being dropped on the way in and leaving you with a view that ignores half of what you sent.\n\nView names are unique within a vault once trimmed, and the comparison is case sensitive, so `Renewals` and `renewals` can both exist. A name already taken returns `409`.\n\nRequires the `editor` or `owner` role in the vault, the organization-level permission to manage vaults, and the organization-level Manage Views permission. A caller who holds the vault role but not both permissions gets `403`.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "createVaultView",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VaultViewCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created view",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultViewResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, or a field key the vault does not have",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot manage views in this vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault not found or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, or another view in it already has that name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/vaults/{id}/views/{viewId}": {
      "patch": {
        "summary": "Update a saved view",
        "description": "Rename a saved view, replace its layout, or both. Send at least one of `name` and `view_state`.\n\n`view_state` is a full replacement of all four of `hidden_field_keys`, `field_order`, `sort`, and `filters`. A field you leave out of the object is cleared, not kept, so read the view with `GET /vaults/{id}/views` first when you mean to change one part of it.\n\nColumn visibility is stored as a hide list. `hidden_field_keys` names the columns a view hides, so an empty list means the view shows every column the vault has. A column added to the vault later appears in the view until you hide it.\n\nEvery field key has to exist in the vault. Keys in `hidden_field_keys` and `field_order` can also name a system column (`actions`, `fileName`, `relationships`, `extractedAt`, `sourceName`). `sort.field` takes a vault column or one of `fileName`, `extractedAt`, `sourceName`, because those are the only system columns the table can sort by. A filter `field_key` takes a vault column or `__notes__`, the any-column notes filter. Anything else returns `400` naming the keys it could not place, rather than being dropped on the way in and leaving you with a view that ignores half of what you sent.\n\nThe view has to belong to the vault in the path. A view ID from another vault returns `404`, even when the caller can reach both vaults.\n\nA change here is visible to every member of the vault, because views are shared rather than per-person.\n\nRequires the `editor` or `owner` role in the vault, the organization-level permission to manage vaults, and the organization-level Manage Views permission. A caller who holds the vault role but not both permissions gets `403`.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "updateVaultView",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "View ID from `GET /vaults/{id}/views`."
            },
            "required": true,
            "description": "View ID from `GET /vaults/{id}/views`.",
            "name": "viewId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VaultViewUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated view",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultViewResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request body, or a field key the vault does not have",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot manage views in this vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or view not found, the view belongs to another vault, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived, or another view in it already has that name",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a saved view",
        "description": "Delete a saved view and every share on it.\n\nThis also revokes access. A view can be shared with people who are not vault members, and that share is the only thing letting them read the vault through it, so deleting the view cuts off everyone who reached the vault that way. Pending shares to people who had not accepted yet go too. This cannot be undone: recreating the view does not restore the shares.\n\nThe view has to belong to the vault in the path. A view ID from another vault returns `404`, even when the caller can reach both vaults.\n\nThe documents, columns, and extracted data in the vault are untouched. Only the saved layout and its shares go away.\n\nRequires the `editor` or `owner` role in the vault, the organization-level permission to manage vaults, and the organization-level Manage Views permission. A caller who holds the vault role but not both permissions gets `403`.\n\nRequires a user-scoped API key (`u:gcai_...`). A vault is shared with named people, so an organization-scoped key has no identity to resolve vault access with.",
        "operationId": "deleteVaultView",
        "tags": [
          "Contract Intelligence"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "The vault ID"
            },
            "required": true,
            "description": "The vault ID",
            "name": "id",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "View ID from `GET /vaults/{id}/views`."
            },
            "required": true,
            "description": "View ID from `GET /vaults/{id}/views`.",
            "name": "viewId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "View deleted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VaultViewDeleteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Contract Intelligence is not enabled for this account. Contact support to request access., or the caller cannot manage views in this vault",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Vault or view not found, the view belongs to another vault, or access denied",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The vault is archived. Restore it with `POST /vaults/{id}/restore` before changing it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Vault access is per-user and requires a user-scoped API key (u:gcai_...).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ping": {
      "get": {
        "summary": "Health check",
        "description": "Returns a simple health check response. Useful for verifying API key validity and connectivity.",
        "operationId": "ping",
        "tags": [
          "Utility"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "API is reachable and key is valid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PingResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/credit-usage": {
      "get": {
        "summary": "Get credit usage",
        "description": "Billing view of the organization's credit consumption, broken down by billable operation and by day, with rate-card pricing.\n\nRequires an org-scoped API key: credit usage is an organization-level concern. User-scoped keys receive a 403.\n\nIf rate-card pricing can't be resolved for every observed operation, `pricing_available` is `false` and all credit fields are null; raw request counts are still returned.",
        "operationId": "getCreditUsage",
        "tags": [
          "Usage"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "Inclusive range start (`YYYY-MM-DD`).",
              "example": "2026-06-01"
            },
            "required": true,
            "description": "Inclusive range start (`YYYY-MM-DD`).",
            "name": "start_date",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "Inclusive range end (`YYYY-MM-DD`).",
              "example": "2026-06-30"
            },
            "required": true,
            "description": "Inclusive range end (`YYYY-MM-DD`).",
            "name": "end_date",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "default": "UTC",
              "description": "IANA timezone for day boundaries (default `UTC`), e.g. `America/New_York`."
            },
            "required": false,
            "description": "IANA timezone for day boundaries (default `UTC`), e.g. `America/New_York`.",
            "name": "timezone",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Credit usage for the requested range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditUsageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid date range or timezone (bad calendar date, end before start, unknown timezone, or range over 366 days)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Credit usage requires an org-scoped API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/usage": {
      "get": {
        "summary": "Get usage summary",
        "description": "Organization-wide product-usage summary by channel: `web` (web app), `word` (Word add-in), and `api`.\n\nRequires an org-scoped API key: usage is reported org-wide, so a user-scoped key receives a 403. For credit/billing totals, use `GET /v1/credit-usage`.\n\nNote: web/word counts are sourced from product analytics; day boundaries for those channels are approximate (UTC).",
        "operationId": "getUsage",
        "tags": [
          "Usage"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "Inclusive range start (`YYYY-MM-DD`).",
              "example": "2026-06-01"
            },
            "required": true,
            "description": "Inclusive range start (`YYYY-MM-DD`).",
            "name": "start_date",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
              "description": "Inclusive range end (`YYYY-MM-DD`).",
              "example": "2026-06-30"
            },
            "required": true,
            "description": "Inclusive range end (`YYYY-MM-DD`).",
            "name": "end_date",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "default": "UTC",
              "description": "IANA timezone for the api channel day boundaries (default `UTC`)."
            },
            "required": false,
            "description": "IANA timezone for the api channel day boundaries (default `UTC`).",
            "name": "timezone",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Usage summary for the requested range",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummaryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid date range or timezone (bad calendar date, end before start, unknown timezone, or range over 366 days)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Usage requires an org-scoped API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp/credentials": {
      "post": {
        "summary": "Provision MCP client-credentials",
        "description": "Mint an OAuth 2.0 client-credentials credential so a machine client (e.g. Salesforce AgentForce) can obtain org-scoped MCP access tokens.\n\nRequires an **org-scoped** API key (`gcai_...`); user-scoped keys receive 403. The organization's single M2M application is created on first call and reused thereafter, so this endpoint is safe to call repeatedly. Each call mints a **new** secret and returns it **once** (it cannot be retrieved again). A WorkOS application allows up to 5 live credentials; once that limit is reached the identity provider rejects further mints (returned here as 502) until an existing credential is revoked.\n\nHand the returned `client_id`, `client_secret`, `token_endpoint`, and `resource` to the machine client's OAuth configuration.",
        "operationId": "provisionMcpCredentials",
        "tags": [
          "MCP"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "A newly minted credential (secret shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpCredentialResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or malformed API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key is not org-scoped, or the API key is invalid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MCP is not configured for this deployment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. See [Rate Limits](https://docs.gc.ai/api-reference/concepts/rate-limits) for the tiers, limits, and how to back off.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a rate-limit block.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a rate-limit block."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "string",
                  "description": "Request quota for the applicable window.",
                  "example": "3"
                },
                "required": true,
                "description": "Request quota for the applicable window."
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "string",
                  "description": "Requests remaining in the current window.",
                  "example": "0"
                },
                "required": true,
                "description": "Requests remaining in the current window."
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "string",
                  "description": "Seconds until the quota resets.",
                  "example": "60"
                },
                "required": true,
                "description": "Seconds until the quota resets."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "The identity provider failed to provision the credential (includes the 5-credential limit being reached)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Service temporarily unavailable",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "string",
                  "description": "Seconds to wait before retrying after a transient service outage.",
                  "example": "5"
                },
                "required": true,
                "description": "Seconds to wait before retrying after a transient service outage."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}
