{
  "openapi": "3.1.0",
  "info": {
    "title": "varsafe API",
    "version": "1.0.0",
    "summary": "Programmatic access to varsafe secrets management.",
    "description": "varsafe stores environment variables — database URLs, API keys, signing secrets — encrypted at rest, and hands them to the process that needs them without writing a `.env` file to disk.\n\n## When to use this API\n\n- Inject a project environment into a process or pipeline (`GET /secrets/inject`).\n- Read one secret value at the moment it is needed (`GET /secrets/value`), rather than caching a whole environment.\n- Create, update or delete secrets from automation (`POST /secrets`, `POST /secrets/bulk`).\n- Discover what a credential may do before acting (`GET /me/cli`, `GET /capabilities`).\n\nIf you are an AI agent, prefer the Model Context Protocol endpoint at `POST /mcp` over these REST routes: it exposes the same capabilities as typed tools with per-tool scope enforcement and a consent step. See https://docs.varsafe.dev/guides/mcp.\n\n## Authentication\n\nRead the `security` field on each operation — it is derived from what the guards and handlers actually accept, and it is not uniform.\n\nMost routes take an **API token** (`Authorization: Bearer …`), created self-serve in the dashboard and scopable to a project, an environment and read-only access. Routes carrying `x-varsafe-cli-scopes` also accept a **CLI grant** from the device authorization flow and enforce the listed scopes. Four routes are narrower: `GET /me/cli` and `POST /auth/cli/logout` answer only to a CLI grant, because both describe or revoke that grant itself; `POST /auth/cli/device/token` and `GET /auth/cli/device/events` authenticate with the device code rather than an account. `GET /me` accepts a session or a CLI grant but not an API token. The MCP endpoint at `POST /mcp` uses **OAuth 2.1**, or an API token, with the scope vocabulary in `components.securitySchemes.varsafeMcpOAuth`.\n\n## Scope of this document\n\nThis is the programmatic surface: the routes a token, a CLI grant or an agent may call. Dashboard-only and administrative routes are intentionally not described here. Success payloads are documented by status and content type; their schemas are not yet published — the wire types are exported from the `@varsafe/shared` package and mirrored in the docs.",
    "termsOfService": "https://varsafe.dev/terms",
    "contact": {
      "name": "varsafe support",
      "email": "support@varsafe.dev",
      "url": "https://varsafe.dev/contact"
    },
    "license": {
      "name": "Proprietary — varsafe Terms of Service",
      "url": "https://varsafe.dev/terms"
    }
  },
  "externalDocs": {
    "description": "varsafe documentation",
    "url": "https://docs.varsafe.dev"
  },
  "servers": [
    {
      "url": "https://api.varsafe.dev",
      "description": "Production (EU)"
    }
  ],
  "x-varsafe-scopes": {
    "secrets:read": "List secrets and read their metadata. Never returns a secret value.",
    "secrets:read_values": "Read decrypted secret values.",
    "secrets:write": "Create, update and delete secrets.",
    "secrets:run": "Resolve a full environment for injection into a process.",
    "projects:read": "List projects and environments.",
    "audit:read": "Read the audit trail. Available to MCP credentials only.",
    "identity:read": "Read the identity and team memberships of the calling credential."
  },
  "x-varsafe-mcp": {
    "endpoint": "https://api.varsafe.dev/mcp",
    "transport": "streamable-http",
    "protectedResourceMetadata": "https://api.varsafe.dev/.well-known/oauth-protected-resource/mcp",
    "documentation": "https://docs.varsafe.dev/guides/mcp"
  },
  "tags": [
    {
      "name": "Capabilities",
      "description": "What this deployment supports, so a client can adapt instead of probing."
    },
    {
      "name": "CliDeviceAuth",
      "description": "Device authorization grant — how a CLI or an unattended agent obtains a credential."
    },
    {
      "name": "CliSession",
      "description": "Lifecycle of a CLI grant, including self-revocation."
    },
    {
      "name": "Environments",
      "description": "Environments within a project — development, staging, production, and any others."
    },
    {
      "name": "Health",
      "description": "Liveness and readiness probes."
    },
    {
      "name": "Keypairs",
      "description": "Per-environment keypairs used to encrypt values into a committable .env file."
    },
    {
      "name": "McpTransport",
      "description": "Model Context Protocol endpoint over Streamable HTTP."
    },
    {
      "name": "Me",
      "description": "The identity and authority behind the calling credential."
    },
    {
      "name": "OAuthProviderWellKnown",
      "description": "RFC 8414 and RFC 9728 discovery documents for the OAuth 2.1 flow."
    },
    {
      "name": "Projects",
      "description": "Projects, the top-level grouping that owns environments and secrets."
    },
    {
      "name": "SecretComposition",
      "description": "How secrets reference one another through ${KEY} templates."
    },
    {
      "name": "Secrets",
      "description": "Reading, writing and resolving secrets. The core of the API."
    }
  ],
  "paths": {
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "OAuthProviderWellKnownController_authorizationServer",
        "summary": "OAuth 2.1 authorization server metadata",
        "description": "RFC 8414 metadata describing the authorization and token endpoints, supported grant types and the scope vocabulary used by the MCP endpoint.",
        "tags": ["OAuthProviderWellKnown"],
        "parameters": [],
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource": {
      "get": {
        "operationId": "OAuthProviderWellKnownController_protectedResourceRoot",
        "summary": "Protected resource metadata",
        "description": "RFC 9728 metadata naming the authorization server for this API and the scopes it supports.",
        "tags": ["OAuthProviderWellKnown"],
        "parameters": [],
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource/mcp": {
      "get": {
        "operationId": "OAuthProviderWellKnownController_protectedResourceMcp",
        "summary": "Protected resource metadata for the MCP endpoint",
        "description": "RFC 9728 metadata for https://api.varsafe.dev/mcp. MCP clients read this after a 401 to discover where to authorize.",
        "tags": ["OAuthProviderWellKnown"],
        "parameters": [],
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/me/verify": {
      "get": {
        "operationId": "MeController_verify",
        "summary": "Verify the calling credential",
        "description": "Confirms that the presented credential is valid and returns the identity behind it. The cheapest call to make first when diagnosing an authentication problem.",
        "tags": ["Me"],
        "parameters": [],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["identity:read"],
        "x-varsafe-cli-subject": "all-granted-teams",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/me/token": {
      "delete": {
        "operationId": "MeController_revokeOwnToken",
        "summary": "Revoke the calling API token",
        "description": "Revokes the API token presented on this request. It takes no id, so a token can only ever destroy itself — the safe thing for an automation to call when it believes it has been compromised. Idempotent: revoking an already-revoked token still answers 200.",
        "tags": ["Me"],
        "parameters": [],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "operationId": "MeController_me",
        "summary": "Get the current identity",
        "description": "Returns the user, their teams and the active team for the calling credential.",
        "tags": ["Me"],
        "parameters": [],
        "security": [
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["identity:read"],
        "x-varsafe-cli-subject": "all-granted-teams",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/me/cli": {
      "get": {
        "operationId": "MeController_whoamiCli",
        "summary": "Get the CLI grant behind the credential",
        "description": "Returns what the person who approved this CLI credential consented to: the teams it may act on, the scopes it holds per team, and any project or environment restriction. This is what `varsafe whoami` prints.",
        "tags": ["Me"],
        "parameters": [],
        "security": [
          {
            "varsafeCliGrant": []
          }
        ],
        "x-varsafe-cli-scopes": ["identity:read"],
        "x-varsafe-cli-subject": "all-granted-teams",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/auth/cli/device": {
      "post": {
        "operationId": "CliDeviceAuthController_start",
        "summary": "Start device authorization",
        "description": "Begins the device authorization grant. Returns a user code and a verification URL that a human opens in a browser to approve the credential, plus a device code to poll with. This is how a CLI or an unattended agent obtains a credential without a password.",
        "tags": ["CliDeviceAuth"],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "credentialProtection": {
                        "default": "os_keychain",
                        "type": "string",
                        "enum": ["os_keychain", "plaintext_local"]
                      },
                      "installationId": {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      "machineCredential": {
                        "type": "string",
                        "const": "grant"
                      },
                      "host": {
                        "type": "object",
                        "properties": {
                          "hostname": {
                            "type": "string",
                            "maxLength": 256
                          },
                          "os": {
                            "type": "string",
                            "maxLength": 256
                          }
                        },
                        "additionalProperties": false
                      }
                    },
                    "additionalProperties": false
                  },
                  {}
                ]
              }
            }
          }
        },
        "security": [],
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/auth/cli/device/token": {
      "post": {
        "operationId": "CliDeviceAuthController_token",
        "summary": "Exchange a device code for a CLI credential",
        "description": "Polls the device authorization grant. Returns the CLI credential once a human has approved it, and an authorization-pending error until then.",
        "tags": ["CliDeviceAuth"],
        "parameters": [],
        "security": [
          {
            "varsafeDeviceCode": []
          }
        ],
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/auth/cli/device/events": {
      "get": {
        "operationId": "CliDeviceAuthController_events",
        "summary": "Stream device-approval events",
        "description": "Server-sent events that signal approval or denial of a pending device authorization, so a client can stop polling immediately instead of waiting for its next interval.",
        "tags": ["CliDeviceAuth"],
        "parameters": [],
        "security": [
          {
            "varsafeDeviceCode": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/auth/cli/logout": {
      "post": {
        "operationId": "CliSessionController_logout",
        "summary": "Revoke the calling CLI credential",
        "description": "Revokes the CLI grant presented on the request. Self-service and immediate — it needs no scope because it can only ever destroy the caller’s own credential.",
        "tags": ["CliSession"],
        "parameters": [],
        "security": [
          {
            "varsafeCliGrant": []
          }
        ],
        "x-varsafe-cli-scopes": [],
        "x-varsafe-cli-subject": "self",
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/projects": {
      "get": {
        "operationId": "ProjectsController_list",
        "summary": "List projects",
        "description": "Lists the projects visible to the credential across every team it has been granted. A CLI credential restricted to a subset of projects sees only that subset.",
        "tags": ["Projects"],
        "parameters": [],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["projects:read"],
        "x-varsafe-cli-subject": "each-granted-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/projects/{projectId}/environments": {
      "get": {
        "operationId": "EnvironmentsController_list",
        "summary": "List environments in a project",
        "description": "Lists the environments of one project — the second half of resolving a `project/environment` context before reading secrets.",
        "tags": ["Environments"],
        "parameters": [
          {
            "name": "projectId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["projects:read"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health/live": {
      "get": {
        "operationId": "HealthController_live",
        "summary": "Liveness check",
        "description": "Returns 200 while the process is running. It does not check dependencies — use the readiness probe for that.",
        "tags": ["Health"],
        "parameters": [],
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health/ready": {
      "get": {
        "operationId": "HealthController_ready",
        "summary": "Readiness check",
        "description": "Reports whether the API and its dependencies (database, cache, vault) can serve traffic. Returns 503 when any dependency is unavailable.",
        "tags": ["Health"],
        "parameters": [],
        "security": [],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/environments/{envId}/keypair": {
      "get": {
        "operationId": "KeypairsController_get",
        "summary": "Get an environment public key",
        "description": "Returns the public half of the environment keypair, used to encrypt values into a committable encrypted .env file. The private half is never returned by this route.",
        "tags": ["Keypairs"],
        "parameters": [
          {
            "name": "envId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:read"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets": {
      "post": {
        "operationId": "SecretsController_create",
        "summary": "Create a secret",
        "description": "Creates one secret in a project environment. Fails rather than overwrites when the key already exists.",
        "tags": ["Secrets"],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "environment": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "pattern": "^[a-z0-9][a-z0-9-]*$"
                  },
                  "key": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "pattern": "^[A-Z][A-Z0-9_]*$"
                  },
                  "kind": {
                    "type": "string",
                    "enum": ["literal", "template"]
                  },
                  "value": {
                    "type": "string",
                    "maxLength": 65536
                  },
                  "source": {
                    "type": "string",
                    "maxLength": 65536
                  },
                  "expectedVersion": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  }
                },
                "required": ["projectId", "environment", "key"],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:write"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "SecretsController_list",
        "summary": "List secrets",
        "description": "Lists secret keys and metadata for a project environment. Values are never included — that requires `secrets:read_values`.",
        "tags": ["Secrets"],
        "parameters": [
          {
            "name": "projectId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 500
            }
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["materialized", "source"]
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:read"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/bulk": {
      "post": {
        "operationId": "SecretsController_createBulk",
        "summary": "Create or update secrets in bulk",
        "description": "Writes many secrets to one environment in a single transaction. The intended path for importing an existing .env file.",
        "tags": ["Secrets"],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projectId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "environment": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "pattern": "^[a-z0-9][a-z0-9-]*$"
                  },
                  "secrets": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 255,
                          "pattern": "^[A-Z][A-Z0-9_]*$"
                        },
                        "value": {
                          "type": "string",
                          "maxLength": 65536
                        }
                      },
                      "required": ["key", "value"],
                      "additionalProperties": false
                    }
                  }
                },
                "required": ["projectId", "environment", "secrets"],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:write"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/with-values": {
      "get": {
        "operationId": "SecretsController_listWithValues",
        "summary": "List secrets with values",
        "description": "Lists secrets for a project environment including decrypted values. Every call is recorded in the audit trail.",
        "tags": ["Secrets"],
        "parameters": [
          {
            "name": "projectId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 500
            }
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["materialized", "source"]
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:read_values"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/value": {
      "get": {
        "operationId": "SecretsController_getValue",
        "summary": "Read one secret value",
        "description": "Returns the decrypted value of a single secret. Prefer this over listing with values when only one key is needed, so the audit trail records what was actually read.",
        "tags": ["Secrets"],
        "parameters": [
          {
            "name": "projectId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          },
          {
            "name": "key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255,
              "pattern": "^[A-Z][A-Z0-9_]*$"
            }
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["materialized", "source"]
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:read_values"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/inject": {
      "get": {
        "operationId": "SecretsController_inject",
        "summary": "Resolve an environment for injection",
        "description": "Returns the fully resolved key/value set for a project environment, with composed secrets expanded. This is what `varsafe run` calls before spawning a child process.",
        "tags": ["Secrets"],
        "parameters": [
          {
            "name": "projectId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 10000
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "maximum": 500
            }
          },
          {
            "name": "representation",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["materialized", "source"]
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:run"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/diff": {
      "get": {
        "operationId": "SecretsController_diff",
        "summary": "Diff two environments",
        "description": "Compares the secret keys of two environments and reports what is added, removed or changed. Useful before promoting configuration between environments.",
        "tags": ["Secrets"],
        "parameters": [
          {
            "name": "projectId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "sourceEnv",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          },
          {
            "name": "targetEnv",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:read"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/{secretId}": {
      "delete": {
        "operationId": "SecretsController_delete",
        "summary": "Delete a secret",
        "description": "Deletes one secret from a project environment. The deletion is recorded in the audit trail and, on plans with versioning, earlier versions remain recoverable.",
        "tags": ["Secrets"],
        "parameters": [
          {
            "name": "secretId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "disposition",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["flatten", "cascade"]
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:write"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/delete-bulk": {
      "post": {
        "operationId": "SecretsController_deleteBulk",
        "summary": "Delete secrets in bulk",
        "description": "Deletes several secrets from one environment in a single transaction, so a partial failure leaves the environment unchanged.",
        "tags": ["Secrets"],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "projectId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "environment": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "pattern": "^[a-z0-9][a-z0-9-]*$"
                  }
                },
                "required": ["ids", "projectId", "environment"],
                "additionalProperties": false
              }
            }
          }
        },
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:write"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/secrets/composition": {
      "get": {
        "operationId": "SecretCompositionController_composition",
        "summary": "Get the secret composition graph",
        "description": "Returns which secrets reference which others through `${KEY}` templates, so a caller can see what a rotation will change. Returns no values.",
        "tags": ["SecretComposition"],
        "parameters": [
          {
            "name": "projectId",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50,
              "pattern": "^[a-z0-9][a-z0-9-]*$"
            }
          }
        ],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": ["secrets:read"],
        "x-varsafe-cli-subject": "resource-team",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/capabilities": {
      "get": {
        "operationId": "CapabilitiesController_get",
        "summary": "Get server capabilities",
        "description": "Reports the features and limits this deployment supports, so a client can adapt instead of probing endpoints and interpreting failures.",
        "tags": ["Capabilities"],
        "parameters": [],
        "security": [
          {
            "varsafeApiToken": []
          },
          {
            "varsafeCliGrant": []
          },
          {
            "varsafeSessionCookie": []
          }
        ],
        "x-varsafe-cli-scopes": [],
        "x-varsafe-cli-subject": "self",
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "McpTransportController_handlePost",
        "summary": "MCP transport (JSON-RPC request)",
        "description": "Model Context Protocol endpoint over Streamable HTTP. Send JSON-RPC requests here to list and call varsafe tools. Requires an OAuth 2.1 access token whose granted scopes cover the tool being called; an unauthenticated request answers 401 with a WWW-Authenticate header pointing at the protected-resource metadata.",
        "tags": ["McpTransport"],
        "parameters": [],
        "security": [
          {
            "varsafeMcpOAuth": []
          },
          {
            "varsafeApiToken": []
          }
        ],
        "responses": {
          "201": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "McpTransportController_handleGet",
        "summary": "MCP transport (event stream)",
        "description": "Opens the server-to-client server-sent event stream for an established MCP session.",
        "tags": ["McpTransport"],
        "parameters": [],
        "security": [
          {
            "varsafeMcpOAuth": []
          },
          {
            "varsafeApiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "McpTransportController_handleDelete",
        "summary": "MCP transport (end session)",
        "description": "Terminates an established MCP session and releases its server-side state. Polite shutdown; sessions also expire on their own.",
        "tags": ["McpTransport"],
        "parameters": [],
        "security": [
          {
            "varsafeMcpOAuth": []
          },
          {
            "varsafeApiToken": []
          }
        ],
        "responses": {
          "200": {
            "description": "Success."
          },
          "400": {
            "description": "The request failed validation. `field` names the offending input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "No credential was presented, or it is invalid or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "The credential is valid but lacks the required scope, role or team access.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The resource does not exist, or is not visible to this credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the interval named in the response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "varsafeApiToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "varsafe API token",
        "description": "A team-scoped API token, created self-serve in the dashboard and presented as `Authorization: Bearer <token>`. A token can be restricted to specific projects and environments and to read-only access. Intended for CI pipelines and unattended automation."
      },
      "varsafeCliGrant": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "varsafe CLI grant",
        "description": "An opaque, database-backed credential obtained through the device authorization grant (`POST /auth/cli/device`) and revocable on the spot. Presented as `Authorization: Bearer <token>`. A route accepts it only when it declares CLI access; the scopes it must hold are listed per operation under `x-varsafe-cli-scopes`."
      },
      "varsafeSessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Secure-varsafe.session_token",
        "description": "The browser session cookie issued to the dashboard (named `varsafe.session_token` without the `__Secure-` prefix on non-production deployments). Listed for completeness: it authorizes the same routes, but programmatic callers should use an API token or a CLI grant."
      },
      "varsafeDeviceCode": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "varsafe device code",
        "description": "The single-use device code returned by `POST /auth/cli/device`, presented as `Authorization: Bearer <device_code>` while polling for approval. It is a 48-byte secret and never travels in a query string — it is a credential, even though these routes need no account."
      },
      "varsafeMcpOAuth": {
        "type": "oauth2",
        "description": "OAuth 2.1 authorization code flow with PKCE, used by MCP clients against https://api.varsafe.dev/mcp. Clients may register dynamically (RFC 7591). The granted scopes are the intersection of what the client requests and what the approving user may delegate.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.varsafe.dev/auth/oauth2/authorize",
            "tokenUrl": "https://api.varsafe.dev/auth/oauth2/token",
            "refreshUrl": "https://api.varsafe.dev/auth/oauth2/token",
            "scopes": {
              "secrets:read": "List secrets and read their metadata. Never returns a secret value.",
              "secrets:read_values": "Read decrypted secret values.",
              "secrets:write": "Create, update and delete secrets.",
              "secrets:run": "Resolve a full environment for injection into a process.",
              "projects:read": "List projects and environments.",
              "audit:read": "Read the audit trail. Available to MCP credentials only.",
              "identity:read": "Read the identity and team memberships of the calling credential.",
              "offline_access": "Issue a refresh token so the client can keep access without re-consent."
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "description": "The error body every failing varsafe endpoint returns.",
        "properties": {
          "statusCode": {
            "type": "integer",
            "description": "HTTP status code, repeated in the body."
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code, e.g. `SECRET_NOT_FOUND` or `FORBIDDEN`. Branch on this, never on the message."
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation. Wording may change."
          },
          "field": {
            "type": "string",
            "description": "The offending request field, present on validation failures."
          }
        },
        "required": ["statusCode", "code", "message"]
      }
    }
  }
}
