{
  "openapi": "3.1.0",
  "info": {
    "title": "Rungate API",
    "description": "Agent execution control plane — governance proxy for LLM API calls. Provides budget enforcement, rate limiting, model/tool restrictions, multi-provider routing with failover, and full observability.",
    "version": "0.1.0",
    "license": {
      "name": "MIT"
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Current server"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Server health and OpenAPI spec"
    },
    {
      "name": "ProviderKeys",
      "description": "Manage provider API keys (OpenAI, Anthropic, etc.)"
    },
    {
      "name": "Policies",
      "description": "Governance policies: budgets, rate limits, model/tool restrictions"
    },
    {
      "name": "Agents",
      "description": "Agent management and API key lifecycle"
    },
    {
      "name": "Runs",
      "description": "Execution runs and their steps/ledger entries"
    },
    {
      "name": "Analytics",
      "description": "Cost analytics, overview stats, and data cleanup"
    },
    {
      "name": "Webhooks",
      "description": "Webhook subscriptions for event notifications"
    },
    {
      "name": "Approvals",
      "description": "Tool approval request management"
    },
    {
      "name": "AlertRules",
      "description": "Alert rule management"
    },
    {
      "name": "AdminTokens",
      "description": "Scoped admin API tokens for authentication"
    },
    {
      "name": "Accounts",
      "description": "Multi-tenant account management"
    },
    {
      "name": "Registration",
      "description": "Self-service account registration (no auth required)"
    },
    {
      "name": "Invitations",
      "description": "Org member invitation management"
    },
    {
      "name": "Members",
      "description": "Org member management — roles, removal, ownership transfer"
    },
    {
      "name": "Auth",
      "description": "Magic link authentication, session management, and account registration completion"
    },
    {
      "name": "Proxy",
      "description": "LLM proxy endpoints with governance enforcement"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Health check",
        "description": "Returns server health status, version, uptime, and resource counts. No authentication required.",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Server is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/provider-keys": {
      "post": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Create a provider key",
        "operationId": "createProviderKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProviderKeyInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Provider key created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created provider key (api_key masked)",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "List provider keys",
        "operationId": "listProviderKeys",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by provider name"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "disabled",
                "deleted"
              ]
            },
            "description": "Filter by status. Default (no filter) returns active + disabled, excluding deleted."
          }
        ],
        "responses": {
          "200": {
            "description": "List of provider keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Provider keys (api_key masked)",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProviderKey"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/provider-keys/{id}": {
      "get": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Get a provider key by ID",
        "operationId": "getProviderKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider key details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Provider key (api_key masked)",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Update a provider key",
        "description": "Update name, base_url, or api_key. Setting api_key also updates rotated_at.",
        "operationId": "updateProviderKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "base_url": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "api_key": {
                    "type": "string",
                    "description": "New plaintext API key — triggers rotated_at update"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider key updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated provider key",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Delete a provider key",
        "description": "Permanently deletes the key (scrubs the encrypted secret). Optionally remaps dependent agents to a replacement key via the remap_to query parameter.",
        "operationId": "deleteProviderKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "remap_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "ID of replacement key (must be active, same provider, same org). Agents using the deleted key are remapped to this key."
          }
        ],
        "responses": {
          "200": {
            "description": "Provider key deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "remapped_agents": {
                          "type": "number"
                        }
                      },
                      "required": [
                        "message",
                        "remapped_agents"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/provider-keys/{id}/disable": {
      "post": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Disable a provider key",
        "description": "Sets status to \"disabled\". Key is excluded from routing but bindings are preserved. Idempotent — returns 200 if already disabled.",
        "operationId": "disableProviderKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider key disabled (or already disabled)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated provider key",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/provider-keys/{id}/enable": {
      "post": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Enable a provider key",
        "description": "Sets status to \"active\". Key resumes participating in routing. Idempotent — returns 200 if already active.",
        "operationId": "enableProviderKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider key enabled (or already active)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated provider key",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/provider-keys/{id}/dependents": {
      "get": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Get provider key dependents",
        "description": "Returns agents using this key, active run count, and 30-day usage. Used by the dashboard to show impact before disable or delete.",
        "operationId": "getProviderKeyDependents",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider key dependents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "agents": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "is_only_key_for_provider": {
                                "type": "boolean"
                              }
                            }
                          }
                        },
                        "active_run_count": {
                          "type": "number"
                        },
                        "runs_last_30_days": {
                          "type": "number"
                        },
                        "last_used_at": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/provider-keys/by-name/{name}": {
      "put": {
        "tags": [
          "ProviderKeys"
        ],
        "summary": "Upsert a provider key by name",
        "description": "Creates the provider key if it does not exist, or updates it if it does. Name comes from the URL path. On create, provider and api_key are required. Revoked keys with the same name are ignored (a new key is created).",
        "operationId": "upsertProviderKeyByName",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Provider key name"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertProviderKeyInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider key updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated provider key",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Provider key created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created provider key",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProviderKey"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies": {
      "post": {
        "tags": [
          "Policies"
        ],
        "summary": "Create a policy",
        "operationId": "createPolicy",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePolicyInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Policy created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created policy",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Policy"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Policies"
        ],
        "summary": "List policies",
        "operationId": "listPolicies",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by name (LIKE substring match)"
          }
        ],
        "responses": {
          "200": {
            "description": "List of policies",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Policies",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Policy"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies/{id}/stats": {
      "get": {
        "tags": [
          "Policies"
        ],
        "summary": "Get aggregate KPI stats for a policy",
        "description": "Returns aggregate statistics for all runs that used this policy: total runs, spend, average cost/steps/duration, success rate, and budget utilization. All avg/rate fields are nullable (null when no qualifying runs exist).",
        "operationId": "getPolicyStats",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Start of date range (ISO 8601)"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "End of date range (ISO 8601)"
          }
        ],
        "responses": {
          "200": {
            "description": "Policy stats",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "total_runs": {
                          "type": "integer"
                        },
                        "total_spend_usd": {
                          "type": "number"
                        },
                        "avg_cost_per_run_usd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "avg_steps_per_run": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "avg_duration_ms": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "success_rate": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "budget_utilization": {
                          "type": [
                            "number",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies/{id}/cost-trend": {
      "get": {
        "tags": [
          "Policies"
        ],
        "summary": "Get per-run cost data for charting",
        "description": "Returns one entry per non-running run ordered by started_at ascending. Used for cost trend charts on the policy view page.",
        "operationId": "getPolicyCostTrend",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 500
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cost trend data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "run_id": {
                            "type": "string"
                          },
                          "name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "cost_usd": {
                            "type": "number"
                          },
                          "step_count": {
                            "type": "integer"
                          },
                          "started_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies/{id}": {
      "get": {
        "tags": [
          "Policies"
        ],
        "summary": "Get a policy by ID",
        "operationId": "getPolicy",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Policy details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Policy",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Policy"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Policies"
        ],
        "summary": "Update a policy",
        "description": "Deep-merges sent fields into existing policy. Omitted fields are preserved.",
        "operationId": "updatePolicy",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePolicyInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Policy updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated policy",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Policy"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Policies"
        ],
        "summary": "Delete a policy",
        "description": "Fails with 409 if agents still reference this policy.",
        "operationId": "deletePolicy",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Policy deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies/by-name/{name}": {
      "put": {
        "tags": [
          "Policies"
        ],
        "summary": "Upsert a policy by name",
        "description": "Creates the policy if it does not exist, or updates it if it does. Name comes from the URL path. All fields are optional; defaults applied on create, deep-merged on update.",
        "operationId": "upsertPolicyByName",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Policy name"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertPolicyInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Policy updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated policy",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Policy"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Policy created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created policy with defaults",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Policy"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies/{id}/versions": {
      "get": {
        "tags": [
          "Policies"
        ],
        "summary": "List policy version history",
        "description": "Returns all version snapshots for a policy, ordered by version number ascending. Works even if the policy has been deleted (versions are audit records).",
        "operationId": "listPolicyVersions",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Policy ID"
          }
        ],
        "responses": {
          "200": {
            "description": "List of policy versions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Policy versions",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PolicyVersion"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/policies/{id}/versions/{version}": {
      "get": {
        "tags": [
          "Policies"
        ],
        "summary": "Get a specific policy version",
        "operationId": "getPolicyVersion",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Policy ID"
          },
          {
            "name": "version",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Version number"
          }
        ],
        "responses": {
          "200": {
            "description": "Policy version details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Policy version",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PolicyVersion"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents": {
      "post": {
        "tags": [
          "Agents"
        ],
        "summary": "Create an agent",
        "description": "Creates an agent with an auto-generated API key. The api_key is returned once in the response and cannot be retrieved later. Use POST /api/agents/{id}/rotate-key to generate a new key.",
        "operationId": "createAgent",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAgentInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Agent created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created agent with one-time api_key",
                  "properties": {
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Agent"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "api_key": {
                              "type": "string",
                              "description": "One-time: the generated API key (rg_sk_...). Not retrievable later."
                            },
                            "_note": {
                              "type": "string",
                              "description": "Present if name was auto-suffixed for uniqueness"
                            }
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "List agents",
        "operationId": "listAgents",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "disabled"
              ]
            },
            "description": "Filter by status"
          },
          {
            "name": "policy_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by policy ID"
          }
        ],
        "responses": {
          "200": {
            "description": "List of agents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Agents",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Agent"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/stats/all": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "Get all agent statistics",
        "description": "Returns spending statistics for all agents, keyed by agent ID.",
        "operationId": "getAllAgentStats",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Agent statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Per-agent stats",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AllAgentStats"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/{id}": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "Get an agent by ID",
        "operationId": "getAgent",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Agent details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Agent",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Agents"
        ],
        "summary": "Update an agent (full)",
        "operationId": "updateAgent",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "policy_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "provider_keys": {
                    "type": "object",
                    "additionalProperties": {
                      "oneOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "key_id": {
                                "type": "string"
                              },
                              "weight": {
                                "type": "integer"
                              }
                            },
                            "required": [
                              "key_id",
                              "weight"
                            ]
                          }
                        }
                      ]
                    }
                  },
                  "routing_override": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "default_chain": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "timeout_ms": {
                        "type": "integer",
                        "description": "Per-agent override of the policy routing.timeout_ms. See policy schema for semantics and default (120000)."
                      }
                    }
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "disabled"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated agent",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Agents"
        ],
        "summary": "Update an agent (partial)",
        "operationId": "patchAgent",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "policy_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "disabled"
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "member_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Reassign agent to a different member (requires agents.reassign permission)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated agent",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/{id}/rotate-key": {
      "post": {
        "tags": [
          "Agents"
        ],
        "summary": "Rotate an agent API key",
        "description": "Generates a new API key for the agent. The old key is immediately invalidated. The new key is returned once.",
        "operationId": "rotateAgentKey",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key rotated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "api_key": {
                          "type": "string",
                          "description": "New API key (rg_sk_...). Shown once."
                        },
                        "api_key_prefix": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message",
                        "api_key",
                        "api_key_prefix"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/agents/by-name/{name}": {
      "put": {
        "tags": [
          "Agents"
        ],
        "summary": "Upsert an agent by name",
        "description": "Creates the agent if it does not exist, or updates it if it does. Name comes from the URL path. On create, policy_id is required and an API key is generated (returned once in the 201 response). On update, all fields are optional. Does not auto-suffix names.",
        "operationId": "upsertAgentByName",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Agent name"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertAgentInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Agent updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated agent",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Agent created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created agent with one-time api_key",
                  "properties": {
                    "data": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Agent"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "api_key": {
                              "type": "string",
                              "description": "One-time: the generated API key (rg_sk_...). Not retrievable later."
                            }
                          }
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/runs": {
      "get": {
        "tags": [
          "Runs"
        ],
        "summary": "List runs",
        "operationId": "listRuns",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "running",
                "completed",
                "failed",
                "budget_exceeded",
                "force_stopped"
              ]
            },
            "description": "Filter by status"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filter runs started after this time"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Filter runs started before this time"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Sort field"
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            },
            "description": "Sort order (default: desc)"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            },
            "description": "Max results (capped at 200)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Pagination offset"
          },
          {
            "name": "had_governance_block",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Filter by governance block presence (true = only runs with blocks, false = only clean runs)"
          },
          {
            "name": "had_failover",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Filter by failover presence (true = only runs with failover, false = only runs without)"
          }
        ],
        "responses": {
          "200": {
            "description": "List of runs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Runs",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Run"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/runs/{id}": {
      "get": {
        "tags": [
          "Runs"
        ],
        "summary": "Get a run by ID",
        "operationId": "getRun",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Run details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Run",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Run"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Runs"
        ],
        "summary": "Rename a run",
        "description": "Update a run's name. Works on runs in any status (running, completed, force_stopped, etc.). Max 255 characters.",
        "operationId": "renameRun",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "New name for the run"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated run",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Run"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/runs/{id}/steps": {
      "get": {
        "tags": [
          "Runs"
        ],
        "summary": "List steps for a run",
        "operationId": "listRunSteps",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Sort field"
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            },
            "description": "Sort order"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 200
            },
            "description": "Max results (capped at 200)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "List of steps",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Steps",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Step"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/runs/{id}/ledger": {
      "get": {
        "tags": [
          "Runs"
        ],
        "summary": "List ledger entries for a run",
        "operationId": "listRunLedger",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          }
        ],
        "responses": {
          "200": {
            "description": "List of ledger entries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Ledger entries",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LedgerEntry"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/runs/{id}/stop": {
      "post": {
        "tags": [
          "Runs"
        ],
        "summary": "Force-stop a run",
        "description": "Sets run status to \"force_stopped\". Use for emergency termination of runaway agents. For normal job completion, use /api/runs/{id}/complete instead.",
        "operationId": "stopRun",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Run stopped",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/runs/{id}/unblock": {
      "post": {
        "summary": "Lift force-stop block",
        "description": "Lifts the implicit run creation block on a force-stopped run. After this, new implicit runs for the same agent+policy are allowed again.",
        "tags": [
          "Runs"
        ],
        "operationId": "unblockRun",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Block lifted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "lifted_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Run is not force-stopped"
          },
          "401": {
            "description": "Unauthorized"
          },
          "404": {
            "description": "Run not found"
          }
        }
      }
    },
    "/api/runs/{id}/complete": {
      "post": {
        "tags": [
          "Runs"
        ],
        "summary": "Complete a run",
        "description": "Marks a running run as completed with status \"completed\" and completion_reason \"explicit\". Use for normal job completion. For emergency termination, use /api/runs/{id}/stop instead. Returns the full run object.",
        "operationId": "completeRun",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Optional completion reason. Defaults to \"admin_completed\"."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Run"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/costs": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get cost analytics",
        "description": "Returns cost breakdown grouped by the specified dimension with optional time-series.",
        "operationId": "getCostAnalytics",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group_by",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "provider",
                "model",
                "day"
              ]
            },
            "description": "Grouping dimension"
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "provider",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by provider"
          },
          {
            "name": "model",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by model"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Start of time range"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "End of time range"
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week"
              ]
            },
            "description": "Time bucket granularity"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "description": "Max results (default 50)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Cost breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CostAnalyticsResult"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/latency": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get latency analytics",
        "description": "Returns latency percentiles (p50, p95, p99) grouped by dimension with optional time-series.",
        "operationId": "getLatencyAnalytics",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group_by",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "provider",
                "model",
                "agent",
                "provider_key"
              ]
            },
            "description": "Grouping dimension"
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "provider",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by provider"
          },
          {
            "name": "model",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by model"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Start of time range"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "End of time range"
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week"
              ]
            },
            "description": "Time bucket granularity"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "description": "Max results (default 50)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Latency percentiles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "group": {
                            "type": "string"
                          },
                          "period": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "p50_ms": {
                            "type": "number"
                          },
                          "p95_ms": {
                            "type": "number"
                          },
                          "p99_ms": {
                            "type": "number"
                          },
                          "avg_ms": {
                            "type": "number"
                          },
                          "request_count": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/errors": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get error analytics",
        "description": "Returns error rates and status breakdown grouped by dimension with optional time-series.",
        "operationId": "getErrorAnalytics",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group_by",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "provider",
                "model",
                "agent",
                "provider_key"
              ]
            },
            "description": "Grouping dimension"
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "provider",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by provider"
          },
          {
            "name": "model",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by model"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Start of time range"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "End of time range"
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week"
              ]
            },
            "description": "Time bucket granularity"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "description": "Max results (default 50)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Error breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "group": {
                            "type": "string"
                          },
                          "period": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "total_requests": {
                            "type": "integer"
                          },
                          "success_count": {
                            "type": "integer"
                          },
                          "error_count": {
                            "type": "integer"
                          },
                          "timeout_count": {
                            "type": "integer"
                          },
                          "budget_blocked_count": {
                            "type": "integer"
                          },
                          "policy_blocked_count": {
                            "type": "integer"
                          },
                          "approval_pending_count": {
                            "type": "integer"
                          },
                          "error_rate_pct": {
                            "type": "number"
                          },
                          "failover_count": {
                            "type": "integer"
                          },
                          "avg_failover_attempts": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/throughput": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get throughput analytics",
        "description": "Returns request count and token throughput grouped by dimension with optional time-series.",
        "operationId": "getThroughputAnalytics",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "group_by",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "provider",
                "model",
                "agent",
                "provider_key"
              ]
            },
            "description": "Grouping dimension"
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "provider",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by provider"
          },
          {
            "name": "model",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by model"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Start of time range"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "End of time range"
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week"
              ]
            },
            "description": "Time bucket granularity"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "description": "Max results (default 50)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Throughput data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "group": {
                            "type": "string"
                          },
                          "period": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "request_count": {
                            "type": "integer"
                          },
                          "input_tokens": {
                            "type": "integer"
                          },
                          "output_tokens": {
                            "type": "integer"
                          },
                          "cache_read_tokens": {
                            "type": "integer"
                          },
                          "cache_creation_tokens": {
                            "type": "integer"
                          },
                          "total_tokens": {
                            "type": "integer",
                            "description": "Sum of input + output + cache_read + cache_creation tokens"
                          },
                          "total_cost_usd": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/provider-reliability": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get provider reliability metrics",
        "description": "Returns per-provider health: success rate, latency percentiles, error counts, failover frequency.",
        "operationId": "getProviderReliability",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider reliability",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "provider": {
                            "type": "string"
                          },
                          "total_requests": {
                            "type": "integer"
                          },
                          "success_count": {
                            "type": "integer"
                          },
                          "error_count": {
                            "type": "integer"
                          },
                          "success_rate_pct": {
                            "type": "number"
                          },
                          "avg_latency_ms": {
                            "type": "number"
                          },
                          "p50_latency_ms": {
                            "type": "number"
                          },
                          "p95_latency_ms": {
                            "type": "number"
                          },
                          "failover_count": {
                            "type": "integer"
                          },
                          "total_cost_usd": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/runs": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get run analytics",
        "description": "Returns run completion stats, duration, cost per run, with optional time-series.",
        "operationId": "getRunAnalytics",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter by agent"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "granularity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Run analytics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "period": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "total_runs": {
                            "type": "integer"
                          },
                          "completed_count": {
                            "type": "integer"
                          },
                          "failed_count": {
                            "type": "integer"
                          },
                          "budget_exceeded_count": {
                            "type": "integer"
                          },
                          "force_stopped_count": {
                            "type": "integer"
                          },
                          "running_count": {
                            "type": "integer"
                          },
                          "completion_rate_pct": {
                            "type": "number"
                          },
                          "avg_duration_ms": {
                            "type": "number"
                          },
                          "avg_steps_per_run": {
                            "type": "number"
                          },
                          "avg_cost_per_run": {
                            "type": "number"
                          },
                          "total_cost_usd": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/top": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get top-N rankings",
        "description": "Returns ranked list of entities by metric (spend, requests, tokens, latency, errors).",
        "operationId": "getTopN",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "metric",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "spend",
                "requests",
                "tokens",
                "latency_p95",
                "errors"
              ]
            },
            "description": "Ranking metric"
          },
          {
            "name": "entity",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "model",
                "provider"
              ]
            },
            "description": "Entity type to rank"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "description": "Top N (default 10, max 100)"
          },
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter results to a specific agent"
          }
        ],
        "responses": {
          "200": {
            "description": "Top-N rankings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "rank": {
                            "type": "integer"
                          },
                          "entity": {
                            "type": "string"
                          },
                          "value": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/overview/stats": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get overview statistics",
        "description": "Returns dashboard summary stats (active agents, spend today, run counts, trends).",
        "operationId": "getOverviewStats",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Overview statistics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Note: no \"total\" field — only { data }",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OverviewStats"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/providers/health": {
      "get": {
        "tags": [
          "Providers"
        ],
        "summary": "Get provider health status",
        "description": "Returns circuit breaker state for all tracked provider keys.",
        "operationId": "getProviderHealth",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Provider health status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "provider_key_id": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string",
                            "enum": [
                              "closed",
                              "open",
                              "half_open"
                            ]
                          },
                          "failure_count": {
                            "type": "integer"
                          },
                          "last_failure_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "last_success_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "opened_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "recovery_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/cleanup-preview": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Preview data cleanup",
        "description": "Shows how many records would be deleted for the given retention period.",
        "operationId": "previewCleanup",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 30,
              "minimum": 1
            },
            "description": "Retention period in days"
          }
        ],
        "responses": {
          "200": {
            "description": "Cleanup preview",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Records eligible for deletion",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OldDataCount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/analytics/cleanup": {
      "post": {
        "tags": [
          "Analytics"
        ],
        "summary": "Delete old data",
        "description": "Permanently deletes runs, steps, and ledger entries older than the specified number of days.",
        "operationId": "deleteOldData",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CleanupInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cleanup completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Deletion counts",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DeleteOldDataResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/chat/completions": {
      "post": {
        "tags": [
          "Proxy"
        ],
        "summary": "Proxy: OpenAI Chat Completions",
        "description": "Forwards requests to the configured OpenAI-compatible provider after applying governance checks (auth, policy, budget, rate limits, routing). Request and response bodies follow the OpenAI Chat Completions format. Supports streaming (stream: true). Rungate adds response headers: X-Rungate-Run-Id, X-Rungate-Step-Id, X-Rungate-Provider, X-Rungate-Model, X-Rungate-Tokens-Used, X-Rungate-Cost-Usd, X-Rungate-Budget-Remaining-Usd, X-Rungate-Budget-Remaining-Tokens. When a per-run policy fallback occurs: X-Rungate-Policy-Fallback, X-Rungate-Policy-Fallback-Reason. All x-rungate-* parameters can also be passed as top-level fields in the request body (headers take precedence). Body fields are stripped before forwarding to the provider.",
        "operationId": "proxyChatCompletions",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "x-rungate-run-id",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Attach request to an existing run by ID. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-run-policy",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Select a per-run policy by name or ID. Falls back to agent default if not found/allowed. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-run-name",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Human-readable name for the run. Set on the first request; ignored on subsequent requests. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-run-metadata",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "JSON object of metadata to attach to the run. In headers: JSON string. In body: object or JSON string. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-new-run",
            "in": "header",
            "schema": {
              "type": "string",
              "enum": [
                "true"
              ]
            },
            "description": "Force a new run by completing all running runs first. Also accepted as a top-level body field (boolean or string \"true\")."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "description": "OpenAI Chat Completions request body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider response (OpenAI format)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "OpenAI Chat Completions response"
                }
              }
            }
          },
          "202": {
            "description": "Tools require approval — awaiting human/agent decision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "awaiting_approval"
                      ]
                    },
                    "approval_requests": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "tool": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "tool"
                        ]
                      }
                    },
                    "run_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "approval_requests",
                    "run_id",
                    "message"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "402": {
            "description": "Budget exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "403": {
            "description": "Governance block (model/tool/agent/run restriction)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "502": {
            "description": "Provider error (all providers failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "post": {
        "tags": [
          "Proxy"
        ],
        "summary": "Proxy: Anthropic Messages",
        "description": "Forwards requests to the configured Anthropic-compatible provider after applying governance checks. Request and response bodies follow the Anthropic Messages format. Supports streaming (stream: true). Same Rungate response headers as /v1/chat/completions, including policy fallback headers when applicable. All x-rungate-* parameters can also be passed as top-level fields in the request body (headers take precedence). Body fields are stripped before forwarding to the provider.",
        "operationId": "proxyMessages",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "x-rungate-run-id",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Attach request to an existing run by ID. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-run-policy",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Select a per-run policy by name or ID. Falls back to agent default if not found/allowed. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-run-name",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Human-readable name for the run. Set on the first request; ignored on subsequent requests. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-run-metadata",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "JSON object of metadata to attach to the run. In headers: JSON string. In body: object or JSON string. Also accepted as a top-level body field."
          },
          {
            "name": "x-rungate-new-run",
            "in": "header",
            "schema": {
              "type": "string",
              "enum": [
                "true"
              ]
            },
            "description": "Force a new run by completing all running runs first. Also accepted as a top-level body field (boolean or string \"true\")."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true,
                "description": "Anthropic Messages request body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider response (Anthropic format)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Anthropic Messages response"
                }
              }
            }
          },
          "202": {
            "description": "Tools require approval — awaiting human/agent decision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "awaiting_approval"
                      ]
                    },
                    "approval_requests": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "tool": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "tool"
                        ]
                      }
                    },
                    "run_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status",
                    "approval_requests",
                    "run_id",
                    "message"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "402": {
            "description": "Budget exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "403": {
            "description": "Governance block (model/tool/agent/run restriction)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "502": {
            "description": "Provider error (all providers failed)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/complete-all": {
      "post": {
        "tags": [
          "Proxy"
        ],
        "summary": "Complete all running runs",
        "description": "Completes all running runs for the authenticated agent in one call. Returns the count of completed runs. Idempotent — returns 0 if no running runs. Use this to bookend jobs: call before starting a new job to ensure clean run boundaries.",
        "operationId": "completeAllRuns",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ended_reason": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Reason for completion (default: \"agent_complete_all\")"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Runs completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "completed_count": {
                      "type": "integer"
                    },
                    "completed_run_ids": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "format": "uuid"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/current/complete": {
      "post": {
        "tags": [
          "Proxy"
        ],
        "summary": "Complete current run",
        "description": "Marks the agent's latest running run as completed. If the agent has no running run, returns 404.",
        "operationId": "completeCurrentRun",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunCompletionInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunCompletionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Agent disabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GovernanceBlockResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/complete": {
      "post": {
        "tags": [
          "Proxy"
        ],
        "summary": "Complete a specific run",
        "description": "Marks a specific run as completed. The run must belong to the authenticated agent and be in \"running\" status.",
        "operationId": "completeRun",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RunCompletionInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunCompletionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Agent disabled or run belongs to different agent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}/steps": {
      "post": {
        "tags": [
          "Proxy"
        ],
        "summary": "Create a tool_call step in a run",
        "description": "Log a non-LLM tool call (web search, DB query, etc.) as a step in an active run. Uses agent API key authentication. The agent can only create steps in its own runs.",
        "operationId": "createRunStep",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "tool_call"
                    ],
                    "description": "Must be \"tool_call\""
                  },
                  "name": {
                    "type": "string",
                    "description": "Tool name (e.g., \"web_search\", \"database_query\")"
                  },
                  "provider": {
                    "type": "string",
                    "description": "Tool provider (default: \"sdk\")"
                  },
                  "request": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Tool call request payload"
                  },
                  "response": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Tool call response payload"
                  },
                  "tokens": {
                    "type": "object",
                    "properties": {
                      "input": {
                        "type": "integer"
                      },
                      "output": {
                        "type": "integer"
                      },
                      "cache_read": {
                        "type": "integer"
                      },
                      "cache_creation": {
                        "type": "integer"
                      }
                    },
                    "description": "Token usage (default: 0/0/0/0 — tool calls do not have cache tokens)"
                  },
                  "cost_usd": {
                    "type": "number",
                    "description": "Cost in USD (default: 0)"
                  },
                  "latency_ms": {
                    "type": "number",
                    "description": "Latency in milliseconds"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "success",
                      "error",
                      "timeout"
                    ],
                    "description": "Step status"
                  },
                  "error_message": {
                    "type": "string",
                    "nullable": true,
                    "description": "Error message if status is error"
                  }
                },
                "required": [
                  "type",
                  "name",
                  "status"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Step created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created tool_call step",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Step"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Run belongs to different agent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Get steps for a run",
        "description": "Returns steps for a specific run. The run must belong to the authenticated agent. Uses agent API key authentication.",
        "operationId": "getAgentRunSteps",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            },
            "description": "Max items to return"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Sort field"
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            },
            "description": "Sort order"
          }
        ],
        "responses": {
          "200": {
            "description": "Steps list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Steps for the run",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Step"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Run belongs to different agent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "API discovery",
        "description": "Returns available agent-scoped endpoints. No authentication required — designed for agent discovery on first contact.",
        "operationId": "discoverAgentApi",
        "responses": {
          "200": {
            "description": "Available agent endpoints",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "version": {
                      "type": "string"
                    },
                    "auth": {
                      "type": "string"
                    },
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "method": {
                            "type": "string"
                          },
                          "path": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "admin_api": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Get agent info",
        "description": "Returns the authenticated agent's info including name, status, policy details, and limits. Uses agent API key authentication.",
        "operationId": "getAgentInfo",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Agent info",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "description": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active",
                            "disabled"
                          ]
                        },
                        "policy_name": {
                          "type": "string"
                        },
                        "hourly_cost_limit_usd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "budget_hard_limit_usd": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "max_steps_per_run": {
                          "type": "integer"
                        },
                        "allowed_models": {
                          "type": [
                            "array",
                            "null"
                          ],
                          "items": {
                            "type": "string"
                          }
                        },
                        "model_override": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/mine": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "List your runs",
        "description": "Returns the authenticated agent's own runs. Supports filtering by status, date range, and pagination. Uses agent API key authentication.",
        "operationId": "listAgentRuns",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "running",
                "completed",
                "failed",
                "budget_exceeded",
                "force_stopped"
              ]
            },
            "description": "Filter by run status"
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only runs started after this time"
          },
          {
            "name": "until",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only runs started before this time"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "started_at",
                "ended_at",
                "cost_usd",
                "status",
                "step_count",
                "name"
              ]
            },
            "description": "Sort field (default: started_at)"
          },
          {
            "name": "order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            },
            "description": "Sort order (default: desc)"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50
            },
            "description": "Max items to return"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          }
        ],
        "responses": {
          "200": {
            "description": "Agent runs",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Agent's own runs",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Run"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/current": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Get current run",
        "description": "Returns the authenticated agent's current (latest running) run. Returns 404 if no run is currently active. Uses agent API key authentication.",
        "operationId": "getAgentCurrentRun",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current run",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "The agent's current running run",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Run"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Agent"
        ],
        "summary": "Update current run",
        "description": "Update the authenticated agent's current (latest running) run. Accepts partial updates to name, outcome, and outcome_reason. Null values explicitly clear. Returns 404 if no running run exists.",
        "operationId": "updateAgentCurrentRun",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 255,
                    "description": "Human-readable name, or null to clear"
                  },
                  "outcome": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "success",
                      "partial",
                      "failed",
                      null
                    ],
                    "description": "Agent-reported semantic outcome, or null to clear"
                  },
                  "outcome_reason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 1024,
                    "description": "Free-text reason for the outcome, or null to clear"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "run_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "outcome": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "success",
                            "partial",
                            "failed",
                            null
                          ]
                        },
                        "outcome_reason": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/runs/{id}": {
      "get": {
        "tags": [
          "Agent"
        ],
        "summary": "Get a specific run",
        "description": "Returns a specific run by ID. The run must belong to the authenticated agent. Uses agent API key authentication.",
        "operationId": "getAgentRun",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Run details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Run details",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Run"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Run belongs to different agent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Agent"
        ],
        "summary": "Update a specific run (any status)",
        "description": "Update the agent's own run by ID. Works on any status — running, completed, force_stopped, budget_exceeded. Accepts partial updates to name, outcome, and outcome_reason. Null values explicitly clear. Does NOT fire a webhook (agent-side post-termination amendments are API-read-only; consumers that need to track outcome drift should poll or watch for a future run.outcome_updated event).",
        "operationId": "updateAgentRun",
        "security": [
          {
            "AgentApiKey": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Run ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 255,
                    "description": "Human-readable name, or null to clear"
                  },
                  "outcome": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "success",
                      "partial",
                      "failed",
                      null
                    ],
                    "description": "Agent-reported semantic outcome, or null to clear"
                  },
                  "outcome_reason": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 1024,
                    "description": "Free-text reason for the outcome, or null to clear"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Run updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "run_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "outcome": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "success",
                            "partial",
                            "failed",
                            null
                          ]
                        },
                        "outcome_reason": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid agent API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Run belongs to different agent",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook",
        "description": "Register a new webhook subscription. The plaintext secret is returned only in this response.",
        "operationId": "createWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created (includes plaintext secret)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created webhook with plaintext secret",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "List all webhooks. Secrets are masked in responses.",
        "operationId": "listWebhooks",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "failing"
              ]
            },
            "description": "Filter by status"
          },
          {
            "name": "event",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "Filter to webhooks subscribed to this event type"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "List of webhooks with masked secrets",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a webhook",
        "description": "Retrieve a single webhook by ID. Secret is masked.",
        "operationId": "getWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Webhook with masked secret",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook",
        "description": "Partial update — only provided fields are changed. Events array is fully replaced (not merged).",
        "operationId": "updateWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/WebhookEventType"
                    },
                    "minItems": 1
                  },
                  "secret": {
                    "type": "string"
                  },
                  "agent_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated webhook",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated webhook with masked secret",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook",
        "description": "Permanently delete a webhook.",
        "operationId": "deleteWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}/enable": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Enable a webhook",
        "description": "Activate a paused or failing webhook. Resets failure_count to 0. Idempotent — returns 200 if already active.",
        "operationId": "enableWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook enabled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Enabled webhook with masked secret",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}/disable": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Disable a webhook",
        "description": "Pause a webhook. Pending deliveries will be marked failed by the retry sweep. Idempotent — returns 200 if already paused.",
        "operationId": "disableWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook disabled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Disabled webhook with masked secret",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate the webhook secret with a 10-minute grace window",
        "description": "Generates a new webhook secret. Moves the previous secret into `previous_secret` with a 10-minute expiry. During the grace window, each outgoing delivery carries TWO signature headers: `X-Rungate-Signature-256` (current secret) and `X-Rungate-Signature-256-Previous` (previous secret). Receivers that verify either header accept deliveries on both sides of rotation; receivers that check only the primary header continue to work unchanged. Response includes BOTH plaintext secrets and the grace expiry timestamp — secrets are shown only once here, so record them before navigating away.",
        "operationId": "rotateWebhookSecret",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rotation details with both plaintext secrets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "previous_secret": {
                          "type": "string",
                          "description": "The pre-rotation secret. Still valid for verification via X-Rungate-Signature-256-Previous header until grace_expires_at."
                        },
                        "current_secret": {
                          "type": "string",
                          "description": "The new secret. Signs the primary X-Rungate-Signature-256 header going forward."
                        },
                        "grace_expires_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "ISO 8601 timestamp after which the previous secret is no longer used for signing."
                        }
                      },
                      "required": [
                        "previous_secret",
                        "current_secret",
                        "grace_expires_at"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}/expire-previous-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Close a pending rotation grace window early",
        "description": "Clears `previous_secret` and `previous_secret_expires_at` on the webhook row, immediately ending the dual-signature grace window. The delivery engine already stops sending the previous-secret signature header once the expiry passes naturally; this endpoint is for operators who have confirmed their receiver cutover and want to close the window explicitly. Idempotent — a no-op if no rotation is pending.",
        "operationId": "expirePreviousWebhookSecret",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook with cleared previous-secret fields",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Webhook with masked secret",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List deliveries for a webhook",
        "description": "Returns delivery history for a specific webhook, with optional filters.",
        "operationId": "listWebhookDeliveries",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "success",
                "failed"
              ]
            },
            "description": "Filter by delivery status"
          },
          {
            "name": "event_type",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "Filter by event type"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "maximum": 200
            },
            "description": "Max results (default 50, max 200)"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Pagination offset"
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "List of webhook deliveries",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event to a webhook",
        "description": "Creates and delivers a webhook.test event directly to the specified webhook. Bypasses event subscription filtering. No retries (max_attempts=1).",
        "operationId": "testWebhook",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Test event sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "delivery_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "warning": {
                          "type": "string",
                          "description": "Present when webhook is paused or failing"
                        }
                      },
                      "required": [
                        "message",
                        "delivery_id"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Delivery engine not available",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/approval-requests": {
      "get": {
        "tags": [
          "Approvals"
        ],
        "summary": "List approval requests",
        "operationId": "listApprovalRequests",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "run_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by run ID"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "approved",
                "rejected",
                "expired"
              ]
            },
            "description": "Filter by status"
          }
        ],
        "responses": {
          "200": {
            "description": "List of approval requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Approval requests",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApprovalRequest"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/approval-requests/{id}": {
      "get": {
        "tags": [
          "Approvals"
        ],
        "summary": "Get an approval request by ID",
        "operationId": "getApprovalRequest",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Approval request details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Approval request",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApprovalRequest"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/approval-requests/{id}/approve": {
      "post": {
        "tags": [
          "Approvals"
        ],
        "summary": "Approve a pending request",
        "operationId": "approveApprovalRequest",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Approval request approved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Approved request",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApprovalRequest"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/approval-requests/{id}/reject": {
      "post": {
        "tags": [
          "Approvals"
        ],
        "summary": "Reject a pending request",
        "operationId": "rejectApprovalRequest",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Optional rejection reason"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approval request rejected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Rejected request",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ApprovalRequest"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/alert-rules": {
      "post": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Create an alert rule",
        "operationId": "createAlertRule",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAlertRuleInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Alert rule created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Created alert rule",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AlertRule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "AlertRules"
        ],
        "summary": "List alert rules",
        "operationId": "listAlertRules",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by agent ID"
          },
          {
            "name": "condition_type",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by condition type"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "disabled"
              ]
            },
            "description": "Filter by status"
          }
        ],
        "responses": {
          "200": {
            "description": "List of alert rules",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Alert rules",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AlertRule"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/alert-rules/{id}": {
      "get": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Get an alert rule by ID",
        "operationId": "getAlertRule",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert rule details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Alert rule",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AlertRule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Update an alert rule",
        "operationId": "updateAlertRule",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAlertRuleInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Alert rule updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated alert rule",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AlertRule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Delete an alert rule",
        "operationId": "deleteAlertRule",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert rule deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/alert-rules/{id}/enable": {
      "post": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Enable an alert rule",
        "operationId": "enableAlertRule",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert rule enabled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Enabled alert rule",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AlertRule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/alert-rules/{id}/disable": {
      "post": {
        "tags": [
          "AlertRules"
        ],
        "summary": "Disable an alert rule",
        "operationId": "disableAlertRule",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert rule disabled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Disabled alert rule",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AlertRule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin-tokens": {
      "post": {
        "tags": [
          "AdminTokens"
        ],
        "summary": "Create an admin token",
        "description": "Create a new scoped admin API token. The plaintext token is returned only in this response — save it immediately.",
        "operationId": "createAdminToken",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAdminTokenInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Admin token created (includes plaintext token)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AdminToken"
                    },
                    "token": {
                      "type": "string",
                      "description": "Plaintext token (rg_adm_...). Shown only once."
                    }
                  },
                  "required": [
                    "data",
                    "token"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "AdminTokens"
        ],
        "summary": "List admin tokens",
        "description": "List all admin tokens. Token hashes are never returned.",
        "operationId": "listAdminTokens",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "revoked"
              ]
            },
            "description": "Filter by status"
          }
        ],
        "responses": {
          "200": {
            "description": "Admin token list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "List of admin tokens",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AdminToken"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin-tokens/{id}": {
      "get": {
        "tags": [
          "AdminTokens"
        ],
        "summary": "Get an admin token",
        "description": "Retrieve a single admin token by ID. Token hash is never returned.",
        "operationId": "getAdminToken",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Admin token details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Admin token",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AdminToken"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin-tokens/{id}/revoke": {
      "post": {
        "tags": [
          "AdminTokens"
        ],
        "summary": "Revoke an admin token",
        "description": "Revoke an admin token. Idempotent — returns 200 if already revoked.",
        "operationId": "revokeAdminToken",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Token revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations": {
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "Create an invitation",
        "description": "Invite a new member to the org by email. Requires Owner or Admin role. Sends an invitation email with a single-use acceptance token.",
        "operationId": "createInvitation",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "role"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "member",
                      "viewer"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invitation created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Invitation",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Invitation"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error"
          },
          "409": {
            "description": "Conflict (already member, already invited, or email taken in another org)"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      },
      "get": {
        "tags": [
          "Invitations"
        ],
        "summary": "List invitations",
        "description": "List all invitations for the org, optionally filtered by status.",
        "operationId": "listInvitations",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "accepted",
                "expired",
                "revoked"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of invitations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Invitations",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invitation"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/{id}": {
      "delete": {
        "tags": [
          "Invitations"
        ],
        "summary": "Revoke an invitation",
        "description": "Revoke a pending invitation. Invalidates the acceptance token.",
        "operationId": "revokeInvitation",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Revoked invitation",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Invitation"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Not pending"
          }
        }
      }
    },
    "/api/invitations/{id}/resend": {
      "post": {
        "tags": [
          "Invitations"
        ],
        "summary": "Resend an invitation",
        "description": "Resend the invitation email with a new acceptance token. Resets the 7-day expiry.",
        "operationId": "resendInvitation",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation resent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Resent invitation",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Invitation"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Not found"
          },
          "409": {
            "description": "Not pending"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/api/members": {
      "get": {
        "tags": [
          "Members"
        ],
        "summary": "List org members",
        "description": "List all members of the authenticated org.",
        "operationId": "listMembers",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "List of members",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Members",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Member"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/members/{id}": {
      "patch": {
        "tags": [
          "Members"
        ],
        "summary": "Update member role or display name",
        "description": "Update a member's role or display name. Requires Owner or Admin role. Cannot change the owner's role — use transfer-ownership instead.",
        "operationId": "updateMember",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Member ID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "member",
                      "viewer"
                    ],
                    "description": "New role for the member"
                  },
                  "display_name": {
                    "type": "string",
                    "description": "New display name"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated member",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Member"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Members"
        ],
        "summary": "Remove member from organization",
        "description": "Remove a member from the org. Reassigns or deletes their personal resources. Cannot remove the owner — use transfer-ownership first.",
        "operationId": "removeMember",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Member ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Member removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "agents_reassigned": {
                          "type": "integer",
                          "description": "Number of agents reassigned to the caller"
                        },
                        "policies_reassigned": {
                          "type": "integer",
                          "description": "Number of personal policies reassigned"
                        },
                        "webhooks_deleted": {
                          "type": "integer",
                          "description": "Number of personal webhooks deleted"
                        },
                        "alert_rules_deleted": {
                          "type": "integer",
                          "description": "Number of personal alert rules deleted"
                        }
                      },
                      "required": [
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/members/{id}/transfer-ownership": {
      "patch": {
        "tags": [
          "Members"
        ],
        "summary": "Transfer ownership to another member",
        "description": "Transfer org ownership to the specified member. The current owner is demoted to admin. Only the current owner can perform this operation.",
        "operationId": "transferOwnership",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Member ID of the new owner"
          }
        ],
        "responses": {
          "200": {
            "description": "Ownership transferred",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/account": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "Get current account (self-inspection)",
        "description": "Returns the account associated with the authenticated admin token. Requires an org-scoped admin token. Account CRUD operations have moved to the platform API.",
        "operationId": "getCurrentAccount",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Caller's own account",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Account context required (unscoped token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Accounts"
        ],
        "summary": "Update current account",
        "description": "Updates the authenticated caller's own account. Only the name field can be updated via this endpoint. Tier, status, and other fields are managed via the platform API.",
        "operationId": "updateCurrentAccount",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Organization name",
                    "maxLength": 255
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Updated account",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "403": {
            "description": "Account context required (unscoped token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions": {
      "get": {
        "tags": [
          "Sessions"
        ],
        "summary": "List sessions for current account",
        "description": "Returns all active sessions belonging to the authenticated account. Requires session cookie auth.",
        "operationId": "listSessions",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Session list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Active sessions for the account",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Session"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "data",
                    "total"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions/{id}": {
      "delete": {
        "tags": [
          "Sessions"
        ],
        "summary": "Revoke a session",
        "description": "Deletes (revokes) a specific session by ID. The session must belong to the authenticated account.",
        "operationId": "revokeSession",
        "security": [
          {
            "DashboardAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Session ID"
          }
        ],
        "responses": {
          "204": {
            "description": "Session revoked"
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardAuthError"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/register": {
      "post": {
        "tags": [
          "Registration"
        ],
        "summary": "Register a new account",
        "description": "Creates a new account with admin token, default policy, and default agent. No auth required. Rate limited to 10 registrations per IP per hour.",
        "operationId": "registerAccount",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Organization/account name",
                    "maxLength": 100
                  },
                  "slug": {
                    "type": "string",
                    "description": "URL-safe slug (auto-generated from name if omitted)"
                  },
                  "agent_name": {
                    "type": "string",
                    "description": "Name for the default agent (defaults to slug)"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Account registered successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "account": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "slug": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "tier": {
                              "type": "string"
                            }
                          }
                        },
                        "admin_token": {
                          "type": "string",
                          "description": "Admin token (shown once)"
                        },
                        "agent": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "api_key": {
                              "type": "string",
                              "description": "Agent API key (shown once)"
                            }
                          }
                        },
                        "policy": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            }
                          }
                        },
                        "_note": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error (missing name, invalid slug)"
          },
          "429": {
            "description": "Rate limited — too many registration attempts from this IP"
          }
        }
      }
    },
    "/auth/invitation-by-token": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Get invitation details by token",
        "description": "Public endpoint. Returns invitation details (org name, role, inviter) for rendering the acceptance page. Does not consume the token.",
        "operationId": "getInvitationByToken",
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation details"
          },
          "404": {
            "description": "Invalid, expired, revoked, or already-accepted token"
          }
        }
      }
    },
    "/auth/accept-invitation": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Accept an invitation",
        "description": "Public endpoint. Accepts an invitation using a single-use token, creates a member record and session.",
        "operationId": "acceptInvitation",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token",
                  "display_name"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  },
                  "display_name": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invitation accepted, session created"
          },
          "404": {
            "description": "Invalid or expired token"
          },
          "409": {
            "description": "Already accepted"
          },
          "410": {
            "description": "Org no longer available"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/auth/config": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Get auth configuration",
        "description": "Returns whether the email service is in dev mode (no real emails sent). No auth required.",
        "operationId": "getAuthConfig",
        "responses": {
          "200": {
            "description": "Auth configuration",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "devMode": {
                          "type": "boolean",
                          "description": "True if email service is in dev mode"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/start": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Initiate magic link authentication",
        "description": "Sends a magic link email to the given address. Always returns 200 regardless of whether the email exists (enumeration defense). Rate limited per-email, per-IP, and globally.",
        "operationId": "startAuth",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Email address to send the magic link to"
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Magic link sent (always returned, even for unknown emails)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "message": {
                          "type": "string"
                        },
                        "devMode": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error (missing or invalid email)"
          },
          "429": {
            "description": "Rate limited — too many auth attempts"
          },
          "503": {
            "description": "Email service not configured"
          }
        }
      }
    },
    "/auth/verify": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Verify magic link token or code",
        "description": "Verifies a magic link token (from URL) or a 6-digit code (with email). Creates or resumes a session on success. Sets an HttpOnly session cookie.",
        "operationId": "verifyAuth",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "URL token from magic link (hex string)"
                  },
                  "code": {
                    "type": "string",
                    "description": "6-digit verification code"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Email address (required when using code)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verification successful — session cookie set",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "isNewUser": {
                          "type": "boolean",
                          "description": "True if this is a new or pending account"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error (missing token or code+email)"
          },
          "401": {
            "description": "Invalid or expired token/code"
          },
          "429": {
            "description": "Rate limited — too many verification attempts"
          }
        }
      }
    },
    "/auth/session": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Get current session",
        "description": "Returns current session state and account information. Requires a valid session cookie.",
        "operationId": "getAuthSession",
        "responses": {
          "200": {
            "description": "Current session information",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "account": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "enum": [
                                "pending",
                                "active"
                              ]
                            },
                            "email": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "slug": {
                              "type": "string"
                            },
                            "tier": {
                              "type": "string"
                            }
                          }
                        },
                        "scopes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "No session, invalid session, or expired session"
          }
        }
      }
    },
    "/auth/complete-registration": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Complete pending account registration",
        "description": "Finalizes a pending account. Two flows: (1) claim an existing account via admin token, or (2) create a new account with a name. Requires a valid pending session cookie.",
        "operationId": "completeRegistration",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Display name for the account",
                    "maxLength": 100
                  },
                  "admin_token": {
                    "type": "string",
                    "description": "Admin token for claiming an existing account (optional)"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Registration completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "account": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string"
                            },
                            "email": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "slug": {
                              "type": "string"
                            },
                            "tier": {
                              "type": "string"
                            }
                          }
                        },
                        "admin_token": {
                          "type": "string",
                          "description": "Admin token for new accounts (shown once, non-claim flow only)"
                        },
                        "agent": {
                          "type": "object",
                          "description": "Default agent (non-claim flow only)",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "name": {
                              "type": "string"
                            },
                            "api_key": {
                              "type": "string"
                            }
                          }
                        },
                        "claimed": {
                          "type": "boolean",
                          "description": "True when using claim flow"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error (missing name, slug conflict)"
          },
          "401": {
            "description": "No session or invalid session"
          },
          "403": {
            "description": "Account not in pending state, or invalid admin token"
          },
          "429": {
            "description": "Rate limited"
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Log out",
        "description": "Ends the current session and clears the session cookie. Returns 204 No Content.",
        "operationId": "logout",
        "responses": {
          "204": {
            "description": "Logged out successfully — session cookie cleared"
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "OpenAPI specification",
        "description": "Returns this OpenAPI 3.1 specification as JSON. No authentication required.",
        "operationId": "getOpenAPISpec",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 specification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/docs/guides/{name}": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Integration guide",
        "description": "Returns an integration guide as Markdown. No authentication required. Available guides: setup, core-tests, advanced-tests, reference.",
        "operationId": "getIntegrationGuide",
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "description": "Guide name (e.g., \"setup\", \"core-tests\", \"advanced-tests\", \"reference\")",
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9_-]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Guide content in Markdown format",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Guide not found"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProviderKey": {
        "type": "object",
        "description": "A provider API key (e.g., OpenAI, Anthropic). The api_key field is masked in all responses.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider": {
            "type": "string",
            "description": "Provider identifier (e.g., \"openai\", \"anthropic\")"
          },
          "name": {
            "type": "string"
          },
          "api_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Masked in responses. Null for deleted keys (secret scrubbed). Plaintext only accepted in POST/PUT."
          },
          "base_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom provider base URL"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled",
              "deleted"
            ]
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "rotated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "provider",
          "name",
          "api_key",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "Policy": {
        "type": "object",
        "description": "Governance policy controlling budget, routing, rate limits, and model/tool restrictions.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "dry_run": {
            "type": "boolean",
            "default": false,
            "description": "When true, governance checks run normally but requests are not forwarded to the LLM provider. Returns a mock response with zero cost. Use for testing integration and policy configuration."
          },
          "content_logging": {
            "type": "string",
            "enum": [
              "default",
              "enabled",
              "disabled"
            ],
            "default": "default",
            "description": "Controls whether request/response content is stored in step records. \"default\" follows the global server setting. \"enabled\" always stores content. \"disabled\" never stores content (stores {\"redacted\": true} instead). Requires server-level allow_policy_override to be true."
          },
          "budget": {
            "type": "object",
            "properties": {
              "alert_threshold_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "alert_threshold_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "hard_limit_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "hard_limit_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "max_cost_per_hour_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "on_alert_threshold": {
                "type": "string",
                "enum": [
                  "continue_and_alert",
                  "stop_and_alert",
                  "continue_and_block_new"
                ]
              }
            }
          },
          "allowed_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "allowed_tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "require_approval": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "approval_expiry_ms": {
            "type": "integer",
            "description": "Approval request expiry in ms. Default: 28800000 (8 hours). Min: 60000 (1 min). Max: 604800000 (7 days)."
          },
          "rate_limits": {
            "type": "object",
            "description": "Rate limits are per-agent-per-policy. Each policy has its own counter for each agent — requests under one policy do not count toward another policy's limits.",
            "properties": {
              "max_requests_per_minute": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "max_tokens_per_minute": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "routing": {
            "type": "object",
            "properties": {
              "default_chain": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Ordered list of provider names for failover"
              },
              "model_routes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pattern": {
                      "type": "string",
                      "description": "Model name or glob pattern (e.g., \"gpt-4o\", \"gpt-*\", \"claude-*\")"
                    },
                    "chain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Provider chain for matching models"
                    },
                    "timeout_ms": {
                      "type": "integer",
                      "description": "Optional timeout override for this route (ms)"
                    }
                  },
                  "required": [
                    "pattern",
                    "chain"
                  ]
                },
                "description": "Model-specific routing rules. Ordered — first matching pattern wins. Falls back to default_chain."
              },
              "timeout_ms": {
                "type": "integer",
                "description": "Maximum time (ms) for the full request lifecycle — time-to-first-byte plus body read. Applies after the TCP+TLS handshake completes (handshake is governed by connect_timeout_ms). Default: 120000 (120s). Raise for heavy synthesis workloads (large prompts, long completions); Anthropic non-streaming calls commonly take 30–60s before first byte. Lower for interactive workloads where fast error surfacing matters more than provider patience."
              },
              "connect_timeout_ms": {
                "type": "integer",
                "minimum": 1000,
                "maximum": 600000,
                "description": "Maximum time (ms) to complete TCP+TLS handshake with a provider. After the socket is established, timeout_ms governs the full request lifecycle (TTFB and body). Default: 10000 (10s). Must be <= timeout_ms. Maximum: 600000 (10min)."
              },
              "retry_on": {
                "type": "array",
                "items": {
                  "type": "integer"
                },
                "description": "HTTP status codes that trigger retry"
              },
              "max_retries": {
                "type": "integer",
                "description": "Maximum total attempts (not retries after first)"
              },
              "on_rate_limit": {
                "type": "string",
                "enum": [
                  "failover_first",
                  "backoff_first"
                ]
              },
              "load_balancing": {
                "type": "string",
                "enum": [
                  "failover",
                  "round_robin",
                  "weighted"
                ],
                "description": "Key selection strategy for multi-key providers. Default: failover."
              },
              "circuit_breaker": {
                "type": "object",
                "properties": {
                  "failure_threshold": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Consecutive failures before opening circuit. 0 to disable. Default: 5."
                  },
                  "recovery_timeout_ms": {
                    "type": "integer",
                    "minimum": 1000,
                    "description": "Base cooldown before half-open test request (ms). Doubles on each failed probe. Default: 30000."
                  },
                  "max_recovery_timeout_ms": {
                    "type": "integer",
                    "minimum": 1000,
                    "description": "Maximum recovery timeout after exponential backoff (ms). Default: 600000 (10 min)."
                  }
                }
              },
              "routing_preference": {
                "type": "string",
                "enum": [
                  "default",
                  "cost",
                  "latency"
                ],
                "description": "Chain ordering strategy. default: user-defined. cost: cheapest first. latency: fastest p50 first."
              }
            }
          },
          "model_mapping": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            },
            "description": "Source model → { target_provider: target_model } mapping"
          },
          "default_model": {
            "type": [
              "string",
              "null"
            ]
          },
          "model_override": {
            "type": [
              "string",
              "null"
            ],
            "description": "When set, replaces the requested model for all requests under this policy. The original model is preserved in step logs (routed_from) and the X-Rungate-Model-Override response header. When active, allowed_models/blocked_models checks are skipped."
          },
          "runaway_prevention": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "max_steps_per_run": {
                "type": "integer"
              }
            }
          },
          "implicit_run_grouping": {
            "type": "object",
            "properties": {
              "time_window_seconds": {
                "type": "integer"
              },
              "run_idle_timeout_seconds": {
                "type": "integer"
              },
              "force_stop_cooldown_minutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "description": "Minutes to block implicit run creation after a force-stop for the same agent+policy. 0 to disable. Default: 60. Explicit runs (x-rungate-new-run header) always bypass."
              }
            }
          },
          "outcome_defaults": {
            "type": [
              "object",
              "null"
            ],
            "description": "Per-ended_reason automatic outcome defaults. When a run terminates with ended_reason=X and outcome_defaults[X] is set, the run's outcome column is set to that value ONLY if the agent did not set one explicitly. Uses SQL COALESCE — agent-set outcomes (via POST /v1/runs/*/complete body or PATCH /v1/runs/:id) are always preserved. Operators typically configure this for cron-style use cases (e.g. idle_timeout: \"failed\") so stuck runs surface as failures on the dashboard and in termination webhooks.",
            "properties": {
              "agent_signaled": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when the agent explicitly called POST /v1/runs/*/complete without an outcome body field."
              },
              "agent_complete_all": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when the agent called POST /v1/runs/complete-all."
              },
              "cost_limit": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when a hard USD budget limit was exceeded."
              },
              "token_limit": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when a hard token budget limit was exceeded."
              },
              "alert_threshold_stop": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when on_alert_threshold=stop_and_alert triggered a budget-based termination."
              },
              "idle_auto_complete": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when the resolver auto-completed an old run because the implicit grouping window elapsed and the agent started a new run."
              },
              "idle_timeout": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when the background idle sweep (60s interval, 300s default timeout) terminated a run for inactivity. This is the primary signal for \"cron job stuck\" scenarios."
              },
              "new_run_requested": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when an old run was auto-completed because the agent sent x-rungate-new-run: true."
              },
              "admin_stopped": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when an operator force-stopped the run via POST /api/runs/:id/stop."
              },
              "admin_completed": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Fires when an operator completed the run via POST /api/runs/:id/complete with no custom reason."
              }
            },
            "additionalProperties": false
          },
          "visibility": {
            "type": "string",
            "enum": [
              "org",
              "personal"
            ],
            "description": "Visibility scope — org is visible to all members, personal only to the owner"
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the member who owns this policy"
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that created this entity"
          },
          "updated_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that last updated this entity"
          },
          "created_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to create (null for session auth)"
          },
          "updated_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to last update (null for session auth)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "budget",
          "routing",
          "created_at",
          "updated_at"
        ]
      },
      "PolicyVersion": {
        "type": "object",
        "description": "A versioned snapshot of a policy, created on each update or deletion.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "policy_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the policy this version belongs to"
          },
          "version_number": {
            "type": "integer",
            "minimum": 1,
            "description": "Auto-incrementing version number per policy"
          },
          "snapshot": {
            "type": "object",
            "description": "Full policy state at the time of this version"
          },
          "changed_by": {
            "type": "string",
            "description": "Identity of the caller: admin token ID, \"session\", or \"system\""
          },
          "changed_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of top-level fields that were changed. [\"_deleted\"] for deletion snapshots."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "policy_id",
          "version_number",
          "snapshot",
          "changed_by",
          "changed_fields",
          "created_at"
        ]
      },
      "Agent": {
        "type": "object",
        "description": "An agent with its own API key, linked to a policy. The api_key_hash field is never returned.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "api_key_prefix": {
            "type": "string",
            "description": "First characters of the API key for identification"
          },
          "policy_id": {
            "type": "string",
            "format": "uuid"
          },
          "allowed_policies": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Policy IDs this agent may select per-run via x-rungate-run-policy header or body field. null = any policy allowed (default). The agent default policy_id is always implicitly allowed."
          },
          "provider_keys": {
            "type": "object",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string",
                  "description": "Single provider key ID"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "key_id": {
                        "type": "string"
                      },
                      "weight": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100
                      }
                    },
                    "required": [
                      "key_id",
                      "weight"
                    ]
                  }
                }
              ]
            },
            "description": "Provider keys. Single ID for one key, or array of {key_id, weight} for load balancing."
          },
          "routing_override": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "default_chain": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "model_routes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pattern": {
                      "type": "string",
                      "description": "Model name or glob pattern"
                    },
                    "chain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Provider chain for matching models"
                    },
                    "timeout_ms": {
                      "type": "integer",
                      "description": "Optional timeout override (ms)"
                    }
                  },
                  "required": [
                    "pattern",
                    "chain"
                  ]
                }
              },
              "load_balancing": {
                "type": "string",
                "enum": [
                  "failover",
                  "round_robin",
                  "weighted"
                ]
              },
              "routing_preference": {
                "type": "string",
                "enum": [
                  "default",
                  "cost",
                  "latency"
                ]
              },
              "timeout_ms": {
                "type": "integer",
                "description": "Per-agent override of the policy routing.timeout_ms. When set, takes precedence over the policy value for all requests from this agent. Same semantics as policy routing.timeout_ms — governs the full request lifecycle (TTFB plus body). See policy routing.timeout_ms for the default (120000) and sizing guidance."
              }
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the member who owns this agent"
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that created this entity"
          },
          "updated_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that last updated this entity"
          },
          "created_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to create (null for session auth)"
          },
          "updated_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to last update (null for session auth)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "policy_id",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "Run": {
        "type": "object",
        "description": "An execution run — a group of LLM calls from a single agent session.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Account that owns this run. Derived from the agent at creation time."
          },
          "agent_name": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional human-readable name for the run, set via x-rungate-run-name header on the first request."
          },
          "primary_model": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "completed",
              "failed",
              "budget_exceeded",
              "force_stopped"
            ]
          },
          "creation_method": {
            "type": "string",
            "enum": [
              "explicit",
              "implicit",
              "sdk"
            ]
          },
          "ended_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "completion_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "explicit",
              "idle_timeout",
              "server_restart",
              null
            ]
          },
          "budget": {
            "type": "object",
            "properties": {
              "alert_threshold_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "alert_threshold_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "hard_limit_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "hard_limit_usd": {
                "type": [
                  "number",
                  "null"
                ]
              }
            }
          },
          "alert_threshold_exceeded": {
            "type": "boolean"
          },
          "alert_sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "tokens_used": {
            "type": "object",
            "description": "Token usage with 4-bucket breakdown. total = input + output + cache_read + cache_creation.",
            "properties": {
              "input": {
                "type": "integer"
              },
              "output": {
                "type": "integer"
              },
              "cache_read": {
                "type": "integer"
              },
              "cache_creation": {
                "type": "integer"
              },
              "total": {
                "type": "integer"
              }
            }
          },
          "cost_usd": {
            "type": "number"
          },
          "policy_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Name of the policy that governed this run, extracted from policy_snapshot for convenience."
          },
          "policy_snapshot": {
            "type": "object",
            "additionalProperties": true
          },
          "step_count": {
            "type": "integer"
          },
          "last_step_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "force_stop_lifted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the force-stop block was lifted by an admin. Null if not lifted."
          },
          "has_governance_block": {
            "type": "boolean",
            "description": "True if any steps in this run were blocked by governance (policy, budget, rate limit)."
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "success",
              "partial",
              "failed",
              null
            ],
            "description": "Semantic outcome of the run. Set via the completion endpoints. Default: \"success\" for explicit completions, null for runs completed by other means."
          },
          "outcome_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Free-text reason explaining the outcome. Set via the completion endpoints."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "agent_id",
          "status",
          "creation_method",
          "budget",
          "tokens_used",
          "cost_usd",
          "step_count",
          "started_at"
        ]
      },
      "Step": {
        "type": "object",
        "description": "A single step within a run. Usually an `llm_call` (the provider request), but may also be a `failover_transition` — a control-plane event row inserted when Rungate reroutes a request from a failing provider to a working one. Transition rows carry the `failover_context` field with the full attempted-providers history.",
        "properties": {
          "id": {
            "type": "string"
          },
          "run_id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "llm_call",
              "tool_call",
              "retry",
              "dry_run",
              "post_completion_sweep",
              "failover_transition"
            ]
          },
          "provider": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "provider_key_id": {
            "type": "string",
            "format": "uuid"
          },
          "streaming": {
            "type": "boolean"
          },
          "request": {
            "type": "object",
            "additionalProperties": true
          },
          "response": {
            "type": "object",
            "additionalProperties": true,
            "description": "Provider response, redacted content marker, or error envelope. On failed steps, an `error` or `errors[]` field is present; each error/errors[] entry includes `kind` (#85), e.g. tcp_connect_timeout, request_timeout, http_error.",
            "properties": {
              "error": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "description": "Provider-originated error type (e.g., overloaded_error, server_error)"
                  },
                  "status": {
                    "type": "integer",
                    "description": "HTTP status code mapped from the failure"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "tcp_connect_timeout",
                      "request_timeout",
                      "network_error",
                      "http_error",
                      "empty_stream",
                      "first_events_timeout",
                      "first_events_error",
                      "mid_stream_error",
                      "client_disconnect",
                      "stream_processing_error",
                      "unknown"
                    ],
                    "description": "Failure-category discriminator (#85). Optional — pre-2026-04-14 step rows omit this field."
                  }
                }
              },
              "errors": {
                "type": "array",
                "description": "Per-attempt error array on non-streaming failed steps (logFailedStep). Each entry mirrors the single `error` shape with `kind`.",
                "items": {
                  "type": "object",
                  "properties": {
                    "provider": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    },
                    "kind": {
                      "type": "string",
                      "enum": [
                        "tcp_connect_timeout",
                        "request_timeout",
                        "network_error",
                        "http_error",
                        "empty_stream",
                        "first_events_timeout",
                        "first_events_error",
                        "mid_stream_error",
                        "client_disconnect",
                        "stream_processing_error",
                        "unknown"
                      ]
                    }
                  }
                }
              }
            }
          },
          "tokens": {
            "type": "object",
            "properties": {
              "input": {
                "type": "integer"
              },
              "output": {
                "type": "integer"
              },
              "cache_read": {
                "type": "integer"
              },
              "cache_creation": {
                "type": "integer"
              }
            }
          },
          "cost_usd": {
            "type": "number"
          },
          "latency_ms": {
            "type": "integer"
          },
          "routed_from": {
            "type": [
              "string",
              "null"
            ]
          },
          "failover_attempts": {
            "type": "integer",
            "description": "Number of failed provider attempts before this step succeeded. 0 on same-provider sticky steps. On a `failover_transition` row this equals the number of providers that failed before Rungate found a working one. On the successful `llm_call` row that followed the transition, this matches the transition row's count."
          },
          "status": {
            "type": "string",
            "enum": [
              "success",
              "error",
              "timeout",
              "budget_blocked",
              "policy_blocked"
            ]
          },
          "error_message": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "failover_context": {
            "description": "Full history of failover attempts. Present ONLY on `failover_transition` rows — null or absent on every other step type. The transition row is the sole carrier of this data; the successful `llm_call` that follows a failover does NOT duplicate it. Operators who need to correlate a specific `llm_call` with its failover event should either (a) find the most recent `failover_transition` row for the same run ordered before the `llm_call`, or (b) subscribe to the `step.failed_over` webhook, which fires once per failover and carries the full `failover_context` in its payload.",
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "attempted": {
                    "type": "array",
                    "description": "Each failed provider attempt in order, with the error Rungate received from the provider.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "provider": {
                          "type": "string"
                        },
                        "provider_key_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "status": {
                          "type": "integer",
                          "description": "HTTP status code the provider returned."
                        },
                        "error": {
                          "type": "string",
                          "description": "Truncated/redacted error message. Capped at 1000 characters."
                        },
                        "kind": {
                          "type": "string",
                          "enum": [
                            "tcp_connect_timeout",
                            "request_timeout",
                            "network_error",
                            "http_error",
                            "empty_stream",
                            "first_events_timeout",
                            "first_events_error",
                            "mid_stream_error",
                            "client_disconnect",
                            "stream_processing_error",
                            "unknown"
                          ],
                          "description": "Failure-category discriminator (#85). Optional — pre-2026-04-14 step rows omit this field."
                        }
                      },
                      "required": [
                        "provider",
                        "provider_key_id",
                        "status",
                        "error"
                      ]
                    }
                  },
                  "resolved_provider": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The provider that ultimately served the request. Null when every provider in the chain failed (exhaustion)."
                  },
                  "resolved_model": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The model the resolved provider was asked to serve. Null on exhaustion."
                  },
                  "original_model": {
                    "type": "string",
                    "description": "The model the client originally requested, before any cross-provider translation."
                  }
                },
                "required": [
                  "attempted",
                  "resolved_provider",
                  "resolved_model",
                  "original_model"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "run_id",
          "type",
          "provider",
          "model",
          "status",
          "cost_usd",
          "latency_ms",
          "created_at"
        ]
      },
      "LedgerEntry": {
        "type": "object",
        "description": "Immutable cost record for a single step.",
        "properties": {
          "id": {
            "type": "string"
          },
          "run_id": {
            "type": "string",
            "format": "uuid"
          },
          "step_id": {
            "type": "string"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "provider": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "provider_key_id": {
            "type": "string",
            "format": "uuid"
          },
          "tokens": {
            "type": "object",
            "properties": {
              "input": {
                "type": "integer"
              },
              "output": {
                "type": "integer"
              },
              "cache_read": {
                "type": "integer"
              },
              "cache_creation": {
                "type": "integer"
              }
            }
          },
          "cost_usd": {
            "type": "number"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "run_id",
          "step_id",
          "agent_id",
          "provider",
          "model",
          "cost_usd",
          "created_at"
        ]
      },
      "HealthResponse": {
        "type": "object",
        "description": "Health check response. Returned as a bare object (no { data } envelope).",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "healthy"
            ]
          },
          "version": {
            "type": "string"
          },
          "uptime_seconds": {
            "type": "integer"
          },
          "storage": {
            "type": "string",
            "enum": [
              "connected",
              "error"
            ]
          },
          "agents_count": {
            "type": "integer"
          },
          "active_runs": {
            "type": "integer"
          }
        },
        "required": [
          "status",
          "version",
          "uptime_seconds",
          "storage",
          "agents_count",
          "active_runs"
        ]
      },
      "OverviewStats": {
        "type": "object",
        "description": "Dashboard overview statistics.",
        "properties": {
          "active_agents": {
            "type": "integer"
          },
          "total_spend_today": {
            "type": "number"
          },
          "total_runs_today": {
            "type": "integer"
          },
          "tokens_processed_today": {
            "type": "integer"
          },
          "spend_trend_pct": {
            "type": "number"
          },
          "runs_trend_pct": {
            "type": "number"
          },
          "completed_runs_today": {
            "type": "integer"
          },
          "completion_rate_pct": {
            "type": "number"
          }
        },
        "required": [
          "active_agents",
          "total_spend_today",
          "total_runs_today",
          "tokens_processed_today",
          "spend_trend_pct",
          "runs_trend_pct",
          "completed_runs_today",
          "completion_rate_pct"
        ]
      },
      "AllAgentStats": {
        "type": "object",
        "description": "Per-agent spending statistics. Keys are agent IDs, values are stats objects.",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "total_spend": {
              "type": "number"
            },
            "total_runs": {
              "type": "integer"
            }
          },
          "required": [
            "total_spend",
            "total_runs"
          ]
        }
      },
      "CostAnalyticsResult": {
        "type": "object",
        "description": "A single group in a cost analytics breakdown.",
        "properties": {
          "group": {
            "type": "string"
          },
          "period": {
            "type": [
              "string",
              "null"
            ],
            "description": "Time bucket (null if no granularity specified)"
          },
          "total_cost_usd": {
            "type": "number"
          },
          "total_tokens": {
            "type": "integer"
          },
          "request_count": {
            "type": "integer"
          }
        },
        "required": [
          "group",
          "period",
          "total_cost_usd",
          "total_tokens",
          "request_count"
        ]
      },
      "OldDataCount": {
        "type": "object",
        "description": "Preview of data eligible for cleanup.",
        "properties": {
          "runs": {
            "type": "integer"
          },
          "steps": {
            "type": "integer"
          },
          "ledgerEntries": {
            "type": "integer"
          }
        },
        "required": [
          "runs",
          "steps",
          "ledgerEntries"
        ]
      },
      "DeleteOldDataResult": {
        "type": "object",
        "description": "Result of a cleanup operation.",
        "properties": {
          "runsDeleted": {
            "type": "integer"
          },
          "stepsDeleted": {
            "type": "integer"
          },
          "ledgerEntriesDeleted": {
            "type": "integer"
          }
        },
        "required": [
          "runsDeleted",
          "stepsDeleted",
          "ledgerEntriesDeleted"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Standard admin API error response.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "validation_error",
                  "not_found",
                  "conflict",
                  "forbidden",
                  "internal_error",
                  "service_unavailable"
                ]
              },
              "message": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Field-level error details (present for validation_error)"
              }
            },
            "required": [
              "type",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "DashboardAuthError": {
        "type": "object",
        "description": "Dashboard authentication error. Note: uses a flat string, NOT the nested { type, message } format.",
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "Authentication required"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "GovernanceBlockResponse": {
        "type": "object",
        "description": "Governance block error returned by proxy endpoints when a policy check fails.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "governance_block"
                ]
              },
              "code": {
                "type": "string",
                "enum": [
                  "budget_exceeded",
                  "budget_alert_exceeded",
                  "rate_limited",
                  "model_not_allowed",
                  "tool_blocked",
                  "tool_approval_required",
                  "agent_disabled",
                  "run_force_stopped",
                  "run_blocked_after_force_stop",
                  "runaway_prevention"
                ]
              },
              "message": {
                "type": "string"
              },
              "run_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "details": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": true
              },
              "context": {
                "type": "object",
                "description": "Run/policy/agent state for self-reporting and corrective action. Present on post-run governance blocks.",
                "properties": {
                  "policy_name": {
                    "type": "string"
                  },
                  "agent_name": {
                    "type": "string"
                  },
                  "steps_used": {
                    "type": "number"
                  },
                  "max_steps_per_run": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "cost_usd": {
                    "type": "number"
                  },
                  "hard_limit_usd": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "hard_limit_tokens": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "tokens_used": {
                    "type": "number"
                  },
                  "max_cost_per_hour_usd": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                }
              }
            },
            "required": [
              "type",
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ProxyAuthError": {
        "type": "object",
        "description": "Proxy authentication error for missing or invalid agent API key.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "unauthorized"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "type",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "ProviderErrorResponse": {
        "type": "object",
        "description": "Provider error when no providers are available or all providers failed.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "provider_error"
                ]
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "provider": {
                      "type": "string"
                    },
                    "status": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            },
            "required": [
              "type",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "CreateProviderKeyInput": {
        "type": "object",
        "description": "Request body for creating a provider key.",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Provider identifier (e.g., \"openai\", \"anthropic\")"
          },
          "name": {
            "type": "string"
          },
          "api_key": {
            "type": "string",
            "description": "Plaintext API key — will be encrypted at rest"
          },
          "base_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom provider base URL"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "provider",
          "name",
          "api_key"
        ]
      },
      "CreatePolicyInput": {
        "type": "object",
        "description": "Request body for creating a policy. All fields optional except name.",
        "properties": {
          "name": {
            "type": "string"
          },
          "budget": {
            "type": "object",
            "properties": {
              "alert_threshold_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "alert_threshold_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "hard_limit_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "hard_limit_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "max_cost_per_hour_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "on_alert_threshold": {
                "type": "string",
                "enum": [
                  "continue_and_alert",
                  "stop_and_alert",
                  "continue_and_block_new"
                ]
              }
            }
          },
          "allowed_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "allowed_tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "require_approval": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "approval_expiry_ms": {
            "type": "integer",
            "description": "Approval request expiry in ms. Default: 28800000 (8 hours). Min: 60000 (1 min). Max: 604800000 (7 days)."
          },
          "rate_limits": {
            "type": "object",
            "description": "Rate limits are per-agent-per-policy. Each policy has its own counter for each agent — requests under one policy do not count toward another policy's limits.",
            "properties": {
              "max_requests_per_minute": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "max_tokens_per_minute": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "routing": {
            "type": "object",
            "properties": {
              "default_chain": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "model_routes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pattern": {
                      "type": "string",
                      "description": "Model name or glob pattern"
                    },
                    "chain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Provider chain for matching models"
                    },
                    "timeout_ms": {
                      "type": "integer",
                      "description": "Optional timeout override (ms)"
                    }
                  },
                  "required": [
                    "pattern",
                    "chain"
                  ]
                }
              },
              "timeout_ms": {
                "type": "integer",
                "description": "Maximum time (ms) for the full request lifecycle — time-to-first-byte plus body read. Applies after the TCP+TLS handshake completes (handshake is governed by connect_timeout_ms). Default: 120000 (120s). Raise for heavy synthesis workloads (large prompts, long completions); Anthropic non-streaming calls commonly take 30–60s before first byte. Lower for interactive workloads where fast error surfacing matters more than provider patience."
              },
              "connect_timeout_ms": {
                "type": "integer",
                "minimum": 1000,
                "maximum": 600000,
                "description": "Maximum time (ms) to complete TCP+TLS handshake with a provider. After the socket is established, timeout_ms governs the full request lifecycle (TTFB and body). Default: 10000 (10s). Must be <= timeout_ms. Maximum: 600000 (10min)."
              },
              "retry_on": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "max_retries": {
                "type": "integer"
              },
              "on_rate_limit": {
                "type": "string",
                "enum": [
                  "failover_first",
                  "backoff_first"
                ]
              },
              "load_balancing": {
                "type": "string",
                "enum": [
                  "failover",
                  "round_robin",
                  "weighted"
                ],
                "description": "Key selection strategy for multi-key providers. Default: failover."
              },
              "circuit_breaker": {
                "type": "object",
                "properties": {
                  "failure_threshold": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Consecutive failures before opening circuit. 0 to disable. Default: 5."
                  },
                  "recovery_timeout_ms": {
                    "type": "integer",
                    "minimum": 1000,
                    "description": "Base cooldown before half-open test request (ms). Doubles on each failed probe. Default: 30000."
                  },
                  "max_recovery_timeout_ms": {
                    "type": "integer",
                    "minimum": 1000,
                    "description": "Maximum recovery timeout after exponential backoff (ms). Default: 600000 (10 min)."
                  }
                }
              },
              "routing_preference": {
                "type": "string",
                "enum": [
                  "default",
                  "cost",
                  "latency"
                ],
                "description": "Chain ordering strategy. default: user-defined. cost: cheapest first. latency: fastest p50 first."
              }
            }
          },
          "model_mapping": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "default_model": {
            "type": [
              "string",
              "null"
            ]
          },
          "model_override": {
            "type": [
              "string",
              "null"
            ],
            "description": "When set, replaces the requested model for all requests under this policy. The original model is preserved in step logs (routed_from) and the X-Rungate-Model-Override response header. When active, allowed_models/blocked_models checks are skipped."
          },
          "runaway_prevention": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "max_steps_per_run": {
                "type": "integer"
              }
            }
          },
          "implicit_run_grouping": {
            "type": "object",
            "properties": {
              "time_window_seconds": {
                "type": "integer"
              },
              "run_idle_timeout_seconds": {
                "type": "integer",
                "description": "Must be a positive integer, capped at 86400"
              },
              "force_stop_cooldown_minutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "description": "Minutes to block implicit run creation after a force-stop for the same agent+policy. 0 to disable. Default: 60. Explicit runs (x-rungate-new-run header) always bypass."
              }
            }
          },
          "outcome_defaults": {
            "type": [
              "object",
              "null"
            ],
            "description": "Per-ended_reason automatic outcome defaults. See the Policy schema for the full description and allowed keys.",
            "properties": {
              "agent_signaled": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "agent_complete_all": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "cost_limit": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "token_limit": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "alert_threshold_stop": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "idle_auto_complete": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "idle_timeout": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "new_run_requested": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "admin_stopped": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "admin_completed": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              }
            },
            "additionalProperties": false
          },
          "visibility": {
            "type": "string",
            "enum": [
              "org",
              "personal"
            ],
            "description": "Visibility scope. Members can only create personal. Default: org."
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name"
        ]
      },
      "CreateAgentInput": {
        "type": "object",
        "description": "Request body for creating an agent. Returns the generated api_key once (not retrievable later).",
        "properties": {
          "name": {
            "type": "string",
            "description": "Agent name. Auto-suffixed if not unique (e.g., \"my-agent-2\")."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "policy_id": {
            "type": "string",
            "format": "uuid",
            "description": "Must reference an existing policy"
          },
          "provider_keys": {
            "type": "object",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "key_id": {
                        "type": "string"
                      },
                      "weight": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100
                      }
                    },
                    "required": [
                      "key_id",
                      "weight"
                    ]
                  }
                }
              ]
            },
            "description": "Provider keys. Single ID or array of {key_id, weight}."
          },
          "routing_override": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "default_chain": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "model_routes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pattern": {
                      "type": "string",
                      "description": "Model name or glob pattern"
                    },
                    "chain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Provider chain for matching models"
                    },
                    "timeout_ms": {
                      "type": "integer",
                      "description": "Optional timeout override (ms)"
                    }
                  },
                  "required": [
                    "pattern",
                    "chain"
                  ]
                }
              },
              "load_balancing": {
                "type": "string",
                "enum": [
                  "failover",
                  "round_robin",
                  "weighted"
                ]
              },
              "routing_preference": {
                "type": "string",
                "enum": [
                  "default",
                  "cost",
                  "latency"
                ]
              },
              "timeout_ms": {
                "type": "integer",
                "description": "Per-agent override of the policy routing.timeout_ms. When set, takes precedence over the policy value for all requests from this agent. Same semantics as policy routing.timeout_ms — governs the full request lifecycle (TTFB plus body). See policy routing.timeout_ms for the default (120000) and sizing guidance."
              }
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "name",
          "policy_id"
        ]
      },
      "UpsertProviderKeyInput": {
        "type": "object",
        "description": "Request body for upserting a provider key by name. On create, provider and api_key are required. On update, all fields are optional.",
        "properties": {
          "provider": {
            "type": "string",
            "description": "Provider identifier. Required on create, must match existing on update."
          },
          "api_key": {
            "type": "string",
            "description": "Plaintext API key. Required on create. If sent on update, triggers key rotation."
          },
          "base_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Custom provider base URL"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpsertPolicyInput": {
        "type": "object",
        "description": "Request body for upserting a policy by name. Name comes from URL, not body. All fields optional; defaults applied on create, deep-merged on update.",
        "properties": {
          "budget": {
            "type": "object",
            "properties": {
              "alert_threshold_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "alert_threshold_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "hard_limit_tokens": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "hard_limit_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "max_cost_per_hour_usd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "on_alert_threshold": {
                "type": "string",
                "enum": [
                  "continue_and_alert",
                  "stop_and_alert",
                  "continue_and_block_new"
                ]
              }
            }
          },
          "allowed_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_models": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "allowed_tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "blocked_tools": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "require_approval": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rate_limits": {
            "type": "object",
            "description": "Rate limits are per-agent-per-policy. Each policy has its own counter for each agent — requests under one policy do not count toward another policy's limits.",
            "properties": {
              "max_requests_per_minute": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "max_tokens_per_minute": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "routing": {
            "type": "object",
            "properties": {
              "default_chain": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "model_routes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pattern": {
                      "type": "string",
                      "description": "Model name or glob pattern"
                    },
                    "chain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Provider chain for matching models"
                    },
                    "timeout_ms": {
                      "type": "integer",
                      "description": "Optional timeout override (ms)"
                    }
                  },
                  "required": [
                    "pattern",
                    "chain"
                  ]
                }
              },
              "timeout_ms": {
                "type": "integer",
                "description": "Maximum time (ms) for the full request lifecycle — time-to-first-byte plus body read. Applies after the TCP+TLS handshake completes (handshake is governed by connect_timeout_ms). Default: 120000 (120s). Raise for heavy synthesis workloads (large prompts, long completions); Anthropic non-streaming calls commonly take 30–60s before first byte. Lower for interactive workloads where fast error surfacing matters more than provider patience."
              },
              "connect_timeout_ms": {
                "type": "integer",
                "minimum": 1000,
                "maximum": 600000,
                "description": "Maximum time (ms) to complete TCP+TLS handshake with a provider. After the socket is established, timeout_ms governs the full request lifecycle (TTFB and body). Default: 10000 (10s). Must be <= timeout_ms. Maximum: 600000 (10min)."
              },
              "retry_on": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "max_retries": {
                "type": "integer"
              },
              "on_rate_limit": {
                "type": "string",
                "enum": [
                  "failover_first",
                  "backoff_first"
                ]
              },
              "load_balancing": {
                "type": "string",
                "enum": [
                  "failover",
                  "round_robin",
                  "weighted"
                ],
                "description": "Key selection strategy for multi-key providers. Default: failover."
              },
              "circuit_breaker": {
                "type": "object",
                "properties": {
                  "failure_threshold": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Consecutive failures before opening circuit. 0 to disable. Default: 5."
                  },
                  "recovery_timeout_ms": {
                    "type": "integer",
                    "minimum": 1000,
                    "description": "Base cooldown before half-open test request (ms). Doubles on each failed probe. Default: 30000."
                  },
                  "max_recovery_timeout_ms": {
                    "type": "integer",
                    "minimum": 1000,
                    "description": "Maximum recovery timeout after exponential backoff (ms). Default: 600000 (10 min)."
                  }
                }
              },
              "routing_preference": {
                "type": "string",
                "enum": [
                  "default",
                  "cost",
                  "latency"
                ],
                "description": "Chain ordering strategy. default: user-defined. cost: cheapest first. latency: fastest p50 first."
              }
            }
          },
          "model_mapping": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              }
            }
          },
          "default_model": {
            "type": [
              "string",
              "null"
            ]
          },
          "model_override": {
            "type": [
              "string",
              "null"
            ],
            "description": "When set, replaces the requested model for all requests under this policy. The original model is preserved in step logs (routed_from) and the X-Rungate-Model-Override response header. When active, allowed_models/blocked_models checks are skipped."
          },
          "runaway_prevention": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "max_steps_per_run": {
                "type": "integer"
              }
            }
          },
          "implicit_run_grouping": {
            "type": "object",
            "properties": {
              "time_window_seconds": {
                "type": "integer"
              },
              "run_idle_timeout_seconds": {
                "type": "integer",
                "description": "Must be a positive integer, capped at 86400"
              },
              "force_stop_cooldown_minutes": {
                "type": "integer",
                "minimum": 0,
                "maximum": 1440,
                "description": "Minutes to block implicit run creation after a force-stop for the same agent+policy. 0 to disable. Default: 60. Explicit runs (x-rungate-new-run header) always bypass."
              }
            }
          },
          "outcome_defaults": {
            "type": [
              "object",
              "null"
            ],
            "description": "Per-ended_reason automatic outcome defaults. See the Policy schema for the full description and allowed keys.",
            "properties": {
              "agent_signaled": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "agent_complete_all": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "cost_limit": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "token_limit": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "alert_threshold_stop": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "idle_auto_complete": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "idle_timeout": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "new_run_requested": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "admin_stopped": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              },
              "admin_completed": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ]
              }
            },
            "additionalProperties": false
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpsertAgentInput": {
        "type": "object",
        "description": "Request body for upserting an agent by name. Name comes from URL, not body. On create, policy_id is required and an API key is generated. On update, all fields optional.",
        "properties": {
          "policy_id": {
            "type": "string",
            "format": "uuid",
            "description": "Required on create. Must reference an existing policy."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider_keys": {
            "type": "object",
            "additionalProperties": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "key_id": {
                        "type": "string"
                      },
                      "weight": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100
                      }
                    },
                    "required": [
                      "key_id",
                      "weight"
                    ]
                  }
                }
              ]
            },
            "description": "Provider keys. Single ID or array of {key_id, weight}."
          },
          "routing_override": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "default_chain": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "model_routes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "pattern": {
                      "type": "string",
                      "description": "Model name or glob pattern"
                    },
                    "chain": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Provider chain for matching models"
                    },
                    "timeout_ms": {
                      "type": "integer",
                      "description": "Optional timeout override (ms)"
                    }
                  },
                  "required": [
                    "pattern",
                    "chain"
                  ]
                }
              },
              "load_balancing": {
                "type": "string",
                "enum": [
                  "failover",
                  "round_robin",
                  "weighted"
                ]
              },
              "routing_preference": {
                "type": "string",
                "enum": [
                  "default",
                  "cost",
                  "latency"
                ]
              },
              "timeout_ms": {
                "type": "integer",
                "description": "Per-agent override of the policy routing.timeout_ms. When set, takes precedence over the policy value for all requests from this agent. Same semantics as policy routing.timeout_ms — governs the full request lifecycle (TTFB plus body). See policy routing.timeout_ms for the default (120000) and sizing guidance."
              }
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ],
            "description": "Accepted on update (toggle active/disabled). Ignored on create (always active)."
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "workspace_id": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "RunCompletionInput": {
        "type": "object",
        "description": "Request body for completing a run.",
        "properties": {
          "ended_reason": {
            "type": "string",
            "description": "Reason for ending the run. Defaults to \"agent_signaled\" if omitted."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Merged into existing run metadata"
          },
          "outcome": {
            "type": "string",
            "enum": [
              "success",
              "partial",
              "failed"
            ],
            "description": "Semantic outcome of the run. Default: \"success\"."
          },
          "outcome_reason": {
            "type": "string",
            "maxLength": 1024,
            "description": "Free-text reason explaining the outcome."
          }
        }
      },
      "RunCompletionResponse": {
        "type": "object",
        "description": "Run summary returned after completing a run. Includes cost, step count, duration, and other useful fields so the agent does not need a follow-up query.",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Run name (from x-rungate-run-name header)"
              },
              "status": {
                "type": "string"
              },
              "ended_at": {
                "type": "string",
                "format": "date-time"
              },
              "ended_reason": {
                "type": "string"
              },
              "completion_reason": {
                "type": "string"
              },
              "outcome": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "success",
                  "partial",
                  "failed",
                  null
                ],
                "description": "Semantic outcome of the run. Default: \"success\" for explicit completions."
              },
              "outcome_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Free-text reason for the outcome."
              },
              "step_count": {
                "type": "integer",
                "description": "Total number of steps in the run"
              },
              "cost_usd": {
                "type": "number",
                "description": "Total cost in USD"
              },
              "tokens_used": {
                "type": "object",
                "properties": {
                  "input": {
                    "type": "integer"
                  },
                  "output": {
                    "type": "integer"
                  },
                  "cache_read": {
                    "type": "integer"
                  },
                  "cache_creation": {
                    "type": "integer"
                  },
                  "total": {
                    "type": "integer"
                  }
                },
                "description": "Token usage breakdown (input + output + cache_read + cache_creation = total)"
              },
              "duration_ms": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Run duration in milliseconds (ended_at - started_at)"
              },
              "policy_name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Policy name from the run's policy snapshot"
              },
              "primary_model": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Most-used model in the run"
              },
              "governance_events": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "description": "Governance block code (e.g. budget_exceeded, runaway_prevention, model_not_allowed, tool_approval_required)"
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of times this governance event occurred"
                    }
                  },
                  "required": [
                    "type",
                    "count"
                  ]
                },
                "description": "Governance events that occurred during the run, sorted by count descending. Empty array for clean runs."
              },
              "limits_hit": {
                "type": "boolean",
                "description": "True if any governance events (blocked steps) occurred during the run"
              }
            },
            "required": [
              "id",
              "status",
              "ended_at",
              "ended_reason",
              "completion_reason",
              "step_count",
              "cost_usd",
              "tokens_used",
              "governance_events",
              "limits_hit"
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "CleanupInput": {
        "type": "object",
        "description": "Request body for cleanup operation.",
        "properties": {
          "days": {
            "type": "integer",
            "minimum": 1,
            "description": "Delete data older than this many days"
          }
        },
        "required": [
          "days"
        ]
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "run.started",
          "run.completed",
          "run.budget_exceeded",
          "run.force_stopped",
          "run.alert_threshold",
          "step.completed",
          "step.policy_blocked",
          "step.budget_blocked",
          "step.failed",
          "agent.created",
          "agent.updated",
          "agent.disabled",
          "policy.created",
          "policy.updated",
          "policy.deleted",
          "policy.version_created",
          "provider_key.created",
          "provider_key.disabled",
          "provider_key.enabled",
          "provider_key.deleted",
          "provider_key.rotated",
          "step.approval_required",
          "approval.approved",
          "approval.rejected",
          "admin_token.created",
          "admin_token.revoked",
          "alert.triggered",
          "alert_rule.created",
          "alert_rule.updated",
          "alert_rule.deleted",
          "member.role_changed",
          "member.removed",
          "member.ownership_transferred",
          "webhook.test"
        ],
        "description": "Webhook event type identifier"
      },
      "Webhook": {
        "type": "object",
        "description": "A webhook subscription. The secret field is masked in GET responses; plaintext only in the POST 201 creation response.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Human-friendly webhook name (unique per org)"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Owning account ID (derived from auth token)"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Delivery endpoint URL"
          },
          "secret": {
            "type": "string",
            "description": "Masked in GET responses. Plaintext only in POST 201 response."
          },
          "previous_secret": {
            "type": [
              "string",
              "null"
            ],
            "description": "Masked in GET responses. Populated only during a rotation grace window. Plaintext only in the POST /rotate-secret response."
          },
          "previous_secret_expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "ISO 8601 timestamp after which previous_secret is no longer used for signing. Null when no rotation is pending."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "description": "Subscribed event types"
          },
          "agent_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional agent scope — only fire for events involving this agent"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "failing"
            ],
            "description": "active = delivering, paused = admin-disabled, failing = auto-disabled after consecutive failures"
          },
          "failure_count": {
            "type": "integer",
            "description": "Consecutive delivery failures (reset on success)"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "org",
              "personal"
            ],
            "description": "Scope — org is visible to all members, personal only to the owner"
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the member who owns this webhook"
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that created this entity"
          },
          "updated_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that last updated this entity"
          },
          "created_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to create (null for session auth)"
          },
          "updated_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to last update (null for session auth)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "secret",
          "events",
          "status",
          "failure_count",
          "created_at",
          "updated_at"
        ]
      },
      "CreateWebhookInput": {
        "type": "object",
        "description": "Request body for creating a webhook.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Webhook name (must be unique)"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Delivery endpoint URL (HTTP or HTTPS)"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "minItems": 1,
            "description": "Event types to subscribe to"
          },
          "secret": {
            "type": "string",
            "description": "Webhook secret for HMAC signing. Auto-generated (whsec_...) if omitted."
          },
          "agent_id": {
            "type": "string",
            "description": "Scope to a specific agent ID"
          },
          "description": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "enum": [
              "org",
              "personal"
            ],
            "description": "Scope. Members can only create personal. Default: org."
          }
        },
        "required": [
          "name",
          "url",
          "events"
        ]
      },
      "WebhookDelivery": {
        "type": "object",
        "description": "A webhook delivery attempt record.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "event_id": {
            "type": "string",
            "format": "uuid"
          },
          "payload": {
            "type": "string",
            "description": "JSON-encoded event payload"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "success",
              "failed"
            ]
          },
          "attempts": {
            "type": "integer"
          },
          "max_attempts": {
            "type": "integer"
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status code from delivery attempt"
          },
          "response_body": {
            "type": [
              "string",
              "null"
            ],
            "description": "Truncated response body (max 4KB)"
          },
          "next_retry_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "webhook_id",
          "event_type",
          "event_id",
          "payload",
          "status",
          "attempts",
          "max_attempts",
          "created_at"
        ]
      },
      "ApprovalRequest": {
        "type": "object",
        "description": "A tool approval request. Created when a proxy request includes tools requiring approval.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "run_id": {
            "type": "string",
            "format": "uuid"
          },
          "step_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Account that owns this approval request. Derived from the run/agent at creation time."
          },
          "policy_id": {
            "type": "string",
            "format": "uuid"
          },
          "tool_name": {
            "type": "string",
            "description": "Name of the tool requiring approval"
          },
          "request_snapshot": {
            "type": "object",
            "description": "Full request body at the time approval was requested"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "rejected",
              "expired"
            ]
          },
          "decided_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity of approver/rejector"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rejection reason (optional)"
          },
          "decided_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "run_id",
          "agent_id",
          "policy_id",
          "tool_name",
          "status",
          "expires_at",
          "created_at"
        ]
      },
      "AlertRule": {
        "type": "object",
        "description": "An alert rule that monitors conditions and triggers webhook events.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Alert rule name (unique per org)"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "org_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Owning account ID (derived from auth token)"
          },
          "agent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Null means global (all agents)"
          },
          "condition_type": {
            "type": "string",
            "enum": [
              "cost_threshold",
              "error_rate",
              "rate_limit_approaching",
              "approval_pending_timeout",
              "failover_rate"
            ]
          },
          "condition_config": {
            "type": "object",
            "description": "Condition-specific configuration (threshold values, window sizes, etc.)"
          },
          "cooldown_seconds": {
            "type": "integer",
            "description": "Minimum seconds between triggers (default: 300)"
          },
          "last_triggered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "scope": {
            "type": "string",
            "enum": [
              "org",
              "personal"
            ],
            "description": "Scope — org is visible to all members, personal only to the owner"
          },
          "member_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID of the member who owns this alert rule"
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that created this entity"
          },
          "updated_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Identity that last updated this entity"
          },
          "created_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to create (null for session auth)"
          },
          "updated_by_token_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Admin token ID used to last update (null for session auth)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "condition_type",
          "condition_config",
          "cooldown_seconds",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "CreateAlertRuleInput": {
        "type": "object",
        "description": "Input for creating an alert rule.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Unique alert rule name"
          },
          "description": {
            "type": "string"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "description": "Scope to specific agent. Required for rate_limit_approaching."
          },
          "condition_type": {
            "type": "string",
            "enum": [
              "cost_threshold",
              "error_rate",
              "rate_limit_approaching",
              "approval_pending_timeout",
              "failover_rate"
            ]
          },
          "condition_config": {
            "type": "object",
            "description": "Condition-specific configuration"
          },
          "cooldown_seconds": {
            "type": "integer",
            "description": "Cooldown between triggers (default: 300)"
          },
          "scope": {
            "type": "string",
            "enum": [
              "org",
              "personal"
            ],
            "description": "Scope. Members can only create personal. Default: org."
          }
        },
        "required": [
          "name",
          "condition_type"
        ]
      },
      "AdminToken": {
        "type": "object",
        "description": "A scoped admin API token. The token_hash field is never returned. Plaintext token is only shown once at creation.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Human-friendly token name (unique per account)"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "admin"
              ]
            },
            "description": "Token scopes. Hierarchy: admin > write > read."
          },
          "token_prefix": {
            "type": "string",
            "description": "First 11 characters of the token for identification (e.g., \"rg_adm_abcd\")"
          },
          "account_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Account this token belongs to. Derived from the creating token — not user-settable."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "revoked"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Null means no expiration"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "scopes",
          "token_prefix",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "CreateAdminTokenInput": {
        "type": "object",
        "description": "Request body for creating an admin token.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Unique token name"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "write",
                "admin"
              ]
            },
            "minItems": 1,
            "description": "Token scopes (at least one required)"
          },
          "description": {
            "type": "string"
          },
          "expires_in": {
            "type": "string",
            "description": "Expiration duration, e.g., \"30d\", \"90d\". Omit for no expiration."
          }
        },
        "required": [
          "name",
          "scopes"
        ]
      },
      "Invitation": {
        "type": "object",
        "description": "An invitation to join an org. The token_hash field is never returned in API responses.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "member",
              "viewer"
            ]
          },
          "invited_by": {
            "type": "string",
            "description": "Member ID or token:<name> for admin token invitations"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "accepted",
              "expired",
              "revoked"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "accepted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "org_id",
          "email",
          "role",
          "invited_by",
          "status",
          "expires_at",
          "created_at"
        ]
      },
      "Member": {
        "type": "object",
        "description": "An org member with a role-based permission level.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "display_name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "member",
              "viewer"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "removed"
            ]
          },
          "invited_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "accepted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "org_id",
          "email",
          "display_name",
          "role",
          "status",
          "created_at",
          "updated_at"
        ]
      },
      "Account": {
        "type": "object",
        "description": "An organizational account containing agents, policies, and provider keys.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string",
            "description": "URL-safe identifier (e.g., \"acme-corp\"). 3-50 chars, lowercase alphanumeric and hyphens."
          },
          "name": {
            "type": "string"
          },
          "tier": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "growth",
              "enterprise"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "description": "Contact email for magic link auth and notifications."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "cancelled",
              "pending"
            ]
          },
          "is_hosted": {
            "type": "boolean"
          },
          "monthly_step_count": {
            "type": "integer",
            "description": "Steps used in current billing period."
          },
          "monthly_step_count_reset_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the monthly step counter was last reset."
          },
          "step_limit_override": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Per-account step limit override. Null uses tier default."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "tier",
          "status",
          "is_hosted",
          "created_at",
          "updated_at"
        ]
      },
      "CreateAccountInput": {
        "type": "object",
        "description": "Request body for creating an account.",
        "properties": {
          "slug": {
            "type": "string",
            "description": "URL-safe identifier. 3-50 chars, lowercase alphanumeric and hyphens. Cannot be a reserved slug."
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "description": "Contact email for magic link auth and notifications."
          },
          "tier": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "growth",
              "enterprise"
            ],
            "default": "free"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "cancelled",
              "pending"
            ],
            "default": "active"
          },
          "is_hosted": {
            "type": "boolean",
            "default": false
          },
          "step_limit_override": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Per-account step limit override. Null uses tier default."
          }
        },
        "required": [
          "slug",
          "name"
        ]
      },
      "Session": {
        "type": "object",
        "description": "An authenticated dashboard session.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_active_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ip_address": {
            "type": [
              "string",
              "null"
            ]
          },
          "user_agent": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "account_id",
          "expires_at",
          "created_at"
        ]
      }
    },
    "securitySchemes": {
      "DashboardAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Dashboard authentication via admin token (rg_adm_...) or session cookie. Admin tokens support scoped access (read/write/admin)."
      },
      "AgentApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Agent API key authentication (rg_sk_...). Generated when creating an agent. Also accepts x-api-key header as an alternative to Authorization: Bearer."
      }
    }
  }
}