{"openapi": "3.1.0", "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema", "info": {"title": "PatchFirst owner API", "version": "1.0.0", "description": "Personal Bearer tokens are created in the account dashboard after confirming the current password. 120 requests/minute/account; refresh: 10/minute/account. Limits are shared across the account’s tokens and API/MCP requests. Tokens never belong in URLs. Cross-origin browser access is disabled. Additive fields may appear; existing fields retain their v1 meanings and types."}, "servers": [{"url": "/"}], "paths": {"/v1/openapi.json": {"get": {"operationId": "openapi", "summary": "OpenAPI 3.1 document", "security": [], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object"}}}}}}}, "/.well-known/oauth-protected-resource": {"get": {"operationId": "protectedResourceMetadata", "summary": "Static Bearer token resource metadata", "security": [], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProtectedResourceMetadata"}}}}}}}, "/v1/me/fleets": {"get": {"operationId": "listFleets", "summary": "List the token owner’s fleets", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"fleets": {"type": "array", "items": {"$ref": "#/components/schemas/Fleet"}}}, "required": ["fleets"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}}}, "/v1/me/fleets/{fleet}/servers": {"get": {"operationId": "listServers", "summary": "List readable paid servers", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"anyOf": [{"type": "object", "properties": {"servers": {"type": "array", "items": {"$ref": "#/components/schemas/Server"}}}, "required": ["servers"]}, {"$ref": "#/components/schemas/ServerPage"}]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "parameters": [{"in": "query", "name": "limit", "required": false, "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 25}, "description": "Items per page. Adding limit or offset opts into pagination."}, {"in": "query", "name": "offset", "required": false, "schema": {"type": "integer", "minimum": 0, "default": 0}, "description": "Starting index; use the previous page’s next value to continue."}, {"in": "query", "name": "cursor", "required": false, "schema": {"type": "string"}, "description": "Pass next_cursor unchanged. Contains report version; 409 stale means the report changed: restart pagination."}, {"name": "fleet", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}], "description": "Requests without limit or offset retain the existing servers array response. With either parameter, returns a page with total, limit, offset, next and truncated. Repeat with offset=next until next is null."}}, "/v1/me/fleets/{fleet}/report": {"get": {"operationId": "fleetReport", "summary": "Fleet findings and rating", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"anyOf": [{"$ref": "#/components/schemas/FleetReport"}, {"$ref": "#/components/schemas/FleetSummary"}, {"$ref": "#/components/schemas/FleetReportPage"}]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "parameters": [{"in": "query", "name": "view", "required": false, "schema": {"type": "string", "enum": ["summary", "full", "dashboard"]}, "description": "summary returns ratings, P0–P3 and KEV totals, urgent findings and continuation. dashboard returns the compact cabinet report. full without limit/offset/section preserves the complete report."}, {"in": "query", "name": "section", "required": false, "schema": {"type": "string", "enum": ["assets", "findings", "pending_assets"], "default": "assets"}, "description": "In full view: servers without nested findings, findings with server identifiers, or pending servers."}, {"in": "query", "name": "urgent_only", "required": false, "schema": {"type": "boolean", "default": false}, "description": "Only P0 or KEV findings; requires full view and findings section."}, {"in": "query", "name": "limit", "required": false, "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 25}, "description": "Items per page. Adding limit or offset opts into pagination."}, {"in": "query", "name": "offset", "required": false, "schema": {"type": "integer", "minimum": 0, "default": 0}, "description": "Starting index; use the previous page’s next value to continue."}, {"in": "query", "name": "cursor", "required": false, "schema": {"type": "string"}, "description": "Pass next_cursor unchanged. Contains report version; 409 stale means the report changed: restart pagination."}, {"name": "fleet", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}], "description": "Requests without new query parameters retain the existing full FleetReport format. Use view=summary for a compact overview or view=full with section=assets or section=findings or section=pending_assets for details. Pages include total, limit, offset, next and truncated. Keep fleet, view and section unchanged and pass next_cursor as cursor. A stale cursor returns 409: restart pagination. summary with section returns 400. Numeric next/offset remains available. MCP findings are compact; use finding_details by id and version for full data."}}, "/v1/me/fleets/{fleet}/servers/{server}/report": {"get": {"operationId": "serverReport", "summary": "Server findings and rating", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ServerReport"}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "parameters": [{"name": "fleet", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "server", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}]}}, "/v1/me/fleets/{fleet}/servers/{server}/history": {"get": {"operationId": "ratingHistory", "summary": "Persisted rating history", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"history": {"type": "array", "items": {"$ref": "#/components/schemas/HistoryEntry"}}}, "required": ["history"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "parameters": [{"name": "fleet", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}, {"name": "server", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}]}}, "/v1/me/fleets/{fleet}/refresh": {"post": {"operationId": "refreshFleet", "summary": "Start recalculation with current paid monitoring", "security": [{"bearerAuth": []}], "responses": {"202": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"started": {"type": "boolean"}, "hosts": {"type": "integer"}}, "required": ["started", "hosts"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "x-required-scope": "write", "parameters": [{"name": "fleet", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}]}}, "/v1/me/cves/{cve}": {"get": {"operationId": "cveDetails", "summary": "CVE record and exploitation signals", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CVE"}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "description": "Requires active paid monitoring. Archive access is limited to saved report snapshots; it does not provide current CVE records, KEV, EPSS, exploits, sightings or mentions.", "parameters": [{"name": "cve", "in": "path", "required": true, "schema": {"type": "string", "pattern": "^CVE-\\d{4}-\\d{4,7}$"}}]}}, "/v1/account/api-tokens": {"delete": {"operationId": "revokeAllAPITokens", "summary": "Revoke all API tokens without signing out", "security": [{"accountSession": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"ok": {"const": true}}, "required": ["ok"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}}, "get": {"operationId": "listAPITokens", "summary": "List token metadata; secrets are never returned again", "security": [{"accountSession": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"tokens": {"type": "array", "items": {"$ref": "#/components/schemas/APIToken"}}}, "required": ["tokens"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}}, "post": {"operationId": "createAPIToken", "summary": "Create a token and show its secret once", "security": [{"accountSession": []}], "responses": {"201": {"description": "Success", "content": {"application/json": {"schema": {"allOf": [{"$ref": "#/components/schemas/APIToken"}, {"type": "object", "properties": {"token": {"type": "string"}}, "required": ["token"]}]}}}}, "409": {"description": "Limit of 50 active tokens reached.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 64}, "scope": {"type": "string", "enum": ["read", "write"]}, "expires_in_days": {"type": "integer", "minimum": 1, "maximum": 365}, "host_ids": {"type": ["array", "null"], "items": {"type": "string", "format": "uuid"}, "description": "null (default): all current and future servers. An explicit list limits a read token; [] grants no server data. Deleted servers are removed."}, "password": {"type": "string", "writeOnly": true, "description": "Current account password; required to confirm token creation."}}, "required": ["name", "scope", "expires_in_days", "password"]}}}}, "description": "Confirm the current account password to create a token. All API tokens are revoked on password change, password recovery or an explicit revoke-all action. Signing out preserves API tokens. Revocation metadata remains visible in the dashboard."}}, "/v1/account/api-tokens/{token_id}": {"delete": {"operationId": "revokeAPIToken", "summary": "Revoke an owned token", "security": [{"accountSession": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"ok": {"const": true}}, "required": ["ok"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "parameters": [{"name": "token_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}]}, "patch": {"operationId": "updateAPITokenServers", "summary": "Change the server selection of an owned read token", "security": [{"accountSession": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/APIToken"}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"host_ids": {"type": ["array", "null"], "items": {"type": "string", "format": "uuid"}, "description": "null (default): all current and future servers. An explicit list limits a read token; [] grants no server data. Deleted servers are removed."}, "password": {"type": "string", "writeOnly": true, "description": "Current account password; required when expanding server access."}}, "required": ["host_ids"]}}}}, "description": "Only the owner account session can change server access. Bearer tokens cannot edit their own scope. Expanding access beyond the previous list (including null for all servers) requires the current password; narrowing does not. All selected server IDs must belong to the account fleet. Omitted creation scope or explicit null keeps all-server access.", "parameters": [{"name": "token_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}]}}, "/v1/account/api-tokens/{token_id}/usage": {"get": {"operationId": "apiTokenUsage", "summary": "Usage metadata without request or response bodies", "security": [{"accountSession": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"type": "object", "properties": {"usage": {"type": "array", "items": {"$ref": "#/components/schemas/TokenUsage"}}}, "required": ["usage"]}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}}, "parameters": [{"name": "token_id", "in": "path", "required": true, "schema": {"type": "string", "format": "uuid"}}]}}, "/v1/mcp": {"post": {"operationId": "mcp", "summary": "MCP 2025-06-18 over stateless Streamable HTTP", "security": [{"bearerAuth": []}], "responses": {"200": {"description": "Success", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JSONRPCResponse"}}}}, "409": {"description": "Report updated; restart pagination with a fresh cursor.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "400": {"description": "Invalid input or a token in the URL; use the Authorization header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired or revoked token.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"WWW-Authenticate": {"schema": {"type": "string"}, "description": "Bearer challenge with resource_metadata pointing to /.well-known/oauth-protected-resource."}}}, "402": {"description": "Active paid monitoring required for current CVE details and recalculation. Archive access includes only saved report snapshots under billing rules.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Insufficient write scope or invalid request origin.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Resource missing or belongs to another owner.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Rate limit exceeded. Retry after the Retry-After header.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"schema": {"type": "integer"}, "description": "Seconds until retry."}}}, "202": {"description": "Accepted notification, no response body."}, "406": {"description": "Accept must include application/json and text/event-stream.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "415": {"description": "Content-Type must be application/json.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/JSONRPCRequest"}}}}, "parameters": [{"in": "header", "name": "MCP-Protocol-Version", "required": false, "schema": {"const": "2025-06-18"}, "description": "Required on requests after initialize; initialize negotiates the version."}], "description": "Send Accept: application/json, text/event-stream and Content-Type: application/json. Supports initialize, notifications/initialized, ping, tools/list and tools/call. Tool execution errors, including payment and refresh limits, use HTTP 200 with result.isError. HTTP 402/429 apply to transport admission checks before tool execution. Tools: list_servers, server_report, fleet_report, cve_details, patch_first. The refresh_fleet tool takes a fleet UUID, requires write scope and active paid monitoring, and shares the separate refresh limit of 10/minute/account with the API. Only static Bearer tokens issued in the dashboard are supported; no OAuth authorization server. No server-side session ID or server-initiated SSE stream is required."}, "get": {"operationId": "mcpStreamUnsupported", "summary": "Server initiated SSE is not provided", "security": [], "responses": {"405": {"description": "Method not allowed. Use POST.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Allow": {"schema": {"type": "string", "const": "POST"}}}}}}}}, "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "PatchFirst personal API token", "description": "Only static Bearer tokens issued in the account dashboard are supported; no OAuth authorization server. Discover resource and dashboard URLs at /.well-known/oauth-protected-resource."}, "accountSession": {"type": "apiKey", "in": "cookie", "name": "psr_s", "description": "Dashboard session only; state changes also require a same-origin Origin header and X-PSR: 1."}}, "schemas": {"Error": {"type": "object", "properties": {"error": {"type": "string"}, "code": {"type": "string"}}, "required": ["error", "code"]}, "Fleet": {"type": "object", "properties": {"id": {"type": "string", "format": "uuid"}, "created_at": {"type": "number", "description": "Unix timestamp in seconds (UTC)."}}, "required": ["id", "created_at"]}, "Server": {"type": "object", "properties": {"id": {"type": "string", "format": "uuid"}, "name": {"type": "string", "description": "Owner-chosen public alias or an opaque identifier. Encrypted names are never decrypted by the service."}, "name_kind": {"type": "string", "enum": ["alias", "opaque"]}, "updated_at": {"type": "number", "description": "Unix timestamp in seconds (UTC)."}, "score": {"type": ["number", "null"]}, "grade": {"type": "string"}, "global_score": {"type": ["number", "null"], "minimum": 0, "maximum": 100}, "global_grade": {"type": "string"}, "coverage": {"$ref": "#/components/schemas/Coverage"}}, "required": ["id", "name", "name_kind", "updated_at", "score", "grade", "global_score", "global_grade", "coverage"]}, "Counts": {"type": "object", "properties": {"P0": {"type": "integer", "minimum": 0}, "P1": {"type": "integer", "minimum": 0}, "P2": {"type": "integer", "minimum": 0}, "P3": {"type": "integer", "minimum": 0}}, "required": ["P0", "P1", "P2", "P3"]}, "FindingCVE": {"type": "object", "properties": {"cve": {"type": "string"}, "risk": {"type": "number"}, "severity": {"type": "number"}, "tags": {"type": "array", "items": {"type": "string"}}}, "required": ["cve", "risk", "severity", "tags"]}, "ExposureReason": {"type": "object", "properties": {"basis": {"type": "string", "enum": ["host", "service"], "description": "service means inventory proves the association; host means it does not."}, "services": {"type": "array", "items": {"type": "object", "properties": {"category": {"type": "string"}, "program": {"type": "string"}}, "required": ["category", "program"]}}}, "required": ["basis", "services"]}, "Finding": {"type": "object", "properties": {"priority": {"type": "string", "enum": ["P0", "P1", "P2", "P3"]}, "risk": {"type": ["number", "null"]}, "component": {"type": ["string", "null"]}, "version": {"type": ["string", "null"]}, "kind": {"type": ["string", "null"]}, "where": {"type": ["string", "null"]}, "exposure": {"type": ["string", "null"]}, "fix": {"type": ["string", "null"]}, "pro_only": {"type": ["boolean", "null"]}, "pro_rest": {"type": ["string", "null"]}, "unfixed": {"type": ["boolean", "null"]}, "ncves": {"type": ["integer", "null"]}, "tags": {"type": ["array", "null"], "items": {"type": "string"}}, "note": {"type": ["string", "null"]}, "dev": {"type": ["boolean", "null"]}, "category": {"type": ["string", "null"]}, "program": {"type": ["string", "null"]}, "exposure_reason": {"$ref": "#/components/schemas/ExposureReason"}, "top": {"type": "array", "items": {"$ref": "#/components/schemas/FindingCVE"}}, "action": {"type": "string", "description": "Recommended update, mitigation or reboot."}}, "required": ["priority", "component", "version", "fix", "top", "action"]}, "Coverage": {"type": "object", "properties": {"checked": {"type": "integer", "minimum": 0}, "total": {"type": "integer", "minimum": 0}}, "required": ["checked", "total"]}, "ServerReport": {"type": "object", "properties": {"id": {"type": "string", "format": "uuid"}, "name": {"type": "string"}, "name_kind": {"type": "string", "enum": ["alias", "opaque"]}, "kind": {"type": "string"}, "title": {"type": "string"}, "score": {"type": ["number", "null"]}, "grade": {"type": "string"}, "global_score": {"type": ["number", "null"], "minimum": 0, "maximum": 100}, "global_grade": {"type": "string"}, "coverage": {"$ref": "#/components/schemas/Coverage"}, "counts": {"$ref": "#/components/schemas/Counts"}, "findings": {"type": "array", "items": {"$ref": "#/components/schemas/Finding"}}, "computed_at": {"type": ["string", "null"]}, "received_at": {"type": ["number", "null"]}, "rating_complete": {"type": "boolean"}, "complete": {"type": "boolean"}, "rating_status": {"type": "string"}, "reasons": {"type": "array", "items": {"type": "string"}}, "blind": {"type": "array", "items": {"type": "string"}}, "tags": {"type": "array", "items": {"type": "string"}}, "terms": {"type": "array", "items": {"type": "string"}}, "error": {"type": "string"}, "public_services": {"type": "array", "items": {"type": "object"}}}, "required": ["id", "name", "name_kind", "score", "grade", "global_score", "global_grade", "coverage", "counts", "findings"]}, "FleetReport": {"type": "object", "properties": {"score": {"type": "number"}, "grade": {"type": "string"}, "global_score": {"type": ["number", "null"], "minimum": 0, "maximum": 100}, "global_grade": {"type": "string"}, "coverage": {"$ref": "#/components/schemas/Coverage"}, "counts": {"$ref": "#/components/schemas/Counts"}, "assets": {"type": "array", "items": {"$ref": "#/components/schemas/ServerReport"}}, "pending_assets": {"type": "array", "items": {"type": "object"}}, "rating_complete": {"type": "boolean"}, "complete": {"type": "boolean"}, "rating_status": {"type": "string"}, "reasons": {"type": "array", "items": {"type": "string"}}, "meta": {"type": "object"}, "recomputing": {"type": "boolean"}}, "required": ["score", "grade", "global_score", "global_grade", "coverage", "counts", "assets"]}, "HistoryEntry": {"type": "object", "properties": {"recorded_at": {"type": "number", "description": "Unix timestamp in seconds (UTC)."}, "computed_at": {"type": ["string", "null"]}, "score": {"type": ["number", "null"]}, "grade": {"type": "string"}, "global_score": {"type": ["number", "null"], "minimum": 0, "maximum": 100}, "global_grade": {"type": "string"}, "coverage": {"$ref": "#/components/schemas/Coverage"}, "counts": {"$ref": "#/components/schemas/Counts"}}, "required": ["recorded_at", "computed_at", "score", "grade", "global_score", "global_grade", "coverage", "counts"]}, "CVE": {"type": "object", "properties": {"cve": {"type": "string"}, "record": {"type": ["object", "null"]}, "kev": {"type": ["object", "null"]}, "epss": {"anyOf": [{"type": "object", "properties": {"score": {"type": "number"}, "percentile": {"type": "number"}}, "required": ["score", "percentile"]}, {"type": "null"}]}, "exploits": {"type": "array", "items": {}}, "sightings": {"type": "array", "items": {"type": "string"}}, "mentions": {"type": "array", "items": {"type": "object"}}}, "required": ["cve", "record", "kev", "epss", "exploits", "sightings", "mentions"]}, "APIToken": {"type": "object", "properties": {"id": {"type": "string", "format": "uuid"}, "name": {"type": "string"}, "scope": {"type": "string", "enum": ["read", "write"]}, "host_ids": {"type": ["array", "null"], "items": {"type": "string", "format": "uuid"}, "description": "null (default): all current and future servers. An explicit list limits a read token; [] grants no server data. Deleted servers are removed."}, "created_at": {"type": "number", "description": "Unix timestamp in seconds (UTC)."}, "expires_at": {"type": "number", "description": "Unix timestamp in seconds (UTC)."}, "revoked_at": {"type": ["number", "null"]}, "revoked_reason": {"type": ["string", "null"], "enum": ["password_changed", "logout_all", "service_rollback", null]}, "last_used_at": {"type": ["number", "null"]}}, "required": ["id", "name", "scope", "created_at", "expires_at"]}, "TokenUsage": {"type": "object", "properties": {"used_at": {"type": "number", "description": "Unix timestamp in seconds (UTC)."}, "method": {"type": "string"}, "path": {"type": "string"}, "status": {"type": "integer"}}, "required": ["used_at", "method", "path", "status"]}, "JSONRPCRequest": {"type": "object", "properties": {"jsonrpc": {"const": "2.0"}, "id": {"type": ["string", "number"]}, "method": {"type": "string"}, "params": {"type": "object"}}, "required": ["jsonrpc", "method"]}, "JSONRPCResponse": {"type": "object", "properties": {"jsonrpc": {"const": "2.0"}, "id": {"type": ["string", "number", "null"]}, "result": {}, "error": {"type": "object"}}, "required": ["jsonrpc", "id"]}, "ProtectedResourceMetadata": {"type": "object", "properties": {"resource": {"type": "string", "format": "uri"}, "resource_name": {"type": "string"}, "bearer_methods_supported": {"type": "array", "items": {"const": "header"}}, "resource_documentation": {"type": "string", "format": "uri"}, "scopes_supported": {"type": "array", "items": {"type": "string", "enum": ["read", "write"]}}, "token_issuance_uri": {"type": "string", "format": "uri"}, "description": {"type": "string"}}, "required": ["resource", "resource_name", "bearer_methods_supported", "resource_documentation", "scopes_supported", "token_issuance_uri", "description"]}, "PageInfo": {"type": "object", "properties": {"total": {"type": "integer", "minimum": 0, "description": "Total matching items before pagination."}, "limit": {"type": "integer", "minimum": 1, "maximum": 200}, "offset": {"type": "integer", "minimum": 0}, "next": {"type": ["integer", "null"], "minimum": 0, "description": "Pass this value as offset for the next page; null means the final page."}, "version": {"type": ["integer", "string"], "description": "Report revision for stable pagination."}, "next_cursor": {"type": ["string", "null"], "description": "Continuation including version; prefer over numeric offset."}, "truncated": {"type": "boolean", "description": "More matching items are available."}}, "required": ["total", "limit", "offset", "next", "truncated", "version", "next_cursor"]}, "PagedFinding": {"allOf": [{"$ref": "#/components/schemas/Finding"}, {"type": "object", "properties": {"server": {"type": "string", "format": "uuid"}, "server_name": {"type": "string"}}, "required": ["server", "server_name"]}]}, "FleetSummary": {"type": "object", "properties": {"score": {"type": "number"}, "grade": {"type": "string"}, "global_score": {"type": ["number", "null"], "minimum": 0, "maximum": 100}, "global_grade": {"type": "string"}, "counts": {"$ref": "#/components/schemas/Counts"}, "coverage": {"$ref": "#/components/schemas/Coverage"}, "view": {"const": "summary"}, "version": {"type": ["integer", "string"]}, "kev_total": {"type": "integer"}, "early_advisories_total": {"type": "integer"}, "urgent_findings": {"type": "array", "items": {"type": "object"}}, "urgent_remaining": {"type": "integer"}, "urgent_next": {"type": ["object", "null"]}, "next_cursor": {"type": ["string", "null"]}, "top_findings": {"type": "array", "maxItems": 10, "items": {"type": "object", "properties": {"priority": {"type": "string", "enum": ["P0", "P1", "P2", "P3"]}, "risk": {"type": ["number", "null"]}, "component": {"type": ["string", "null"]}, "version": {"type": ["string", "null"]}, "fix": {"type": ["string", "null"]}, "action": {"type": "string", "description": "Recommended update, mitigation or reboot."}, "ncves": {"type": ["integer", "null"]}, "exposure_reason": {"$ref": "#/components/schemas/ExposureReason"}, "server": {"type": "string", "format": "uuid"}, "server_name": {"type": "string"}}, "required": []}}, "assets_total": {"type": "integer", "minimum": 0}, "findings_total": {"type": "integer", "minimum": 0}, "pending_assets_total": {"type": "integer", "minimum": 0}, "totals": {"$ref": "#/components/schemas/Counts"}, "assets": {"type": "array", "maxItems": 10, "items": {"type": "object"}}, "assets_truncated": {"type": "boolean"}, "next": {"type": "object", "properties": {"view": {"const": "full"}, "section": {"const": "assets"}, "limit": {"type": "integer", "minimum": 1, "maximum": 200}, "offset": {"const": 0}}, "required": ["view", "section", "limit", "offset"]}}, "required": ["score", "grade", "counts", "coverage", "top_findings", "assets_total", "findings_total", "pending_assets_total", "totals", "assets", "assets_truncated", "next"]}, "FleetReportPage": {"allOf": [{"$ref": "#/components/schemas/PageInfo"}, {"type": "object", "properties": {"assets": {"type": "array", "items": {"type": "object", "description": "Server report metadata without nested findings."}}, "findings": {"type": "array", "items": {"$ref": "#/components/schemas/PagedFinding"}}, "pending_assets": {"type": "array", "items": {"type": "object"}}}, "required": []}]}, "ServerPage": {"allOf": [{"$ref": "#/components/schemas/PageInfo"}, {"type": "object", "properties": {"servers": {"type": "array", "items": {"$ref": "#/components/schemas/Server"}}}, "required": ["servers"]}]}}}}