{
  "openapi": "3.1.0",
  "info": {
    "title": "Kastra HTTP API",
    "version": "1.0.0",
    "summary": "Runtime authorization API for AI agents and control-plane administration.",
    "description": "Kastra evaluates every agent action against policy before it executes.\n\n## Planes\n- Data plane `https://api.kastra.ai/v1/*` — API key `Authorization: Bearer ka_<env>_<hex>`.\n- Management plane `https://api.kastra.ai/api/v1/*` — session JWT plus `X-Organization-ID`.\n- MCP `https://api.kastra.ai/mcp/account` — OAuth 2.0 (PKCE S256), scope `kastra.account.read`.\n\n## Rate limits\nResponses include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset` (Unix epoch seconds). A 429 carries `Retry-After` in seconds and the standard error envelope.\n\n## Versioning and deprecation\n- Both planes are URL-versioned (`/v1/*`, `/api/v1/*`) and every response carries `X-API-Version: v1`.\n- Additive within a version: new endpoints and new optional response fields may appear under the current prefix; ignore fields you do not know.\n- Breaking changes (removing a field or endpoint, changing a type or meaning) ship only under a new version prefix, with the previous version still served.\n- Deprecation is signalled in-band: responses from an endpoint scheduled for removal carry `Deprecation` (RFC 9745) and `Sunset` (RFC 8594) headers with the removal date, and https://kastra.ai/docs/api names the replacement. Deprecated endpoints keep working until the `Sunset` date. Nothing is currently deprecated.\n\n## Errors\nEvery 4xx/5xx body is `components.schemas.Error`, except the /v1/evaluate 403 which is a policy DENY carrying the decision envelope.\n\nHuman docs: https://kastra.ai/docs/api",
    "contact": {
      "name": "Kastra Labs Inc.",
      "email": "hello@kastra.ai",
      "url": "https://kastra.ai/docs/api"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://api.kastra.ai",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Data plane",
      "description": "Low-latency evaluate and checkpoint routes. API key."
    },
    {
      "name": "Policies",
      "description": "Policy documents and revisions. Session JWT."
    },
    {
      "name": "Audit",
      "description": "Decision log and hash-chain verification."
    },
    {
      "name": "Keys",
      "description": "Environment API keys. Secret shown once."
    },
    {
      "name": "Environments",
      "description": "Tenant environments."
    },
    {
      "name": "Auth",
      "description": "Self-serve signup and session JWT."
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol over streamable HTTP."
    }
  ],
  "paths": {
    "/v1/evaluate": {
      "post": {
        "operationId": "publicEvaluate",
        "summary": "Evaluate an action against the active policy",
        "description": "Hot path. Returns ALLOW (200), DENY (403), or HOLD (202 when Accept-Kastra-Hold: 1). Authenticated with an environment-scoped API key. Recorded decisions form a hash-chained audit trail.",
        "tags": [
          "Data plane"
        ],
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Accept-Kastra-Hold",
            "in": "header",
            "required": false,
            "description": "Opt in to HOLD. Send `1` to receive a 202 checkpoint when policy places the action on hold; without it a HOLD rule is not surfaced as 202.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Evaluate an action against the active policy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "decision",
                        "reason",
                        "latency_ms"
                      ],
                      "properties": {
                        "decision_id": {
                          "type": "string",
                          "description": "Present when the decision was recorded to the audit chain. Omitted if recording failed open."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "ALLOW",
                            "DENY"
                          ]
                        },
                        "reason": {
                          "type": "string"
                        },
                        "policy_version": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "matched_rule": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "additionalProperties": true
                        },
                        "latency_ms": {
                          "type": "number"
                        },
                        "entry_hash": {
                          "type": "string",
                          "description": "Present when the decision was recorded to the audit chain. Omitted if recording failed open."
                        },
                        "meter": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "prompt_max_bytes": {
                          "type": "integer"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Policy evaluation created a HOLD checkpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "decision",
                        "checkpoint_id",
                        "expires_at",
                        "on_timeout",
                        "server_now"
                      ],
                      "properties": {
                        "decision": {
                          "type": "string",
                          "enum": [
                            "HOLD"
                          ]
                        },
                        "checkpoint_id": {
                          "type": "string"
                        },
                        "mqtt_topic": {
                          "type": "string"
                        },
                        "mqtt_credentials": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "on_timeout": {
                          "type": "string"
                        },
                        "server_now": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "title": {
                          "type": "string"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Policy evaluation returned DENY.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "decision",
                        "reason",
                        "latency_ms"
                      ],
                      "properties": {
                        "decision_id": {
                          "type": "string",
                          "description": "Present when the decision was recorded to the audit chain. Omitted if recording failed open."
                        },
                        "decision": {
                          "type": "string",
                          "enum": [
                            "ALLOW",
                            "DENY"
                          ]
                        },
                        "reason": {
                          "type": "string"
                        },
                        "policy_version": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "matched_rule": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "additionalProperties": true
                        },
                        "latency_ms": {
                          "type": "number"
                        },
                        "entry_hash": {
                          "type": "string",
                          "description": "Present when the decision was recorded to the audit chain. Omitted if recording failed open."
                        },
                        "meter": {
                          "type": "object",
                          "additionalProperties": true
                        },
                        "prompt_max_bytes": {
                          "type": "integer"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jurisdiction",
                  "model",
                  "workload_type"
                ],
                "properties": {
                  "environment": {
                    "type": "string",
                    "description": "Environment override. Defaults to the API key's environment."
                  },
                  "jurisdiction": {
                    "type": "string",
                    "description": "Jurisdiction used for policy matching, e.g. US or BR."
                  },
                  "model": {
                    "type": "string",
                    "description": "Model identifier, optionally qualified by provider."
                  },
                  "provider": {
                    "type": "string",
                    "description": "Optional provider prefix, e.g. openai or anthropic."
                  },
                  "customer_id": {
                    "type": "string",
                    "description": "Customer identifier used for policy scoping."
                  },
                  "workload_type": {
                    "type": "string",
                    "description": "Workload type used for policy matching, e.g. inference."
                  },
                  "data_classification": {
                    "type": "string",
                    "description": "Data sensitivity classification."
                  },
                  "user_age_group": {
                    "type": "string",
                    "description": "User age group used for policy matching."
                  },
                  "request_id": {
                    "type": "string",
                    "description": "Caller-supplied correlation identifier."
                  },
                  "action": {
                    "type": "string",
                    "description": "Action being authorized, e.g. shell.exec or tool.call."
                  },
                  "resource": {
                    "type": "string",
                    "description": "Target resource identifier."
                  },
                  "principal": {
                    "type": "string",
                    "description": "Unverified caller identity claim. Policy matching uses a server-bound principal when configured."
                  },
                  "attributes": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "Action-specific string attributes evaluated by policy."
                  },
                  "source": {
                    "type": "string",
                    "description": "Kastra integration surface. Defaults to server."
                  },
                  "prompt": {
                    "type": "string",
                    "description": "Raw prompt for prompt-policy evaluation. Subject to the tenant byte limit."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/fail-open": {
      "post": {
        "operationId": "logFailOpen",
        "summary": "Record a fail-open fallback",
        "description": "Telemetry when the policy engine was unreachable and the caller fell open. Does not change policy.",
        "tags": [
          "Data plane"
        ],
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Record a fail-open fallback",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "accepted": {
                          "type": "integer"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "events"
                ],
                "properties": {
                  "events": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "required": [
                        "id",
                        "occurred_at",
                        "reason",
                        "source"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "occurred_at": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "reason": {
                          "type": "string"
                        },
                        "http_status": {
                          "type": "integer"
                        },
                        "source": {
                          "type": "string"
                        },
                        "tool": {
                          "type": "string"
                        },
                        "environment": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkpoints": {
      "get": {
        "operationId": "listCheckpoints",
        "summary": "List HOLD checkpoints",
        "description": "List human-approval checkpoints for the API key's environment. Filter with status, source, since, and limit.",
        "tags": [
          "Data plane"
        ],
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "pending | approved | denied | cancelled",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–100.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List HOLD checkpoints",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkpoints/{checkpointId}": {
      "get": {
        "operationId": "getCheckpoint",
        "summary": "Get one checkpoint",
        "description": "Read a HOLD checkpoint and its effective_decision.",
        "tags": [
          "Data plane"
        ],
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "checkpointId",
            "in": "path",
            "required": true,
            "description": "Checkpoint identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get one checkpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "effective_decision": {
                          "type": "string"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkpoints/{checkpointId}/approve": {
      "post": {
        "operationId": "approveCheckpoint",
        "summary": "Approve a HOLD checkpoint",
        "description": "Resolve a pending checkpoint as ALLOW. Optional note. 409 if already final.",
        "tags": [
          "Data plane"
        ],
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "checkpointId",
            "in": "path",
            "required": true,
            "description": "Checkpoint identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Approve a HOLD checkpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "approved"
                          ]
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkpoints/{checkpointId}/deny": {
      "post": {
        "operationId": "denyCheckpoint",
        "summary": "Deny a HOLD checkpoint",
        "description": "Resolve a pending checkpoint as DENY. Optional note. 409 if already final.",
        "tags": [
          "Data plane"
        ],
        "security": [
          {
            "apiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "checkpointId",
            "in": "path",
            "required": true,
            "description": "Checkpoint identifier.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deny a HOLD checkpoint",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "denied"
                          ]
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/policies": {
      "get": {
        "operationId": "listPolicies",
        "summary": "List policies",
        "description": "Paginated list of governance policies for the organization selected by X-Organization-ID.",
        "tags": [
          "Policies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–100, default 20.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Default 0.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List policies",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "environment": {
                            "type": "string"
                          },
                          "revision": {
                            "type": "integer"
                          },
                          "status": {
                            "type": "string"
                          },
                          "content": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createPolicy",
        "summary": "Create a policy",
        "description": "Create a deny-rule policy document. MEMBER or above. Updates later create revisions.",
        "tags": [
          "Policies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Create a policy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "environment": {
                          "type": "string"
                        },
                        "revision": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string"
                        },
                        "content": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "deny": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "additionalProperties": true
                    },
                    "description": "Deny, hold, monitor, redact, rate-limit, and spend-cap policy rules."
                  },
                  "required_attributes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "default_decision": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "deny"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/policies/{policyId}": {
      "get": {
        "operationId": "getPolicy",
        "summary": "Get a policy",
        "description": "Return one policy by ID. Cross-tenant access returns 404.",
        "tags": [
          "Policies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "policyId",
            "in": "path",
            "required": true,
            "description": "Policy UUID.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get a policy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "environment": {
                          "type": "string"
                        },
                        "revision": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string"
                        },
                        "content": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/policies/active": {
      "get": {
        "operationId": "getActivePolicy",
        "summary": "Get the active policy",
        "description": "Active policy for the current app and environment.",
        "tags": [
          "Policies"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Get the active policy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "environment": {
                          "type": "string"
                        },
                        "revision": {
                          "type": "integer"
                        },
                        "status": {
                          "type": "string"
                        },
                        "content": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/decisions": {
      "get": {
        "operationId": "listDecisions",
        "summary": "List authorization decisions",
        "description": "Cursor-paginated immutable decision log. Filter by environment, decision, and time range.",
        "tags": [
          "Audit"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque pagination cursor.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "decision",
            "in": "query",
            "required": false,
            "description": "ALLOW | DENY | PENDING_REVIEW",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List authorization decisions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "decision": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/decisions/verify-chain": {
      "get": {
        "operationId": "verifyDecisionChain",
        "summary": "Verify the decision hash chain",
        "description": "Independent integrity check of the tamper-evident audit chain.",
        "tags": [
          "Audit"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Verify the decision hash chain",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "valid": {
                          "type": "boolean"
                        },
                        "head": {
                          "type": "string"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "Masked API-key metadata. Plaintext secrets are shown only at creation time.",
        "tags": [
          "Keys"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List API keys",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "prefix": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Mint an environment-scoped key (ka_<env>_<hex>). The secret is returned once. ADMIN.",
        "tags": [
          "Keys"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Create an API key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "key"
                      ],
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "key": {
                          "type": "string"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "environment_id"
                ],
                "properties": {
                  "environment_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/environments": {
      "get": {
        "operationId": "listEnvironments",
        "summary": "List environments",
        "description": "Environments (local, staging, production, …) in the current organization.",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Organization-ID",
            "in": "header",
            "required": true,
            "description": "Organization UUID selected by the session.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List environments",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/signup": {
      "post": {
        "operationId": "signup",
        "summary": "Create a Kastra account",
        "description": "Self-serve signup. No sales form. Starts the 15-day trial.",
        "tags": [
          "Auth"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "201": {
            "description": "Create a Kastra account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "description": "The created user's profile. Email verification is required before login.",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string",
                          "format": "email"
                        },
                        "full_name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email_verified": {
                          "type": "boolean"
                        },
                        "created_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "operationId": "login",
        "summary": "Log in and receive a session JWT",
        "description": "Returns an access JWT and refresh token for the management plane.",
        "tags": [
          "Auth"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Log in and receive a session JWT",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "access_token": {
                          "type": "string"
                        },
                        "refresh_token": {
                          "type": "string"
                        }
                      }
                    },
                    "error": {
                      "type": "string",
                      "description": "Present when success is false."
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "password"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mcp/account": {
      "post": {
        "operationId": "mcpAccountInitialize",
        "summary": "Kastra account MCP (streamable HTTP)",
        "description": "OAuth-gated Model Context Protocol endpoint. Use scope kastra.account.read. JSON-RPC methods: initialize, tools/list, tools/call. Transport: streamable HTTP.",
        "tags": [
          "MCP"
        ],
        "security": [
          {
            "oauth2": [
              "kastra.account.read"
            ]
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Kastra account MCP (streamable HTTP)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string"
                    },
                    "result": {
                      "type": "object"
                    },
                    "error": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Malformed request or failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, invalid, or expired credentials.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient role, inactive account, or plan entitlement missing (see `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found (also used for cross-tenant access).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the `Retry-After` seconds; see the X-RateLimit-* headers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal error. The message is generic; nothing internal is leaked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "enum": [
                      "2.0"
                    ]
                  },
                  "id": {},
                  "method": {
                    "type": "string"
                  },
                  "params": {
                    "type": "object"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Uniform error envelope for every 4xx and 5xx response, except the /v1/evaluate 403 which is a policy DENY carrying the decision envelope. `error` is a human-readable message (generic for 5xx; internal detail is never leaked). `code` is a stable machine-readable identifier present only on errors that define one, for example plan_upgrade_required, account_inactive, at_capacity, captcha_failed.",
        "required": [
          "success",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string",
            "description": "Human-readable message."
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable identifier. Present only on errors that define one."
          }
        }
      }
    },
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API key",
        "description": "Environment-scoped API key `ka_<env>_<64-hex>`. Created in the console Keys page or via createApiKey."
      },
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Session JWT from login or refresh. Send X-Organization-ID on every management-plane call."
      },
      "oauth2": {
        "type": "oauth2",
        "description": "OAuth 2.0 authorization code + PKCE for the account MCP connector.",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.kastra.ai/oauth/authorize",
            "tokenUrl": "https://api.kastra.ai/oauth/token",
            "refreshUrl": "https://api.kastra.ai/oauth/token",
            "scopes": {
              "kastra.account.read": "Read-only access to one tenant's governance data: decisions, policies, environments, incidents, HOLD checkpoints, audit trail, and rule statistics. Cannot write, change settings, or read another tenant."
            }
          }
        }
      }
    }
  }
}
