{
 "openapi": "3.1.0",
 "info": {
  "title": "Stackurity API",
  "version": "v1",
  "description": "The Stackurity REST API. Requests and responses are JSON. Every operation names the role it needs (x-stackurity-role); roles apply organisation-wide or through project grants (see docs/api.md, \"Projects and access\"). Send X-Stackurity-Project: <id> (or project_id) to limit project-scoped reads to one project. Operations marked x-stackurity-edition: ee exist in the licensed build only. Response bodies are described in docs/api.md; this document lists every operation, its parameters and its authentication. AI assistants use /mcp instead (docs/ai-assistants.md).",
  "license": {
   "name": "Apache-2.0",
   "identifier": "Apache-2.0"
  }
 },
 "externalDocs": {
  "description": "API reference in prose",
  "url": "https://github.com/stackurity/stackurity/blob/main/docs/api.md"
 },
 "servers": [
  {
   "url": "https://app.stackurity.dev/api/v1",
   "description": "Stackurity Cloud"
  },
  {
   "url": "https://{host}/api/v1",
   "description": "Self-hosted Stackurity",
   "variables": {
    "host": {
     "default": "stackurity.example.com"
    }
   }
  }
 ],
 "security": [
  {
   "bearerToken": []
  },
  {
   "session": []
  }
 ],
 "tags": [
  {
   "name": "Account"
  },
  {
   "name": "Agents and uploads"
  },
  {
   "name": "Automatic fixes"
  },
  {
   "name": "Findings and fixes"
  },
  {
   "name": "Instance administration"
  },
  {
   "name": "Integrations"
  },
  {
   "name": "Intelligence"
  },
  {
   "name": "Inventory"
  },
  {
   "name": "Notifications"
  },
  {
   "name": "Projects and people"
  },
  {
   "name": "Reports"
  },
  {
   "name": "Setup"
  },
  {
   "name": "VEX"
  }
 ],
 "paths": {
  "/access-grants": {
   "get": {
    "operationId": "get_access_grants",
    "summary": "Access grants, with project, asset, person and team names",
    "description": "Access grants, with project, asset, person and team names\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "user_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "team_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_access_grants",
    "summary": "Grant a role on a project or asset to a person, team or email",
    "description": "`{\"project_id\" or \"asset_id\", \"user_id\" or \"team_id\" or \"email\", \"role\"}`. With `email`, someone who is not a member joins with no organisation-wide role (an account is created with `password` when there is none; `account_created` says so). A grant that exists for the same person or team and project or asset has its role changed (200); a new one is 201\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/access-grants/{id}": {
   "delete": {
    "operationId": "delete_access_grants_id",
    "summary": "Remove a grant",
    "description": "Change a grant's `role`, or remove it. Takes effect on the next request\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_access_grants_id",
    "summary": "Change a grant's role",
    "description": "Change a grant's `role`, or remove it. Takes effect on the next request\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/coverage-gaps": {
   "get": {
    "operationId": "get_admin_coverage_gaps",
    "summary": "What Stackurity cannot check, across workspaces",
    "description": "What Stackurity cannot check across every active workspace, as counts of assets and workspaces by type: `unread_files` (files no built-in reader or installed stack pack reads, by kind such as `hex:mix.lock`), `no_vulnerability_source` (components with unsupported coverage, by package type and reason, vendor builds by repository) and `no_lifecycle` (products no lifecycle source tracks, release lines missing from the data, runtimes and operating systems with no lifecycle product), with `workspaces`, `assets` and the lifecycle `overlay_version`. Names no workspace, asset, path or package (compatibility.md)\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/health": {
   "get": {
    "operationId": "get_admin_health",
    "summary": "Platform health across workspaces",
    "description": "Platform health across workspaces: `status` (`ok`, `warning`, `critical`), `problems` (each with `last_success`, `last_error`, `scope`, `next_step` and `docs`; objects are named only for the caller's active workspace), background `tasks` with their last success and error, job counts by kind and state, jobs that failed in the last 24 hours, notification `deliveries` by channel kind and state, the age of the oldest due notification and `failing_channels` (install.md)\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/license": {
   "delete": {
    "operationId": "delete_admin_license",
    "summary": "Remove the licence key",
    "description": "Remove the licence key\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "get": {
    "operationId": "get_admin_license",
    "summary": "The installation's licence",
    "description": "The installation's licence\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_admin_license",
    "summary": "Install a licence key",
    "description": "Install a licence key\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/packs": {
   "get": {
    "operationId": "get_admin_packs",
    "summary": "Installed stack packs",
    "description": "Installed stack packs\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/packs/install": {
   "post": {
    "operationId": "post_admin_packs_install",
    "summary": "Install a stack pack from the catalogue",
    "description": "Install a stack pack from the catalogue\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/packs/upload": {
   "post": {
    "operationId": "post_admin_packs_upload",
    "summary": "Upload and install a stack pack archive",
    "description": "Upload and install a stack pack archive\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/octet-stream": {
       "schema": {
        "type": "string",
        "contentEncoding": "binary"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/packs/{id}": {
   "delete": {
    "operationId": "delete_admin_packs_id",
    "summary": "Remove a stack pack",
    "description": "Remove a stack pack\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_admin_packs_id",
    "summary": "Enable, disable or update a stack pack",
    "description": "Enable, disable or update a stack pack\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/packs/{id}/rollback": {
   "post": {
    "operationId": "post_admin_packs_id_rollback",
    "summary": "Roll a stack pack back to its previous version",
    "description": "Roll a stack pack back to its previous version\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/workspaces": {
   "get": {
    "operationId": "get_admin_workspaces",
    "summary": "Workspaces with their members, assets and limits",
    "description": "Workspaces with `member_count`, `asset_count`, `monitored` and `asset_limit` (null: none). `PATCH` takes `name`, `disabled`, `plan` and `asset_limit` (`-1` removes the limit; see asset-limits.md)\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_admin_workspaces",
    "summary": "Create a workspace and name its first admin",
    "description": "Workspaces with `member_count`, `asset_count`, `monitored` and `asset_limit` (null: none). `PATCH` takes `name`, `disabled`, `plan` and `asset_limit` (`-1` removes the limit; see asset-limits.md)\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/workspaces/{id}": {
   "patch": {
    "operationId": "patch_admin_workspaces_id",
    "summary": "Rename, disable or set the plan, limits, read-only state and report mode of a workspace",
    "description": "Workspaces with `member_count`, `asset_count`, `monitored` and `asset_limit` (null: none). `PATCH` takes `name`, `disabled`, `plan`, `asset_limit` and `project_limit` (`-1` removes a limit), `read_only` with `read_only_reason`, and `report_mode` (`full` or `trial`); see asset-limits.md\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/advisories/{key}": {
   "get": {
    "operationId": "get_advisories_key",
    "summary": "Advisories in a group",
    "description": "Advisories in a group\n\nRole: viewer",
    "tags": [
     "Intelligence"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "key",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/agent/actions": {
   "get": {
    "operationId": "get_agent_actions",
    "summary": "Remediation actions waiting for this agent (licensed edition; empty in Community)",
    "description": "Agent fetches approved changes and reports results\n\nRole: host-bound token",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "host-bound token",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/agent/actions/{id}/report": {
   "post": {
    "operationId": "post_agent_actions_id_report",
    "summary": "Report the progress of a remediation action (licensed edition)",
    "description": "Agent fetches approved changes and reports results\n\nRole: host-bound token",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "host-bound token",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/agent/check": {
   "get": {
    "operationId": "get_agent_check",
    "summary": "Whether the agent should collect now (Check again), for the assets its last report went to",
    "description": "The agent's check-again poll: `{\"check\": true, \"poll_seconds\": 45}` when someone asked for a fresh report from one of the listed assets\n\nRole: collector, engineer",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "collector, engineer",
    "parameters": [
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets": {
   "get": {
    "operationId": "get_assets",
    "summary": "List assets",
    "description": "List assets. `reboot_required=true` lists hosts that run older code than is installed. `exposed=true` or `false` filters by `exposed`, the exposure risk scoring uses: `internet_exposed` when set by hand, else what a collector observed (a Kubernetes workload's `exposure`, or for an image the workloads deployed as it). `unfiled=true` lists the assets in no active project. Each asset has `projects`, the active projects it is in that the caller can see\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "environment",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "owner_team_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "reboot_required",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "exposed",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "unfiled",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}": {
   "delete": {
    "operationId": "delete_assets_id",
    "summary": "Delete an asset and its history",
    "description": "Delete an asset and its history\n\nRole: admin",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "get": {
    "operationId": "get_assets_id",
    "summary": "Asset and identifiers",
    "description": "Asset and identifiers\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_assets_id",
    "summary": "Set name, environment, owner, criticality, exposure, tags",
    "description": "Set name, environment, owner, criticality, exposure, tags\n\nRole: engineer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/check": {
   "post": {
    "operationId": "post_assets_id_check",
    "summary": "Check the whole asset again",
    "description": "Check the whole asset again\n\nRole: engineer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/collections": {
   "get": {
    "operationId": "get_assets_id_collections",
    "summary": "The asset's collection history",
    "description": "The asset's collection history\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/coverage": {
   "get": {
    "operationId": "get_assets_id_coverage",
    "summary": "The asset's coverage ledger",
    "description": "Coverage ledger, collection history, relations\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/coverage-summary": {
   "get": {
    "operationId": "get_assets_id_coverage_summary",
    "summary": "How far the asset's findings can be trusted",
    "description": "How far the asset's findings can be trusted: its coverage states with reasons, components by coverage, gap reasons and stale feeds\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/drift": {
   "get": {
    "operationId": "get_assets_id_drift",
    "summary": "Components whose versions differ from another asset",
    "description": "Components whose versions differ from another asset (`with`, or the asset this one is a `replica_of`). Each item is `behind`, `ahead`, `differs`, `only_here` or `only_there`, compared by the component's ecosystem rules\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "with",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/inventory": {
   "get": {
    "operationId": "get_assets_id_inventory",
    "summary": "Components on the asset, with evidence and coverage",
    "description": "Components on the asset, with evidence and coverage (see below)\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "direct",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "include_removed",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "coverage",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/relations": {
   "delete": {
    "operationId": "delete_assets_id_relations",
    "summary": "Remove a relation to another asset",
    "description": "Add or remove `runs_on`, `built_from`, `deployed_as`, `contains`, `depends_on`, `replica_of` (a standby, staging or DR copy that should run the same versions as the target)\n\nRole: engineer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "get": {
    "operationId": "get_assets_id_relations",
    "summary": "The asset's relations to other assets",
    "description": "The asset's relations to other assets\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_assets_id_relations",
    "summary": "Add a relation to another asset",
    "description": "Add or remove `runs_on`, `built_from`, `deployed_as`, `contains`, `depends_on`, `replica_of` (a standby, staging or DR copy that should run the same versions as the target)\n\nRole: engineer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/remediation": {
   "get": {
    "operationId": "get_assets_id_remediation",
    "summary": "Remediation actions for an asset (licensed edition; empty in Community)",
    "description": "Remediation actions for an asset\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/remediation-token": {
   "post": {
    "operationId": "post_assets_id_remediation_token",
    "summary": "Create the host-bound agent token used for remediation (licensed edition)",
    "description": "Collector token bound to this host, required for remediation\n\nRole: admin",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/sbom": {
   "get": {
    "operationId": "get_assets_id_sbom",
    "summary": "CycloneDX 1.6 export",
    "description": "CycloneDX 1.6 export\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "The document",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assets/{id}/stack": {
   "get": {
    "operationId": "get_assets_id_stack",
    "summary": "Everything the asset relies on, followed through relations, with open findings grouped by layer",
    "description": "Everything the asset relies on, followed through relations, with open findings grouped by layer (`web_server`, `os`, `runtime`, `data_store`, `libraries`, `declared`, `managed_service`, `platform`, `other`). For an application this is its hosts, repository, images and dependencies (up to three hops); for a host, the applications running on it; for a cluster, its workloads and their images; for an image, the workloads deployed as it; for a repository, its deployments and their hosts\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assistants": {
   "get": {
    "operationId": "get_assistants",
    "summary": "The caller's connected assistants in every organisation they belong to",
    "description": "The caller's connected assistants in every organisation they belong to: `client_name`, `redirect_host`, `workspace_name`, `project_name`, `role`, `allow_changes`, `created_at`, `last_used_at`. `mcp_url` is the address to add in an assistant, empty while the server has no `STACKURITY_BASE_URL` (assistants are off).\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/assistants/{id}": {
   "delete": {
    "operationId": "delete_assistants_id",
    "summary": "Disconnect one of the caller's assistants",
    "description": "Disconnect one of the caller's assistants: its tokens stop working at once (404 for anyone else's). Audited as `assistant.revoke`\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_assistants_id",
    "summary": "Allow or stop changes by one of the caller's assistants",
    "description": "`{\"allow_changes\": true | false}` for one of the caller's assistants (404 for anyone else's). Audited as `assistant.update`\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/audit": {
   "get": {
    "operationId": "get_audit",
    "summary": "Audit events",
    "description": "Audit events\n\nRole: viewer",
    "tags": [
     "Reports"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "object_type",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "object_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/default-project": {
   "put": {
    "operationId": "put_auth_default_project",
    "summary": "Choose the project the dashboard opens with",
    "description": "`{\"project_id\": N}` (0: all projects): the project the dashboard opens with. `GET /auth/me` returns it as `default_project_id`, with `projects` (the projects the caller can choose), `access` and `project_role`\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/login": {
   "post": {
    "operationId": "post_auth_login",
    "summary": "Sign in with email and password (starts a session)",
    "description": "Session handling\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/logout": {
   "post": {
    "operationId": "post_auth_logout",
    "summary": "Sign out (ends the session)",
    "description": "Session handling\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/me": {
   "get": {
    "operationId": "get_auth_me",
    "summary": "The caller: user, role, organisation, projects and edition",
    "description": "Session handling\n\nRole: any signed-in user or token",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user or token",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/oidc/callback": {
   "get": {
    "operationId": "get_auth_oidc_callback",
    "summary": "Single sign-on callback from the identity provider (licensed edition)",
    "description": "Single sign-on callback from the identity provider (licensed edition)\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/oidc/login": {
   "get": {
    "operationId": "get_auth_oidc_login",
    "summary": "Start single sign-on (licensed edition)",
    "description": "Start single sign-on (licensed edition)\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/password": {
   "post": {
    "operationId": "post_auth_password",
    "summary": "Change your own password (current_password, new_password)",
    "description": "Change your own password (`current_password`, `new_password`). Your other sessions are signed out\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/password-reset": {
   "post": {
    "operationId": "post_auth_password_reset",
    "summary": "Email a password reset link (same answer whether or not the account exists)",
    "description": "Email a password reset link (same answer whether or not the account exists)\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/password-reset/preview": {
   "post": {
    "operationId": "post_auth_password_reset_preview",
    "summary": "Whose account a reset link is for, and how many API tokens it has",
    "description": "Whose account a reset link is for, and how many API tokens it has\n\nRole: none (a reset link's token)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none (a reset link's token)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/password-reset/confirm": {
   "post": {
    "operationId": "post_auth_password_reset_confirm",
    "summary": "Set a new password with a reset link; ends every session",
    "description": "Set a new password with a reset link; ends every session\n\nRole: none (a reset link's token)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none (a reset link's token)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/mfa/verify": {
   "post": {
    "operationId": "post_auth_mfa_verify",
    "summary": "Second step of a password sign-in: a TOTP or recovery code",
    "description": "After `POST /auth/login` answered `mfa_required`: `{\"code\": \"123456\"}` (or a recovery code) with the challenge cookie starts the session\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/mfa": {
   "get": {
    "operationId": "get_auth_mfa",
    "summary": "Your two-factor sign-in status",
    "description": "Your two-factor sign-in status\n\nRole: any signed-in user (session)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user (session)",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "delete": {
    "operationId": "delete_auth_mfa",
    "summary": "Turn off your two-factor sign-in (password)",
    "description": "Turn off your two-factor sign-in (password)\n\nRole: any signed-in user (session)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user (session)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/mfa/totp": {
   "post": {
    "operationId": "post_auth_mfa_totp",
    "summary": "Start setting up TOTP (password): secret, otpauth URL and QR code",
    "description": "Start setting up TOTP (password): secret, otpauth URL and QR code\n\nRole: any signed-in user (session)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user (session)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/mfa/totp/confirm": {
   "post": {
    "operationId": "post_auth_mfa_totp_confirm",
    "summary": "Confirm TOTP with a code; returns ten recovery codes once",
    "description": "Confirm TOTP with a code; returns ten recovery codes once\n\nRole: any signed-in user (session)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user (session)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/mfa/recovery-codes": {
   "post": {
    "operationId": "post_auth_mfa_recovery_codes",
    "summary": "Replace your recovery codes (password)",
    "description": "Replace your recovery codes (password)\n\nRole: any signed-in user (session)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user (session)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/channels": {
   "get": {
    "operationId": "get_channels",
    "summary": "Notification channels",
    "description": "Notification configuration and delivery log\n\nRole: security",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "security",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_channels",
    "summary": "Create a notification channel",
    "description": "Create a notification channel\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/channels/{id}": {
   "delete": {
    "operationId": "delete_channels_id",
    "summary": "Delete a notification channel",
    "description": "Email, Slack, Teams, webhook, Jira, PagerDuty (`pagerduty`, Events API v2) and ServiceNow (`servicenow`, Table API) channels. Jira, PagerDuty and ServiceNow keep one record per incident. Test: Jira and ServiceNow check access without creating anything; PagerDuty triggers a test alert (severity info) and resolves it at once\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_channels_id",
    "summary": "Change a notification channel",
    "description": "Email, Slack, Teams, webhook, Jira, PagerDuty (`pagerduty`, Events API v2) and ServiceNow (`servicenow`, Table API) channels. Jira, PagerDuty and ServiceNow keep one record per incident. Test: Jira and ServiceNow check access without creating anything; PagerDuty triggers a test alert (severity info) and resolves it at once\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/channels/{id}/test": {
   "post": {
    "operationId": "post_channels_id_test",
    "summary": "Send a test message (Jira, ServiceNow: check access only)",
    "description": "Email, Slack, Teams, webhook, Jira, PagerDuty (`pagerduty`, Events API v2) and ServiceNow (`servicenow`, Table API) channels. Jira, PagerDuty and ServiceNow keep one record per incident. Test: Jira and ServiceNow check access without creating anything; PagerDuty triggers a test alert (severity info) and resolves it at once\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/checks": {
   "get": {
    "operationId": "get_checks",
    "summary": "Checks, newest first",
    "description": "Checks, newest first; `open=true` keeps the ones not done\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fix_group",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "open",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/checks/options": {
   "get": {
    "operationId": "get_checks_options",
    "summary": "How each fix group or asset can be checked again",
    "description": "How each fix group (fix_group) or asset (asset_id) can be checked again: on_demand when a check gets a fresh report within minutes, else reason (removed, agent, upload, not_found), with method, host_name and the latest check (last_check). Repeat a parameter or separate values with commas; at most 50.\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "fix_group",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/checks/{id}": {
   "get": {
    "operationId": "get_checks_id",
    "summary": "One check",
    "description": "One check\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/collections/{id}/result": {
   "get": {
    "operationId": "get_collections_id_result",
    "summary": "Whether a submitted collection has been evaluated, and its findings",
    "description": "Whether a submitted collection has been evaluated (`status`: `pending`, `scoring` (matched, findings not prioritised yet), `evaluated` (matched and prioritised), `failed`), then the asset's open findings and its count of `evaluation_gaps`. Used by `stackurity scan --fail-on`\n\nRole: collector (own submissions), engineer+",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "collector (own submissions), engineer+",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/components": {
   "get": {
    "operationId": "get_components",
    "summary": "Components, searchable",
    "description": "Component explorer\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/components/{id}": {
   "get": {
    "operationId": "get_components_id",
    "summary": "One component",
    "description": "Component explorer\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/components/{id}/intel": {
   "get": {
    "operationId": "get_components_id_intel",
    "summary": "Release data (latest stable, publish date, deprecation) and lifecycle cycles",
    "description": "Release data (latest stable, publish date, deprecation) and lifecycle cycles\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/components/{id}/upgrade": {
   "get": {
    "operationId": "get_components_id_upgrade",
    "summary": "An upgrade recommendation for each installed version with open findings",
    "description": "An upgrade recommendation for each installed version with open findings (most findings first, at most 50; `total` counts all), with `version`, `distro` and `asset_count`\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/conflicts": {
   "get": {
    "operationId": "get_conflicts",
    "summary": "Asset identity conflicts",
    "description": "Resolve asset identity conflicts by merging assets. The answer lists `projects_joined` and `grants_moved`, with a `notice`, when the kept asset joins the merged assets' projects or takes their access grants\n\nRole: admin",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/conflicts/{id}/resolve": {
   "post": {
    "operationId": "post_conflicts_id_resolve",
    "summary": "Resolve an identity conflict by merging assets",
    "description": "Resolve asset identity conflicts by merging assets. The answer lists `projects_joined` and `grants_moved`, with a `notice`, when the kept asset joins the merged assets' projects or takes their access grants\n\nRole: admin",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/coverage": {
   "get": {
    "operationId": "get_coverage",
    "summary": "Coverage ledger across assets",
    "description": "Coverage ledger across assets\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "problems",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "description": "One asset",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/deliveries": {
   "get": {
    "operationId": "get_deliveries",
    "summary": "Notification delivery log",
    "description": "Notification configuration and delivery log\n\nRole: security",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "security",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "incident_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "channel_id",
      "in": "query",
      "required": false,
      "description": "One channel",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/deliveries/{id}/retry": {
   "post": {
    "operationId": "post_deliveries_id_retry",
    "summary": "Retry a failed or held delivery",
    "description": "Retry a failed or held delivery\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/enroll": {
   "post": {
    "operationId": "post_enroll",
    "summary": "Exchange a one-time enrollment code for a collector token",
    "description": "Exchange a one-time enrollment code (`{\"code\", \"hostname\"}`) for a collector token and the agent settings chosen with it, including the code's `project_id` (null when it has none). Refusals of a code do not say why. Optional `project_id` (`stackurity enroll --project`) is a check, not a choice: when the code adds hosts to another project or to none, the answer is 403 and the code keeps its use. Servers before 0.10 answer 400 to the unknown field, also without using the code\n\nRole: none (rate limited)",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/enrollments": {
   "get": {
    "operationId": "get_enrollments",
    "summary": "Enrollment codes",
    "description": "Create, list and revoke enrollment codes: `label`, `environment`, `app_dirs`, `discover_apps`, `uses` (1\u2013500, default 1), `ttl_hours` (1\u2013720, default 24), `project_id` (hosts enrolled with the code, and the assets their agent reports, are added to that project when first created). The code is returned once\n\nRole: admin",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_enrollments",
    "summary": "Create an enrollment code (shown once)",
    "description": "Create, list and revoke enrollment codes: `label`, `environment`, `app_dirs`, `discover_apps`, `uses` (1\u2013500, default 1), `ttl_hours` (1\u2013720, default 24), `project_id` (hosts enrolled with the code, and the assets their agent reports, are added to that project when first created). The code is returned once\n\nRole: admin",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/enrollments/{id}": {
   "delete": {
    "operationId": "delete_enrollments_id",
    "summary": "Revoke an enrollment code",
    "description": "Create, list and revoke enrollment codes: `label`, `environment`, `app_dirs`, `discover_apps`, `uses` (1\u2013500, default 1), `ttl_hours` (1\u2013720, default 24), `project_id` (hosts enrolled with the code, and the assets their agent reports, are added to that project when first created). The code is returned once\n\nRole: admin",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/evaluate": {
   "post": {
    "operationId": "post_evaluate",
    "summary": "Queue a full re-evaluation",
    "description": "Queue a full re-evaluation\n\nRole: engineer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "engineer",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/evaluation-gaps": {
   "get": {
    "operationId": "get_evaluation_gaps",
    "summary": "Components that could not be evaluated, one entry per component and reason, with coverage",
    "description": "Components that could not be evaluated, one entry per component and reason, with `coverage` (`unsupported` or `not_evaluated`)\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    },
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ]
   }
  },
  "/facets": {
   "get": {
    "operationId": "get_facets",
    "summary": "Distinct environments, asset kinds and component types",
    "description": "Distinct environments, asset kinds and component types\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/feedback": {
   "post": {
    "operationId": "post_feedback",
    "summary": "Send feedback to the Stackurity team",
    "description": "Send feedback to the Stackurity team: `kind` (`bug`, `idea`, `question`), `message` (up to 5000 characters), optional `email` and `page` (a path). The server adds its version and edition and forwards it to `STACKURITY_FEEDBACK_URL`; answers 202 when delivered, 502 when the feedback service cannot be reached, and 404 when feedback is turned off (`GET /auth/me` then has `feedback_enabled: false`). See network.md\n\nRole: any signed-in user (rate limited, 10 an hour)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user (rate limited, 10 an hour)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/feeds": {
   "get": {
    "operationId": "get_feeds",
    "summary": "Intelligence feeds and their freshness",
    "description": "Intelligence feeds and their freshness\n\nRole: viewer",
    "tags": [
     "Intelligence"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/feeds/{name}": {
   "patch": {
    "operationId": "patch_feeds_name",
    "summary": "Enable or disable a feed (feeds are shared by every workspace)",
    "description": "Enable or disable a feed (feeds are shared by every workspace)\n\nRole: instance admin",
    "tags": [
     "Intelligence"
    ],
    "x-stackurity-role": "instance admin",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/feeds/{name}/refresh": {
   "post": {
    "operationId": "post_feeds_name_refresh",
    "summary": "Queue a manual refresh",
    "description": "Queue a manual refresh\n\nRole: engineer",
    "tags": [
     "Intelligence"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings": {
   "get": {
    "operationId": "get_findings",
    "summary": "Vulnerability and end-of-life findings, SOS, priority, known-exploited and most severe first",
    "description": "Vulnerability and end-of-life findings, SOS, priority, known-exploited and most severe first. `new_within=N` keeps findings first seen in the last N days, `resolved_within=N` those resolved in the last N days (with `status=resolved`), `resolution_kind` (comma-separated: remediated, removed, superseded, advisory_withdrawn, advisory_changed, not_evaluated, other) those closed for that reason, and `sort=asset` orders by asset name first. `epss_min` (0 to 1) keeps findings one of whose CVEs has at least that EPSS. Each finding carries `epss`, `epss_percentile`, `epss_date`, `epss_model_version` and `epss_cve` (null without a score): the highest EPSS among the finding's CVEs (its key, and the CVEs its advisories list as aliases or upstream ids), and the CVE it is for. Also filters by `priority`, `state`, `sos`, `overdue`, assignee (`assignee_user`, `assignee_team`, `assignee=none`), `fix_group`, `incident_id` and `second_check`; paged with `limit` and `offset`\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "severity",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "verification",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "component_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "environment",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "known_exploited",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "epss_min",
      "in": "query",
      "required": false,
      "description": "Vulnerability findings whose CVE has a FIRST EPSS of at least this probability, 0 to 1 (0.1 is 10%)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "key",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "new_within",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "resolved_within",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "resolution_kind",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sort",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "priority",
      "in": "query",
      "required": false,
      "description": "P1 to P4, comma-separated",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "state",
      "in": "query",
      "required": false,
      "description": "active, new, acknowledged, in_progress, suppressed, risk_accepted or regressed",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sos",
      "in": "query",
      "required": false,
      "description": "true: SOS findings only",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "overdue",
      "in": "query",
      "required": false,
      "description": "true: past their fix deadline",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "assignee_user",
      "in": "query",
      "required": false,
      "description": "Assigned to this user id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "assignee_team",
      "in": "query",
      "required": false,
      "description": "Assigned to this team id",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "assignee",
      "in": "query",
      "required": false,
      "description": "none: unassigned findings",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "fix_group",
      "in": "query",
      "required": false,
      "description": "In this fix group (its id)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "incident_id",
      "in": "query",
      "required": false,
      "description": "In this incident",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "second_check",
      "in": "query",
      "required": false,
      "description": "agreed, disagreed or could_not_check",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/actions": {
   "post": {
    "operationId": "post_findings_actions",
    "summary": "Apply a workflow action to up to 500 findings",
    "description": "The same action on up to 500 findings (`ids`)\n\nRole: engineer (security for suppress, accept_risk, ignore, reopen)",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "engineer (security for suppress, accept_risk, ignore, reopen)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/summary": {
   "get": {
    "operationId": "get_findings_summary",
    "summary": "Counts by severity, kind, verification, priority and state, plus SOS, overdue, unassigned, stale feeds,\u2026",
    "description": "Counts by severity, kind, verification, priority and state, plus SOS, overdue, unassigned, stale feeds, evaluation gaps and `resolved_7d` (resolved in the last 7 days)\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/verify": {
   "get": {
    "operationId": "get_findings_verify",
    "summary": "What was resolved, and what is still open, since a time",
    "description": "What changed since `since` (RFC 3339 time or `YYYY-MM-DD`): findings `resolved` since then with their `cause`, `resolution_kind` and whether it `counts_as_remediation` (the totals `remediated` and `closed_not_remediation`, and `resolved_by_kind`), findings that existed then and are `still_open`, `opened_since`, and each asset's last complete collection. `asset_rescanned_since` tells \"fixed\" from \"not scanned again yet\". Lists are capped at `limit` (default 100, max 500) with a `total`\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/{id}": {
   "get": {
    "operationId": "get_findings_id",
    "summary": "One finding, with every source advisory in its group and, while it is open, its upgrade recommendation",
    "description": "One finding (with `resolution_kind` and `resolution_detail` once resolved), with every source advisory in its group and, while it is open, its `upgrade` recommendation\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/{id}/actions": {
   "post": {
    "operationId": "post_findings_id_actions",
    "summary": "Apply a workflow action to a finding",
    "description": "Workflow action, see below\n\nRole: engineer (security for suppress, accept_risk, ignore, reopen)",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "engineer (security for suppress, accept_risk, ignore, reopen)",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/{id}/events": {
   "get": {
    "operationId": "get_findings_id_events",
    "summary": "A finding's workflow history",
    "description": "A finding's workflow history\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/{id}/explain": {
   "get": {
    "operationId": "get_findings_id_explain",
    "summary": "Why the finding matched (why, as in GET /findings/{id}) and why it has its priority",
    "description": "Why the finding matched (`why`, as in `GET /findings/{id}`) and why it has its priority: `risk` (priority, score, each factor with its points, `policy_version`: the risk policy that produced this priority, `current_policy_version` and `policy_changed`, the current thresholds, the SLA for the priority, deadlines, and `epss`: FIRST's EPSS score, percentile, model and date for the CVE, the policy threshold and whether and why it counts, also under `why.epss`), the stored `evidence`, the matched `advisories` (id, feed, severity, dates, an osv.dev link), the freshness of the `feeds` they came from, and the asset's last (complete) `collection` time\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/findings/{id}/upgrade": {
   "get": {
    "operationId": "get_findings_id_upgrade",
    "summary": "The upgrade recommendation for the installed copy the finding is on, covering every open finding on it",
    "description": "The upgrade recommendation for the installed copy the finding is on, covering every open finding on it\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/fix-groups": {
   "get": {
    "operationId": "get_fix_groups",
    "summary": "Fixes (fix groups), most urgent first",
    "description": "Fixes (fix groups), most urgent first. `bucket` is `focus` (a fix exists, SOS or P1, on a production asset or one with no environment), `no_fix`, `old_kernels`, `non_production` or `lower_priority`; every group is in exactly one, checked in that order. `group_by` is `fix` (the same change in several places is one entry with `places`: group, asset, app directory and finding count per place; counts are added up, `unique_issues` is not) or `asset` (one entry per asset); the default is the workspace's setting (`/settings/fix-grouping`)\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "environment",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "bucket",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "group_by",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "fix",
        "asset"
       ]
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/fix-groups/summary": {
   "get": {
    "operationId": "get_fix_groups_summary",
    "summary": "Fix groups and findings per kind and bucket",
    "description": "Groups and findings per kind, plus `focus`: the number of focus groups and their findings, groups and findings per other bucket (`hidden`), and the assets with focus groups. Counts follow `group_by` as `GET /fix-groups` does: grouped by fix, the same fix in several places counts once\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "group_by",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "fix",
        "asset"
       ]
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/fix-groups/{id}": {
   "get": {
    "operationId": "get_fix_groups_id",
    "summary": "One fix group with its findings, paged",
    "description": "One fix group with its findings, paged\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/fix-groups/{id}/applied": {
   "post": {
    "operationId": "post_fix_groups_id_applied",
    "summary": "Mark a fix as applied and request a check",
    "description": "\"I applied this\": the fix's active issues go to `in_progress` with the reason \"applied, waiting for a check\", and a check is requested. Nothing is resolved by this call. Returns `updated` and `check`\n\nRole: engineer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/fix-groups/{id}/check": {
   "post": {
    "operationId": "post_fix_groups_id_check",
    "summary": "Check a fix again",
    "description": "Check again the fix: asks the asset's agent (or a server-side scan) for a fresh report. 201 with the new check, or 200 with the check already waiting for a report\n\nRole: engineer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/ignore-requests": {
   "get": {
    "operationId": "get_ignore_requests",
    "summary": "The approval inbox",
    "description": "The approval inbox. `status` is `pending` (default), `approved`, `declined` or `all`. Security and admin users see every request; others see their own. `can_decide` says which\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_ignore_requests",
    "summary": "Ask to ignore issues",
    "description": "Ask to ignore issues: `finding_ids` (up to 2,000 open findings) or `fix_group` (its active issues), with `reason`, `scope`, `expiry`, `until`, `note` and `mitigation` as for the `ignore` action. Validated like an ignore; 201 with the request\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/ignore-requests/{id}": {
   "get": {
    "operationId": "get_ignore_requests_id",
    "summary": "One request (its requester, or security and admin users)",
    "description": "One request (its requester, or security and admin users)\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/ignore-requests/{id}/decision": {
   "post": {
    "operationId": "post_ignore_requests_id_decision",
    "summary": "Approve or decline a request to ignore issues",
    "description": "`{\"decision\": \"approve\" | \"decline\", \"note\": \"...\"}`. Approval ignores the request's issues that are still open and active, as the decider; 409 when already decided\n\nRole: security",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "security",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/ignore-rules": {
   "get": {
    "operationId": "get_ignore_rules",
    "summary": "Ignore rules in force (or every one with status=all), with the open findings each ignores",
    "description": "Ignore rules in force (or every one with `status=all`), with the open findings each ignores\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/ignore-rules/{id}": {
   "delete": {
    "operationId": "delete_ignore_rules_id",
    "summary": "End an ignore rule",
    "description": "End a rule: the open findings it ignores return to `new`\n\nRole: security",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "security",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/incidents": {
   "get": {
    "operationId": "get_incidents",
    "summary": "Incidents: findings grouped by issue and owner team",
    "description": "Incidents: findings grouped by issue and owner team\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "priority",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "sos",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "team_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "escalated",
      "in": "query",
      "required": false,
      "description": "true: escalated incidents only",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/incidents/{id}": {
   "get": {
    "operationId": "get_incidents_id",
    "summary": "An incident with its findings (and deliveries, for security and above)",
    "description": "An incident with its findings (and deliveries, for security and above)\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/incidents/{id}/actions": {
   "post": {
    "operationId": "post_incidents_id_actions",
    "summary": "Apply a workflow action to every open finding of an incident",
    "description": "Apply an action to every open finding in the incident\n\nRole: engineer (security for suppress, accept_risk, ignore, reopen)",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "engineer (security for suppress, accept_risk, ignore, reopen)",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/ingest": {
   "post": {
    "operationId": "post_ingest",
    "summary": "Submit an ObservationBatch (gzip accepted)",
    "description": "Submit an `ObservationBatch` (gzip accepted). `project_id` files the asset in a project, see Uploads into a project\n\nRole: collector, engineer+",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "collector, engineer+",
    "parameters": [
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "An ObservationBatch (pkg/model), optionally gzip-compressed (Content-Encoding: gzip)",
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ObservationBatch"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations": {
   "get": {
    "operationId": "get_integrations",
    "summary": "Integrations",
    "description": "List integrations, trigger a run\n\nRole: engineer",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "engineer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_integrations",
    "summary": "Create an integration",
    "description": "Create an integration\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations/slack/actions": {
   "post": {
    "operationId": "post_integrations_slack_actions",
    "summary": "Slack's interactivity Request URL (verified by Slack's signature)",
    "description": "Slack's interactivity Request URL. Form-encoded `payload` as Slack sends it, with `X-Slack-Request-Timestamp` and `X-Slack-Signature`. 200 once verified (the answer goes to Slack's `response_url`), 401 for any request that cannot be verified, is older than 5 minutes or was already received, 400 for a verified payload with an unexpected team, user or `response_url`\n\nRole: none: Slack's signature (see Acting from Slack)",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "none: Slack's signature (see Acting from Slack)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/x-www-form-urlencoded": {
       "schema": {
        "type": "object",
        "properties": {
         "payload": {
          "type": "string"
         }
        }
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations/{id}": {
   "delete": {
    "operationId": "delete_integrations_id",
    "summary": "Delete an integration",
    "description": "Manage integrations\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_integrations_id",
    "summary": "Change an integration",
    "description": "Manage integrations\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations/{id}/run": {
   "post": {
    "operationId": "post_integrations_id_run",
    "summary": "Run an integration now",
    "description": "List integrations, trigger a run\n\nRole: engineer",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/inventory": {
   "get": {
    "operationId": "get_inventory",
    "summary": "Where a component is used",
    "description": "Where a component is used\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "component_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "coverage",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Search",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "in": "query",
      "required": false,
      "description": "Component type",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "direct",
      "in": "query",
      "required": false,
      "description": "true or false: direct dependencies only, or transitive only",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "include_removed",
      "in": "query",
      "required": false,
      "description": "true: include removed rows",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "Page size (default 100, at most 500)",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "description": "Items to skip",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/invitations": {
   "get": {
    "operationId": "get_invitations",
    "summary": "Invitations, open and recent",
    "description": "Invitations: open ones, and the others of the last 30 days, with `status` (`pending`, `accepted`, `revoked`, `expired`). Never the link\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_invitations",
    "summary": "Invite someone to the organisation or a project",
    "description": "`{\"email\", \"name\", \"role\", \"project_id\"}` (`project_id` 0: an organisation-wide role). 201 with `invitation` and `emailed`; when the email was not sent, `link` (shown once) and `email_problem`. Inviting the same person to the same project again replaces the open invitation. Someone already a member gets the project role at once (`granted`, `grant`); an organisation-wide invitation for a member is 409\n\nRole: admin (30 an hour per organisation)",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin (30 an hour per organisation)",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/invitations/accept": {
   "post": {
    "operationId": "post_invitations_accept",
    "summary": "Accept an invitation",
    "description": "`{\"token\", \"name\", \"password\"}`. Joins the invitation's organisation with its role (see Invitations); answers `workspace_id`, `project_id`, `role`, `account_created` and `joined`, and the browser session then works in that organisation. 410: the link does not work; 409 `sign_in_required` or `wrong_account`\n\nRole: none, or the invitee's session (rate limited)",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "none, or the invitee's session (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/invitations/preview": {
   "post": {
    "operationId": "post_invitations_preview",
    "summary": "What an invitation link is for",
    "description": "`{\"token\"}`: what the link is for (`workspace`, `project`, `role`, `email`, `invited_by`, `expires_at`, `account_exists`) and `signed_in_as`. 410 for any link that does not work, without saying why\n\nRole: none (rate limited)",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/invitations/{id}": {
   "delete": {
    "operationId": "delete_invitations_id",
    "summary": "Withdraw a pending invitation",
    "description": "Withdraw a pending invitation: its link stops working\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/jobs": {
   "get": {
    "operationId": "get_jobs",
    "summary": "Background job queue",
    "description": "Background job queue\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "state",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/jobs/{id}": {
   "get": {
    "operationId": "get_jobs_id",
    "summary": "Status of one background job",
    "description": "Status of one job, e.g. after *Run now*\n\nRole: engineer",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "engineer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/meta": {
   "get": {
    "operationId": "get_meta",
    "summary": "Version, whether first-time setup is required, and features",
    "description": "Version, whether first-time setup is required, and `features`: what this server supports that an older one would silently ignore. `upload_project` means `POST /ingest` and `POST /sbom/import` honour `project_id` (0.10); `stackurity` checks it before an upload with `--project`\n\nRole: none",
    "tags": [
     "Setup"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/oauth/authorize": {
   "post": {
    "operationId": "post_oauth_authorize",
    "summary": "Allow or deny an assistant's connection (the consent page)",
    "description": "The same parameters with `decision` (`allow` or `deny`), `workspace_id` (the organisation the page showed; 409 if the session switched), `project_id` (0: the whole organisation), `role` and `allow_changes` (default false: read only): answers `redirect`, the client's redirect URI with a single-use `code` (2 minutes) or `error=access_denied`, plus `state` and `iss`. A role above the caller's is 403. Audited as `assistant.authorize`\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/oauth/authorize/preview": {
   "post": {
    "operationId": "post_oauth_authorize_preview",
    "summary": "The consent page's view of an authorization request",
    "description": "The consent page's view of an authorization request (its `response_type`, `client_id`, `redirect_uri`, `code_challenge`, `code_challenge_method`, `state`, `scope`, `resource`): the `client` (name, `redirect_host`), `signed_in_as`, the active `workspace`, the `projects` and the `roles` (up to the caller's own) the person may give. 400 with `error.redirect` (the client's redirect URI with the error) when the request is wrong, or without it when the client or redirect URI cannot be trusted\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/onboarding": {
   "get": {
    "operationId": "get_onboarding",
    "summary": "The first-run flow",
    "description": "The first-run flow: `state` (`new`, `skipped`, `done`), `show_flow` (state `new` and no assets yet), `has_assets`, `project_id` and `project` (chosen in the flow), and `steps` (`project`, `asset`, `notifications`, `invite`), each read from what exists. When every step is done the state becomes `done`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_onboarding",
    "summary": "Set the first-run flow's state and project",
    "description": "`{\"state\": \"new\" | \"skipped\" | \"done\", \"project_id\": N}`; audited as `onboarding.update`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/onboarding/results": {
   "get": {
    "operationId": "get_onboarding_results",
    "summary": "The waiting screen's poll",
    "description": "The waiting screen's poll: assets created since `since` (RFC 3339; default the last 24 hours), newest first, at most 20, in the chosen project (`project_id` or the header). Each has `packages`, `issues` (active), `checked` (its first complete report has been evaluated, so the counts are final) and `fixes_now` (fixes in Home's focus)\n\nRole: viewer",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/openapi.json": {
   "get": {
    "operationId": "get_openapi_json",
    "summary": "This OpenAPI document",
    "description": "This API as an OpenAPI 3.1 document\n\nRole: none",
    "tags": [
     "Setup"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/overview": {
   "get": {
    "operationId": "get_overview",
    "summary": "Inventory, coverage and status counts, including assets by coverage state",
    "description": "Inventory, coverage and status counts, including assets by coverage state (`asset_coverage`) and components by row coverage (`component_coverage`)\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/packs": {
   "get": {
    "operationId": "get_packs",
    "summary": "Stack packs available to this organisation",
    "description": "Stack packs available to this organisation\n\nRole: any signed-in user",
    "tags": [
     "Intelligence"
    ],
    "x-stackurity-role": "any signed-in user",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/packs/{id}/archive": {
   "get": {
    "operationId": "get_packs_id_archive",
    "summary": "Download a stack pack archive",
    "description": "Download a stack pack archive\n\nRole: any signed-in user",
    "tags": [
     "Intelligence"
    ],
    "x-stackurity-role": "any signed-in user",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "The document",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/plugins": {
   "get": {
    "operationId": "get_plugins",
    "summary": "Installed plugins with their declared permissions, credentials and network access",
    "description": "Installed plugins with their declared permissions, credentials and network access\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/project-suggestions": {
   "get": {
    "operationId": "get_project_suggestions",
    "summary": "Groupings proposed from runs_on, built_from and deployed_as relations",
    "description": "Groupings proposed from `runs_on`, `built_from` and `deployed_as` relations: assets in no project related to a project's assets (`project_id`), or related assets all in no project (`suggested_name`). Nothing changes until someone adds the assets; `{\"key\"}` hides one until its assets change\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/project-suggestions/dismiss": {
   "post": {
    "operationId": "post_project_suggestions_dismiss",
    "summary": "Hide a grouping suggestion",
    "description": "Groupings proposed from `runs_on`, `built_from` and `deployed_as` relations: assets in no project related to a project's assets (`project_id`), or related assets all in no project (`suggested_name`). Nothing changes until someone adds the assets; `{\"key\"}` hides one until its assets change\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/projects": {
   "get": {
    "operationId": "get_projects",
    "summary": "Projects the caller can see",
    "description": "Projects the caller can see (members with project access only: theirs, each with their `role`), with `asset_count`; organisation-wide callers also get `unfiled_assets`, the assets in no active project. `archived=true` (admins) includes archived projects\n\nRole: viewer, or any grant",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "viewer, or any grant",
    "parameters": [
     {
      "name": "archived",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_projects",
    "summary": "Create a project",
    "description": "`{\"name\", \"description\", \"asset_ids\"}`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/projects/{id}": {
   "get": {
    "operationId": "get_projects_id",
    "summary": "One project (with its grants, for admins)",
    "description": "A project; for admins also its `grants`\n\nRole: viewer, or a grant on it",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "viewer, or a grant on it",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_projects_id",
    "summary": "Rename, describe, archive or restore a project",
    "description": "`name`, `description`, `archived` (true archives: grants on it stop giving access and routes limited to it stop matching; false restores)\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/projects/{id}/assets": {
   "delete": {
    "operationId": "delete_projects_id_assets",
    "summary": "Remove assets from a project",
    "description": "`{\"asset_ids\": [...]}` (1 to 5000): add or remove assets; returns `changed`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_projects_id_assets",
    "summary": "Add assets to a project",
    "description": "`{\"asset_ids\": [...]}` (1 to 5000): add or remove assets; returns `changed`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/plans": {
   "get": {
    "operationId": "get_remediation_plans",
    "summary": "Remediation plans (licensed edition)",
    "description": "Plans and their per-asset actions\n\nRole: viewer",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/plans/{id}": {
   "get": {
    "operationId": "get_remediation_plans_id",
    "summary": "One remediation plan with its actions (licensed edition)",
    "description": "Plans and their per-asset actions\n\nRole: viewer",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/plans/{id}/decision": {
   "post": {
    "operationId": "post_remediation_plans_id_decision",
    "summary": "Approve or decline a remediation plan (licensed edition)",
    "description": "`{\"decision\": \"approve\" | \"reject\" | \"cancel\", \"note\": \"...\"}`\n\nRole: security (admin for major)",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "security (admin for major)",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/policies": {
   "get": {
    "operationId": "get_remediation_policies",
    "summary": "Remediation policies (licensed edition)",
    "description": "Remediation policies\n\nRole: security",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "security",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_remediation_policies",
    "summary": "Create a remediation policy (licensed edition)",
    "description": "Manage policies (remediation.md)\n\nRole: admin",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/policies/preview": {
   "post": {
    "operationId": "post_remediation_policies_preview",
    "summary": "Preview what a remediation policy would plan (licensed edition)",
    "description": "Which fixable packages and assets a proposed policy would authorise or stop authorising, without saving (remediation.md)\n\nRole: admin",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/policies/{id}": {
   "delete": {
    "operationId": "delete_remediation_policies_id",
    "summary": "Delete a remediation policy (licensed edition)",
    "description": "Manage policies (remediation.md)\n\nRole: admin",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_remediation_policies_id",
    "summary": "Replace a remediation policy (licensed edition)",
    "description": "Manage policies (remediation.md)\n\nRole: admin",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "ee",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/remediation/renovate.json": {
   "get": {
    "operationId": "get_remediation_renovate_json",
    "summary": "Renovate configuration from approved remediation plans (licensed edition)",
    "description": "Renovate rules for approved repository plans\n\nRole: collector, engineer",
    "tags": [
     "Automatic fixes"
    ],
    "x-stackurity-role": "collector, engineer",
    "parameters": [
     {
      "name": "repository",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "mode",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/reports/evidence": {
   "get": {
    "operationId": "get_reports_evidence",
    "summary": "Patch-management evidence for a period (licensed edition)",
    "description": "Patch-management evidence for a period (dates, `to` inclusive; default the last 30 days, at most a year): assets and their collection status, hosts needing a reboot, evaluation gaps, open findings by severity and priority, overdue findings, findings remediated in the period (upgraded, fixed or removed) with the share resolved within their deadline and the median days from first detection to resolution, findings closed without remediation (advisory withdrawn or changed) counted apart, every active exception with its reason, mitigation and expiry, and drift for each `replica_of` pair\n\nRole: viewer",
    "tags": [
     "Reports"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "from",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "to",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/reports/outcomes": {
   "get": {
    "operationId": "get_reports_outcomes",
    "summary": "Remediation outcomes over the last days (1 to 365, default 90)",
    "description": "Remediation outcomes over the last `days` (1 to 365, default 90). `resolved`, time to remedy and SLA count remediated and removed findings only; findings closed with nothing changed on the asset (advisory withdrawn or changed, still affected after an upgrade, no longer evaluated) are counted apart in `closed_not_remediation` by `resolution_kind`\n\nRole: viewer",
    "tags": [
     "Reports"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "days",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/risk-policy": {
   "get": {
    "operationId": "get_risk_policy",
    "summary": "The risk policy: priority weights, thresholds, deadlines and SOS rules",
    "description": "Priority weights, thresholds, deadlines and SOS rules, with the policy `version`. `PUT` replaces the policy (fields left out take their defaults; unknown fields are rejected), returns `version`, `previous_version` and the `changed` fields, and writes a `risk_policy.update` audit event holding the policy before and after. `GET` includes `last_change` (who, when, versions, changed fields; null when never changed)\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_risk_policy",
    "summary": "Replace the risk policy",
    "description": "Priority weights, thresholds, deadlines and SOS rules, with the policy `version`. `PUT` replaces the policy (fields left out take their defaults; unknown fields are rejected), returns `version`, `previous_version` and the `changed` fields, and writes a `risk_policy.update` audit event holding the policy before and after. `GET` includes `last_change` (who, when, versions, changed fields; null when never changed)\n\nRole: admin",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/risk-policy/preview": {
   "post": {
    "operationId": "post_risk_policy_preview",
    "summary": "Preview a risk policy's effect without saving it",
    "description": "Validates a proposed policy like `PUT` and returns its effect on the workspace's open findings without saving anything: `before` / `after` counts per priority, `sos_before` / `sos_after`, `priority_changed` (`raised`, `lowered`), `sos_changed`, `score_changed`, `stored_differs`, and `sample` (at most `sample_limit`, 50) of changed findings with factor deltas (risk.md)\n\nRole: admin",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/routes": {
   "get": {
    "operationId": "get_routes",
    "summary": "Notification routes",
    "description": "Notification configuration and delivery log\n\nRole: security",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "security",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_routes",
    "summary": "Create a notification route",
    "description": "Which incidents go to which channel. `project_ids` limits a route to those projects' assets: its messages count and name only them, and only their collection and coverage problems. For a Jira channel, at most one project (400 otherwise): its issues then describe only that project's part of each incident, see Incidents and notifications. A route to a PagerDuty or ServiceNow channel cannot name projects (400). `events`: any of `urgent`, `new_issues`, `regressed`, `overdue`, `connected`, `problems`, `daily_summary`, `weekly_summary`; `event_channels` (Slack only) sends some events to other Slack channels; `new_min_priority` is the threshold of `new_issues`. `mode` (`urgent_summary`, `urgent_weekly`, `urgent_only`, `daily`, `weekly`) is still accepted and translated to events; returned as one of them or `custom`\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/routes/{id}": {
   "delete": {
    "operationId": "delete_routes_id",
    "summary": "Delete a notification route",
    "description": "Which incidents go to which channel. `project_ids` limits a route to those projects' assets: its messages count and name only them, and only their collection and coverage problems. For a Jira channel, at most one project (400 otherwise): its issues then describe only that project's part of each incident, see Incidents and notifications. A route to a PagerDuty or ServiceNow channel cannot name projects (400). `mode`: `urgent_summary`, `urgent_only`, `daily`, `weekly`\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_routes_id",
    "summary": "Replace a notification route",
    "description": "Which incidents go to which channel. `project_ids` limits a route to those projects' assets: its messages count and name only them, and only their collection and coverage problems. For a Jira channel, at most one project (400 otherwise): its issues then describe only that project's part of each incident, see Incidents and notifications. A route to a PagerDuty or ServiceNow channel cannot name projects (400). `events`: any of `urgent`, `new_issues`, `regressed`, `overdue`, `connected`, `problems`, `daily_summary`, `weekly_summary`; `event_channels` (Slack only) sends some events to other Slack channels; `new_min_priority` is the threshold of `new_issues`. `mode` (`urgent_summary`, `urgent_weekly`, `urgent_only`, `daily`, `weekly`) is still accepted and translated to events; returned as one of them or `custom`\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/sbom/import": {
   "post": {
    "operationId": "post_sbom_import",
    "summary": "Import a CycloneDX or SPDX JSON document",
    "description": "Import a CycloneDX or SPDX JSON document. `project_id` files the asset in a project, see Uploads into a project. A collector token made for a project adds the assets it creates to it\n\nRole: collector, engineer+",
    "tags": [
     "Agents and uploads"
    ],
    "x-stackurity-role": "collector, engineer+",
    "parameters": [
     {
      "name": "asset_name",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_kind",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "environment",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "A CycloneDX or SPDX JSON document",
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/search": {
   "get": {
    "operationId": "get_search",
    "summary": "Search the organisation",
    "description": "Global search of the current workspace, see Search\n\nRole: viewer",
    "tags": [
     "Inventory"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/second-checks": {
   "get": {
    "operationId": "get_second_checks",
    "summary": "The independent second check of high-impact findings",
    "description": "The independent second check of high-impact findings: open findings `agreed`, `disagreed` and `could_not_check`, `pending` (covered, not checked yet), `logged_30d` and the 50 latest logged disagreements with their differences and inputs. `GET /findings?second_check=disagreed` (or `agreed`, `could_not_check`) lists the findings; every finding carries `second_check` and `second_check_reason`, and `GET /findings/summary` counts `second_check_disagreed`. A disagreement never changes a finding's verification, priority, SOS or alerts. Narrowed to the caller's projects\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/secrets": {
   "get": {
    "operationId": "get_secrets",
    "summary": "Stored secrets of the organisation (names only, never values)",
    "description": "Stored secrets of the organisation (names only, never values)\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/secrets/{name}": {
   "delete": {
    "operationId": "delete_secrets_name",
    "summary": "Delete a stored secret",
    "description": "Delete a stored secret\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_secrets_name",
    "summary": "Store a secret (encrypted; never returned)",
    "description": "Store a secret (encrypted; never returned)\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "name",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/setup": {
   "post": {
    "operationId": "post_setup",
    "summary": "Create the first admin",
    "description": "Create the first admin\n\nRole: setup token",
    "tags": [
     "Setup"
    ],
    "x-stackurity-role": "setup token",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/slack/links": {
   "get": {
    "operationId": "get_slack_links",
    "summary": "The caller's linked Slack accounts in the current organisation",
    "description": "The caller's linked Slack accounts in the current organisation (`team_id`, `team_name`, `slack_user_id`, `slack_user_name`, `created_at`, `last_used_at`)\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/slack/links/confirm": {
   "post": {
    "operationId": "post_slack_links_confirm",
    "summary": "Link a Slack account to the caller",
    "description": "`{\"token\"}`: links that Slack account to the caller (single use). 410 as above; 409 when it is linked to another account, which has to unlink it first. API tokens get 403. Audited as `slack_link.create`\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/slack/links/preview": {
   "post": {
    "operationId": "post_slack_links_preview",
    "summary": "The Slack account a one-time link would link",
    "description": "`{\"token\"}` from the link offered in Slack: the Slack account it would link, `linked_to_you`, `linked_to_other`, and `signed_in_as`. 410: the link was used, expired (15 minutes) or belongs to another organisation\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/slack/links/{id}": {
   "delete": {
    "operationId": "delete_slack_links_id",
    "summary": "Unlink one of the caller's Slack accounts (404 for anyone else's)",
    "description": "Unlink one of the caller's Slack accounts (404 for anyone else's). Audited as `slack_link.delete`\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/teams": {
   "get": {
    "operationId": "get_teams",
    "summary": "Teams",
    "description": "Teams\n\nRole: viewer",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_teams",
    "summary": "Create a team",
    "description": "Create a team\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/teams/{id}": {
   "delete": {
    "operationId": "delete_teams_id",
    "summary": "Delete a team",
    "description": "Manage teams and members (members must belong to the workspace)\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_teams_id",
    "summary": "Change a team and its members",
    "description": "Manage teams and members (members must belong to the workspace)\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/tokens": {
   "get": {
    "operationId": "get_tokens",
    "summary": "API tokens (yours; admins: all)",
    "description": "Personal tokens (admins: all tokens and collector tokens). A collector token can name a `project_id`: assets it creates are added to that project (the first-run flow's repository step)\n\nRole: any user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any user",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_tokens",
    "summary": "Create an API token (shown once)",
    "description": "Personal tokens (admins: all tokens and collector tokens). A collector token can name a `project_id`: assets it creates are added to that project (the first-run flow's repository step)\n\nRole: any user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any user",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/tokens/{id}": {
   "delete": {
    "operationId": "delete_tokens_id",
    "summary": "Revoke an API token",
    "description": "Personal tokens (admins: all tokens and collector tokens). A collector token can name a `project_id`: assets it creates are added to that project (the first-run flow's repository step)\n\nRole: any user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any user",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/updates": {
   "get": {
    "operationId": "get_updates",
    "summary": "Whether a newer release is available, and the release check's state",
    "description": "Whether a newer release is available, and the release check's state\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/usage": {
   "get": {
    "operationId": "get_usage",
    "summary": "Monitored assets against the organisation's limit",
    "description": "Monitored assets against the organisation's limit: `monitored`, `limit` (null: none), `at_limit`, `by_kind`, `stale`, `workloads` (not counted), `refused` (the most recent new assets refused at the limit) and `refused_recently` (last 7 days). Also `projects`, `project_limit`, `projects_at_limit`, `read_only` (`since`, `reason`) and `report_mode` (`full`, `trial`). At the limit, requests that would create an asset answer `402` with code `asset_limit`, a new project `402 project_limit`; while read-only, uploads, enrollment, integrations, checks and notifications answer `402 read_only`\n\nRole: viewer (organisation-wide)",
    "tags": [
     "Reports"
    ],
    "x-stackurity-role": "viewer (organisation-wide)",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/users": {
   "get": {
    "operationId": "get_users",
    "summary": "Users of the organisation",
    "description": "Manage users. `role` `none` keeps someone a member with no organisation-wide role (access through projects only); each user has `access`: `organisation` or `projects`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_users",
    "summary": "Add a user to the organisation",
    "description": "Manage users. `role` `none` keeps someone a member with no organisation-wide role (access through projects only); each user has `access`: `organisation` or `projects`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/users/directory": {
   "get": {
    "operationId": "get_users_directory",
    "summary": "Active users (id, email, name) for assignment",
    "description": "Active users (id, email, name) for assignment. Members with project access only get themselves and the people granted one of their projects\n\nRole: engineer",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "engineer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/users/{id}": {
   "delete": {
    "operationId": "delete_users_id",
    "summary": "Remove a member from the organisation",
    "description": "Remove a member from the organisation\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "patch": {
    "operationId": "patch_users_id",
    "summary": "Change a user's role, name or status",
    "description": "Manage users. `role` `none` keeps someone a member with no organisation-wide role (access through projects only); each user has `access`: `organisation` or `projects`\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/users/{id}/mfa": {
   "delete": {
    "operationId": "delete_users_id_mfa",
    "summary": "Reset a member's two-factor sign-in",
    "description": "Reset a member's two-factor sign-in\n\nRole: admin",
    "tags": [
     "Projects and people"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success (usually 204 No Content)"
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/workspaces": {
   "get": {
    "operationId": "get_workspaces",
    "summary": "The organisations (workspaces) the caller belongs to",
    "description": "The organisations (workspaces) the caller belongs to\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/workspaces/{id}/activate": {
   "post": {
    "operationId": "post_workspaces_id_activate",
    "summary": "Switch the session to another of the caller's organisations",
    "description": "Switch the session to another of the caller's organisations\n\nRole: a browser session",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "a browser session",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/signup": {
   "post": {
    "operationId": "post_signup",
    "summary": "Start a sign-up (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. Email, name, organisation, password, challenge token (action `signup`) and `accept_terms`; answers `202 check_email` whatever the email's state\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/signup/verify": {
   "post": {
    "operationId": "post_signup_verify",
    "summary": "Verify a sign-up and create the organisation (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. Uses the emailed token once: creates the account and the organisation on its trial, and starts a session\n\nRole: none",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/billing": {
   "get": {
    "operationId": "get_billing",
    "summary": "Plan and billing of the organisation (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. Status (trial, trial_ended, awaiting_payment, active, past_due, halted, cancelling, cancelled), plans, limits, read-only and deletion dates, `billing_enabled` and `contact_url`\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/billing/subscribe": {
   "post": {
    "operationId": "post_billing_subscribe",
    "summary": "Subscribe to or change a plan (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `plan_id`, `extra_assets`, `country` (asked once; decides the currency), `replace`. Answers `billing`, `payment_url` and `message`. An upgrade the payment provider applies only at the end of the period (a card mandate it changes then) applies now and `message` says what is added to the next invoice. `409 replace_required` for a subscription whose plan the payment provider cannot change (UPI, e-mandate, an Indian card): asked again with `replace: true` it is replaced by the bigger plan, paid on `payment_url`. A browser session only. `503 billing_off` while billing is off; `409` while a payment is being confirmed\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/billing/cancel": {
   "post": {
    "operationId": "post_billing_cancel",
    "summary": "Cancel the plan at the end of the period (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. A browser session only. Then the organisation becomes read-only\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/billing/invoices": {
   "get": {
    "operationId": "get_billing_invoices",
    "summary": "Invoices of the organisation (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. Invoices of this organisation's subscriptions\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/admin/trials/{id}": {
   "put": {
    "operationId": "put_admin_trials_id",
    "summary": "Extend one organisation's trial (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `trial_ends_at` (RFC 3339, in the future and within a year); applied at once and audited `cloud.trial_extended`\n\nRole: instance admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "instance admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/settings/fix-grouping": {
   "get": {
    "operationId": "get_fix_grouping",
    "summary": "How fix lists group the same fix in several places",
    "description": "How fix lists show the same fix in several places: `fix_grouping` is `fix` (one entry per fix listing its places; the default) or `asset` (one entry per asset). `PUT` writes a `settings.update` audit event\n\nRole: viewer",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "viewer",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_fix_grouping",
    "summary": "Change how fix lists group the same fix",
    "description": "How fix lists show the same fix in several places: `fix_grouping` is `fix` (one entry per fix listing its places; the default) or `asset` (one entry per asset). `PUT` writes a `settings.update` audit event\n\nRole: admin",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/settings/security": {
   "get": {
    "operationId": "get_settings_security",
    "summary": "Require two-factor sign-in for all members, and how many have none",
    "description": "Require two-factor sign-in for all members, and how many have none\n\nRole: admin",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "admin",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_settings_security",
    "summary": "Require (or stop requiring) two-factor sign-in for all members",
    "description": "Require (or stop requiring) two-factor sign-in for all members\n\nRole: admin",
    "tags": [
     "Findings and fixes"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/notification-options": {
   "get": {
    "operationId": "get_notification_options",
    "summary": "What notifications this server offers",
    "description": "`slack_app` (Add to Slack is configured), `platform_email` (`enabled`; when enabled also `from`, `max_recipients` and `quota` with `per_minute`, `per_hour`, `per_day`: email sent by Stackurity), `secrets` (stored secrets work) and `base_url` (STACKURITY_BASE_URL is set)\n\nRole: security",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "security",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email-recipients": {
   "get": {
    "operationId": "get_email_recipients",
    "summary": "Addresses that email sent by Stackurity may reach",
    "description": "Addresses named by `stackurity_email` channels that are not members: `email`, `status` (`pending` until the address clicks the confirmation link, then `confirmed`), `requested_at`, `confirmed_at`\n\nRole: security",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "security",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email-recipients/resend": {
   "post": {
    "operationId": "post_email_recipients_resend",
    "summary": "Send a confirmation link again",
    "description": "`{\"email\"}` of a pending address. 202; 429 `too_soon` when one was sent in the last 10 minutes; 404 for an unknown or confirmed address\n\nRole: admin",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email-recipients/confirm": {
   "post": {
    "operationId": "post_email_recipients_confirm",
    "summary": "Confirm an address for email sent by Stackurity",
    "description": "`{\"token\"}` from the emailed link (`/email/confirm#emc_...`). Answers `email` and `organisation`; 410 `link_invalid` when the link is unknown, used or expired (7 days)\n\nRole: none (rate limited)",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations/slack/install": {
   "post": {
    "operationId": "post_integrations_slack_install",
    "summary": "Start Add to Slack",
    "description": "`{\"return_to\": \"/settings/integrations\"}` (a dashboard path). Answers `url`, Slack's consent page with a single-use state bound to the caller and organisation (10 minutes). 404 `not_configured` without the Stackurity Slack app (STACKURITY_SLACK_CLIENT_ID, ...)\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations/slack/oauth": {
   "post": {
    "operationId": "post_integrations_slack_oauth",
    "summary": "Finish Add to Slack",
    "description": "`{\"code\", \"state\"}` from Slack's redirect to `/integrations/slack/oauth/callback`. The state must be the caller's, in this organisation, unused and fresh (400 `slack_state` otherwise). Creates a Slack channel for the webhook Slack returned (201: `channel`, `return_to`, `team_name`, `slack_channel`); 502 `slack_refused` when Slack does not complete the install\n\nRole: admin",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/integrations/slack/events": {
   "post": {
    "operationId": "post_integrations_slack_events",
    "summary": "Slack app events (verified by Slack's signature)",
    "description": "The Stackurity Slack app's Event Subscriptions Request URL: `url_verification`, and `app_uninstalled` or `tokens_revoked`, which disable that Slack workspace's app channels in every organisation and delete their webhooks and tokens. 401 for a request the app's signing secret does not verify or older than 5 minutes; 404 without the app\n\nRole: none: Slack's signature (the app's signing secret)",
    "tags": [
     "Integrations"
    ],
    "x-stackurity-role": "none: Slack's signature (the app's signing secret)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email-recipients/block": {
   "post": {
    "operationId": "post_email_recipients_block",
    "summary": "Never email this address again",
    "description": "`{\"token\"}` from a confirmation email's \"Never email me again\" link (`/email/block#emc_...`): the address is blocked for every organisation on the server and its pending requests removed. Answers `email`; 410 `link_invalid`\n\nRole: none (rate limited)",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email/unsubscribe": {
   "post": {
    "operationId": "post_email_unsubscribe",
    "summary": "Stop email sent by Stackurity to an address",
    "description": "`{\"token\"}` from an email's \"Stop these emails\" link (`/email/unsubscribe#...`), signed for one organisation and address: the address is taken out of that organisation's `stackurity_email` channels. Answers `email` and `organisation`; 410 `link_invalid`. Mail clients use the one-click address in the `List-Unsubscribe` header (RFC 8058), `POST /email/unsubscribe/one-click?t=...`, outside /api/v1\n\nRole: none (rate limited)",
    "tags": [
     "Notifications"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/sso": {
   "get": {
    "operationId": "get_sso",
    "summary": "The organisation's own single sign-on (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `available` (the plan includes it), `config` (provider, attribute mapping, `version`, `tested_version`, `test_result`, `enabled`, `require_sso`, `link_existing`), `service_provider` (`entity_id`, `acs_url`, `metadata_url`, `login_url`), `domains`, `owner_id`\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_sso",
    "summary": "Save the organisation's SAML identity provider (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `idp_metadata_url` (https) or `idp_metadata` (XML; neither keeps the saved one), `label`, `email_attribute`, `name_attribute`, `groups_attribute`, `role_map`, `default_role`, `link_existing`. The metadata is checked at once. A save is a new version and switches single sign-on off until a test passes. `402 plan_required` without the plan\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "delete": {
    "operationId": "delete_sso",
    "summary": "Remove the organisation's single sign-on (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. Removes the provider and switches single sign-on off\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/sso/state": {
   "put": {
    "operationId": "put_sso_state",
    "summary": "Switch the organisation's single sign-on on or off (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `enabled`, `require_sso`. Switching on needs a passed test of the current version and a verified domain; requiring it needs it on. The owner can always sign in with a password\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/sso/domains": {
   "post": {
    "operationId": "post_sso_domains",
    "summary": "Claim an email domain for single sign-on (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `domain`. Answers the TXT `record_name` and `record_value` that prove it\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/sso/domains/{id}/verify": {
   "post": {
    "operationId": "post_sso_domains_id_verify",
    "summary": "Verify a claimed domain by its DNS TXT record (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `409` when another organisation verified the domain first\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/sso/domains/{id}": {
   "delete": {
    "operationId": "delete_sso_domains_id",
    "summary": "Remove a claimed domain (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. Sign-ins with the domain's addresses stop\n\nRole: admin",
    "tags": [
     "Instance administration"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/sso/discover": {
   "post": {
    "operationId": "post_auth_sso_discover",
    "summary": "Find an organisation's single sign-on from an email (hosted edition)",
    "description": "Stackurity Cloud (hosted) only. `email`. Answers `login_url` and `label` for the organisation that verified the address's domain, if its single sign-on is on; otherwise 404\n\nRole: anyone",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "anyone",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "x-stackurity-edition": "cloud",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/auth/email-preferences": {
   "get": {
    "operationId": "get_auth_email_preferences",
    "summary": "Your bulk email preferences (hosted installations)",
    "description": "Your choices for bulk email: `categories` (`marketing`, `vulnerability_news`) with `subscribed`, `source` and `changed_at` of the last change, `label` and `description`; and `locked`, the email that cannot be turned off here. 404 on servers that send no bulk email (`email_preferences` in `GET /meta`)\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "put": {
    "operationId": "put_auth_email_preferences",
    "summary": "Change your bulk email preferences",
    "description": "`{\"marketing\": false}`, `{\"vulnerability_news\": true}` or both: changes your choices at once and answers as `GET`. Subscribing again lifts a suppression of your address for that category\n\nRole: any signed-in user",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "any signed-in user",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email/preferences": {
   "post": {
    "operationId": "post_email_preferences",
    "summary": "Open the bulk email preference page from a signed link",
    "description": "`{\"token\"}` from a bulk email's link (`/email/preferences#...`). Changes nothing. Answers `kind` (`preferences` or `unsubscribe`), `email` (partly hidden), `categories` and `locked`; an unsubscribe link answers its `category` only. 410 `link_expired` or `link_invalid`\n\nRole: none (rate limited)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/email/preferences/update": {
   "post": {
    "operationId": "post_email_preferences_update",
    "summary": "Change bulk email preferences from a signed link",
    "description": "`{\"token\", \"marketing\"?, \"vulnerability_news\"?}`. An unsubscribe link can only set its own category to `false` (403 otherwise); an Email preferences link can change both. Mail clients use the one-click address in the `List-Unsubscribe` header (RFC 8058), `POST /email/preferences/one-click?t=...`, outside /api/v1\n\nRole: none (rate limited)",
    "tags": [
     "Account"
    ],
    "x-stackurity-role": "none (rate limited)",
    "security": [],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/import": {
   "post": {
    "operationId": "post_vex_import",
    "summary": "Import a VEX document",
    "description": "The body is an OpenVEX or CycloneDX VEX document (or a CycloneDX BOM with VEX embedded), plain or as a DSSE envelope or Sigstore bundle; at most 16 MiB. `source_id` names a source, `asset_id` or `project_id` limits matching, `filename` is recorded. not_affected statements wait in the approval inbox unless the source is trusted to apply and every pin held. Answers what matched, what waits, what applied and why statements did not match\n\nRole: engineer+",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "engineer+",
    "parameters": [
     {
      "name": "source_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "filename",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "description": "The VEX document",
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/documents": {
   "get": {
    "operationId": "get_vex_documents",
    "summary": "Imported VEX documents",
    "description": "Imported documents, newest first, paged\n\nRole: viewer",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/documents/{id}": {
   "get": {
    "operationId": "get_vex_documents_id",
    "summary": "One imported VEX document",
    "description": "One document\n\nRole: viewer",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/documents/{id}/statements": {
   "get": {
    "operationId": "get_vex_documents_id_statements",
    "summary": "A VEX document's statements",
    "description": "Statements with what each matched, its problems and its approval request. `outcome`: matched, unmatched or pending\n\nRole: viewer",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "outcome",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/documents/{id}/decision": {
   "post": {
    "operationId": "post_vex_documents_id_decision",
    "summary": "Approve or decline a VEX document's pending statements",
    "description": "`{\"decision\": \"approve\" | \"decline\", \"note\": \"...\"}` for every pending request of the document; organisation-wide security or admin only\n\nRole: security",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "security",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/sources": {
   "get": {
    "operationId": "get_vex_sources",
    "summary": "VEX sources",
    "description": "Sources and how far each is trusted\n\nRole: security",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "security",
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "post": {
    "operationId": "post_vex_sources",
    "summary": "Add a VEX source",
    "description": "`name`, `auto_apply`, `token_id`, `public_key` (PEM). auto_apply needs a public key or a token\n\nRole: admin",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "admin",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/sources/{id}": {
   "patch": {
    "operationId": "patch_vex_sources_id",
    "summary": "Change a VEX source",
    "description": "Changes the fields sent; `token_id: 0` and `public_key: \"\"` remove a pin\n\nRole: admin",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   },
   "delete": {
    "operationId": "delete_vex_sources_id",
    "summary": "Remove a VEX source",
    "description": "Its documents keep its name\n\nRole: admin",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "admin",
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "Success",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  },
  "/vex/export": {
   "get": {
    "operationId": "get_vex_export",
    "summary": "Export decisions as VEX",
    "description": "False positives, mitigations and imported statements about open issues. `format`: openvex (default) or cyclonedx; `asset_id` or `project_id` narrows it\n\nRole: viewer",
    "tags": [
     "VEX"
    ],
    "x-stackurity-role": "viewer",
    "parameters": [
     {
      "name": "format",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "asset_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "2XX": {
      "description": "The document",
      "content": {
       "application/octet-stream": {
        "schema": {
         "type": "string"
        }
       }
      }
     },
     "4XX": {
      "$ref": "#/components/responses/Error"
     },
     "5XX": {
      "$ref": "#/components/responses/Error"
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearerToken": {
    "type": "http",
    "scheme": "bearer",
    "description": "An API token (stk_...) from Settings, API tokens, or a collector token. A user's token never acts above its owner's current role."
   },
   "session": {
    "type": "apiKey",
    "in": "cookie",
    "name": "stackurity_session",
    "description": "The dashboard's session (POST /auth/login). Requests with the cookie that change state must send X-Stackurity-CSRF: 1."
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "required": [
     "error"
    ],
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string",
        "examples": [
         "invalid",
         "not_found",
         "forbidden"
        ]
       },
       "message": {
        "type": "string"
       },
       "details": {
        "type": "array",
        "items": {
         "type": "string"
        }
       }
      }
     }
    }
   },
   "ObservationBatch": {
    "type": "object",
    "description": "What a collector observed on one asset (pkg/model.ObservationBatch)",
    "required": [
     "schema_version",
     "collector",
     "asset",
     "observations"
    ],
    "properties": {
     "schema_version": {
      "type": "string"
     },
     "collector": {
      "type": "object"
     },
     "asset": {
      "type": "object"
     },
     "observations": {
      "type": "array",
      "items": {
       "type": "object"
      }
     },
     "complete": {
      "type": "boolean"
     }
    }
   }
  },
  "responses": {
   "Error": {
    "description": "An error",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   }
  }
 }
}
