{
  "openapi": "3.1.0",
  "info": {
    "title": "Agentic Control Plane — Gateway API",
    "version": "0.1.0",
    "description": "The public, gsk_-key-authenticated surface of the ACP gateway: agent profiles, run summaries,\nself-introspection (cost / usage / decisions / traces), delegation-chain child-key minting,\nscoped-token issuance, the governed model proxy, and the MCP endpoint.\n\n**Rate limits.** Rate-limited endpoints return IETF draft-7 `RateLimit` / `RateLimit-Policy`\nheaders on every response and a 429 with the same headers when exceeded.\n\n**Errors.** Three envelopes coexist and are documented per-endpoint: `{ error: string }` on\n/api/v1/*, `{ error: 'validation_failed', details }` on schema-validated bodies, and the\nOpenAI-compatible `{ error: { message, type, param, code } }` on the model proxy.\n\n**Feature-flagged surfaces.** `/api/v1/keys/child`, `/api/v1/scoped-tokens`, and\n`/v1/sandbox-tenants` are deployment-flagged; when disabled they 404.\n\nHuman docs: https://agenticcontrolplane.com/agents/configure-as-code — agent-facing site\nindex: https://agenticcontrolplane.com/llms.txt",
    "contact": {
      "name": "Agentic Control Plane",
      "email": "hello@agenticcontrolplane.com",
      "url": "https://agenticcontrolplane.com/contact"
    }
  },
  "servers": [
    {
      "url": "https://api.agenticcontrolplane.com"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "agents",
      "description": "Agent profiles — the governed identity + limits an agent runs under."
    },
    {
      "name": "runs",
      "description": "Run summaries — the same pre-aggregated data the console reads."
    },
    {
      "name": "introspect",
      "description": "Read-only self-introspection over the caller's own governed footprint."
    },
    {
      "name": "delegation",
      "description": "Agent-to-agent delegation: scope-narrowed child API keys (ADCS)."
    },
    {
      "name": "credentials",
      "description": "Short-lived scoped tokens bound to a user's stored OAuth credential."
    },
    {
      "name": "sandbox",
      "description": "Zero-signup sandbox workspaces for agents with no tenant yet."
    },
    {
      "name": "proxy",
      "description": "Governed model proxy — OpenAI- and Anthropic-compatible."
    },
    {
      "name": "mcp",
      "description": "Model Context Protocol endpoint (streamable HTTP)."
    },
    {
      "name": "meta",
      "description": "Service metadata."
    }
  ],
  "paths": {
    "/api/v1/agents": {
      "post": {
        "tags": [
          "agents"
        ],
        "operationId": "createAgentProfile",
        "summary": "Create an agent profile",
        "description": "Creates a governed agent profile. `name` and `model` are required; budget/limit fields default conservatively.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Agent profile fields. On PATCH the body is strict (unknown fields rejected) and `model` must be on the platform allowlist; see /api/v1 docs for per-field bounds.",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "icon": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "model": {
                    "type": "string",
                    "description": "Must be an allow-listed model id."
                  },
                  "systemPrompt": {
                    "type": "string",
                    "maxLength": 20000
                  },
                  "enabledTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 200
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "maxToolCalls": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "maxBudgetCents": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000000
                  },
                  "maxDurationMs": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "maxToolRounds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "delegatable": {
                    "type": "boolean"
                  },
                  "canDelegate": {
                    "type": "boolean"
                  },
                  "maxDelegationDepth": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Missing required field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "agents"
        ],
        "operationId": "listAgentProfiles",
        "summary": "List agent profiles",
        "responses": {
          "200": {
            "description": "Profiles, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "profiles": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "agents"
        ],
        "operationId": "getAgentProfile",
        "summary": "Get one agent profile",
        "responses": {
          "200": {
            "description": "The profile.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "profile": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "agents"
        ],
        "operationId": "replaceAgentProfileFields",
        "summary": "Update agent profile (lenient)",
        "description": "Field-by-field update; unknown fields ignored. Prefer PATCH, which validates strictly.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Agent profile fields. On PATCH the body is strict (unknown fields rejected) and `model` must be on the platform allowlist; see /api/v1 docs for per-field bounds.",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "icon": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "model": {
                    "type": "string",
                    "description": "Must be an allow-listed model id."
                  },
                  "systemPrompt": {
                    "type": "string",
                    "maxLength": 20000
                  },
                  "enabledTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 200
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "maxToolCalls": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "maxBudgetCents": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000000
                  },
                  "maxDurationMs": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "maxToolRounds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "delegatable": {
                    "type": "boolean"
                  },
                  "canDelegate": {
                    "type": "boolean"
                  },
                  "maxDelegationDepth": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "agents"
        ],
        "operationId": "patchAgentProfile",
        "summary": "Update agent profile (strict, validated)",
        "description": "Strict zod-validated patch: unknown fields rejected, `model` checked against the platform allowlist, numeric bounds enforced. Rate limited per tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Agent profile fields. On PATCH the body is strict (unknown fields rejected) and `model` must be on the platform allowlist; see /api/v1 docs for per-field bounds.",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "icon": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "model": {
                    "type": "string",
                    "description": "Must be an allow-listed model id."
                  },
                  "systemPrompt": {
                    "type": "string",
                    "maxLength": 20000
                  },
                  "enabledTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 200
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100
                  },
                  "maxToolCalls": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  },
                  "maxBudgetCents": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000000
                  },
                  "maxDurationMs": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "maxToolRounds": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "delegatable": {
                    "type": "boolean"
                  },
                  "canDelegate": {
                    "type": "boolean"
                  },
                  "maxDelegationDepth": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10
                  }
                },
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Patched.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Standard draft-7 RateLimit / RateLimit-Policy headers are set; retry after the window resets.",
            "headers": {
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF draft-7 rate-limit header."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "agents"
        ],
        "operationId": "deleteAgentProfile",
        "summary": "Delete an agent profile",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agents/{id}/run": {
      "post": {
        "tags": [
          "agents"
        ],
        "operationId": "runAgent",
        "summary": "Run an agent",
        "description": "Triggers a governed run of the profile. The run executes under the profile's limits (budget, tool rounds, duration) and every tool call is policy-checked and audited.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run result / run reference.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runs": {
      "get": {
        "tags": [
          "runs"
        ],
        "operationId": "listRuns",
        "summary": "List run summaries",
        "parameters": [
          {
            "name": "agent",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter by agent name."
          },
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "24h",
                "7d",
                "30d",
                "90d"
              ],
              "default": "30d"
            },
            "description": "Time window (endpoints accept the subset that makes sense for them; default 30d)."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Runs, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "window": {
                      "type": "string"
                    },
                    "runs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runs/{runKey}": {
      "get": {
        "tags": [
          "runs"
        ],
        "operationId": "getRun",
        "summary": "Get one run summary (with ordered steps)",
        "parameters": [
          {
            "name": "runKey",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The run.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "run": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/usage": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectUsage",
        "summary": "Plan meter + caller's own share",
        "description": "The workspace-shared plan meter (used / limit / state) plus the caller's own contribution. Lets an agent answer \"am I about to lose governance?\" itself.",
        "responses": {
          "200": {
            "description": "Usage.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/cost": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectCost",
        "summary": "Model spend, by model",
        "description": "Principal-scoped by default; a key with the `admin` scope may pass `?scope=workspace`.",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "24h",
                "7d",
                "30d",
                "90d"
              ],
              "default": "30d"
            },
            "description": "Time window (endpoints accept the subset that makes sense for them; default 30d)."
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "workspace"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Spend.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/decisions": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectDecisions",
        "summary": "Recent governance decisions, risk-annotated",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "24h",
                "7d",
                "30d",
                "90d"
              ],
              "default": "30d"
            },
            "description": "Time window (endpoints accept the subset that makes sense for them; default 30d)."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "workspace"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Decisions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/trace/{sessionId}": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectTrace",
        "summary": "Run trace for one session",
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ordered runs for the session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not your session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No trace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/agents": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectAgents",
        "summary": "Agent identities the caller has run",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "24h",
                "7d",
                "30d",
                "90d"
              ],
              "default": "30d"
            },
            "description": "Time window (endpoints accept the subset that makes sense for them; default 30d)."
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "workspace"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregated agents.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/recommendations": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectRecommendations",
        "summary": "Evidence-backed policy recommendations",
        "description": "Ranked suggestions mined from the caller's approval + decision history, each carrying a mergeable policy patch. Read-only — nothing is applied.",
        "responses": {
          "200": {
            "description": "Recommendations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/introspect/cost-insights": {
      "get": {
        "tags": [
          "introspect"
        ],
        "operationId": "introspectCostInsights",
        "summary": "Quantified cost-optimization insights",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "24h",
                "7d",
                "30d",
                "90d"
              ],
              "default": "30d"
            },
            "description": "Time window (endpoints accept the subset that makes sense for them; default 30d)."
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "workspace"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Insights.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/keys/child": {
      "post": {
        "tags": [
          "delegation"
        ],
        "operationId": "mintChildKey",
        "summary": "Mint a scope-narrowed child API key",
        "description": "The delegation-chain primitive (ADCS): a parent key mints a child key bound to a delegatable agent profile. Scopes intersect with the parent's, budget clamps to the parent's remaining, TTL caps at 24h, `originSub` is preserved for end-to-end audit. Feature-flagged; 404 when disabled. Rate limited per tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "profileId"
                ],
                "properties": {
                  "profileId": {
                    "type": "string",
                    "description": "Delegatable agent profile the child is bound to."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Optional further narrowing; cannot widen beyond the parent."
                  },
                  "maxBudgetCents": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000000
                  },
                  "ttlSeconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 86400,
                    "default": 3600
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Free-text audit label."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The child key (returned once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Profile not delegatable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Profile not found / feature disabled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Delegation cycle detected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Standard draft-7 RateLimit / RateLimit-Policy headers are set; retry after the window resets.",
            "headers": {
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF draft-7 rate-limit header."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scoped-tokens": {
      "post": {
        "tags": [
          "credentials"
        ],
        "operationId": "issueScopedToken",
        "summary": "Issue a short-lived scoped token",
        "description": "Issues an opaque, short-lived ACP-managed token bound to the calling user's stored OAuth credential for a provider — the agent never sees the underlying vendor token. 409 with a `connectUrl` when the provider isn't connected yet. Per-tenant feature flag; 404 when disabled. Rate limited per tenant.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "provider"
                ],
                "properties": {
                  "provider": {
                    "type": "string",
                    "description": "Canonical lowercase provider key (e.g. \"github\", \"google\", \"slack\")."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Optional narrowing; cannot widen beyond the user's OAuth grant."
                  },
                  "ttlSeconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 86400,
                    "default": 3600
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The scoped token (returned once).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "No associated user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Feature disabled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Provider not connected — response carries a connectUrl.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Standard draft-7 RateLimit / RateLimit-Policy headers are set; retry after the window resets.",
            "headers": {
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF draft-7 rate-limit header."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scoped-tokens/{tokenId}/revoke": {
      "post": {
        "tags": [
          "credentials"
        ],
        "operationId": "revokeScopedToken",
        "summary": "Revoke a scoped token",
        "parameters": [
          {
            "name": "tokenId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/sandbox-tenants": {
      "post": {
        "tags": [
          "sandbox"
        ],
        "operationId": "createSandboxTenant",
        "summary": "Provision a sandbox workspace (no signup)",
        "description": "Unauthenticated, heavily rate-limited: provisions a disposable governed workspace so an agent with no tenant can demo governance in under a minute. The response includes `nextSteps.claimPageUrl` — the link to hand a human to claim the workspace permanently. Feature-flagged; 404 when disabled.",
        "security": [],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "intent": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "fingerprint": {
                    "type": "string",
                    "maxLength": 128
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sandbox created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Validation failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Standard draft-7 RateLimit / RateLimit-Policy headers are set; retry after the window resets.",
            "headers": {
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF draft-7 rate-limit header."
              },
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat/completions": {
      "post": {
        "tags": [
          "proxy"
        ],
        "operationId": "proxyChatCompletions",
        "summary": "OpenAI-compatible chat completions (governed)",
        "description": "Drop-in replacement for the OpenAI chat-completions endpoint: point your client's base URL at the gateway and every call is policy-checked, priced, and audited. Request/response bodies follow the OpenAI API. Errors use the OpenAI-compatible envelope; 429s carry Retry-After.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vendor-shaped completion (or SSE stream)."
          },
          "401": {
            "description": "Auth error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "402": {
            "description": "Budget exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "403": {
            "description": "Denied by policy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After set).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "tags": [
          "proxy"
        ],
        "operationId": "proxyListModels",
        "summary": "List models (OpenAI-compatible)",
        "responses": {
          "200": {
            "description": "OpenAI-shaped model list."
          },
          "401": {
            "description": "Auth error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          }
        }
      }
    },
    "/anthropic/v1/messages": {
      "post": {
        "tags": [
          "proxy"
        ],
        "operationId": "proxyAnthropicMessages",
        "summary": "Anthropic-compatible messages (governed)",
        "description": "Anthropic-native proxy path — same governance treatment as /v1/chat/completions with Anthropic request/response shapes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vendor-shaped response (or SSE stream)."
          },
          "401": {
            "description": "Auth error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "403": {
            "description": "Denied by policy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After set).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          }
        }
      }
    },
    "/openai/v1/responses": {
      "post": {
        "tags": [
          "proxy"
        ],
        "operationId": "proxyOpenAiResponses",
        "summary": "OpenAI Responses API (governed)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Vendor-shaped response (or SSE stream)."
          },
          "401": {
            "description": "Auth error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "403": {
            "description": "Denied by policy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After set).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyError"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "tags": [
          "mcp"
        ],
        "operationId": "mcp",
        "summary": "MCP endpoint (streamable HTTP)",
        "description": "Model Context Protocol over streamable HTTP: 9 governance tools (8 read-only introspection tools plus acp_propose_rule, which drafts a rule for a human to confirm — it never applies policy). Authenticate with a gsk_ key or via the advertised OAuth flow (see /.well-known/oauth-protected-resource). Server card: https://agenticcontrolplane.com/mcp/server-card.json",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "description": "JSON-RPC 2.0 message per the MCP spec."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response or SSE stream."
          },
          "401": {
            "description": "Missing, malformed, invalid, or revoked gsk_ API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/status.json": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "status",
        "summary": "Service health",
        "security": [],
        "responses": {
          "200": {
            "description": "Healthy."
          },
          "503": {
            "description": "Degraded."
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "meta"
        ],
        "operationId": "getOpenApi",
        "summary": "This document",
        "security": [],
        "responses": {
          "200": {
            "description": "The OpenAPI 3.1 description of this API."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Workspace API key (`gsk_{slug}_…`) as a Bearer token. Mint keys in the console: https://cloud.agenticcontrolplane.com"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Default error shape on /api/v1/*: a single machine-readable-ish message string.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string"
          }
        }
      },
      "ValidationError": {
        "type": "object",
        "description": "Returned (HTTP 400) when a zod-validated body or query fails. `details` is the zod treeified error.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "validation_failed"
            ]
          },
          "details": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "ProxyError": {
        "type": "object",
        "description": "OpenAI-compatible error envelope used by the model-proxy endpoints (/v1/chat/completions, /anthropic/v1/messages, /openai/v1/responses).",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "message",
              "type"
            ],
            "properties": {
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "description": "authentication_error | permission_error | rate_limit_error | billing_error | invalid_request_error | api_error"
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "code": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      }
    }
  }
}