{
  "openapi": "3.1.0",
  "info": {
    "title": "DenkOps agent management API",
    "version": "1.0.0",
    "description": "Host and operate Bun/Python APIs, webhook handlers, scheduled endpoints and MCP servers on managed EU infrastructure. This reference covers core agent operations and owner-managed connections. Sign in at https://app.denkops.com and create a scoped connection first. Management MCP: stdio, npx -y @denkopsai/mcp. Hosted connectors have separate MCP endpoints and OAuth. Deployment consumes paid project capacity. Obtain user approval for costs and mutations; discovery is not authorization to deploy."
  },
  "servers": [
    {
      "url": "https://api.denkops.com",
      "description": "Management API; customer applications have separate project hosts."
    }
  ],
  "externalDocs": {
    "url": "https://denkops.com/docs#agent-api",
    "description": "Authentication, permissions and error recovery."
  },
  "security": [
    {
      "connectionToken": []
    }
  ],
  "components": {
    "securitySchemes": {
      "connectionToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque connection token",
        "description": "Authorization: Bearer <DENKOPS_TOKEN>. Create a scoped, revocable connection in Dashboard → Connect. Permissions are server-stored JSON capabilities, not OAuth scope strings. Connector OAuth at connect.denkops.com is a separate authentication system.",
        "x-denkops-permissions-schema": {
          "$ref": "#/components/schemas/ConnectionScopes"
        }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri-reference"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "format": "uri-reference"
          },
          "error": {
            "type": "string",
            "description": "Legacy error string retained for existing clients."
          },
          "code": {
            "type": "string",
            "description": "Stable HTTP-status category. Inspect detail for the specific failure."
          },
          "resolution": {
            "type": "string"
          },
          "docs": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "instance",
          "error",
          "code",
          "resolution",
          "docs"
        ]
      },
      "ConnectionScopes": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "agent",
              "owner"
            ],
            "description": "New connections use agent; legacy owner credentials have workspace-wide privileges."
          },
          "projects": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Allowed project IDs. null means all workspace projects; [] permits none."
          },
          "canCreate": {
            "type": "boolean",
            "description": "May create projects. Set false for a token pinned to an existing project; updates to allowed projects are still permitted."
          },
          "env": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ],
            "description": "none denies access; read lists key names only; write also sets/deletes values. Stored values are never returned."
          },
          "publicPaths": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ],
            "description": "Access to the authentication-free routing allowlist. write may expose endpoints publicly."
          },
          "egress": {
            "type": "string",
            "enum": [
              "none",
              "read",
              "write"
            ],
            "description": "Access to the project's outbound domain allowlist."
          }
        },
        "required": [
          "role",
          "projects",
          "canCreate",
          "env",
          "publicPaths",
          "egress"
        ]
      },
      "Connection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "agentType": {
            "type": [
              "string",
              "null"
            ]
          },
          "scopes": {
            "$ref": "#/components/schemas/ConnectionScopes"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "expired",
              "revoked"
            ]
          }
        },
        "required": [
          "id",
          "label",
          "agentType",
          "scopes",
          "createdAt",
          "lastSeenAt",
          "expiresAt",
          "status"
        ]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string"
          },
          "runtime": {
            "type": "string",
            "enum": [
              "bun",
              "python"
            ]
          },
          "status": {
            "type": "string"
          },
          "activeVersion": {
            "type": [
              "integer",
              "null"
            ]
          },
          "host": {
            "type": "string",
            "description": "Project hostname; prefix with https:// to form its origin."
          },
          "connector": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "slug",
          "runtime",
          "status",
          "activeVersion",
          "host",
          "connector"
        ]
      },
      "DeploymentHandle": {
        "type": "object",
        "properties": {
          "deploymentId": {
            "type": "string",
            "format": "uuid"
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "version": {
            "type": "integer"
          },
          "host": {
            "type": "string"
          },
          "apiKey": {
            "type": "string",
            "description": "Secret project API key. Never log or expose it to end users."
          }
        },
        "required": [
          "deploymentId",
          "projectId",
          "version",
          "host",
          "apiKey"
        ]
      },
      "DeployMeta": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
          },
          "name": {
            "type": "string"
          },
          "runtime": {
            "type": "string",
            "enum": [
              "bun",
              "python"
            ]
          },
          "projectId": {
            "type": "string",
            "format": "uuid"
          },
          "expectNew": {
            "type": "boolean",
            "description": "Reject a slug collision instead of redeploying an existing workspace project."
          },
          "env": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Case-sensitive names and values."
          },
          "public": {
            "type": "boolean",
            "default": false,
            "description": "Disables default project API-key protection; requires user approval."
          },
          "streaming": {
            "type": "boolean",
            "default": false
          },
          "connector": {
            "type": "boolean",
            "default": false,
            "description": "Enable connector OAuth; application code must implement /mcp itself."
          },
          "commit": {
            "type": "string"
          },
          "cron": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "schedule": {
                  "type": "string",
                  "description": "Five-field cron expression."
                },
                "path": {
                  "type": "string",
                  "description": "Project endpoint path starting with /."
                },
                "method": {
                  "type": "string",
                  "enum": [
                    "GET",
                    "POST"
                  ]
                },
                "timezone": {
                  "type": "string",
                  "description": "IANA timezone, defaults to UTC."
                }
              },
              "required": [
                "schedule",
                "path"
              ]
            }
          }
        },
        "required": [
          "slug",
          "name",
          "runtime"
        ]
      }
    }
  },
  "paths": {
    "/api/projects": {
      "get": {
        "operationId": "listProjects",
        "description": "List projects visible to this connection, filtered to its workspace and allowed project IDs.",
        "summary": "List projects visible to this connection, filtered to its workspace and allowed project IDs",
        "x-denkops-permissions": {
          "projects": "allowed IDs only"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "projects": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    }
                  },
                  "required": [
                    "projects"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/status/{id}": {
      "get": {
        "operationId": "getProjectStatus",
        "description": "Inspect a project's runtime state and most recent active deployment.",
        "summary": "Inspect a project's runtime state and most recent active deployment",
        "x-denkops-permissions": {
          "projects": "must include id"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Project"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "lastDeployedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "memoryMb": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "lastDeployedAt",
                        "memoryMb"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Resource UUID returned by its list operation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/api/logs/{id}": {
      "get": {
        "operationId": "getProjectLogs",
        "description": "Read recent container logs for an allowed project. Logs may contain sensitive application data.",
        "summary": "Read recent container logs for an allowed project",
        "x-denkops-permissions": {
          "projects": "must include id"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "lines": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "lines"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Resource UUID returned by its list operation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "lines",
            "in": "query",
            "description": "Requested line count, default 150.",
            "schema": {
              "type": "integer",
              "default": 150
            }
          }
        ]
      }
    },
    "/api/deploy": {
      "post": {
        "operationId": "deployProject",
        "description": "Upload a gzip tarball and queue a deployment. Poll getProjectStatus afterwards; a handle does not mean the app is healthy. Creates or updates a project and may consume paid capacity.",
        "summary": "Upload a gzip tarball and queue a deployment",
        "x-denkops-permissions": {
          "projects": "must include target when updating",
          "canCreate": "true when creating"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/DeploymentHandle"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "warnings": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      },
                      "required": [
                        "warnings"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "tarball": {
                    "type": "string",
                    "format": "binary",
                    "description": "Project source tar.gz, max 50 MiB."
                  },
                  "meta": {
                    "type": "string",
                    "contentMediaType": "application/json",
                    "contentSchema": {
                      "$ref": "#/components/schemas/DeployMeta"
                    },
                    "description": "JSON-encoded DeployMeta. Use the MCP or CLI to package files correctly."
                  }
                },
                "required": [
                  "tarball",
                  "meta"
                ]
              }
            }
          }
        }
      }
    },
    "/api/rollback/{id}": {
      "post": {
        "operationId": "rollbackProject",
        "description": "Roll back an allowed project. Omitting version selects the previous deployment. Changes the running application.",
        "summary": "Roll back an allowed project",
        "x-denkops-permissions": {
          "projects": "must include id"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "version": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "version"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Resource UUID returned by its list operation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "integer",
                    "description": "Target deployment version."
                  }
                },
                "required": []
              }
            }
          }
        }
      }
    },
    "/api/projects/{id}/env": {
      "get": {
        "operationId": "listEnvironmentKeys",
        "description": "List environment variable names and whether a redeploy is pending. Secret values are never returned.",
        "summary": "List environment variable names and whether a redeploy is pending",
        "x-denkops-permissions": {
          "projects": "must include id",
          "env": [
            "read",
            "write"
          ]
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "vars": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "key": {
                            "type": "string"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "key",
                          "updatedAt"
                        ]
                      }
                    },
                    "pending": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "vars",
                    "pending"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Resource UUID returned by its list operation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/api/projects/{id}/env/{key}": {
      "put": {
        "operationId": "setEnvironmentVariable",
        "description": "Set a case-sensitive environment variable. Redeploy to apply it to the running application.",
        "summary": "Set a case-sensitive environment variable",
        "x-denkops-permissions": {
          "projects": "must include id",
          "env": [
            "write"
          ]
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Resource UUID returned by its list operation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "Case-sensitive name; reserved platform keys are rejected.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string"
                  }
                },
                "required": [
                  "value"
                ]
              }
            }
          }
        }
      }
    },
    "/api/connections": {
      "get": {
        "operationId": "listConnections",
        "description": "List scoped connections in the workspace. Requires owner privileges; agent tokens cannot enumerate or mint credentials.",
        "summary": "List scoped connections in the workspace",
        "x-denkops-permissions": {
          "role": "owner"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "connections": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Connection"
                      }
                    }
                  },
                  "required": [
                    "connections"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/connections/{id}/scopes": {
      "patch": {
        "operationId": "updateConnectionPermissions",
        "description": "Change an existing connection's server-enforced permissions. Requires an owner credential. An agent cannot elevate its own token. Ask the owner to approve changes.",
        "summary": "Change an existing connection's server-enforced permissions",
        "x-denkops-permissions": {
          "role": "owner"
        },
        "responses": {
          "200": {
            "description": "Successful operation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "connection": {
                      "$ref": "#/components/schemas/Connection"
                    }
                  },
                  "required": [
                    "connection"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "default": {
            "description": "Failed request; the legacy error string is preserved alongside recovery information.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Resource UUID returned by its list operation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "projects": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "Allowed project IDs. null means all workspace projects; [] permits none."
                  },
                  "canCreate": {
                    "type": "boolean",
                    "description": "May create projects. Set false for a token pinned to an existing project; updates to allowed projects are still permitted."
                  },
                  "env": {
                    "type": "string",
                    "enum": [
                      "none",
                      "read",
                      "write"
                    ],
                    "description": "none denies access; read lists key names only; write also sets/deletes values. Stored values are never returned."
                  },
                  "publicPaths": {
                    "type": "string",
                    "enum": [
                      "none",
                      "read",
                      "write"
                    ],
                    "description": "Access to the authentication-free routing allowlist. write may expose endpoints publicly."
                  },
                  "egress": {
                    "type": "string",
                    "enum": [
                      "none",
                      "read",
                      "write"
                    ],
                    "description": "Access to the project's outbound domain allowlist."
                  }
                },
                "required": []
              }
            }
          }
        }
      }
    }
  }
}
