{"openapi":"3.0.3","info":{"title":"Elastio API","description":"The Elastio API gives you access to the Elastio platform from code. Hunt looks for ransomware, malware, and corrupted files in live, replicated, and backup data. Pursuit investigates copies of your systems for evidence of compromise. The API returns what both find, the incidents they raise, and the evidence that proves which recovery point is clean.\n\n## Base URL\n\nEvery request goes to your tenant:\n\n```\nhttps://{tenant}.app.elastio.com\n```\n\n`{tenant}` is the subdomain you use to sign in to the Elastio console.\n\n## Authentication\n\nSend a personal access token (PAT) in the `Authorization` header:\n\n```\nAuthorization: Bearer <token>\n```\n\nTenant admins issue tokens from the Elastio console or with `POST /gateway/shared-services/v1/personal-access-tokens`. Tokens can be scoped to the categories `inventory`, `security`, `protection`, `reporting`, `integrations` and `admin`, each with `read` or `write` access. See the [authentication guide](https://developer.elastio.com/api/authentication/) for details.\n\n## Trying requests\n\nSelect **Test Request** on any operation to send it from your browser. Enter your tenant in the server field and your token under **Authentication**. Requests run against your live tenant, so write operations change real data.\n","version":"1.0.0","contact":{"name":"Elastio Support","email":"support@elastio.com","url":"https://support.elastio.com"},"license":{"name":"Copyright © Elastio Software, Inc. All rights reserved.","url":"https://elastio.com"}},"servers":[{"url":"https://{tenant}.app.elastio.com","description":"Your Elastio tenant","variables":{"tenant":{"default":"your-tenant","description":"The subdomain of your Elastio console URL"}}}],"security":[{"authorization":[]}],"tags":[{"name":"System","description":"Liveness and service status for the Elastio API."},{"name":"Tenant Settings","description":"Tenant-level configuration"},{"name":"Licenses","description":"Tenant license keys"},{"name":"Plan","description":"Subscription plan details."},{"name":"Billing","description":"Usage and billing information."},{"name":"Early Access","description":"Opt-in early access features for your tenant."},{"name":"AI Provider Credentials","description":"Tenant AI provider credentials"},{"name":"Users","description":"Operations that create, read, update or disable Users."},{"name":"User Groups","description":"CRUD endpoints for User Groups."},{"name":"Roles","description":"CRUD endpoints for Roles and role assignments."},{"name":"Account Groups","description":"CRUD endpoints for Account Groups."},{"name":"Personal Access Tokens","description":"Endpoints to manage personal access tokens (tenant admin only)"},{"name":"Audit Logs","description":"Endpoints for retrieving and filtering audit logs."},{"name":"Deployments","description":"Connect and manage AWS accounts, networking, and Cloud Connector deployments for your tenant."},{"name":"Assets","description":"Protected assets, their recovery points, hunts and health."},{"name":"Search","description":"Typed and unified search across every asset Elastio inventories."},{"name":"Inventory","description":"Inventory summaries across connected accounts."},{"name":"Asset Accounts","description":"Cloud accounts that own inventoried assets."},{"name":"Tags","description":"Cloud resource tags discovered on inventoried assets."},{"name":"Azure Subscriptions","description":"Connected Microsoft Azure subscriptions."},{"name":"GCP Projects","description":"Connected Google Cloud projects."},{"name":"IBM","description":"IBM Cloud connections."},{"name":"OVA Accounts","description":"Accounts for on-premises OVA (VMware) deployments."},{"name":"Vault","description":"Endpoints to manage vaults"},{"name":"Database Monitoring","description":"Monitored databases, their Database Connectors and declared limits, and what was found."},{"name":"Data","description":"Coverage and usage views over your assets and hunt results."},{"name":"Backup","description":"Backup and recovery point operations."},{"name":"Scans","x-displayName":"Hunts","description":"Start a hunt or a Pursuit investigation on an asset or recovery point."},{"name":"Scan Jobs","x-displayName":"Hunt Results","description":"Each hunt or investigation run, the backups it covered, and what it found."},{"name":"Hunt Rules","description":"Rules that tell Hunt what to look for, including YARA rules."},{"name":"Custom Hunts","description":"Hunts you define with your own hunt rules, and their results."},{"name":"Pursuit","description":"Pursuit investigates copies of your systems off-host for evidence of compromise."},{"name":"Pursuit Scans","x-displayName":"Pursuit Investigations","description":"Investigations Pursuit has run on an asset."},{"name":"Threats","x-displayName":"Hunt Findings","description":"Ransomware, malware, encrypted files, and corrupted files that Hunt found, and how to suppress them."},{"name":"Ransomware","x-displayName":"Ransomware Summary","description":"A summary of ransomware findings across your assets."},{"name":"Data Classification","description":"Sensitive data and exposed credential discovery."},{"name":"Incidents","description":"Incident episodes that group related findings for response."},{"name":"Findings","description":"Unified findings across Hunt, Pursuit, violations and data classification."},{"name":"Violations","description":"Policy and posture violations raised against assets."},{"name":"Issues","description":"Operational issues that need attention."},{"name":"Posture","x-displayName":"Cloud Configuration","description":"Cloud configuration checks: compliance checks against your AWS resources."},{"name":"Compliance","description":"Compliance summaries for frameworks Elastio reports on."},{"name":"DRS","description":"AWS Elastic Disaster Recovery (DRS) integration."},{"name":"Policies","description":"Protection, hunt and investigation policies."},{"name":"Policy Schedules","description":"Schedules attached to policies."},{"name":"Policy Membership","description":"Which assets a policy currently covers."},{"name":"System Policies","description":"Policies for system events and unprotected assets"},{"name":"System Events","description":"Operational event catalog"},{"name":"Jobs","description":"Long-running jobs: hunts, investigations, deployments and Cloud Connector activity."},{"name":"Resilience Program","description":"Program snapshot, trend, and version commits"},{"name":"Recovery Verdict","description":"Estate-wide recovery verdict summary and per-asset verdicts"},{"name":"Recovery Analytics","description":"Recovery readiness analytics."},{"name":"Evidence","description":"Per-asset evidence envelope and fleet-wide evidence ledger"},{"name":"Security Metrics","description":"Security metrics and trend history."},{"name":"Reports","description":"Generate, list, fetch, and delete reports."},{"name":"Report Schedules","description":"Scheduled report generation."},{"name":"EQL","description":"EQL reporting, natural-language drafts, and custom schedules."},{"name":"Alerts","description":"Alert rules and notification management."},{"name":"Webhooks","description":"Outbound webhook configuration and delivery tracking."},{"name":"Slack","description":"Slack workspace connection and channel routing."},{"name":"Splunk","description":"Splunk HTTP Event Collector integration."},{"name":"VirusTotal","description":"VirusTotal integration and file report lookup."},{"name":"Wiz","description":"Wiz incoming channel: receives alert and asset events from Wiz."},{"name":"GuardDuty","description":"Amazon GuardDuty findings ingestion."}],"paths":{"/gateway/api/v2/incident-assignees":{"get":{"operationId":"listIncidentAssignees","summary":"List active tenant members eligible for assignment","tags":["Incidents"],"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents":{"get":{"operationId":"listIncidents","summary":"List retained incident episodes","tags":["Incidents"],"description":"Returns one page of retained incident episodes. Each row is the persisted episode plus a nullable finding overlay (severity, title, asset, finding status). Default status is open. Default sort is SEVERITY_ASC (critical first, threats before violations, oldest first).","parameters":[{"schema":{"type":"string","enum":["open","closed","all"]},"in":"query","name":"status","required":false,"description":"Episode lifecycle. Default open."},{"schema":{"type":"string","maxLength":300},"in":"query","name":"finding_key","required":false},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Substring over handle, finding_key, asset name/id, title, and method."},{"schema":{"type":"string"},"in":"query","name":"finding_status","required":false,"description":"Comma-separated finding dispositions (open,acknowledged,suppressed,resolved)"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Comma-separated finding classes (threat,violation,data_classification)"},{"schema":{"type":"string"},"in":"query","name":"assignee","required":false,"description":"me, unassigned, or a tenant-member UUID."},{"schema":{"type":"string","enum":["SEVERITY_ASC","SEVERITY_DESC","OPENED_AT_ASC","OPENED_AT_DESC","HANDLE_ASC","HANDLE_DESC","ASSET_NAME_ASC","ASSET_NAME_DESC","ASSIGNEE_ASC","ASSIGNEE_DESC"]},"in":"query","name":"sort_by","required":false},{"schema":{"type":"integer","minimum":1,"maximum":20,"default":20},"in":"query","name":"limit","required":false},{"schema":{"type":"integer","minimum":0,"default":0},"in":"query","name":"offset","required":false}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"handle":{"type":"string","description":"Episode handle from the sequence counter, e.g. INC-000001."},"sequence":{"type":"string"},"tenant_name":{"type":"string"},"finding_key":{"type":"string"},"finding_type":{"type":"string"},"asset_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["open","closed"],"description":"Episode lifecycle. Independent of finding.status."},"previous_incident_id":{"type":"string","format":"uuid","nullable":true},"assignee_id":{"type":"string","format":"uuid","nullable":true},"opened_at":{"type":"string"},"last_observed_at":{"type":"string","nullable":true},"closed_at":{"type":"string","nullable":true},"closure_reason":{"type":"string","nullable":true},"evidence":{"type":"object","nullable":true,"additionalProperties":true,"properties":{"source":{"type":"string"},"finding_id":{"type":"string"},"details":{"type":"object","additionalProperties":true}}},"version":{"type":"integer"},"finding":{"type":"object","nullable":true,"additionalProperties":false,"description":"Finding currently associated with this incident. Null if that finding is no longer available. Threat count/signature fields match GET /api/v2/threats; violations leave them empty.","properties":{"id":{"type":"string","description":"Finding identity used by disposition endpoints: threat composite, violation UUID, or data-classification status UUID."},"class":{"type":"string","enum":["threat","violation","data_classification"]},"title":{"type":"string","nullable":true},"kind":{"type":"string","nullable":true},"method":{"type":"string","nullable":true},"severity":{"type":"string","nullable":true,"enum":["critical","high","medium","low","info"]},"status":{"type":"string","nullable":true,"enum":["open","acknowledged","suppressed","resolved"],"description":"Finding disposition. Independent of the episode's open/closed status."},"asset_name":{"type":"string","nullable":true},"asset_kind":{"type":"string","nullable":true},"platform":{"type":"string","nullable":true},"platform_details":{"type":"object","nullable":true,"additionalProperties":false,"description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}}},"count":{"type":"number","nullable":true},"files_affected":{"type":"number","nullable":true,"description":"Active detections for this finding. Null when none are live; consumers fall back to count."},"signature":{"type":"string","nullable":true},"signatures":{"type":"array","items":{"type":"string"}},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"For Pursuit, the investigation's overall_assessment. For custom hunts, hunt_rule_id and hunt_scan_id. Null for Elastio hunts. Never includes raw hunt query output."}},"required":["id","class"]}},"required":["id","handle","sequence","tenant_name","finding_key","finding_type","asset_id","status","previous_incident_id","assignee_id","opened_at","last_observed_at","closed_at","closure_reason","evidence","version","finding"]}}},"required":["total","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents/filters":{"get":{"operationId":"listIncidentFilters","summary":"Get contextual filter options for incidents","tags":["Incidents"],"description":"Contextual filter option counts for GET /api/v2/incidents. Accepts the same filters as the list (except pagination and sort). Each facet omits its own filter. Counts follow the current episode status, search, and the other axes.","parameters":[{"schema":{"type":"string","enum":["open","closed","all"]},"in":"query","name":"status","required":false,"description":"Episode lifecycle. Default open."},{"schema":{"type":"string","maxLength":300},"in":"query","name":"finding_key","required":false},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Substring over handle, finding_key, asset name/id, title, and method."},{"schema":{"type":"string"},"in":"query","name":"finding_status","required":false,"description":"Comma-separated finding dispositions (open,acknowledged,suppressed,resolved)"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Comma-separated finding classes (threat,violation,data_classification)"},{"schema":{"type":"string"},"in":"query","name":"assignee","required":false,"description":"me, unassigned, or a tenant-member UUID."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"total":{"type":"number","description":"Incidents matching the current filters."},"finding_status":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string"},"count":{"type":"number"}},"required":["value","count"]}},"severity":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string"},"count":{"type":"number"}},"required":["value","count"]}},"type":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string"},"count":{"type":"number"}},"required":["value","count"]}},"assignee":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string"},"count":{"type":"number"}},"required":["value","count"]}},"status":{"type":"array","items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string"},"count":{"type":"number"}},"required":["value","count"]}}},"required":["total","finding_status","severity","type","assignee","status"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents/{id}":{"get":{"operationId":"getIncident","summary":"Get an incident and its retained audit history","tags":["Incidents"],"description":"Returns one episode, the same finding overlay as GET /api/v2/incidents, and the append-only audit trail.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"handle":{"type":"string","description":"Episode handle from the sequence counter, e.g. INC-000001."},"sequence":{"type":"string"},"tenant_name":{"type":"string"},"finding_key":{"type":"string"},"finding_type":{"type":"string"},"asset_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["open","closed"],"description":"Episode lifecycle. Independent of finding.status."},"previous_incident_id":{"type":"string","format":"uuid","nullable":true},"assignee_id":{"type":"string","format":"uuid","nullable":true},"opened_at":{"type":"string"},"last_observed_at":{"type":"string","nullable":true},"closed_at":{"type":"string","nullable":true},"closure_reason":{"type":"string","nullable":true},"evidence":{"type":"object","nullable":true,"additionalProperties":true,"properties":{"source":{"type":"string"},"finding_id":{"type":"string"},"details":{"type":"object","additionalProperties":true}}},"version":{"type":"integer"},"finding":{"type":"object","nullable":true,"additionalProperties":false,"description":"Finding currently associated with this incident. Null if that finding is no longer available. Threat count/signature fields match GET /api/v2/threats; violations leave them empty.","properties":{"id":{"type":"string","description":"Finding identity used by disposition endpoints: threat composite, violation UUID, or data-classification status UUID."},"class":{"type":"string","enum":["threat","violation","data_classification"]},"title":{"type":"string","nullable":true},"kind":{"type":"string","nullable":true},"method":{"type":"string","nullable":true},"severity":{"type":"string","nullable":true,"enum":["critical","high","medium","low","info"]},"status":{"type":"string","nullable":true,"enum":["open","acknowledged","suppressed","resolved"],"description":"Finding disposition. Independent of the episode's open/closed status."},"asset_name":{"type":"string","nullable":true},"asset_kind":{"type":"string","nullable":true},"platform":{"type":"string","nullable":true},"platform_details":{"type":"object","nullable":true,"additionalProperties":false,"description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}}},"count":{"type":"number","nullable":true},"files_affected":{"type":"number","nullable":true,"description":"Active detections for this finding. Null when none are live; consumers fall back to count."},"signature":{"type":"string","nullable":true},"signatures":{"type":"array","items":{"type":"string"}},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"For Pursuit, the investigation's overall_assessment. For custom hunts, hunt_rule_id and hunt_scan_id. Null for Elastio hunts. Never includes raw hunt query output."}},"required":["id","class"]},"history":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string"},"at":{"type":"string"},"actor":{"type":"string"},"event":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"required":["id","handle","sequence","tenant_name","finding_key","finding_type","asset_id","status","previous_incident_id","assignee_id","opened_at","last_observed_at","closed_at","closure_reason","evidence","version","finding","history"]}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents/{id}/close":{"post":{"operationId":"closeIncident","summary":"Close an incident","tags":["Incidents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["version","comment","reason"],"properties":{"version":{"type":"integer","minimum":1},"comment":{"type":"string","minLength":1,"maxLength":10000,"pattern":"\\S"},"reason":{"type":"string","enum":["remediated","false_positive","accepted_risk","duplicate"]}}}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents/{id}/reopen":{"post":{"operationId":"reopenIncident","summary":"Reopen an incident","tags":["Incidents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["version","comment"],"properties":{"version":{"type":"integer","minimum":1},"comment":{"type":"string","minLength":1,"maxLength":10000,"pattern":"\\S"}}}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents/{id}/comment":{"post":{"operationId":"commentIncident","summary":"Comment on an incident","tags":["Incidents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["version","comment"],"properties":{"version":{"type":"integer","minimum":1},"comment":{"type":"string","minLength":1,"maxLength":10000,"pattern":"\\S"}}}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incidents/{id}/assign":{"post":{"operationId":"assignIncident","summary":"Assign an incident","tags":["Incidents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["version","assignee_id"],"properties":{"version":{"type":"integer","minimum":1},"comment":{"type":"string","minLength":1,"maxLength":10000,"pattern":"\\S"},"assignee_id":{"type":"string","format":"uuid","nullable":true}}}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/incident-settings":{"get":{"operationId":"getIncidentSettings","summary":"Get tenant incident history retention","tags":["Incidents"],"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"operationId":"updateIncidentSettings","summary":"Set tenant incident history retention, at most 730 days","tags":["Incidents"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["retention_days"],"properties":{"retention_days":{"type":"integer","minimum":1,"maximum":730}}}}},"required":true},"security":[{"authorization":[]}],"responses":{"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{asset_id}/pursuit-exception":{"get":{"operationId":"get_asset_pursuit_exception","summary":"Get an asset's active Pursuit exception","tags":["Pursuit"],"description":"Returns the asset's active Pursuit exception, or JSON null when none was ever set or it was cleared. Admin only (reads included). Returns 404 when Pursuit exceptions are not enabled for your tenant.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"ID (UUID) of the asset the exception applies to."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"The single current Pursuit exception for an asset: one free-text instruction Pursuit reads the next time it analyzes the asset. Not suppression.","content":{"application/json":{"schema":{"type":"object","description":"The single current Pursuit exception for an asset: one free-text instruction Pursuit reads the next time it analyzes the asset. Not suppression.","required":["asset_id","instruction","status","created_by","created_at","updated_by","updated_at","cleared_by","cleared_at"],"properties":{"asset_id":{"type":"string","format":"uuid"},"instruction":{"type":"string","description":"Free-form natural-language instruction, at most 4096 Unicode code points."},"status":{"type":"string","enum":["active","cleared"]},"created_by":{"type":"string","description":"Actor of the first write; preserved across edits and reinstates."},"created_at":{"type":"string","format":"date-time"},"updated_by":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"cleared_by":{"type":"string","nullable":true},"cleared_at":{"type":"string","format":"date-time","nullable":true}},"nullable":true}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"operationId":"put_asset_pursuit_exception","summary":"Create, edit or reinstate an asset's Pursuit exception","tags":["Pursuit"],"description":"Upserts the single exception for the asset. The instruction is trimmed; empty or longer than 4096 Unicode code points is a 400. Creating records `created`, replacing an active one records `edited`, and setting one after a clear records `reinstated` (the original created_by/created_at are kept). The actor comes from the auth token, never the body. Every write is audit-logged. Admin only (reads included). Returns 404 when Pursuit exceptions are not enabled for your tenant.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["instruction"],"properties":{"instruction":{"type":"string","description":"At most 4096 Unicode code points after trimming."}}}}},"required":true},"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"ID (UUID) of the asset the exception applies to."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"The single current Pursuit exception for an asset: one free-text instruction Pursuit reads the next time it analyzes the asset. Not suppression.","content":{"application/json":{"schema":{"type":"object","description":"The single current Pursuit exception for an asset: one free-text instruction Pursuit reads the next time it analyzes the asset. Not suppression.","required":["asset_id","instruction","status","created_by","created_at","updated_by","updated_at","cleared_by","cleared_at"],"properties":{"asset_id":{"type":"string","format":"uuid"},"instruction":{"type":"string","description":"Free-form natural-language instruction, at most 4096 Unicode code points."},"status":{"type":"string","enum":["active","cleared"]},"created_by":{"type":"string","description":"Actor of the first write; preserved across edits and reinstates."},"created_at":{"type":"string","format":"date-time"},"updated_by":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"cleared_by":{"type":"string","nullable":true},"cleared_at":{"type":"string","format":"date-time","nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"operationId":"delete_asset_pursuit_exception","summary":"Clear an asset's Pursuit exception","tags":["Pursuit"],"description":"Soft clear: the record reads as none afterwards, and the history keeps the clear. Idempotent: clearing an absent or already-cleared exception is a 204 that writes nothing. Admin only (reads included). Returns 404 when Pursuit exceptions are not enabled for your tenant.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"ID (UUID) of the asset the exception applies to."}],"security":[{"authorization":[]}],"responses":{"204":{"description":"Cleared (or nothing to clear)."},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{asset_id}/pursuit-exception/history":{"get":{"operationId":"get_asset_pursuit_exception_history","summary":"Get an asset's Pursuit exception change history","tags":["Pursuit"],"description":"The append-only change log for the asset's Pursuit exception, newest first. Admin only (reads included). Returns 404 when Pursuit exceptions are not enabled for your tenant.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"ID (UUID) of the asset the exception applies to."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["asset_id","version","action","instruction","actor","at"],"properties":{"asset_id":{"type":"string","format":"uuid"},"version":{"type":"integer","minimum":1,"description":"1-based, contiguous per asset across clears and reinstates."},"action":{"type":"string","enum":["created","edited","cleared","reinstated"]},"instruction":{"type":"string","nullable":true,"description":"The instruction as of this version; null on a clear."},"actor":{"type":"string","description":"Server-derived from the authenticated caller."},"at":{"type":"string","format":"date-time"}}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/health_check":{"get":{"operationId":"health_check","summary":"Check API health status","tags":["System"],"description":"Health check endpoint","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/trends-history":{"post":{"operationId":"get_trends_history","summary":"Get trends history data","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["start_at","end_at","time_granularity","asset_ids"],"properties":{"start_at":{"type":"object","properties":{"seconds":{"type":"number"},"nanos":{"type":"number"}},"required":["seconds","nanos"]},"end_at":{"type":"object","properties":{"seconds":{"type":"number"},"nanos":{"type":"number"}},"required":["seconds","nanos"]},"time_granularity":{"type":"number"},"asset_ids":{"type":"array","items":{"type":"string","format":"uuid"}}}}}},"required":true},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"entropy_trends_history":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"object","properties":{"seconds":{"type":"string"},"nanos":{"type":"number"}},"required":["seconds","nanos"]},"anomaly_finding_count":{"type":"string"}},"required":["timestamp","anomaly_finding_count"]}},"threats_history":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"object","properties":{"seconds":{"type":"string"},"nanos":{"type":"number"}},"required":["seconds","nanos"]},"threats_finding_count":{"type":"string"}},"required":["timestamp","threats_finding_count"]}},"file_system_threats_history":{"type":"array","items":{"type":"object","properties":{"timestamp":{"type":"object","properties":{"seconds":{"type":"string"},"nanos":{"type":"number"}},"required":["seconds","nanos"]},"threats_finding_count":{"type":"string"}},"required":["timestamp","threats_finding_count"]}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Security Metrics"]}},"/gateway/api/v1/ransomware-short":{"get":{"operationId":"get_ransomware_short","summary":"Get the ransomware summary","tags":["Ransomware"],"description":"Get short ransomware data","security":[{"authorization":[]}],"responses":{"200":{"description":"Ransomware short data","content":{"application/json":{"schema":{"type":"object","description":"Ransomware short data","properties":{"date":{"type":"string","nullable":true,"description":"The date associated with the ransomware data. Can be null if not available."},"ransomware":{"type":"array","description":"A list of ransomware sighting items.","items":{"type":"object","description":"An individual ransomware sighting item.","additionalProperties":true}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":82800000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-scanned-30d":{"get":{"operationId":"get_data_scanned_30d","summary":"Get data covered in the last 30 days","tags":["Data"],"description":"Get data scanned in last 30 days","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"bytesScanned":{"type":"number"},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-scanned-by-date-range":{"get":{"operationId":"get_data_scanned_by_date_range","summary":"Get data covered for a date range","tags":["Data"],"description":"Get data scanned for a specific date range. The end date must be after the start date.","parameters":[{"schema":{"type":"string","format":"date","default":"2023-01-01"},"in":"query","name":"startDate","required":true,"description":"Start date in ISO format (YYYY-MM-DD). Must be before end date."},{"schema":{"type":"string","format":"date","default":"2023-01-31"},"in":"query","name":"endDate","required":true,"description":"End date in ISO format (YYYY-MM-DD). Must be after start date."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"bytesScanned":{"type":"number"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/files-scanned":{"get":{"operationId":"get_files_scanned","summary":"Get files covered","tags":["Data"],"description":"Get infected and clean files count","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"infectedFiles":{"type":"number"},"cleanFiles":{"type":"number"},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets-scanned":{"get":{"operationId":"get_assets_scanned","summary":"Get asset coverage","tags":["Data"],"description":"Get scan coverage by asset type","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"ec2":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"ebs":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"s3":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"efs":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"fsxOntapVolumes":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"ovaServer":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"azureVm":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"azureDisk":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"azureBlob":{"type":"object","properties":{"total":{"type":"number"},"covered":{"type":"number"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scan-insights":{"get":{"operationId":"get_scan_insights","summary":"Get coverage summary","tags":["Data"],"description":"Returns a coverage summary: assets, data, and files covered by hunts, and cloud coverage.","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Scan insights fetched successfully"},"data":{"type":"object","properties":{"assets_scanned":{"type":"number","example":120,"description":"Total number of assets that have been scanned"},"data_scanned_bytes":{"type":"number","example":9876543210,"description":"Total amount of data scanned in bytes"},"files_scanned":{"type":"number","example":456789,"description":"Total number of files that have been scanned"},"cloud_coverage":{"type":"number","example":3,"description":"Number of platforms a tenant has coverage for. For example, if a tenant has assets on AWS, Azure, on-prem, and IBM, the value will be 4."}},"required":["assets_scanned","data_scanned_bytes","files_scanned","cloud_coverage"]},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/recovery-points/{backupId}/assets/{assetId}/threats":{"get":{"operationId":"list_recovery_point_asset_threats","summary":"Get findings for an asset in a recovery point","tags":["Assets"],"description":"Get threats for a specific asset in a recovery point","parameters":[{"schema":{"type":"string"},"in":"query","name":"scanId","required":false,"description":"Filter threats by scan ID (preferred)"},{"schema":{"type":"string"},"in":"query","name":"scanJobId","required":false,"description":"Filter threats by scan job ID (preferred)"},{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Optional: Filter threats by kind (comma-separated)"},{"schema":{"type":"boolean"},"in":"query","name":"suppressed","required":false,"description":"Optional: Filter by suppression status"},{"schema":{"type":"string"},"in":"query","name":"sorting","required":false,"description":"Optional: Sorting criteria (e.g., 'detected_at:asc')"},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"backupId","required":true,"description":"Recovery point ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"detectedAt":{"type":"string","format":"date-time"},"suppressed":{"type":"boolean","nullable":true},"sha256":{"type":"string","nullable":true},"object_threat_hunt":{"type":"object","description":"Optional. Present only for S3 bucket assets when this object was included in at least one S3 hunt; otherwise the key is omitted.","properties":{"s3_threat_hunt_job_id":{"type":"string","format":"uuid","description":"S3 hunt job that produced this result"},"last_clean_version":{"type":"string","nullable":true,"description":"AWS S3 version ID of the last known clean object"},"last_clean_version_timestamp":{"type":"string","format":"date-time","nullable":true,"description":"When the clean version was recorded"}}}}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/recovery-points/{backupId}/entities/asset-items/{assetItemId}/threats":{"get":{"operationId":"list_recovery_point_asset_item_threats","summary":"Get findings for an asset item in a recovery point","tags":["Assets"],"description":"Get threats for a specific asset item in a recovery point","parameters":[{"schema":{"type":"string"},"in":"query","name":"scanId","required":false,"description":"Filter threats by scan ID (preferred)"},{"schema":{"type":"string","deprecated":true},"in":"query","name":"scan_id","required":false,"description":"Filter threats by scan ID (deprecated, for backward compatibility)"},{"schema":{"type":"string"},"in":"query","name":"scanJobId","required":false,"description":"Filter threats by scan job ID (preferred)"},{"schema":{"type":"string","deprecated":true},"in":"query","name":"scan_job_id","required":false,"description":"Filter threats by scan job ID (deprecated, for backward compatibility)"},{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Optional: Filter threats by kind (comma-separated)"},{"schema":{"type":"boolean"},"in":"query","name":"suppressed","required":false,"description":"Optional: Filter by suppression status"},{"schema":{"type":"string"},"in":"query","name":"sorting","required":false,"description":"Optional: Sorting criteria (e.g., 'detected_at:asc')"},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"backupId","required":true,"description":"Recovery point ID"},{"schema":{"type":"string"},"in":"path","name":"assetItemId","required":true,"description":"Asset Item ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"detectedAt":{"type":"string","format":"date-time"},"suppressed":{"type":"boolean","nullable":true},"sha256":{"type":"string","nullable":true}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/recovery-points/{backupId}/entities":{"get":{"operationId":"list_recovery_point_entities","summary":"Get entities for a specific recovery point","tags":["Assets"],"description":"Get entities for a specific recovery point","parameters":[{"schema":{"type":"string"},"in":"query","name":"scanJobId","required":false,"description":"Filter entities by scan job ID (preferred)"},{"schema":{"type":"string","deprecated":true},"in":"query","name":"scan_job_id","required":false,"description":"Filter entities by scan job ID (deprecated, for backward compatibility)"},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"backupId","required":true,"description":"Recovery point ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"}}}},"malware_status":{"type":"string"},"ransomware_status":{"type":"string"},"fs_check_status":{"type":"string"},"name":{"type":"string"},"entity_kind":{"type":"string"},"anomaly_status":{"type":"string"},"kind":{"type":"string"},"anomalies_count":{"type":"number"}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/scanjobs/{scanJobId}/entities":{"get":{"operationId":"list_scan_job_entities","summary":"Get the entities a hunt covered","tags":["Assets"],"description":"Get entities for a specific scan job","parameters":[{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"}}}},"malware_status":{"type":"string"},"ransomware_status":{"type":"string"},"fs_check_status":{"type":"string"},"name":{"type":"string"},"entity_kind":{"type":"string"},"anomaly_status":{"type":"string"},"kind":{"type":"string"},"anomalies_count":{"type":"number"}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scanjobs/{scanJobId}/assets/{assetId}/threats":{"get":{"operationId":"list_scan_job_asset_threats","summary":"Get findings for an asset from a hunt","tags":["Assets"],"description":"Get threats for a specific asset from a scan job","parameters":[{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Optional: Filter threats by kind (comma-separated)"},{"schema":{"type":"boolean"},"in":"query","name":"suppressed","required":false,"description":"Optional: Filter by suppression status"},{"schema":{"type":"string"},"in":"query","name":"sorting","required":false,"description":"Optional: Sorting criteria (e.g., 'detected_at:asc')"},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"detected_at":{"type":"string","format":"date-time"},"suppressed":{"type":"boolean","nullable":true},"sha256":{"type":"string","nullable":true},"object_threat_hunt":{"type":"object","description":"Optional. Present only for S3 bucket assets when this object was included in at least one S3 hunt; otherwise the key is omitted.","properties":{"s3_threat_hunt_job_id":{"type":"string","format":"uuid","description":"S3 hunt job that produced this result"},"last_clean_version":{"type":"string","nullable":true,"description":"AWS S3 version ID of the last known clean object"},"last_clean_version_timestamp":{"type":"string","format":"date-time","nullable":true,"description":"When the clean version was recorded"}}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scanjobs/{scanJobId}/backups":{"get":{"operationId":"list_scan_job_backups","summary":"List the backups a hunt covered","tags":["Scan Jobs"],"description":"Returns backups associated with a scan job.","parameters":[{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string","description":"Backup ID (uuid)"},"tenant_name":{"type":"string"},"timestamp":{"type":"string","format":"date-time","description":"Backup timestamp (timestamptz)"},"provider":{"type":"string"},"kind":{"type":"string"},"protected_asset_item_ids":{"type":"array","items":{"type":"string"},"description":"UUIDs of the protected asset items in the backup"},"fs_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"creation_status":{"type":"string"},"deletion_status":{"type":"string","nullable":true},"replicated":{"type":"boolean"},"drs_source_server_id":{"type":"string","nullable":true},"encryption_check_status":{"type":"string"},"source_asset":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"kind":{"type":"string","description":"Raw asset kind"},"name":{"type":"string","nullable":true}}},"protected_assets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","description":"Raw asset kind"},"name":{"type":"string","nullable":true}}}}}}},"message":{"type":"string"}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scanjobs/{scanJobId}/threats":{"get":{"operationId":"list_scan_job_threats","summary":"List what a hunt found","tags":["Scan Jobs"],"description":"Returns threats for a scan job.","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"Optional: Filter to threats from scans whose target matches this asset UUID"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Optional: Filter by threat kind (comma-separated)"},{"schema":{"type":"string"},"in":"query","name":"threat_status","required":false,"description":"Optional: Filter by threat status (comma-separated)"},{"schema":{"type":"boolean"},"in":"query","name":"suppressed","required":false,"description":"Optional: Filter by suppression status. true = currently suppressed (suppressed_until > now), false = not currently suppressed."},{"schema":{"type":"number","default":10},"in":"query","name":"page_size","required":false,"description":"Number of results per page"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Pagination token for next page"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Pagination token for previous page"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"total":{"type":"number"},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}},"data":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"id":{"type":"string","description":"Threat ID (uuid)"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","description":"Cloud connector id (uuid)"},"source":{"type":"object","description":"Source of the threat","additionalProperties":true},"backup_ids":{"type":"array","items":{"type":"string"}},"name":{"type":"string"},"location":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"detected_at":{"type":"string","format":"date-time"},"ignored_at":{"type":"string","format":"date-time","nullable":true},"resolved_at":{"type":"string","format":"date-time","nullable":true},"detected_by_scan_ids":{"type":"array","items":{"type":"string"}},"resolved_by_scan_id":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"ignored_by_email":{"type":"string","nullable":true},"suppressed_until":{"type":"string","format":"date-time","nullable":true},"suppression_reason":{"type":"string","nullable":true},"suppressed_by_user_id":{"type":"string","nullable":true},"file_name":{"type":"string","nullable":true},"sha256":{"type":"string","nullable":true}}}},"message":{"type":"string"}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/scanjobs/{scanJobId}/threats/pursuit/findings":{"get":{"operationId":"list_scan_job_pursuit_findings_v2","summary":"List Pursuit findings from an investigation","tags":["Scan Jobs"],"description":"Returns the Pursuit findings from this run. Only runs with a low, medium, high, or critical suspicion level are included. Returns 404 when the run does not exist or has no qualifying Pursuit findings.","parameters":[{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Composite list key `{pursuit_scan_id}:{engine_finding_id}`. Not the ID of a current Pursuit finding, and there is no GET by this ID."},"asset_id":{"type":"string"},"pursuit_scan_id":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string","enum":["none","low","medium","high","critical"]},"confidence":{"type":"string","enum":["low","medium","high"]},"details":{"type":"string"},"persistence_type":{"type":"string","nullable":true},"lol_bin":{"type":"object","additionalProperties":true,"nullable":true},"credential_assessment":{"type":"object","additionalProperties":true,"nullable":true},"evidence":{"type":"array"},"extra":{"type":"object","additionalProperties":true},"scanned_at":{"type":"string"}},"required":["id","asset_id","pursuit_scan_id","title","category","severity","confidence","details","evidence","extra","scanned_at"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}},"required":["total","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/scanjobs/{scanJobId}/threats/custom/findings":{"get":{"operationId":"list_scan_job_custom_hunt_findings_v2","summary":"List custom hunt findings from a hunt","tags":["Scan Jobs"],"description":"Returns the custom hunt findings from this run, one row per target and rule. Only rows with a recognized rule name and at least one match are included. Returns 404 when the run does not exist or has no qualifying custom hunt findings.","parameters":[{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"ID of the custom hunt run for this target and rule. Not a finding ID, and not a threat:{asset}:custom:{findingUuid} finding identity."},"asset_id":{"type":"string"},"hunt_scan_id":{"type":"string","format":"uuid"},"hunt_rule_id":{"type":"string","format":"uuid","nullable":true},"hunt_rule_name":{"type":"string"},"severity":{"type":"string","enum":["low","medium","high","critical"]},"count":{"type":"number"},"scanned_at":{"type":"string"},"hits":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string"},"envelope":{"type":"object","additionalProperties":true}},"required":["query","envelope"]}}},"required":["id","asset_id","hunt_scan_id","hunt_rule_name","severity","count","scanned_at","hits"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}},"required":["total","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/application-discoveries":{"get":{"operationId":"get_asset_application_discoveries","summary":"Get latest application discovery for an asset","tags":["Assets"],"description":"Returns the latest application discovery record for the specified asset. For EC2 instances, includes discoveries from attached volumes.","parameters":[{"schema":{"type":"string","enum":["unknown","edr","xdr","db"]},"in":"query","name":"category","required":false,"description":"Filter applications by category"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true,"description":"Asset ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"job_id":{"type":"string"},"discovered_applications":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"category":{"type":"string"},"publisher":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"human_readable_name":{"type":"string","nullable":true},"versions":{"type":"array","items":{"type":"string"},"nullable":true}},"additionalProperties":true}},"attached_volumes_applications":{"type":"array","nullable":true,"description":"Application discoveries from attached volumes (EC2 instances only)","items":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"job_id":{"type":"string","nullable":true},"discovered_applications":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"category":{"type":"string"},"publisher":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"human_readable_name":{"type":"string","nullable":true},"versions":{"type":"array","items":{"type":"string"},"nullable":true}},"additionalProperties":true}}}}}}},"cached":{"type":"boolean"},"expires_in_ms":{"type":"number","nullable":true},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/data-classification":{"get":{"operationId":"get_asset_data_classification","summary":"Get data classification summary for an asset","tags":["Data Classification"],"description":"Returns the latest data classification summary for an asset. For EC2 instances and Azure VMs, includes attached volume/disk classifications.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"tenant_name":{"type":"string"},"asset_id":{"type":"string","format":"uuid"},"asset_kind":{"type":"string"},"latest_data_classification_id":{"type":"string","format":"uuid","nullable":true},"findings_by_category":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"attached_volumes":{"type":"array","items":{"type":"object","additionalProperties":true}},"attached_disks":{"type":"array","items":{"type":"object","additionalProperties":true}}},"required":["tenant_name","asset_id","asset_kind","findings_by_category","created_at","updated_at"],"nullable":true}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scanjobs/{scanJobId}/asset-items/{assetItemId}/threats":{"get":{"operationId":"list_scan_job_asset_item_threats","summary":"Get findings for an asset item from a hunt","tags":["Assets"],"description":"Get threats for a specific asset item (e.g., OVA volume) from a scan job","parameters":[{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Optional: Filter threats by kind (comma-separated)"},{"schema":{"type":"boolean"},"in":"query","name":"suppressed","required":false,"description":"Optional: Filter by suppression status"},{"schema":{"type":"string"},"in":"query","name":"sorting","required":false,"description":"Optional: Sorting criteria (e.g., 'detected_at:asc')"},{"schema":{"type":"string"},"in":"path","name":"assetItemId","required":true,"description":"Asset Item ID"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"path":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"},"detectedAt":{"type":"string","format":"date-time"},"suppressed":{"type":"boolean","nullable":true},"sha256":{"type":"string","nullable":true}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/recovery-points":{"get":{"operationId":"list_asset_recovery_points","summary":"Get asset recovery points","tags":["Assets"],"description":"Get asset recovery points","parameters":[{"schema":{"type":"string"},"in":"query","name":"pageToken","required":false},{"schema":{"type":"number","default":10,"minimum":1,"maximum":100},"in":"query","name":"pageSize","required":false},{"schema":{"type":"number"},"in":"query","name":"days","required":false},{"schema":{"type":"string"},"in":"query","name":"kind","required":false},{"schema":{"type":"string"},"in":"query","name":"type","required":false},{"schema":{"type":"string"},"in":"query","name":"backupType","required":false},{"schema":{"type":"string"},"in":"query","name":"threatKinds","required":false,"description":"CSV of threat kinds to include (ransomware|encryption|malware). Present but EMPTY means clean only; omit the param for no filtering."},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"provider":{"type":"string"},"kind":{"type":"string"},"source_asset_id":{"type":"string"},"drs_source_server_id":{"type":"string","nullable":true},"protected_asset_ids":{"type":"array","items":{"type":"string"}},"protected_asset_item_ids":{"type":"array","items":{"type":"string"}},"fs_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"encryption_check_status":{"type":"string","nullable":true},"creation_status":{"type":"string"},"deletion_status":{"type":"string","nullable":true},"replicated":{"type":"boolean"},"key":{"type":"array","items":{"type":"string"}},"health":{"type":"string"},"latest_ransomware_scan":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"latest_malware_scan":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"all_scans":{"type":"array","items":{"type":"object","properties":{"job_id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}}},"backupType":{"type":"string"},"scan_created_ami_id":{"type":"string","nullable":true}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/recovery-points/backup-types":{"get":{"operationId":"get_asset_backup_types_from_recovery_points","summary":"Get backup types from recovery points for an asset","tags":["Assets"],"description":"Get distinct backup types (kinds) from recovery points for a specific asset","parameters":[{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"The unique identifier of the asset"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"backup_types":{"type":"array","items":{"type":"string"},"description":"Array of distinct backup type names from recovery points","example":["AWS Snapshot","AWS Backup","Elastio Managed - EBS Direct Scan"]}},"required":["backup_types"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/scanjobs":{"get":{"operationId":"list_asset_scan_jobs","summary":"List hunts for an asset","tags":["Assets"],"description":"Get list of scan jobs for an asset","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false,"description":"Pagination token"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"},{"schema":{"type":"number"},"in":"query","name":"days","required":false,"description":"Number of days to look back (default: 365 days)"},{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Scan kind filter (e.g., ransomware_scan)"},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Scan type filter (e.g., direct, backup)"},{"schema":{"type":"string"},"in":"query","name":"backupType","required":false,"description":"Backup type filter (e.g., AWS Backup)"},{"schema":{"type":"string"},"in":"query","name":"triggerSource","required":false,"description":"Comma-separated list of trigger sources to filter by (guardduty, threat-hunt)"},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"job_id":{"type":"string"},"scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"cc_id":{"type":"string"},"target":{"type":"object","properties":{"id":{"type":"string"},"kind_tag":{"type":"string"},"asset_id":{"type":"string","description":"Parent asset ID when kind_tag is asset_item"},"resource":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"kind_tag":{"type":"string"},"asset_id":{"type":"string","description":"Parent asset ID for asset_item targets"}}}}},"job_id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"type":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"scan_created_ebs_snapshot_id":{"type":"string","nullable":true}}}},"health":{"type":"string"},"type":{"type":"string"},"timestamp":{"type":"string"},"key":{"type":"array","items":{"type":"string"}},"backupKind":{"type":"string"},"backupType":{"type":"string"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/scanjobs/{scanJobId}":{"get":{"operationId":"get_asset_scan_job","summary":"Get a hunt for an asset","tags":["Assets"],"description":"Get details of a specific scan job by scanJobId","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false,"description":"Pagination token"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"},{"schema":{"type":"number"},"in":"query","name":"days","required":false,"description":"Number of days to look back (default: 365 days)"},{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Scan kind filter (e.g., ransomware_scan)"},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Scan type filter (e.g., direct, backup)"},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"scanJobId","required":true,"description":"Scan Job ID"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"job_id":{"type":"string"},"data_classifications":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"total":{"type":"number","description":"Files in scan scope for this data classification run."},"analyzed":{"type":"number","description":"Files analyzed in this data classification run."},"containing_sensitive_info":{"type":"number","description":"Sensitive files detected in this scan only. Excludes carry-forward paths from prior runs."},"triggered_ccls":{"type":"number","description":"Number of content classifiers (CCLs) triggered during this scan."},"target":{"type":"object","additionalProperties":true}},"required":["id","job_id","created_at","analyzed","total","containing_sensitive_info","triggered_ccls","target"]}},"scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"cc_id":{"type":"string"},"target":{"type":"object","properties":{"id":{"type":"string"},"kind_tag":{"type":"string"},"asset_id":{"type":"string","description":"Parent asset ID when kind_tag is asset_item"},"resource":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"kind_tag":{"type":"string"},"asset_id":{"type":"string","description":"Parent asset ID for asset_item targets"}}}}},"job_id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"type":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"scan_created_ebs_snapshot_id":{"type":"string","nullable":true},"scan_created_ami_id":{"type":"string","nullable":true}}}},"health":{"type":"string"},"type":{"type":"string"},"timestamp":{"type":"string"},"key":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Milestone labels for this job are no longer populated on this endpoint; the array is always empty. Use list scan jobs for key/badge context."},"backupKind":{"type":"string"},"backupType":{"type":"string"},"triggered_by_sources":{"type":"array","nullable":true,"items":{"type":"object","properties":{"source":{"type":"string","enum":["guardduty","threat-hunt","wiz","s3-threat-hunt"]},"event_type":{"type":"string","nullable":true},"job_id":{"type":"string","nullable":true},"human_readable_cc_job_id":{"type":"string","nullable":true}},"additionalProperties":false}},"triggered_by":{"type":"object","nullable":true,"deprecated":true,"description":"Deprecated. Use triggered_by_sources instead. Always null."}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/scanjobs/{scanJobId}/data-classification/findings/filter-options":{"get":{"operationId":"get_scan_job_data_classification_findings_filter_options","summary":"Get filter options for a hunt's data classification findings","tags":["Data Classification"],"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"scanJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"string"},"description":"Distinct CCL category values available for filtering."},"assets":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"uuid"},"label":{"type":"string"}},"required":["value","label"]},"description":"Classified resources available for the assetId filter."}},"required":["categories","assets"]}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/scanjobs/{scanJobId}/data-classification/findings":{"get":{"operationId":"list_scan_job_data_classification_findings","summary":"List sensitive files a hunt found (aggregated)","tags":["Data Classification"],"description":"Returns paginated sensitive files across all data classifications for the scan job, ordered by path ascending.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string"},"in":"query","name":"path","required":false,"description":"Optional case-insensitive substring filter on file path."},{"schema":{"type":"string"},"in":"query","name":"categories","required":false,"description":"Optional comma-separated category names. Returns findings matching any category."},{"schema":{"type":"string","format":"uuid"},"in":"query","name":"assetId","required":false,"description":"Optional classified resource id. Restricts findings to that scan target."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"scanJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"data_classification_id":{"type":"string","format":"uuid","description":"Data classification this sensitive file belongs to."},"path":{"type":"string","description":"Sensitive file path."},"categories":{"type":"array","items":{"type":"string"},"description":"Detected CCL categories for this file."},"kind":{"type":"string","enum":["data","container"],"description":"data: a single file. container: an archive or container with nested_files."},"nested_files":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Path of a file inside a container or archive."},"categories":{"type":"array","items":{"type":"string"},"description":"Detected CCL categories in this nested file."}},"required":["path","categories"]},"description":"Present when kind is container. Per-file breakdown inside the archive."},"asset_id":{"type":"string","format":"uuid","description":"Classified resource id (volume, VM, bucket, etc.)."},"asset_name":{"type":"string","description":"Display name of the classified resource."}},"required":["data_classification_id","path","categories","kind","asset_id","asset_name"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{assetId}/scanjobs/backup-types":{"get":{"operationId":"get_asset_backup_types_from_scan_jobs","summary":"Get backup types covered by an asset's hunts","tags":["Assets"],"description":"Get distinct backup types from scan jobs that target a specific asset","parameters":[{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"The unique identifier of the asset"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"backup_types":{"type":"array","items":{"type":"string"},"description":"Array of distinct backup type names from scan job targets","example":["AWS Snapshot","AWS AMI Backup","Veeam"]}},"required":["backup_types"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/backupTypes":{"get":{"operationId":"list_backup_types","summary":"Get available backup types","tags":["System"],"description":"Get available backup types","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"backupTypes":{"type":"array","items":{"type":"string"}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/get-filtered-data":{"get":{"operationId":"filter_assets","summary":"Get filtered asset data","parameters":[{"schema":{"type":"string","enum":["ec2","ebs","s3","efs","server","host","fsx"]},"in":"query","name":"asset","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string"}}}},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"}}},"description":"Unique tag keys"},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"tags":["Assets"]}},"/gateway/api/v1/assets/{assetId}/recovery-points/{recoveryPointId}":{"get":{"operationId":"get_asset_recovery_point","summary":"Get recovery point details","tags":["Assets"],"description":"Get details of a specific recovery point for an asset","parameters":[{"schema":{"type":"number","default":365},"in":"query","name":"days","required":false},{"schema":{"type":"string"},"in":"query","name":"key","required":false},{"schema":{"type":"string"},"in":"query","name":"kind","required":false},{"schema":{"type":"string"},"in":"query","name":"type","required":false},{"schema":{"type":"string"},"in":"query","name":"pageToken","required":false},{"schema":{"type":"number","default":10},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string"},"in":"query","name":"backupType","required":false},{"schema":{"type":"string"},"in":"path","name":"assetId","required":true,"description":"Asset ID"},{"schema":{"type":"string"},"in":"path","name":"recoveryPointId","required":true,"description":"Recovery point ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Recovery point details","content":{"application/json":{"schema":{"type":"object","description":"Recovery point details","properties":{"drs_source_server_id":{"type":"string","nullable":true},"id":{"type":"string"},"tenant_name":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"provider":{"type":"string"},"kind":{"type":"string"},"source_asset_id":{"type":"string"},"protected_asset_ids":{"type":"array","items":{"type":"string"}},"protected_asset_item_ids":{"type":"array","items":{"type":"string"}},"fs_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"creation_status":{"type":"string"},"deletion_status":{"type":"string","nullable":true},"replicated":{"type":"boolean"},"key":{"type":"array","items":{"type":"string"}},"health":{"type":"string"},"latest_ransomware_scan":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"latest_fs_check":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"latest_malware_scan":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}}},"all_scans":{"type":"array","items":{"type":"object","properties":{"job_id":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"triggered_by_sources":{"type":"array","nullable":true,"items":{"type":"object","properties":{"source":{"type":"string","enum":["guardduty","threat-hunt","wiz","s3-threat-hunt"]},"event_type":{"type":"string","nullable":true},"job_id":{"type":"string","nullable":true},"human_readable_cc_job_id":{"type":"string","nullable":true}},"additionalProperties":false}},"triggered_by":{"type":"object","nullable":true,"deprecated":true,"description":"Deprecated. Use triggered_by_sources instead. Always null."},"data_classifications":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"created_at":{"type":"string","format":"date-time"},"total":{"type":"number","description":"Files in scan scope for this data classification run."},"analyzed":{"type":"number","description":"Files analyzed in this data classification run."},"containing_sensitive_info":{"type":"number","description":"Sensitive files detected in this scan only. Excludes carry-forward paths from prior runs."},"triggered_ccls":{"type":"number","description":"Number of content classifiers (CCLs) triggered during this scan."},"target":{"type":"object","additionalProperties":true}},"required":["id","job_id","created_at","analyzed","total","containing_sensitive_info","triggered_ccls","target"]}}}}},"backupType":{"type":"string"}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/ebs_volumes":{"get":{"operationId":"search_ebs_volumes","summary":"Search EBS volumes","tags":["Search"],"description":"Search Ebs Volume","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"exclude_tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of AWS account IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"regions","required":false,"description":"List of AWS regions comma separated"},{"schema":{"type":"string"},"in":"query","name":"availability_zones","required":false,"description":"List of availability zones comma separated"},{"schema":{"type":"string"},"in":"query","name":"volume_states","required":false,"description":"List of volume states comma separated. Possible values: creating, available, in_use, deleting, deleted, error, unknown, replicated"},{"schema":{"type":"string"},"in":"query","name":"protection_policy_coverage_states","required":false,"description":"List of protection policy coverage states comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alt Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"has_replicated_backups","required":false,"description":"Has replicated backups"},{"schema":{"type":"string"},"in":"query","name":"scan_sources","required":false,"description":"Filter by scan sources (e.g., 'AWS Backup', 'AWS Snapshot') comma separated"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"backup_coverage","required":false,"description":"Backup coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,NAME_ASC,NAME_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,AWS_ID_ASC,AWS_ID_DESC,ARN_ASC,ARN_DESC,AWS_ACCOUNT_ID_ASC,AWS_ACCOUNT_ID_DESC,AWS_REGION_ASC,AWS_REGION_DESC,AWS_AZ_ASC,AWS_AZ_DESC,KNOWN_TYPE_ASC,KNOWN_TYPE_DESC,CUSTOM_TYPE_ASC,CUSTOM_TYPE_DESC,NON_RECOGNIZED_VOLUME_TYPE_ASC,NON_RECOGNIZED_VOLUME_TYPE_DESC,STATE_ASC,STATE_DESC,SIZE_ASC,SIZE_DESC,CREATED_BY_AWS_AT_ASC,CREATED_BY_AWS_AT_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HAS_REPLICATED_BACKUPS_ASC,HAS_REPLICATED_BACKUPS_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC,SCAN_SOURCES_ASC,SCAN_SOURCES_DESC,POLICY_COVERAGE_ASC,POLICY_COVERAGE_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"last_scan":{"type":"string","format":"date-time","nullable":true},"aws_az":{"type":"string","nullable":true},"size":{"type":"string","nullable":true},"created_by_aws_at":{"type":"string","format":"date-time","nullable":true},"has_replicated_backups":{"type":"boolean"},"encryption_details":{"type":"object","properties":{"encrypted":{"type":"boolean","nullable":true},"encryptedWithCmk":{"type":"boolean","nullable":true}}},"performance_characteristics":{"type":"object","properties":{"iops":{"type":"string","nullable":true},"throughput":{"type":"string","nullable":true}}},"retention_policies":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"backup_policies":{"type":"array","items":{"type":"string"}},"aws_id":{"type":"string"},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"state":{"type":"string"},"scan_sources":{"type":"string","nullable":true}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/ec2_instances":{"get":{"operationId":"search_ec2_instances","summary":"Search EC2 instances","tags":["Search"],"description":"Search Ec2 Instances","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"exclude_tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of AWS account IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"regions","required":false,"description":"List of AWS regions comma separated"},{"schema":{"type":"string"},"in":"query","name":"vpcIds","required":false,"description":"List of vpc ids comma separated"},{"schema":{"type":"string"},"in":"query","name":"instance_states","required":false,"description":"List of instance states comma separated. Possible values: running, stopped, terminated, unknown, replicated"},{"schema":{"type":"string"},"in":"query","name":"protection_policy_coverage_states","required":false,"description":"List of protection policy coverage states comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alt Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"has_replicated_backups","required":false,"description":"Has replicated backups"},{"schema":{"type":"string"},"in":"query","name":"scan_sources","required":false,"description":"Filter by scan sources (e.g., 'AWS Backup', 'AWS Snapshot') comma separated"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"backup_coverage","required":false,"description":"Backup coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,NAME_ASC,NAME_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,AWS_ID_ASC,AWS_ID_DESC,ARN_ASC,ARN_DESC,AWS_ACCOUNT_ID_ASC,AWS_ACCOUNT_ID_DESC,AWS_REGION_ASC,AWS_REGION_DESC,TAGS_ASC,TAGS_DESC,STARTED_AT_ASC,STARTED_AT_DESC,STATE_ASC,STATE_DESC,TYPE_ASC,TYPE_DESC,AMI_DETAILS_ASC,AMI_DETAILS_DESC,AWS_VPC_ID_ASC,AWS_VPC_ID_DESC,OS_KIND_ASC,OS_KIND_DESC,EBS_IDS_ASC,EBS_IDS_DESC,BACKUP_POLICIES_ASC,BACKUP_POLICIES_DESC,RETENTION_POLICIES_ASC,RETENTION_POLICIES_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HAS_REPLICATED_BACKUPS_ASC,HAS_REPLICATED_BACKUPS_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC,SCAN_SOURCES_ASC,SCAN_SOURCES_DESC,POLICY_COVERAGE_ASC,POLICY_COVERAGE_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"health":{"type":"string"},"aws_id":{"type":"string"},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"state":{"type":"string"},"ami_details":{"type":"object","properties":{"name":{"type":"string","nullable":true},"awsId":{"type":"string","nullable":true},"location":{"type":"string","nullable":true}}},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"ebs_ids":{"type":"array","items":{"type":"string"}},"aws_vpc_id":{"type":"string","nullable":true},"os_kind":{"type":"string","nullable":true},"backup_policies":{"type":"array","items":{"type":"string"}},"has_replicated_backups":{"type":"boolean"},"retention_policies":{"type":"array","items":{"type":"string"}},"last_scan":{"type":"string","format":"date-time","nullable":true},"started_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"scan_sources":{"type":"string"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/s3_buckets":{"get":{"operationId":"search_s3_buckets","summary":"Search S3 buckets","tags":["Search"],"description":"Search S3 Buckets","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of account IDs with comma separated"},{"schema":{"type":"string"},"in":"query","name":"regions","required":false,"description":"List of regions comma separated"},{"schema":{"type":"string"},"in":"query","name":"bucket_states","required":false,"description":"List of bucket states comma separated. Possible values: in_use, deleted, unknown, replicated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"exclude_tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"vpc_ids","required":false,"description":"List of vpc ids comma separated"},{"schema":{"type":"string"},"in":"query","name":"protection_policy_coverage_states","required":false,"description":"List of protection policy coverage states comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alt Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"has_replicated_backups","required":false,"description":"Has replicated backups"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"backup_coverage","required":false,"description":"Backup coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,NAME_ASC,NAME_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,AWS_ID_ASC,AWS_ID_DESC,ARN_ASC,ARN_DESC,AWS_ACCOUNT_ID_ASC,AWS_ACCOUNT_ID_DESC,AWS_REGION_ASC,AWS_REGION_DESC,TAGS_ASC,TAGS_DESC,STATE_ASC,STATE_DESC,TYPE_ASC,TYPE_DESC,BACKUP_POLICIES_ASC,BACKUP_POLICIES_DESC,RETENTION_POLICIES_ASC,RETENTION_POLICIES_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC,OBJECT_COUNT_ASC,OBJECT_COUNT_DESC,SIZE_ASC,SIZE_DESC,POLICY_COVERAGE_ASC,POLICY_COVERAGE_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"aws_id":{"type":"string"},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"state":{"type":"string"},"size":{"type":"string"},"object_count":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"health":{"type":"string"},"name":{"type":"string"},"os_name":{"type":"string"},"backup_policies":{"type":"array","items":{"type":"string"}},"has_replicated_backups":{"type":"boolean"},"retention_policies":{"type":"array","items":{"type":"string"}},"last_scan":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/efs_filesystems":{"get":{"operationId":"search_efs_filesystems","summary":"Search EFS filesystems","tags":["Search"],"description":"Search Efs Filesystem","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"exclude_tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of AWS account IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"regions","required":false,"description":"List of AWS regions comma separated"},{"schema":{"type":"string"},"in":"query","name":"filesystem_states","required":false,"description":"List of filesystem states comma separated. Possible values: in_use, deleted, unknown, replicated"},{"schema":{"type":"string"},"in":"query","name":"protection_policy_coverage_states","required":false,"description":"List of protection policy coverage states comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alt Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"has_replicated_backups","required":false,"description":"Has replicated backups"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"backup_coverage","required":false,"description":"Backup coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,NAME_ASC,NAME_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,AWS_ID_ASC,AWS_ID_DESC,ARN_ASC,ARN_DESC,AWS_ACCOUNT_ID_ASC,AWS_ACCOUNT_ID_DESC,AWS_REGION_ASC,AWS_REGION_DESC,TAGS_ASC,TAGS_DESC,STATE_ASC,STATE_DESC,BACKUP_POLICIES_ASC,BACKUP_POLICIES_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC,POLICY_COVERAGE_ASC,POLICY_COVERAGE_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"arn":{"type":"string"},"backup_policies":{"type":"array","items":{"type":"string"}},"aws_id":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"state":{"type":"string"},"cc_asset_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"last_scan":{"type":"string","format":"date-time","nullable":true}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/generic_hosts":{"get":{"operationId":"search_generic_hosts","summary":"Search generic hosts","tags":["Search"],"description":"Search Generic Hosts","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"string"},"in":"query","name":"hostname","required":false,"description":"List of Host names comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,HOSTNAME_ASC,HOSTNAME_DESC,CPU_CORES_COUNT_ASC,CPU_CORES_COUNT_DESC,OS_NAME_ASC,OS_NAME_DESC,RETENTION_POLICIES_ASC,RETENTION_POLICIES_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"health":{"type":"string"},"hostname":{"type":"string"},"cpu_cores_count":{"type":"string"},"os_name":{"type":"string"},"last_scan":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/ova_servers":{"get":{"operationId":"search_ova_servers","summary":"Search OVA servers","tags":["Search"],"description":"Search Ova Servers","parameters":[{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of account IDs with comma separated"},{"schema":{"type":"string"},"in":"query","name":"backup_providers","required":false,"description":"List of backup providers comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alt Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,OVA_ACCOUNT_ID_ASC,OVA_ACCOUNT_ID_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,BACKUP_PROVIDER_ASC,BACKUP_PROVIDER_DESC,BACKUP_PROVIDER_ASSET_ID_ASC,BACKUP_PROVIDER_ASSET_ID_DESC,NAME_ASC,NAME_DESC,OS_NAME_ASC,OS_NAME_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ova_account_id":{"type":"string"},"cc_asset_id":{"type":"string"},"health":{"type":"string"},"name":{"type":"string"},"os_name":{"type":"string"},"backup_provider":{"type":"string"},"backup_provider_asset_id":{"type":"string"},"last_scan":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/fsx_volumes":{"get":{"operationId":"search_fsx_volumes","summary":"Search FSx ONTAP volumes","tags":["Search"],"description":"Search FSx ONTAP Volumes","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"exclude_tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of AWS account IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"regions","required":false,"description":"List of AWS regions comma separated"},{"schema":{"type":"string"},"in":"query","name":"volume_states","required":false,"description":"List of volume states comma separated. Grouped values: 'available' (includes: available, creating, created, misconfigured, pending), 'deleted' (includes: deleting, deleted, failed). Individual states: available, created, creating, deleting, failed, misconfigured, pending, deleted, unknown, replicated. If no filter provided, shows both available and deleted groups."},{"schema":{"type":"string"},"in":"query","name":"fsx_file_system_ids","required":false,"description":"List of FSx file system IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"svm_ids","required":false,"description":"List of SVM IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"ontap_volume_names","required":false,"description":"List of ONTAP volume names comma separated"},{"schema":{"type":"string"},"in":"query","name":"protection_policy_coverage_states","required":false,"description":"List of protection policy coverage states comma separated"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alt Search term"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated"},{"schema":{"type":"integer"},"in":"query","name":"last_scan","required":false,"description":"Last scan"},{"schema":{"type":"string"},"in":"query","name":"has_replicated_backups","required":false,"description":"Has replicated backups"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"backup_coverage","required":false,"description":"Backup coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string","enum":["covered","not_covered"]},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated \n\n ID_ASC,ID_DESC,NAME_ASC,NAME_DESC,CC_ASSET_ID_ASC,CC_ASSET_ID_DESC,AWS_VOLUME_ID_ASC,AWS_VOLUME_ID_DESC,ONTAP_VOLUME_NAME_ASC,ONTAP_VOLUME_NAME_DESC,AWS_FILE_SYSTEM_ID_ASC,AWS_FILE_SYSTEM_ID_DESC,AWS_SVM_ID_ASC,AWS_SVM_ID_DESC,JUNCTION_PATH_ASC,JUNCTION_PATH_DESC,ARN_ASC,ARN_DESC,AWS_ACCOUNT_ID_ASC,AWS_ACCOUNT_ID_DESC,AWS_REGION_ASC,AWS_REGION_DESC,TAGS_ASC,TAGS_DESC,STATE_ASC,STATE_DESC,SIZE_IN_BYTES_ASC,SIZE_IN_BYTES_DESC,CREATED_IN_AWS_AT_ASC,CREATED_IN_AWS_AT_DESC,BACKUP_POLICIES_ASC,BACKUP_POLICIES_DESC,CREATED_AT_ASC,CREATED_AT_DESC,UPDATED_AT_ASC,UPDATED_AT_DESC,HEALTH_ASC,HEALTH_DESC,LAST_SCAN_ASC,LAST_SCAN_DESC,POLICY_COVERAGE_ASC,POLICY_COVERAGE_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"total":{"type":"string"},"assetsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"last_scan":{"type":"string","format":"date-time","nullable":true},"aws_volume_id":{"type":"string"},"ontap_volume_name":{"type":"string","nullable":true},"aws_file_system_id":{"type":"string"},"aws_svm_id":{"type":"string"},"junction_path":{"type":"string"},"size_in_bytes":{"type":"number","nullable":true},"root":{"type":"boolean","nullable":true},"created_in_aws_at":{"type":"string","format":"date-time","nullable":true},"state":{"type":"string"},"state_transition_reason":{"type":"string","nullable":true},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"backup_policies":{"type":"array","items":{"type":"string"}},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"scan_sources":{"type":"string","nullable":true}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/assets":{"get":{"operationId":"search_unified_assets","summary":"Search unified assets across all platforms and types","tags":["Search"],"description":"Search unified assets across all platforms and types","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term across asset_name, region, and subscription"},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Alternative search for specific asset names (comma separated)"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Health status comma separated. Possible values: infected, at_risk, clean"},{"schema":{"type":"string"},"in":"query","name":"threat_type","required":false,"description":"List of threat types comma separated. Possible values: malware, ransomware, filesystem_error, encryption"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Platform comma separated. Possible values: aws, azure, on_prem, ibm"},{"schema":{"type":"string"},"in":"query","name":"name","required":false,"description":"Asset name filter"},{"schema":{"type":"string"},"in":"query","name":"subscription","required":false,"description":"Subscription/account ID comma separated"},{"schema":{"type":"string"},"in":"query","name":"region","required":false,"description":"Region comma separated"},{"schema":{"type":"string"},"in":"query","name":"asset_type","required":false,"description":"Asset type filter. Possible values: ec2_instance, ebs_volume, s3_bucket, efs_filesystem, fsx_ontap_volume, ova_server, azure_compute_vm, azure_compute_disk, azure_storage_blob_container, azure_storage_file_share, ibm_cos_bucket"},{"schema":{"type":"string"},"in":"query","name":"storage_account","required":false,"description":"Storage account name filter (for Azure Storage Blob Containers and Azure Storage File Shares)"},{"schema":{"type":"string"},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage status. Possible values: covered, not_covered"},{"schema":{"type":"string"},"in":"query","name":"last_threat_detected_range","required":false,"description":"Filter assets by latest detected threat recency. Possible values: last_hour, last_6_hours, last_day, last_week, last_month"},{"schema":{"type":"string"},"in":"query","name":"state","required":false,"description":"Asset state filter (comma separated). Note: Different asset types support different states. Common states include: running, stopped, deleted, unknown, available, in_use, creating, etc. The filter will only return assets whose type supports the specified state(s)."},{"schema":{"type":"string"},"in":"query","name":"volume_attachment_status","required":false,"description":"Volume attachment status filter (comma separated). Only applies to volume asset types (ebs_volume, fsx_ontap_volume). Possible values: attached, unattached"},{"schema":{"type":"boolean","default":false},"in":"query","name":"edr_bypass","required":false,"description":"Filter to show only assets that have EDR installed but still have threats (EDR bypass)"},{"schema":{"type":"string"},"in":"query","name":"findings_category","required":false,"description":"Comma-separated data classification category names. Returns assets with effective findings > 0 for any listed category."},{"schema":{"type":"boolean"},"in":"query","name":"has_sensitive_data","required":false,"description":"When true, only assets with sensitive data findings. When false, only assets without sensitive data findings."},{"schema":{"type":"string"},"in":"query","name":"trigger_sources","required":false,"description":"Filter assets by scan trigger source (comma separated). Only assets that had scans triggered by these sources are returned. Possible values: guardduty, threat-hunt, wiz"},{"schema":{"type":"string"},"in":"query","name":"page_token","required":false,"description":"Page token for cursor-based pagination"},{"schema":{"type":"integer","minimum":1,"maximum":100},"in":"query","name":"page_size","required":false,"description":"Page size (max 100)"},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Sorting fields with comma separated. Possible values: HEALTH_ASC, HEALTH_DESC, PLATFORM_ASC, PLATFORM_DESC, SUBSCRIPTION_ASC, SUBSCRIPTION_DESC, REGION_ASC, REGION_DESC, ASSET_TYPE_ASC, ASSET_TYPE_DESC, LAST_THREAT_DETECTED_AT_ASC, LAST_THREAT_DETECTED_AT_DESC"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"assets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"health":{"type":"string","enum":["infected","at_risk","clean"]},"asset_name":{"type":"string"},"threat_type":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use threat_counts to determine threat presence and counts by type."},"threat_counts":{"type":"object","properties":{"malware":{"type":"number"},"ransomware":{"type":"number"},"filesystem_error":{"type":"number"},"encryption":{"type":"number"},"total":{"type":"number"}},"required":["malware","ransomware","filesystem_error","encryption","total"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"last_threat_detected_at":{"type":"string","format":"date-time","nullable":true},"latest_scans":{"type":"object","properties":{"malware":{"type":"string","format":"date-time","nullable":true},"ransomware":{"type":"string","format":"date-time","nullable":true},"filesystem_check":{"type":"string","format":"date-time","nullable":true},"encryption":{"type":"string","format":"date-time","nullable":true}},"required":["malware","ransomware","filesystem_check","encryption"]},"platform":{"type":"string","enum":["aws","azure","on_prem","ibm"]},"subscription":{"type":"string"},"region":{"type":"string","nullable":true},"asset_type":{"type":"string","enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","fsx_ontap_volume","ova_server","azure_compute_vm","azure_compute_disk","azure_storage_blob_container","azure_storage_file_share","ibm_cos_bucket"]},"state":{"type":"string","nullable":true},"storage_account":{"type":"string","description":"Storage account name (only present for Azure Storage Blob Containers and Azure Storage File Shares)"},"aws_resource_name":{"type":"string","nullable":true,"description":"AWS resource name from Name tag (only present for AWS assets, null if tag doesn't exist)"},"data_classification_findings":{"type":"object","nullable":true,"additionalProperties":{"type":"number"},"description":"Rolled-up sensitive data findings by category (category name to count). Null when no findings."}},"required":["id","health","asset_name","threat_type","threat_counts","created_at","updated_at","latest_scans","platform","subscription","asset_type","state","data_classification_findings"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string","nullable":true,"description":"Token for the next page of results"},"prev_page_token":{"type":"string","nullable":true,"description":"Token for the previous page of results"},"total":{"type":"string","description":"Total number of assets as a string"}},"required":["total"]}},"required":["assets","pagination"]},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expires_in_ms":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Null if not cached.","example":240000,"nullable":true},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/search/assets/filters":{"get":{"operationId":"get_assets_filter_options","summary":"Get filter options for assets search","tags":["Search"],"parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search term to filter assets by name, ID, or other searchable text."},{"schema":{"type":"string"},"in":"query","name":"alt_search","required":false,"description":"Comma-separated list of alternative search terms."},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Comma-separated list of health statuses to filter by (clean,at_risk,infected)."},{"schema":{"type":"string"},"in":"query","name":"threat_type","required":false,"description":"Comma-separated list of threat types to filter by (ransomware,malware,etc)."},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated list of platforms to filter by (aws,azure,on_prem)."},{"schema":{"type":"string"},"in":"query","name":"asset_type","required":false,"description":"Comma-separated list of asset types to filter by (ec2_instance,ebs_volume,etc)."},{"schema":{"type":"string"},"in":"query","name":"name","required":false,"description":"Comma-separated list of asset names/IDs to filter by."},{"schema":{"type":"string"},"in":"query","name":"subscription","required":false,"description":"Comma-separated list of subscription/account IDs to filter by."},{"schema":{"type":"string"},"in":"query","name":"region","required":false,"description":"Comma-separated list of regions to filter by."},{"schema":{"type":"string"},"in":"query","name":"storage_account","required":false,"description":"Comma-separated list of storage account names to filter by (Azure only)."},{"schema":{"type":"string"},"in":"query","name":"scan_coverage","required":false,"description":"Comma-separated list of scan coverage statuses (covered,not_covered)."},{"schema":{"type":"string"},"in":"query","name":"last_threat_detected_range","required":false,"description":"Latest threat detected range filter (last_hour,last_6_hours,last_day,last_week,last_month)."},{"schema":{"type":"string"},"in":"query","name":"state","required":false,"description":"Comma-separated list of asset states to filter by (running,stopped,etc)."},{"schema":{"type":"string"},"in":"query","name":"volume_attachment_status","required":false,"description":"Comma-separated list of volume attachment statuses (attached,unattached)."},{"schema":{"type":"boolean","default":false},"in":"query","name":"edr_bypass","required":false,"description":"Filter to show only assets that have EDR installed but still have threats (EDR bypass)."},{"schema":{"type":"string"},"in":"query","name":"findings_category","required":false,"description":"Comma-separated data classification category names to filter facet options."},{"schema":{"type":"boolean"},"in":"query","name":"has_sensitive_data","required":false,"description":"When true, facet options reflect only assets with sensitive data. When false, only assets without."},{"schema":{"type":"string"},"in":"query","name":"trigger_sources","required":false,"description":"Comma-separated list of trigger sources (guardduty,threat-hunt,wiz)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Get assets filter options"},"data":{"type":"object","properties":{"threat_type":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"malware"},"label":{"type":"string","example":"Malware"}},"required":["value","label"]}},"health":{"type":"array","description":"Available health statuses for filtering.","items":{"type":"object","properties":{"value":{"type":"string","example":"clean"},"label":{"type":"string","example":"Clean"}},"required":["value","label"]}},"name":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"asset-name-123"},"label":{"type":"string","example":"Asset Name 123"},"alternate_label":{"type":"string","nullable":true,"description":"AWS resource name from Name tag (only present for AWS assets with Name tag)","example":"production-web-server"},"asset_type":{"type":"string","nullable":true,"description":"Asset type for this name option (e.g., ec2_instance, ebs_volume, azure_vm)","example":"ec2_instance"}},"required":["value","label"]}},"subscription":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"123456789012"},"label":{"type":"string","example":"Production Account"},"platform":{"type":"string","example":"aws","description":"Platform of the subscription (aws, azure, on_prem)"}},"required":["value","label","platform"]}},"region":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"us-east-1"},"label":{"type":"string","example":"us-east-1"}},"required":["value","label"]}},"asset_type":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"ec2_instance"},"label":{"type":"string","example":"EC2 Instance"}},"required":["value","label"]}},"platform":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","example":"aws"},"label":{"type":"string","example":"AWS"}},"required":["value","label"]}},"scan_coverage":{"type":"array","description":"Available scan coverage options for filtering.","items":{"type":"object","properties":{"value":{"type":"string","example":"covered"},"label":{"type":"string","example":"Covered"}},"required":["value","label"]}},"last_threat_detected_range":{"type":"array","description":"Available latest threat detected time ranges for filtering.","items":{"type":"object","properties":{"value":{"type":"string","example":"last_day"},"label":{"type":"string","example":"Within last day"}},"required":["value","label"]}},"state":{"type":"array","description":"Available asset states for filtering. Note: Different asset types support different states.","items":{"type":"object","properties":{"value":{"type":"string","example":"running"},"label":{"type":"string","example":"Running"}},"required":["value","label"]}},"volume_attachment_status":{"type":"array","description":"Available volume attachment status options for filtering. Only applies to volume asset types (ebs_volume, fsx_ontap_volume).","items":{"type":"object","properties":{"value":{"type":"string","example":"attached"},"label":{"type":"string","example":"Attached"}},"required":["value","label"]}},"trigger_sources":{"type":"array","description":"Trigger sources that have scan data for this tenant. Only sources with data are returned (e.g. guardduty, threat-hunt, wiz).","items":{"type":"object","properties":{"value":{"type":"string","example":"wiz"},"label":{"type":"string","example":"Wiz"}},"required":["value","label"]}},"findings_category":{"type":"array","description":"Available data classification finding categories for filtering.","items":{"type":"object","properties":{"value":{"type":"string","example":"pci"},"label":{"type":"string","example":"pci"}},"required":["value","label"]}}},"required":["threat_type","health","scan_coverage","last_threat_detected_range","name","subscription","region","asset_type","platform","state","volume_attachment_status","trigger_sources","findings_category"]},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":false},"expires_in_ms":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Null if not cached.","example":300000,"nullable":true}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/ova-accounts":{"get":{"operationId":"get_ova_accounts","summary":"Get all OVA accounts for a tenant","tags":["OVA Accounts"],"description":"Get all OVA accounts for a tenant","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","name","created_at","updated_at"]}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expires_in_ms":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Null if not cached.","example":240000,"nullable":true},"message":{"type":"string"}},"required":["status","data","cached","expires_in_ms","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/azure-subscriptions":{"get":{"operationId":"list_azure_subscriptions","summary":"List all Azure subscriptions","tags":["Azure Subscriptions"],"description":"List all Azure subscriptions for a tenant","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Azure subscriptions retrieved successfully"},"data":{"type":"array","description":"List of Azure subscriptions","items":{"type":"object","properties":{"id":{"type":"string","description":"Azure subscription ID"},"name":{"type":"string","description":"Azure subscription name"},"state":{"type":"string","enum":["enabled","warned","past_due","disabled","deleted"],"description":"Azure subscription state"},"azure_tenant_id":{"type":"string","nullable":true,"description":"Azure tenant ID"},"tags":{"type":"array","description":"Azure subscription tags","items":{"type":"object","properties":{"key":{"type":"string","description":"Tag key"},"value":{"type":"string","nullable":true,"description":"Tag value"}},"required":["key"]}},"created_at":{"type":"string","format":"date-time","description":"Subscription creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Subscription last update timestamp"}},"required":["id","name","state","created_at","updated_at","tags"]}}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/azure-subscriptions/{subscriptionId}":{"get":{"operationId":"get_azure_subscription","summary":"Get Azure subscription metadata","tags":["Azure Subscriptions"],"description":"Get Azure subscription metadata including resource groups","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"subscriptionId","required":true,"description":"Azure subscription ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Azure subscription retrieved successfully"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Azure subscription ID"},"name":{"type":"string","description":"Azure subscription name"},"state":{"type":"string","enum":["enabled","warned","past_due","disabled","deleted"],"description":"Azure subscription state"},"azure_tenant_id":{"type":"string","nullable":true,"description":"Azure tenant ID"},"tags":{"type":"array","description":"Azure subscription tags","items":{"type":"object","properties":{"key":{"type":"string","description":"Tag key"},"value":{"type":"string","nullable":true,"description":"Tag value"}},"required":["key"]}},"created_at":{"type":"string","format":"date-time","description":"Subscription creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Subscription last update timestamp"},"resource_groups":{"type":"array","description":"List of resource groups in the subscription","items":{"type":"object","properties":{"id":{"type":"string","description":"Resource group ID"},"name":{"type":"string","description":"Resource group name"},"provisioning_state":{"type":"string","nullable":true,"description":"Resource group provisioning state"},"location":{"type":"string","description":"Resource group location"},"managed_by":{"type":"string","nullable":true,"description":"Resource group managed by"},"state":{"type":"string","enum":["exists","deleted"],"description":"Resource group state"},"tags":{"type":"array","description":"Resource group tags","items":{"type":"object","properties":{"key":{"type":"string","description":"Tag key"},"value":{"type":"string","nullable":true,"description":"Tag value"}},"required":["key"]}},"created_at":{"type":"string","format":"date-time","description":"Resource group creation timestamp"},"updated_at":{"type":"string","format":"date-time","description":"Resource group last update timestamp"}},"required":["id","name","location","state","created_at","updated_at"]}}},"required":["id","name","state","created_at","updated_at","resource_groups"]}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/gcp-projects":{"get":{"operationId":"list_gcp_projects","summary":"List live GCP projects","tags":["GCP Projects"],"description":"List live GCP projects for the authenticated tenant","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"GCP projects retrieved successfully"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Catalog id"},"project_id":{"type":"string","description":"GCP project id. This is the asset account id."},"project_number":{"type":"string"},"name":{"type":"string","description":"GCP resource name, projects/{project_number}"},"display_name":{"type":"string"},"parent":{"type":"string","nullable":true,"description":"Organization or folder resource name"},"state":{"type":"string","enum":["active","delete_requested","deleted","unknown"]},"labels":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string","nullable":true}},"required":["key"]}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","project_id","project_number","name","display_name","state","labels","created_at","updated_at"]}}},"required":["status","message","data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/ibm-scopes":{"get":{"operationId":"list_ibm_scopes","summary":"List IBM scopes","tags":["IBM"],"description":"List distinct IBM COS bucket scopes for the authenticated tenant","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"IBM scopes retrieved successfully"},"data":{"type":"array","items":{"type":"string"},"description":"Distinct IBM scopes available for the tenant"}},"required":["status","message","data"]}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets_count":{"get":{"operationId":"get_assets_count","summary":"Get assets count","tags":["Search"],"description":"Search Ebs Volume","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"ebs":{"type":"number"},"ec2":{"type":"number"},"efs":{"type":"number"},"s3":{"type":"number"},"server":{"type":"number"},"fsx_volumes":{"type":"number"},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":540000,"nullable":true}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/drs_source_servers/{id}":{"get":{"operationId":"get_drs_source_server","summary":"Get DRS source server details","tags":["DRS"],"description":"Get details of a specific DRS source server","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"DRS source server ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"DRS source server details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"aws_source_server_id":{"type":"string"},"asset_id":{"type":"string"},"asset_kind":{"type":"string"},"policy_duration_in_minutes":{"type":"number"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"description":"DRS source server details"}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{asset_id}/drs_source_servers":{"get":{"operationId":"list_drs_source_servers_by_asset_id","summary":"List DRS source servers by asset ID","tags":["DRS"],"description":"Returns all DRS source server rows for the given asset ID. Requires permission to access the asset.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"Asset ID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"List of DRS source servers for the asset","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"aws_source_server_id":{"type":"string"},"asset_id":{"type":"string"},"asset_kind":{"type":"string"},"policy_duration_in_minutes":{"type":"number","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"message":{"type":"string"}},"description":"List of DRS source servers for the asset"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/billing":{"get":{"operationId":"get_billing","summary":"Get rolling 12 months billing metrics","tags":["Data"],"description":"Get rolling 12 months billing metrics including assets, non-S3 scanned capacity, and S3 usage (scanned vs protected).","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","description":"Month in YYYY-MM format"},"total_assets":{"type":"string","description":"Number of assets"},"scanned_capacity":{"type":"string","description":"Non-S3 storage high-water mark in TiB"},"s3_scanned":{"type":"string","description":"S3 storage in TiB from scan fallback (buckets without inventory size)"},"s3_protected":{"type":"string","description":"S3 storage in TiB, from the inventoried bucket size"},"total_s3":{"type":"string","description":"Total S3 storage in TiB (s3_scanned + s3_protected)"},"scanned_files":{"type":"string","description":"Deprecated: alias of total_s3. Use total_s3 instead.","deprecated":true},"total":{"type":"string","description":"Total storage in TiB (scanned_capacity + total_s3)"}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/billing-ytd":{"get":{"operationId":"get_billing_ytd","summary":"Get year-to-date billing metrics","tags":["Data"],"description":"Get year-to-date billing metrics including assets, storage scanned, and S3 usage.","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","description":"Month in YYYY-MM format"},"total_assets":{"type":"string","description":"Number of assets"},"scanned_capacity":{"type":"string","description":"Non-S3 storage high-water mark in TiB"},"s3_scanned":{"type":"string","description":"S3 storage in TiB from scan fallback (buckets without inventory size)"},"s3_protected":{"type":"string","description":"S3 storage in TiB, from the inventoried bucket size"},"total_s3":{"type":"string","description":"Total S3 storage in TiB (s3_scanned + s3_protected)"},"scanned_files":{"type":"string","description":"Deprecated: alias of total_s3. Use total_s3 instead.","deprecated":true},"total":{"type":"string","description":"Total storage in TiB (scanned_capacity + total_s3)"}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/billing-details":{"get":{"operationId":"get_billing_details","summary":"Get last 30 days billing details metrics","tags":["Billing"],"description":"Get per-asset billing details for the last 30 calendar days, including daily high-water marks.","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string","description":"Unique identifier for the asset"},"asset_name":{"type":"string","description":"Name of the asset"},"partid":{"type":"string","description":"Partition identifier"},"day":{"type":"string","description":"Date in YYYY-MM-DD format"},"assets":{"type":"string","description":"Number of assets"},"highwatermark_tb":{"type":"string","description":"Non-S3 high watermark in terabytes"},"s3_scanned_tb":{"type":"string","description":"S3 scan fallback storage in terabytes (buckets without inventory size)"},"s3_protected_tb":{"type":"string","description":"S3 protected storage in terabytes from actual bucket inventory size"},"s3_total_tb":{"type":"string","description":"Total S3 storage in terabytes (s3_scanned_tb + s3_protected_tb)"},"s3scanned_tb":{"type":"string","description":"Deprecated: alias of s3_total_tb. Use s3_total_tb instead.","deprecated":true}},"required":["asset_id","asset_name","partid","day","assets","highwatermark_tb","s3_scanned_tb","s3_protected_tb","s3_total_tb","s3scanned_tb"]}}},"required":["data"]}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scan-jobs/{scan_job_id}/report":{"get":{"operationId":"get_scan_job_report","summary":"Get a hunt report by job ID","tags":["Reports"],"description":"Get scan reports by scan job ID and optionally filter by kind","parameters":[{"schema":{"type":"string","enum":["ransomware_scan","malware_scan","fs_check"]},"in":"query","name":"kind","required":false,"description":"Optional filter by scan kind (e.g., ransomware_scan, malware_scan, fs_check)"},{"schema":{"type":"string"},"in":"path","name":"scan_job_id","required":true,"description":"Scan Job ID"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"created_at":{"type":"string"},"status":{"type":"string"},"kind":{"type":"string"},"type":{"type":"string"},"report_data":{"type":"object","nullable":true,"additionalProperties":true,"description":"Report data may be null if no report exists"}}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scans/{scan_id}/report":{"get":{"operationId":"get_scan_report","summary":"Get a hunt report by run ID","tags":["Reports"],"description":"Get scan report data by scan ID. Serves every scan kind: ransomware_scan, malware_scan and entropy_scan come from the stored full report, fs_check comes from the report the scan-ingest worker uploaded to S3.","parameters":[{"schema":{"type":"string"},"in":"path","name":"scan_id","required":true,"description":"Scan ID"}],"responses":{"200":{"description":"The raw report data","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"The raw report data"}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/scans/schedule":{"post":{"operationId":"schedule_scans","summary":"Schedule hunts and investigations","tags":["Scans"],"description":"Schedule scans for AWS assets and backups, and for Azure, IBM, and GCP assets on a standalone (decoupled) scan cluster.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"scans":{"type":"array","description":"List of scans to schedule. Each scan must match one of the supported scan types.","minItems":1,"items":{"type":"object","required":["type"],"discriminator":{"propertyName":"type"},"oneOf":[{"type":"object","description":"Scan an AWS EC2 instance","properties":{"type":{"type":"string","enum":["ec2"],"description":"Scan type discriminator - must be 'ec2'"},"cc_asset_id":{"type":"string","description":"Cloud Connector asset ID (deprecated, kept for compatibility)"},"aws_instance_id":{"type":"string","description":"AWS EC2 instance ID (e.g., i-1234567890abcdef0)"},"aws_region":{"type":"string","description":"AWS region where the instance is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the instance is located"},"scan_type":{"type":"object","description":"Required scan options for the EC2 instance. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","aws_instance_id","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS EBS volume","properties":{"type":{"type":"string","enum":["aws_ebs"],"description":"Scan type discriminator - must be 'aws_ebs'"},"aws_volume_id":{"type":"string","description":"AWS EBS volume ID (e.g., vol-1234567890abcdef0)"},"aws_region":{"type":"string","description":"AWS region where the volume is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the volume is located"},"scan_type":{"type":"object","description":"Required scan options for the EBS volume. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","aws_volume_id","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS EBS snapshot","properties":{"type":{"type":"string","enum":["aws_ebs_snapshot"],"description":"Scan type discriminator - must be 'aws_ebs_snapshot'"},"snapshot_id":{"type":"string","description":"AWS EBS snapshot ID (e.g., snap-1234567890abcdef0)"},"aws_region":{"type":"string","description":"AWS region where the snapshot is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the snapshot is located"},"scan_type":{"type":"object","description":"Required scan options for the EBS snapshot. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","snapshot_id","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS EFS filesystem","properties":{"type":{"type":"string","enum":["aws_efs"],"description":"Scan type discriminator - must be 'aws_efs'"},"fs_id":{"type":"string","description":"AWS EFS filesystem ID (e.g., fs-12345678)"},"selector":{"type":"object","description":"Optional file system selector. If not provided, the entire filesystem will be scanned.","properties":{"path":{"type":"string","description":"Specific path to scan within the filesystem"},"glob":{"type":"string","description":"Glob pattern to match files (e.g., '*.log')"}},"additionalProperties":false},"aws_region":{"type":"string","description":"AWS region where the EFS filesystem is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the EFS filesystem is located"},"scan_type":{"type":"object","description":"Required scan options for the EFS filesystem. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","fs_id","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS S3 bucket","properties":{"type":{"type":"string","enum":["aws_s3"],"description":"Scan type discriminator - must be 'aws_s3'"},"bucket":{"type":"string","description":"S3 bucket name"},"selectors":{"type":"array","description":"Optional list of S3 object selectors. If not provided, the entire bucket will be scanned.","items":{"type":"object","properties":{"prefix":{"type":"string","description":"S3 key prefix to scan (e.g., 'data/important/')"},"key":{"type":"string","description":"Specific S3 object key to scan"},"glob":{"type":"string","description":"Glob pattern to match S3 keys (e.g., '*.csv')"}},"additionalProperties":false}},"aws_region":{"type":"string","description":"AWS region where the S3 bucket is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the S3 bucket is located"},"scan_type":{"type":"object","description":"Required scan options for the S3 bucket. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","bucket","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS Backup EC2 recovery point","properties":{"type":{"type":"string","enum":["aws_backup_ec2_rp"],"description":"Scan type discriminator - must be 'aws_backup_ec2_rp'"},"arn":{"type":"string","description":"ARN of the AWS Backup recovery point (e.g., arn:aws:backup:us-east-1:123456789012:recovery-point:...)"},"aws_vault_name":{"type":"string","description":"Name of the AWS Backup vault where the recovery point is stored"},"aws_region":{"type":"string","description":"AWS region where the recovery point is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the recovery point is located"},"scan_type":{"type":"object","description":"Required scan options for the AWS Backup EC2 recovery point. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","arn","aws_vault_name","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS Backup EBS recovery point","properties":{"type":{"type":"string","enum":["aws_backup_ebs_rp"],"description":"Scan type discriminator - must be 'aws_backup_ebs_rp'"},"arn":{"type":"string","description":"ARN of the AWS Backup recovery point (e.g., arn:aws:backup:us-east-1:123456789012:recovery-point:...)"},"aws_vault_name":{"type":"string","description":"Name of the AWS Backup vault where the recovery point is stored"},"aws_region":{"type":"string","description":"AWS region where the recovery point is located"},"aws_account_id":{"type":"string","description":"AWS account ID where the recovery point is located"},"scan_type":{"type":"object","description":"Required scan options for the AWS Backup EBS recovery point. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","arn","aws_vault_name","aws_region","aws_account_id","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an AWS EC2 AMI on demand (Inspect now for a machine image). Name the target either by asset_id (an aws_ami_family asset; its newest live version is scanned) or by aws_ami_id + aws_region + aws_account_id, never both. Requires Cloud Connector 0.43.42 or later; an older connector is rejected with 400 and error_code cloud_connector_upgrade_required.","properties":{"type":{"type":"string","enum":["aws_ec2_ami"],"description":"Scan type discriminator - must be 'aws_ec2_ami'"},"asset_id":{"type":"string","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$","description":"Catalog id of an aws_ami_family asset. The API resolves it to the family's newest version that is not deregistered. 404 if the asset is not a machine image or has no live version; 403 if the caller may not access it."},"aws_ami_id":{"type":"string","pattern":"^ami-[0-9a-z]+$","description":"AWS AMI ID (e.g., ami-0123456789abcdef0). Requires aws_region and aws_account_id."},"aws_region":{"type":"string","description":"AWS region where the AMI is registered"},"aws_account_id":{"type":"string","description":"AWS account ID that owns the AMI"},"scan_type":{"type":"object","description":"Required scan options for the AMI. At least one option must be true, hunt_rules must be non-empty, or a pursuit playbook must be set.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Enable hunt scanning. Optional; defaults to false. When true, hunt_rules must be a non-empty list of custom hunt rules."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Custom hunt rules to run. Required when hunt is true. If set, hunt scan is enabled even when hunt is false."},"pursuit":{"type":"boolean","description":"Enable pursuit scanning. Optional; defaults to false. Pursuit runs on Windows only: on AWS, and on Azure VMs and managed disks for tenants with Pursuit on Azure enabled. A request that enables pursuit (or sets pursuit_playbook) on an ec2 instance or aws_ec2_ami whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported, and nothing in the batch is scheduled. The error is \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\", or \"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\" for tenants with Pursuit on Azure enabled. A target whose OS is unknown is let through (the scanner decides per volume)."},"pursuit_playbook":{"type":"object","description":"Pursuit playbook to run. Specify exactly one of custom or built_in. If set, pursuit is enabled even when pursuit is false. Known built-in names include persistence, persistence-optimized, and persistence.too-strict; other names are passed through.","properties":{"custom":{"type":"string","description":"Name of a custom pursuit playbook registered in the scan cluster."},"built_in":{"type":"string","description":"Name of a built-in playbook shipped in the scan image (for example persistence, persistence-optimized, persistence.too-strict)."}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan Elastio recovery points","properties":{"type":{"type":"string","enum":["erp_scan"],"description":"Scan type discriminator - must be 'erp_scan'"},"recovery_points":{"type":"array","description":"List of Elastio recovery points to scan","minItems":1,"items":{"type":"object","properties":{"recovery_point_id":{"type":"string","description":"Cloud Connector recovery point ID in human-readable string form"},"cc_id":{"type":"string","description":"Cloud Connector ID (UUID) that stores the recovery point"},"cc_vault_id":{"type":"string","description":"Cloud Connector vault ID (known to Cloud Connector). Optional field."},"shard":{"type":"string","description":"Shard of the vault where the recovery point is stored"}},"required":["recovery_point_id","cc_id","shard"],"additionalProperties":false}},"scan_type":{"type":"object","description":"Required scan options for Elastio recovery points. At least one option must be true.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning"},"ransomware":{"type":"boolean","description":"Enable ransomware scanning"},"fs_check":{"type":"boolean","description":"Enable filesystem check"}},"required":["malware","ransomware","fs_check"],"additionalProperties":false}},"required":["type","recovery_points","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an Azure virtual machine on a standalone scan cluster","properties":{"type":{"type":"string","enum":["azure_vm"],"description":"Scan type discriminator - must be 'azure_vm'"},"virtual_machine_id":{"type":"string","minLength":1,"description":"Azure Resource ID of the virtual machine (ARM ID)"},"subscription_id":{"type":"string","minLength":1,"description":"Azure subscription ID that owns the resource"},"region":{"type":"string","minLength":1,"description":"Azure region of the resource"},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this subscription and region."},"disk_ids":{"type":"array","items":{"type":"string"},"description":"Optional ARM IDs of attached disks. Omitted or empty lets the cluster use its local inventory."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","virtual_machine_id","subscription_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an Azure managed disk on a standalone scan cluster","properties":{"type":{"type":"string","enum":["azure_managed_disk"],"description":"Scan type discriminator - must be 'azure_managed_disk'"},"disk_id":{"type":"string","minLength":1,"description":"Azure Resource ID of the managed disk (ARM ID)"},"subscription_id":{"type":"string","minLength":1,"description":"Azure subscription ID that owns the resource"},"region":{"type":"string","minLength":1,"description":"Azure region of the resource"},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this subscription and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","disk_id","subscription_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an Azure blob container on a standalone scan cluster","properties":{"type":{"type":"string","enum":["azure_blob_container"],"description":"Scan type discriminator - must be 'azure_blob_container'"},"container_id":{"type":"string","minLength":1,"description":"Azure Resource ID of the blob container (ARM ID)"},"subscription_id":{"type":"string","minLength":1,"description":"Azure subscription ID that owns the resource"},"region":{"type":"string","minLength":1,"description":"Azure region of the resource"},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this subscription and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","container_id","subscription_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an Azure machine image on demand (Inspect now): a Compute Gallery image or a managed image. Queued on the subscription's standalone scan cluster as an elastio:azure:machine-image:restore-and-scan job, which restores the image's disks and scans them. Name the target either by asset_id (an azure_gallery_image or azure_managed_image asset; a gallery image restores its latest version) or by image_id + region, never both. Rejected with 400 when Azure machine images are not enabled for your tenant. Needs scan cluster multicloud-azure-cluster-v0.43.45 or later; a cluster known to be older is rejected with 400 and error_code cloud_connector_upgrade_required (a cluster whose version is unknown is allowed).","properties":{"type":{"type":"string","enum":["azure_machine_image"],"description":"Scan type discriminator - must be 'azure_machine_image'"},"asset_id":{"type":"string","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$","description":"Catalog id of an azure_gallery_image or azure_managed_image asset. The API resolves the image's ARM id, subscription and region. 404 if the asset is not an Azure machine image or has no live version; 403 if the caller may not access it."},"image_id":{"type":"string","minLength":1,"description":"ARM id of a gallery image definition (/subscriptions/S/resourceGroups/R/providers/Microsoft.Compute/galleries/G/images/I; its latest version is restored), of one gallery image version (.../images/I/versions/V), or of a managed image (.../providers/Microsoft.Compute/images/M). Requires region. Community gallery and marketplace images are not supported."},"subscription_id":{"type":"string","minLength":1,"description":"Optional with image_id: must match the subscription in image_id."},"region":{"type":"string","minLength":1,"description":"Azure region of the image (required with image_id); selects the scan cluster."},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this subscription and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an Azure file share on a standalone scan cluster","properties":{"type":{"type":"string","enum":["azure_file_share"],"description":"Scan type discriminator - must be 'azure_file_share'"},"file_share_id":{"type":"string","minLength":1,"description":"Azure Resource ID of the file share (ARM ID)"},"subscription_id":{"type":"string","minLength":1,"description":"Azure subscription ID that owns the resource"},"region":{"type":"string","minLength":1,"description":"Azure region of the resource"},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this subscription and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","file_share_id","subscription_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan an IBM COS bucket on a standalone scan cluster","properties":{"type":{"type":"string","enum":["ibm_cos_bucket"],"description":"Scan type discriminator - must be 'ibm_cos_bucket'"},"bucket_crn":{"type":"string","minLength":1,"description":"IBM Cloud Resource Name of the COS bucket"},"account_id":{"type":"string","minLength":1,"description":"IBM account scope that owns the bucket"},"region":{"type":"string","minLength":1,"description":"IBM location of the bucket (for example us-south or global)"},"selectors":{"type":"array","description":"Optional object selectors. If omitted, the entire bucket is scanned.","items":{"type":"object","properties":{"prefix":{"type":"string","description":"Object key prefix to scan"},"key":{"type":"string","description":"Specific object key to scan"},"glob":{"type":"string","description":"Glob pattern to match object keys"}},"additionalProperties":false}},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this account and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","bucket_crn","account_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan a GCP Compute VM on a standalone scan cluster. An omitted or empty disk_ids scans every attached disk.","properties":{"type":{"type":"string","enum":["gcp_compute_vm"],"description":"Scan type discriminator - must be 'gcp_compute_vm'"},"virtual_machine_id":{"type":"string","minLength":1,"description":"Full VM resource name, projects/{project}/zones/{zone}/instances/{name}"},"project_id":{"type":"string","minLength":1,"description":"GCP project id that owns the resource"},"region":{"type":"string","minLength":1,"description":"Scan-cluster region (for example us-central1). A zone such as us-central1-a is accepted and matched as its region. A multi-region bucket location such as US is not rewritten."},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this project and region."},"disk_ids":{"type":"array","items":{"type":"string"},"description":"Optional full resource names of attached disks. Omitted or empty scans every attached disk."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","virtual_machine_id","project_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan a GCP Compute disk on a standalone scan cluster","properties":{"type":{"type":"string","enum":["gcp_compute_disk"],"description":"Scan type discriminator - must be 'gcp_compute_disk'"},"disk_id":{"type":"string","minLength":1,"description":"Full disk resource name, zonal (projects/{project}/zones/{zone}/disks/{name}) or regional (projects/{project}/regions/{region}/disks/{name})"},"project_id":{"type":"string","minLength":1,"description":"GCP project id that owns the resource"},"region":{"type":"string","minLength":1,"description":"Scan-cluster region (for example us-central1). A zone such as us-central1-a is accepted and matched as its region. A multi-region bucket location such as US is not rewritten."},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this project and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","disk_id","project_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan a GCP Cloud Storage bucket on a standalone scan cluster","properties":{"type":{"type":"string","enum":["gcp_cloud_storage_bucket"],"description":"Scan type discriminator - must be 'gcp_cloud_storage_bucket'"},"resource_name":{"type":"string","minLength":1,"description":"Full bucket resource name, projects/{project}/buckets/{name}"},"project_id":{"type":"string","minLength":1,"description":"GCP project id that owns the resource"},"region":{"type":"string","minLength":1,"description":"Scan-cluster region (for example us-central1). A zone such as us-central1-a is accepted and matched as its region. A multi-region bucket location such as US is not rewritten."},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this project and region."},"selectors":{"type":"array","description":"Optional object selectors. If omitted, the entire bucket is scanned.","items":{"type":"object","properties":{"prefix":{"type":"string","description":"Object key prefix to scan"},"key":{"type":"string","description":"Specific object key to scan"},"glob":{"type":"string","description":"Glob pattern to match object keys"}},"additionalProperties":false}},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","resource_name","project_id","region","scan_type"],"additionalProperties":false},{"type":"object","description":"Scan a GCP machine image on demand. Queued on the project's standalone scan cluster as an elastio:gcp:machine-image:restore-and-scan job, which restores the image's disks and scans them. Name the target either by asset_id (a gcp_compute_machine_image_family; its newest live member is scanned) or by machine_image_id + project_id + region, never both. region selects the scan cluster; the job's zone list stays empty so the cluster uses its own restore zones. Custom images cannot be scanned. Needs scan cluster multicloud-gcp-cluster-v0.43.38 or later; a cluster known to be older is rejected with 400 and error_code cloud_connector_upgrade_required (a cluster whose version is unknown is allowed). Pursuit and custom hunt are rejected.","properties":{"type":{"type":"string","enum":["gcp_compute_machine_image"],"description":"Scan type discriminator - must be 'gcp_compute_machine_image'"},"asset_id":{"type":"string","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$","description":"Catalog id of a gcp_compute_machine_image_family. The API resolves the newest live member's resource name, project and storage location. 404 if the asset is missing, is not a machine-image family, or has no live member; 400 if it is a custom-image family; 403 if the caller may not access it."},"machine_image_id":{"type":"string","pattern":"^projects\\/[^/]+\\/global\\/machineImages\\/[^/]+$","description":"Machine image resource name, projects/{project}/global/machineImages/{name}. Requires project_id and region."},"project_id":{"type":"string","minLength":1,"description":"GCP project id that owns the resource"},"region":{"type":"string","minLength":1,"description":"Scan-cluster region (required with machine_image_id). A zone such as us-central1-a is accepted and matched as its region."},"cluster_name":{"type":"string","minLength":1,"description":"Optional standalone scan cluster name. Required when more than one cluster covers this project and region."},"scan_type":{"type":"object","description":"Custom hunt is not available for Azure, IBM, or GCP on-demand scans. Pursuit is available only on azure_vm and azure_managed_disk targets for tenants with Pursuit on Azure enabled; elsewhere it is rejected with error_code pursuit_not_supported. At least one of malware, ransomware, entropy, data_classification, or (where available) pursuit / pursuit_playbook must be enabled.","properties":{"malware":{"type":"boolean","description":"Enable malware scanning. Optional; defaults to false."},"ransomware":{"type":"boolean","description":"Enable ransomware scanning. Optional; defaults to false."},"entropy":{"type":"boolean","description":"Enable entropy detection scanning. Optional; defaults to false."},"data_classification":{"type":"boolean","description":"Enable data classification scanning. Optional; defaults to false."},"hunt":{"type":"boolean","description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"hunt_rules":{"type":"array","items":{"type":"string"},"description":"Not available for Azure, IBM, or GCP on-demand scans. If present, the request is rejected."},"pursuit":{"type":"boolean","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets."},"pursuit_playbook":{"type":"object","description":"Pursuit on azure_vm and azure_managed_disk targets runs for tenants with Pursuit on Azure enabled, on Windows only: a VM (or the VM a disk is attached to) whose OS is known and not Windows is rejected with 400 and error_code pursuit_not_supported (\"Pursuit is coming soon for Linux. It currently supports Windows on AWS and Azure.\"), and an unknown OS is let through (the scanner decides per volume). pursuit_playbook names one custom or built_in playbook; without one the scanner runs its default built-in playbook. Pursuit on Azure needs an AI provider for the tenant or scan cluster (OpenAI or Azure Foundry); without one the scan fails. Every other case is rejected with 400 and error_code pursuit_not_supported: \"Pursuit on Azure supports Windows virtual machines and managed disks. Blob containers, file shares and machine images are coming soon.\" for other Azure targets when Pursuit on Azure is enabled, \"Pursuit is coming soon for Linux and Azure. It currently supports Windows on AWS only.\" for every Azure target when it is not, and \"Pursuit is coming soon for IBM Cloud and Google Cloud. It currently supports Windows on AWS only.\" for IBM and GCP targets.","properties":{"custom":{"type":"string"},"built_in":{"type":"string"}},"additionalProperties":false}},"additionalProperties":false}},"required":["type","scan_type"],"additionalProperties":false}]}}},"required":["scans"],"additionalProperties":false}}},"required":true},"responses":{"200":{"description":"Successfully scheduled scans","content":{"application/json":{"schema":{"type":"object","description":"Successfully scheduled scans","properties":{"results":{"type":"array","description":"List of scan scheduling results","items":{"type":"object","properties":{"cc_asset_id":{"type":"string","description":"Cloud Connector asset ID (deprecated, empty for most scan types)"},"job_id":{"type":"string","description":"The ID of the scheduled job (UUID in string form)"},"error_message":{"type":"string","description":"Error message if the scan job could not be scheduled"},"queued":{"type":"object","description":"Standalone cluster enqueue result (present when result is queued). Azure, IBM, and GCP on-demand scans do not return a pollable job_id.","properties":{"cluster_name":{"type":"string","description":"Standalone scan cluster that received the job"},"position":{"type":"integer","description":"Action-queue position on that cluster"}},"required":["cluster_name","position"],"additionalProperties":false},"result":{"type":"string","description":"Indicates which result field is set (job_id, error_message, or queued)","enum":["job_id","error_message","queued"]},"resource":{"type":"string","description":"Indicates which resource field is set","enum":["aws_ec2","aws_ebs","aws_ebs_snapshot","aws_efs","aws_s3","aws_backup_ec2_rp","aws_backup_ebs_rp","erp_scan","aws_ec2_ami","azure_vm","azure_managed_disk","azure_blob_container","azure_file_share","azure_machine_image","ibm_cos_bucket","gcp_compute_vm","gcp_compute_disk","gcp_cloud_storage_bucket","gcp_compute_machine_image"]},"aws_ec2":{"type":"object","description":"AWS EC2 resource details (present when resource is aws_ec2)","properties":{"aws_instance_id":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"aws_ebs":{"type":"object","description":"AWS EBS resource details (present when resource is aws_ebs)","properties":{"aws_volume_id":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"aws_ebs_snapshot":{"type":"object","description":"AWS EBS Snapshot resource details (present when resource is aws_ebs_snapshot)","properties":{"snapshot_id":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"aws_efs":{"type":"object","description":"AWS EFS resource details (present when resource is aws_efs)","properties":{"fs_id":{"type":"string"},"selector":{"type":"object","description":"File system tree selector","properties":{"path":{"type":"string"},"glob":{"type":"string"}}},"cc_asset_id":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"aws_s3":{"type":"object","description":"AWS S3 resource details (present when resource is aws_s3)","properties":{"bucket":{"type":"string"},"selectors":{"type":"array","description":"S3 selectors","items":{"type":"object","properties":{"prefix":{"type":"string"},"key":{"type":"string"},"glob":{"type":"string"}}}},"cc_asset_id":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"aws_backup_ec2_rp":{"type":"object","description":"AWS Backup EC2 Recovery Point resource details (present when resource is aws_backup_ec2_rp)","properties":{"arn":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"aws_backup_ebs_rp":{"type":"object","description":"AWS Backup EBS Recovery Point resource details (present when resource is aws_backup_ebs_rp)","properties":{"arn":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"erp_scan":{"type":"object","description":"ERP Scan resource details (present when resource is erp_scan)","properties":{"recovery_point_id":{"type":"string"}}},"aws_ec2_ami":{"type":"object","description":"AWS EC2 AMI resource details (present when resource is aws_ec2_ami). For an asset_id request this is the resolved AMI version.","properties":{"aws_ami_id":{"type":"string"},"aws_region":{"type":"string"},"aws_account_id":{"type":"string"}}},"azure_vm":{"type":"object","description":"Azure VM resource details (present when resource is azure_vm)","properties":{"virtual_machine_id":{"type":"string"},"subscription_id":{"type":"string"},"region":{"type":"string"}}},"azure_managed_disk":{"type":"object","description":"Azure managed disk resource details (present when resource is azure_managed_disk)","properties":{"disk_id":{"type":"string"},"subscription_id":{"type":"string"},"region":{"type":"string"}}},"azure_blob_container":{"type":"object","description":"Azure blob container resource details (present when resource is azure_blob_container)","properties":{"container_id":{"type":"string"},"subscription_id":{"type":"string"},"region":{"type":"string"}}},"azure_file_share":{"type":"object","description":"Azure file share resource details (present when resource is azure_file_share)","properties":{"file_share_id":{"type":"string"},"subscription_id":{"type":"string"},"region":{"type":"string"}}},"azure_machine_image":{"type":"object","description":"Azure machine image resource details (present when resource is azure_machine_image). For an asset_id request, image_id is the resolved image ARM id.","properties":{"asset_id":{"type":"string","nullable":true,"description":"The asset_id the request named, or null for an image_id request."},"image_id":{"type":"string"},"subscription_id":{"type":"string"},"region":{"type":"string"}}},"ibm_cos_bucket":{"type":"object","description":"IBM COS bucket resource details (present when resource is ibm_cos_bucket)","properties":{"bucket_crn":{"type":"string"},"account_id":{"type":"string"},"region":{"type":"string"}}},"gcp_compute_vm":{"type":"object","description":"GCP Compute VM resource details (present when resource is gcp_compute_vm)","properties":{"virtual_machine_id":{"type":"string"},"project_id":{"type":"string"},"region":{"type":"string"}}},"gcp_compute_disk":{"type":"object","description":"GCP Compute disk resource details (present when resource is gcp_compute_disk)","properties":{"disk_id":{"type":"string"},"project_id":{"type":"string"},"region":{"type":"string"}}},"gcp_cloud_storage_bucket":{"type":"object","description":"GCP Cloud Storage bucket resource details (present when resource is gcp_cloud_storage_bucket)","properties":{"resource_name":{"type":"string"},"project_id":{"type":"string"},"region":{"type":"string"}}},"gcp_compute_machine_image":{"type":"object","description":"GCP machine image resource details (present when resource is gcp_compute_machine_image). For an asset_id request, machine_image_id is the newest live member.","properties":{"asset_id":{"type":"string","nullable":true,"description":"The asset_id the request named, or null for a machine_image_id request."},"machine_image_id":{"type":"string"},"project_id":{"type":"string"},"region":{"type":"string"}}}}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{asset_id}/custom-hunts":{"get":{"operationId":"list_hunt_scans_for_asset","summary":"List custom hunt runs for an asset","tags":["Custom Hunts"],"description":"Returns custom hunt scans associated with a given asset. For EC2 instances and Azure VMs, also includes hunts on attached volumes/disks.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"in":"query","name":"page_size","required":false,"description":"Number of results per page. Used on the first request; subsequent pages use page_token."},{"schema":{"type":"string"},"in":"query","name":"page_token","required":false,"description":"Opaque pagination token from a previous response (next_page_token or prev_page_token)."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"start_date","required":false,"description":"Start of the time range filter. Defaults to 6 months ago."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"end_date","required":false,"description":"End of the time range filter. Defaults to now."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"Asset ID to list hunt scans for"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"hunt_scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true},"target_asset":{"type":"object","nullable":true,"description":"The asset this run targeted. kind is the raw asset kind (for example, ebs_volume).","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","generic_host","ova_server","fsx_ontap_volume","azure_storage_blob_container","azure_compute_disk","azure_compute_vm","ibm_cos_bucket","azure_storage_file_share","aws_ami_family","azure_gallery_image","azure_managed_image","gcp_compute_vm","gcp_compute_disk","gcp_cloud_storage_bucket","gcp_compute_image_family","gcp_compute_machine_image_family"],"description":"Raw asset kind"},"name":{"type":"string","nullable":true}}},"report_location":{"type":"object","properties":{"bucket":{"type":"string"},"key":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"integer"}}}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/custom-hunts/{hunt_scan_id}":{"get":{"operationId":"get_hunt_scan_by_id","summary":"Get a custom hunt run by ID","tags":["Custom Hunts"],"description":"Returns a single custom hunt scan with its associated queries. RBAC is enforced based on the asset the hunt scan belongs to.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"hunt_scan_id","required":true,"description":"Hunt scan ID"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"hunt_scan":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true},"target_asset":{"type":"object","nullable":true,"description":"The asset this run targeted. kind is the raw asset kind (for example, ebs_volume).","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","generic_host","ova_server","fsx_ontap_volume","azure_storage_blob_container","azure_compute_disk","azure_compute_vm","ibm_cos_bucket","azure_storage_file_share","aws_ami_family","azure_gallery_image","azure_managed_image","gcp_compute_vm","gcp_compute_disk","gcp_cloud_storage_bucket","gcp_compute_image_family","gcp_compute_machine_image_family"],"description":"Raw asset kind"},"name":{"type":"string","nullable":true}}},"report_location":{"type":"object","properties":{"bucket":{"type":"string"},"key":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"queries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"hunt_scan_id":{"type":"string","format":"uuid"},"query":{"type":"string"},"raw_json":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/pursuit/summary":{"get":{"operationId":"get_pursuit_summary","summary":"Get the estate Pursuit summary","tags":["Pursuit"],"description":"Availability probe and estate rollup of Pursuit investigations. Defaults to the last 30 days. Machine-image reports (AMI, Azure image, and GCP image-family assets, and AMI-version targets) are excluded, as on the timeline. The lateral movement and incident fields are reserved and always empty, and state is never CONFIRMED_LATERAL. all_clear means no host currently has a low/medium/high/critical report, not that the estate is clean.","parameters":[{"schema":{"type":"string","format":"date-time"},"in":"query","name":"start_date","required":false,"description":"Start of the time range. Defaults to 30 days before end_date. The range cannot exceed 180 days."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"end_date","required":false,"description":"End of the time range. Defaults to now."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["state","all_clear","affected_host_count","incident_count","confirmed_lateral_incident_count","primary_incident_id","active_incident_id","lateral_asset_ids","suspicion_asset_ids","standalone_asset_ids"],"properties":{"state":{"type":"string","enum":["CLEAR","SUSPECTED","CONFIRMED_LATERAL"],"description":"SUSPECTED when at least one host's latest report is low, medium, high, or critical; otherwise CLEAR. CONFIRMED_LATERAL is never returned."},"all_clear":{"type":"boolean","description":"True when state is CLEAR (no low/medium/high/critical latest report)."},"affected_host_count":{"type":"integer","description":"Count of standalone_asset_ids."},"incident_count":{"type":"integer","description":"Always 0. No incident entity is stored."},"confirmed_lateral_incident_count":{"type":"integer","description":"Always 0. Lateral movement is not modeled."},"primary_incident_id":{"type":"string","nullable":true,"description":"Always null. No incident entity is stored."},"active_incident_id":{"type":"string","nullable":true,"description":"Always null. No incident entity is stored."},"lateral_asset_ids":{"type":"array","items":{"type":"string"},"description":"Always empty. Lateral movement is not modeled."},"suspicion_asset_ids":{"type":"array","items":{"type":"string"},"description":"Always empty. Classification buckets are not modeled."},"standalone_asset_ids":{"type":"array","items":{"type":"string"},"description":"Host ids whose latest report is low, medium, high, or critical, ordered by first report time ascending."}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/pursuit/timeline":{"get":{"operationId":"get_pursuit_timeline","summary":"Pursuit timeline","tags":["Pursuit"],"description":"The Pursuit timeline: one item per host, holding the host's latest Pursuit report in the window, kept only when its severity is critical, high, or medium. Items are ordered by time_utc ascending, then id. The same reports always produce the same response. Defaults to the last 30 days; the range cannot exceed 180 days. Results are limited to assets you can view, and volumes and disks are rolled up to their parent host.\n\nReports on machine images (aws_ami_family, azure_gallery_image, azure_managed_image, gcp_compute_image_family, and gcp_compute_machine_image_family assets, or a run whose target is an AMI version) are excluded: images are immutable templates, so only running hosts appear on the timeline. Those reports stay readable through /api/v1/pursuit-scans/{id}, /api/v1/pursuit/reports/{id} and the image's /api/v1/assets/{id}/pursuit-scans.\n\nFreshness: the body carries last_updated_utc, and the response carries a weak ETag plus Cache-Control: private, no-cache. Send If-None-Match to receive 304 until a completed Pursuit run changes the timeline. The ETag covers last_updated_utc and data only, not the echoed window, so polling without an explicit window still revalidates.","parameters":[{"schema":{"type":"string","format":"date-time"},"in":"query","name":"start_date","required":false,"description":"Start of the time range. Defaults to 30 days before end_date. The range cannot exceed 180 days."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"end_date","required":false,"description":"End of the time range. Defaults to now."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["window","last_updated_utc","data"],"properties":{"window":{"type":"object","required":["start_utc","end_utc"],"properties":{"start_utc":{"type":"string","format":"date-time"},"end_utc":{"type":"string","format":"date-time"}},"description":"The resolved time range the items were selected from."},"last_updated_utc":{"type":"string","format":"date-time","nullable":true,"description":"Newest scan-row created_at among the permitted reports in the window, across all suspicion levels. Changes exactly when a completed pursuit job could change this timeline. Null when there are no reports."},"data":{"type":"array","items":{"type":"object","required":["id","asset_id","label","severity","time_utc","finding_count","summary","image_id","image_status"],"properties":{"id":{"type":"string","format":"uuid","description":"ID of the host's latest Pursuit report in the window. A stable key for the item."},"asset_id":{"type":"string","format":"uuid","description":"Host the node belongs to. Volume/disk scans are folded to the parent VM when an attachment exists."},"label":{"type":"string","description":"Host display name, or the asset id when the name is unknown."},"severity":{"type":"string","enum":["medium","high","critical"],"description":"suspicionToSeverity(overall_assessment.suspicion_level). Only critical, high, and medium hosts are returned; low and none are excluded. Never derived from findings[].severity."},"time_utc":{"type":"string","format":"date-time","description":"overall_assessment.highest_suspicion_anchor_utc, else report_metadata.generated_utc, else the scan row created_at. The node position on the axis."},"finding_count":{"type":"integer","description":"Length of the engine findings array."},"summary":{"type":"string","description":"First sentence of overall_assessment.summary."},"image_id":{"type":"string","nullable":true,"description":"The scanned machine image from report_metadata.mount_path when its tail is an image id (ami-…, az-img-…, Azure /images/ resource id); otherwise null."},"image_status":{"type":"string","enum":["clean","findings"],"description":"clean when suspicion_level is none or low, findings otherwise. Always findings for a returned item; the field is kept so the FE badge reads it verbatim."}}}}}}}}},"304":{"description":"If-None-Match matched the current ETag; the timeline has not changed."},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/pursuit/reports":{"get":{"operationId":"list_pursuit_reports","summary":"List Pursuit persistence reports","tags":["Pursuit"],"description":"One row per Pursuit report in the time window. Defaults to the last 30 days; the range cannot exceed 180 days. Paginated with page_size (default 50) and page_token, like the Pursuit investigations list. Results are limited to assets you can view, and volumes and disks are rolled up to their parent host. Severity is overall_assessment.suspicion_level, never the highest finding severity.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"in":"query","name":"page_size","required":false,"description":"Number of results per page. Used on the first request; subsequent pages use page_token."},{"schema":{"type":"string"},"in":"query","name":"page_token","required":false,"description":"Opaque pagination token from a previous response (next_page_token or prev_page_token)."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"start_date","required":false,"description":"Start of the time range. Defaults to 30 days before end_date. The range cannot exceed 180 days."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"end_date","required":false,"description":"End of the time range. Defaults to now."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["reports","pagination"],"properties":{"reports":{"type":"array","items":{"type":"object","required":["report_id","asset_ref","generated_utc","highest_suspicion_anchor_utc","ingested_utc","suspicion_level","summary","finding_count","image_id"],"properties":{"report_id":{"type":"string","format":"uuid","description":"Pursuit report ID"},"asset_ref":{"type":"object","required":["id","kind","name"],"properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","generic_host","ova_server","fsx_ontap_volume","azure_storage_blob_container","azure_compute_disk","azure_compute_vm","ibm_cos_bucket","azure_storage_file_share","aws_ami_family","azure_gallery_image","azure_managed_image","gcp_compute_vm","gcp_compute_disk","gcp_cloud_storage_bucket","gcp_compute_image_family","gcp_compute_machine_image_family"]},"name":{"type":"string","nullable":true}},"description":"Host the report is attributed to. Volume/disk scans are folded to the parent VM when an attachment exists."},"generated_utc":{"type":"string","format":"date-time","description":"report_metadata.generated_utc, or the scan row created_at when that value is missing or unparsable."},"highest_suspicion_anchor_utc":{"type":"string","format":"date-time","description":"overall_assessment.highest_suspicion_anchor_utc when the engine report carries a parseable one, otherwise generated_utc."},"ingested_utc":{"type":"string","format":"date-time","description":"When the completed Pursuit run was recorded. Drives last_updated_utc on /pursuit/timeline."},"suspicion_level":{"type":"string","enum":["none","low","medium","high","critical"],"description":"overall_assessment.suspicion_level from the engine report."},"summary":{"type":"string","description":"overall_assessment.summary from the engine report."},"finding_count":{"type":"integer","description":"Length of the engine findings array."},"image_id":{"type":"string","nullable":true,"description":"The scanned machine image from report_metadata.mount_path when its tail is an image id (ami-…, az-img-…, Azure /images/ resource id); otherwise null."}}}},"pagination":{"type":"object","required":["next_page_token","prev_page_token","total_count"],"properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"integer"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/pursuit/reports/{report_id}":{"get":{"operationId":"get_pursuit_report","summary":"Get one Pursuit persistence report","tags":["Pursuit"],"description":"The engine's persistence report document for one Pursuit investigation, served flat and verbatim, plus `text_report`, the plain-text analysis, in the same body. `report_id` is the same ID `GET /api/v1/pursuit/reports` returns and `/api/v2/threats` carries on a pursuit row. Sections are whatever the engine emitted (report_metadata, overall_assessment, findings, evidence, persistence_anchor_inventory, semantic_category_coverage, attack_payload, attack_timeline_reconstruction, executed_binaries_existence_check, lolbins_and_tools_observed, user_writable_driver_load_assessment, edr_av_presence_and_bypass_assessment, firewall_policy_service_change_notes, negative_findings, noise_and_benign_context, errors); an absent section is absent, never an empty stand-in. 404 for an unknown id, an id outside the caller's scope, and a scan with no readable document alike.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"report_id","required":true,"description":"Report ID, as served by the reports index."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"text_report":{"type":"string","description":"The engine's human-readable.txt report (`playbooks[].text`). Absent when the scan carried none."}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/{asset_id}/pursuit-scans":{"get":{"operationId":"list_pursuit_scans_for_asset","summary":"List Pursuit investigations for an asset","tags":["Pursuit Scans"],"description":"Returns pursuit scans associated with a given asset. For EC2 instances and Azure VMs, also includes scans on attached volumes/disks. For an aws_ami_family, an Azure machine image, or a gcp_compute_machine_image_family, includes the scans of every version: matched by the family id the scan target's resource carries and by each version's backup id. Machine-image scans are listed here even though the Pursuit timeline and summary leave them out.","parameters":[{"schema":{"type":"integer","minimum":1,"maximum":500,"default":50},"in":"query","name":"page_size","required":false,"description":"Number of results per page. Used on the first request; subsequent pages use page_token."},{"schema":{"type":"string"},"in":"query","name":"page_token","required":false,"description":"Opaque pagination token from a previous response (next_page_token or prev_page_token)."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"start_date","required":false,"description":"Start of the time range filter. Defaults to 6 months ago."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"end_date","required":false,"description":"End of the time range filter. Defaults to now."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"asset_id","required":true,"description":"Asset ID to list pursuit scans for"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"pursuit_scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true},"target_asset":{"type":"object","nullable":true,"description":"The asset this run targeted. kind is the raw asset kind (for example, ebs_volume).","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","generic_host","ova_server","fsx_ontap_volume","azure_storage_blob_container","azure_compute_disk","azure_compute_vm","ibm_cos_bucket","azure_storage_file_share","aws_ami_family","azure_gallery_image","azure_managed_image","gcp_compute_vm","gcp_compute_disk","gcp_cloud_storage_bucket","gcp_compute_image_family","gcp_compute_machine_image_family"],"description":"Raw asset kind"},"name":{"type":"string","nullable":true}}},"report_location":{"type":"object","properties":{"bucket":{"type":"string"},"key":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"integer"}}}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/pursuit-scans/{pursuit_scan_id}":{"get":{"operationId":"get_pursuit_scan_by_id","summary":"Get a Pursuit investigation by ID","tags":["Pursuit Scans"],"description":"Returns a single pursuit scan including playbook result data. RBAC is enforced based on the asset the pursuit scan belongs to.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"pursuit_scan_id","required":true,"description":"Pursuit scan ID"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"pursuit_scan":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true},"target_asset":{"type":"object","nullable":true,"description":"The asset this run targeted. kind is the raw asset kind (for example, ebs_volume).","properties":{"id":{"type":"string","format":"uuid"},"kind":{"type":"string","enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","generic_host","ova_server","fsx_ontap_volume","azure_storage_blob_container","azure_compute_disk","azure_compute_vm","ibm_cos_bucket","azure_storage_file_share","aws_ami_family","azure_gallery_image","azure_managed_image","gcp_compute_vm","gcp_compute_disk","gcp_cloud_storage_bucket","gcp_compute_image_family","gcp_compute_machine_image_family"],"description":"Raw asset kind"},"name":{"type":"string","nullable":true}}},"report_location":{"type":"object","properties":{"bucket":{"type":"string"},"key":{"type":"string"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"playbooks":{"type":"array","items":{"type":"object","properties":{"playbook":{"type":"string"},"raw_json":{"type":"string"},"text":{"type":"string"},"soft_errors":{"type":"array"},"statistics":{"type":"object","properties":{"total_analysis_time":{"type":"string"},"total_query_time":{"type":"string"},"total_reconnection_time":{"type":"string"},"input_tokens":{"type":"integer"},"cached_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"context_tokens":{"type":"integer"},"model_context_window":{"type":"integer"},"context_window_usage":{"type":"string"},"model":{"type":"string"},"provider":{"type":"string"},"extra":{"type":"object","additionalProperties":true}}},"experimental_structured":{"type":"object","additionalProperties":true}}}}}}}}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/aws/inventory-scans":{"post":{"operationId":"schedule_aws_inventory_scan","summary":"Schedule an AWS inventory refresh","tags":["Inventory"],"description":"Schedules an AWS inventory scan for the given Cloud Connector and asset account. Only admins can call this endpoint. Limited to one successful call per hour per tenant, Cloud Connector, and asset account combination.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"cloud_connector":{"type":"object","description":"Cloud connector identified by AWS account and region","properties":{"aws_account_id":{"type":"string","pattern":"^\\d{12}$","description":"AWS account ID (12 digits)"},"aws_region":{"type":"string","minLength":1,"description":"AWS region (e.g. us-east-1, eu-west-1)"}},"required":["aws_account_id","aws_region"],"additionalProperties":false},"asset_account_id":{"type":"string","pattern":"^\\d{12}$","description":"AWS account ID, 12 digits (optional). When provided, must be a valid 12-digit AWS account ID."}},"required":["cloud_connector"],"additionalProperties":false}}},"required":true},"responses":{"200":{"description":"Successfully scheduled AWS inventory scan","content":{"application/json":{"schema":{"type":"object","description":"Successfully scheduled AWS inventory scan","properties":{"message":{"type":"string","description":"Response message from the service"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/asset-accounts":{"get":{"operationId":"list_asset_accounts","summary":"List asset accounts by connector","tags":["Asset Accounts"],"description":"Returns asset accounts linked to the given Cloud Connector. Filter by connector AWS account ID and/or region (both optional). Results are scoped to the authenticated tenant and exclude soft-deleted accounts.","parameters":[{"schema":{"type":"string","pattern":"^\\d{12}$"},"in":"query","name":"connector_aws_account_id","required":false,"description":"Optional. Connector AWS account ID (12 digits). When provided, filters by this account."},{"schema":{"type":"string"},"in":"query","name":"connector_aws_region","required":false,"description":"Optional. Connector stack region (e.g. us-east-1). When provided, filters by this region."}],"responses":{"200":{"description":"List of asset accounts for the connector","content":{"application/json":{"schema":{"type":"object","description":"List of asset accounts for the connector","properties":{"asset_accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Asset account UUID"},"aws_account_id":{"type":"string","description":"AWS account ID (12 digits)"},"stack_region":{"type":"string","description":"Stack region (e.g. us-east-1)"},"version":{"type":"string","description":"Asset account version"}},"required":["id","aws_account_id","stack_region","version"]}}},"required":["asset_accounts"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/infected-files":{"get":{"operationId":"list_infected_files","summary":"List files with findings","tags":["Assets"],"description":"Get list of infected files across all assets. Note: Results exclude generic_host assets.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false,"description":"Pagination token"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"},{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Filter threats by kind (comma-separated)"},{"schema":{"type":"boolean","default":false},"in":"query","name":"suppressed","required":false,"description":"Filter by suppression status (default: false)"},{"schema":{"type":"string"},"in":"query","name":"assetType","required":false,"description":"Filter by asset type (comma-separated)"},{"schema":{"type":"string"},"in":"query","name":"assetName","required":false,"description":"Filter by asset name (comma-separated)"},{"schema":{"type":"string"},"in":"query","name":"assetId","required":false,"description":"Filter by catalog asset id (comma-separated). Exact, unlike assetName, which matches on the display name and so cannot distinguish same-named assets or survive a rename. Takes precedence over assetName when both are sent."},{"schema":{"type":"string"},"in":"query","name":"detectedFrom","required":false,"description":"Filter by detected from date (YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"detectedTo","required":false,"description":"Filter by detected to date (YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"id","required":false,"description":"Filter by threat id (comma-separated)"},{"schema":{"type":"string"},"in":"query","name":"accountIds","required":false,"description":"Filter by account id (comma-separated)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Filter by platform (comma-separated). Possible values: aws, azure, on_prem"},{"schema":{"type":"string"},"in":"query","name":"name","required":false,"description":"Filter by threat name (comma-separated)"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search across multiple fields including file location, file name, asset name, asset type, account ID, threat name, threat type, and detected date (case-insensitive substring)"},{"schema":{"type":"boolean","default":false},"in":"query","name":"edrBypass","required":false,"description":"Filter to show only files from assets that have EDR installed but still got infected (EDR bypass)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"location":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["malware","ransomware","filesystem_error","encryption"]},"status":{"type":"string","enum":["detected","resolved","ignored","open","acknowledged","suppressed"]},"file_name":{"type":"string"},"detected_at":{"type":"string","format":"date-time"},"suppressed_until":{"type":"string","format":"date-time","nullable":true},"asset_type":{"type":"string","nullable":true,"enum":["ec2_instance","ebs_volume","s3_bucket","efs_filesystem","generic_host","ova_server","fsx_ontap_volume","azure_storage_blob_container","azure_compute_disk","azure_compute_vm","ibm_cos_bucket","azure_storage_file_share"]},"asset_name":{"type":"string","nullable":true},"account_id":{"type":"string","nullable":true},"platform":{"type":"string","nullable":true,"enum":["aws","azure","ibm","on_prem"],"description":"Platform where the asset is located. Possible values: aws, azure, ibm, on_prem"},"storage_account":{"type":"string","nullable":true,"description":"Storage account name (only present for Azure blob containers)"},"sha256":{"type":"string","nullable":true,"description":"SHA256 hash of the file"},"size_bytes":{"type":"number","nullable":true,"description":"Size of the affected file in bytes, as reported by the scan. Null when the scan reported no file metadata"},"mtime":{"type":"string","format":"date-time","nullable":true,"description":"Modification time of the affected file, as reported by the scan. Null when the scan reported no file metadata"},"asset_item":{"type":"object","description":"Present when the threat is filed against an asset item rather than the parent asset","properties":{"id":{"type":"string"},"asset_item_kind":{"type":"string","enum":["generic_asset_item","s3_bucket_item","azure_storage_blob_item","ibm_cos_bucket_item"]},"displayable_name":{"type":"string"},"asset_id":{"type":"string"},"generic_asset_item_kind":{"type":"string","nullable":true,"enum":["file","local_disk","local_volume","stream"],"description":"Item subtype from generic_asset_items. Null for object-storage items."},"cc_asset_id":{"type":"string"}}}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/s3-buckets/{awsS3BucketId}/infected-objects/last-clean-version":{"get":{"operationId":"list_s3_infected_objects_last_clean_version","summary":"List S3 objects with findings and their last clean version","tags":["Assets"],"description":"Get objects for an S3 bucket that currently have active (detected and not suppressed) threats and have a last clean version available. The awsS3BucketId path parameter must be URL-encoded.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false,"description":"Pagination token"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"},{"schema":{"type":"string"},"in":"query","name":"objectPath","required":false,"description":"Optional object path search filter (case-insensitive partial match)."},{"schema":{"type":"string"},"in":"path","name":"awsS3BucketId","required":true,"description":"External S3 bucket id (aws_s3_bucket_id). URL-encoded in path if it contains spaces."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Last clean object versions"},"data":{"type":"object","properties":{"bucket_id":{"type":"string"},"object_versioning_enabled":{"type":"boolean"},"items":{"type":"array","items":{"type":"object","properties":{"object_path":{"type":"string"},"clean_version_aws_version_id":{"type":"string"},"clean_version_timestamp":{"type":"string","format":"date-time"},"threat_id":{"type":"string"},"threat_name":{"type":"string"},"threat_kind":{"type":"string"},"threat_detected_at":{"type":"string","format":"date-time"},"threat_sha256":{"type":"string","nullable":true}},"required":["object_path","clean_version_aws_version_id","clean_version_timestamp","threat_id","threat_name","threat_kind","threat_detected_at"]}}},"required":["bucket_id","object_versioning_enabled","items"]},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/s3-buckets/{s3BucketId}/aws-s3-threat-hunts/{s3ThreatHuntJobId}/scanned-objects":{"get":{"operationId":"list_aws_s3_threat_hunt_scanned_objects","summary":"List the objects an AWS S3 hunt covered in a bucket","tags":["Jobs"],"description":"Returns objects scanned by an AWS S3 hunt for a bucket.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false,"description":"Pagination token (base64-encoded JSON with page number)"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Results per page (1–100)"},{"schema":{"type":"string"},"in":"query","name":"objectPath","required":false,"description":"Optional object path filter (case-insensitive partial match)"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"hasLastKnownClean","required":false,"description":"Optional filter: true for objects with clean version info, false for objects missing clean version info."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"s3BucketId","required":true,"description":"S3 bucket uuid"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"s3ThreatHuntJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string"},"data":{"type":"object","properties":{"s3_bucket_id":{"type":"string","format":"uuid"},"aws_s3_bucket_id":{"type":"string"},"s3_threat_hunt_job_id":{"type":"string","format":"uuid"},"total_objects_scanned":{"type":"number"},"total_objects_with_last_known_clean":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"object_path":{"type":"string"},"clean_version_aws_version_id":{"type":"string","nullable":true},"clean_version_timestamp":{"type":"string","format":"date-time","nullable":true}},"required":["object_path"]}}},"required":["s3_bucket_id","aws_s3_bucket_id","s3_threat_hunt_job_id","total_objects_scanned","total_objects_with_last_known_clean","items"]},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/ibm-cos-buckets/{ibmCosBucketId}/ibm-cos-bucket-threat-hunts/{ibmCosBucketThreatHuntJobId}/scanned-objects":{"get":{"operationId":"list_ibm_cos_bucket_threat_hunt_scanned_objects","summary":"List the objects an IBM COS bucket hunt covered","tags":["Jobs"],"description":"Returns objects scanned by an IBM COS bucket hunt for a bucket.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false,"description":"Pagination token (base64-encoded JSON with page number)"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Results per page (1–100)"},{"schema":{"type":"string"},"in":"query","name":"objectPath","required":false,"description":"Optional object path filter (case-insensitive partial match)"},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"hasLastKnownClean","required":false,"description":"Optional filter: true for objects with clean version info, false for objects missing clean version info."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"ibmCosBucketId","required":true,"description":"IBM COS bucket uuid"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"ibmCosBucketThreatHuntJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string"},"data":{"type":"object","properties":{"ibm_cos_bucket_id":{"type":"string","format":"uuid"},"ibm_cos_bucket_name":{"type":"string"},"ibm_cos_bucket_threat_hunt_job_id":{"type":"string","format":"uuid"},"total_objects_scanned":{"type":"number"},"total_objects_with_last_known_clean":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"object_path":{"type":"string"},"clean_version_id":{"type":"string","nullable":true},"clean_version_timestamp":{"type":"string","format":"date-time","nullable":true}},"required":["object_path"]}}},"required":["ibm_cos_bucket_id","ibm_cos_bucket_name","ibm_cos_bucket_threat_hunt_job_id","total_objects_scanned","total_objects_with_last_known_clean","items"]},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/infected-files-filter-options":{"get":{"operationId":"get_infected_files_filter_options","summary":"Get filter options for files with findings","tags":["Threats"],"description":"Get filter options for infected files including asset names, asset types, threat names, account IDs, and threat types. Note: Filter options exclude generic_host assets for consistency with infected files results.","security":[{"authorization":[]}],"responses":{"200":{"description":"Filter options for infected files","content":{"application/json":{"schema":{"type":"object","description":"Filter options for infected files","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"asset_names":{"type":"array","items":{"type":"string"},"description":"List of asset names"},"asset_types":{"type":"array","items":{"type":"string"},"description":"List of asset types"},"threat_names":{"type":"array","items":{"type":"string"},"description":"List of threat names"},"account_ids":{"type":"array","items":{"type":"string"},"description":"List of account IDs"},"threat_types":{"type":"array","items":{"type":"string"},"description":"List of threat types"},"platforms":{"type":"array","items":{"type":"string"},"description":"List of platforms (aws, azure, on_prem)"}}},"message":{"type":"string","example":"Filter options retrieved successfully"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/issues":{"get":{"operationId":"issues_listing","summary":"List of issues","tags":["Issues"],"description":"Get List of issues","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search query"},{"schema":{"type":"string"},"in":"query","name":"name","required":false,"description":"Name of the issue"},{"schema":{"type":"string"},"in":"query","name":"scan_coverage","required":false,"description":"Scan coverage"},{"schema":{"type":"string"},"in":"query","name":"policy_coverage","required":false,"description":"Filter by direct active policy membership (covered|not_covered). Comma-separated; both values OR. Does not include implied parent coverage. Independent of the no_backup issue type (which remains recovery-based)."},{"schema":{"type":"string"},"in":"query","name":"issue_types","required":false,"description":"List of issue types comma separated"},{"schema":{"type":"string"},"in":"query","name":"asset_type","required":false,"description":"List of asset types comma separated"},{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of AWS account IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"List of platforms comma separated (aws, azure, on_prem, ibm)"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"},{"schema":{"type":"string","enum":["issue","asset"],"default":"issue"},"in":"query","name":"type","required":false,"description":"Response type: 'issue' (default) or 'asset' for unique assets"}],"responses":{"200":{"description":"Filter options for issues list","content":{"application/json":{"schema":{"type":"object","description":"Filter options for issues list","properties":{"status":{"type":"number","example":200},"cached":{"type":"boolean"},"expiresInMs":{"type":"number","nullable":true},"data":{"type":"object","properties":{"total":{"type":"number","example":10},"issues":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"account_id":{"type":"string"},"severity":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"issue_type":{"type":"array","items":{"type":"string"}},"asset_type":{"type":"string"},"platform":{"type":"string","enum":["aws","azure","on_prem"]},"scan_sources":{"type":"array","items":{"type":"string"}},"backup_policy_names":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy field; currently always empty on this endpoint."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"asset_state":{"type":"string","description":"Current state of the asset (e.g., running, stopped, available, etc.)","example":"running"},"message":{"type":"string","nullable":true},"storage_account":{"type":"string","nullable":true,"description":"Storage account name (only present for Azure blob containers)"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}},"message":{"type":"string","example":"Filter options retrieved successfully"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/threat-kind-count":{"get":{"operationId":"threat_kind_count","summary":"Count findings by kind","tags":["Threats"],"description":"Get threat kind count","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"ransomware":{"type":"number"},"malware":{"type":"number"},"filesystemError":{"type":"number"},"insiderThreat":{"type":"number"},"infectedFiles":{"type":"number"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":540000,"nullable":true},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/infections":{"get":{"operationId":"get_infections","summary":"Count findings by type","tags":["Threats"],"description":"Get current infections count by type for both assets and files.","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"asset_count":{"type":"number"},"total_asset_count":{"type":"number"},"assets":{"type":"object","properties":{"ransomware":{"type":"number"},"malware":{"type":"number"},"encryptions":{"type":"number"},"filesystem_corruption":{"type":"number"},"edr_bypass":{"type":"number"}}},"files":{"type":"object","properties":{"ransomware":{"type":"number"},"malware":{"type":"number"},"encryptions":{"type":"number"},"filesystem_corruption":{"type":"number"},"edr_bypass":{"type":"number"}}}}},"cached":{"type":"boolean"},"expiresInMs":{"type":"number"},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/system-optimizations":{"get":{"operationId":"get_system_optimizations","summary":"Get all system optimizations","tags":["Threats"],"description":"Get system optimization counts by type for both assets and files. Defaults to past 30 days if no date range provided.","parameters":[{"schema":{"type":"string","format":"date-time"},"in":"query","name":"start_date","required":false,"description":"Start date for filtering recovery points and scans (ISO 8601 format). Defaults to 30 days ago if not provided."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"end_date","required":false,"description":"End date for filtering recovery points and scans (ISO 8601 format). Defaults to current date if not provided."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"asset_count":{"type":"number"},"total_asset_count":{"type":"number"},"assets":{"type":"object","properties":{"no_backup":{"type":"number"},"unscanned":{"type":"number"},"unattached":{"type":"number"},"scan_errors":{"type":"number"}}},"files":{"type":"object","properties":{"no_backup":{"type":"number"},"unscanned":{"type":"number"},"unattached":{"type":"number"},"scan_errors":{"type":"number"}}}}},"cached":{"type":"boolean"},"expiresInMs":{"type":"number"},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/early-access/features":{"get":{"operationId":"list_early_access_features","summary":"List early access features","tags":["Early Access"],"description":"Retrieve a list of available early access features and their status","parameters":[{"schema":{"type":"string"},"in":"query","name":"pageToken","required":false,"description":"Pagination token for retrieving the next set of results"},{"schema":{"type":"integer","default":10,"minimum":1,"maximum":100},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the feature"},"name":{"type":"string","description":"Name of the early access feature"},"description":{"type":"string","description":"Description of the feature"},"enabled":{"type":"boolean","description":"Whether the feature is enabled"}}}},"pagination":{"type":"object","properties":{"nextPageToken":{"type":"string","description":"Token for the next page of results (only present if there are more results)"},"prevPageToken":{"type":"string","description":"Token for the previous page of results (only present if not on the first page)"},"totalCount":{"type":"number"}}},"message":{"type":"string","example":"Early access features retrieved successfully"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/early-access/features/{featureId}/toggle":{"post":{"operationId":"toggle_early_access_feature","summary":"Toggle early access feature","tags":["Early Access"],"description":"Enable or disable an early access feature by its ID","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"Set to true to enable the feature, false to disable"}}}}},"required":true},"parameters":[{"schema":{"type":"string"},"in":"path","name":"featureId","required":true,"description":"Unique identifier of the feature to toggle"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"description":"Successful response","type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the feature"},"name":{"type":"string","description":"Name of the early access feature"},"enabled":{"type":"boolean","description":"Current status of the feature"}}},"message":{"type":"string","example":"Feature status updated successfully"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/threats":{"get":{"operationId":"list_threats","summary":"List findings","tags":["Threats"],"description":"Get list of threats","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Search query"},{"schema":{"type":"string"},"in":"query","name":"name","required":false,"description":"Name of the threat"},{"schema":{"type":"string"},"in":"query","name":"policy_coverage","required":false,"description":"Filter by direct active policy membership (covered|not_covered)."},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"List of severity comma separated"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"List of threat kinds comma separated"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"List of asset kinds comma separated"},{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"List of asset IDs with comma separated"},{"schema":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"in":"query","name":"tags","required":false,"description":"List of tags as key-value pairs"},{"schema":{"type":"string"},"in":"query","name":"account_ids","required":false,"description":"List of AWS account IDs comma separated"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"List of platforms comma separated (aws, azure, on_prem, ibm)"},{"schema":{"type":"boolean"},"in":"query","name":"edr_bypass","required":false,"description":"Filter to show only assets with EDR that have threats (EDR bypass). Only applies when type=asset."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"name":{"type":"string"},"threat_kind":{"type":"string"},"asset_kind":{"type":"string"},"account_id":{"type":"string"},"platform":{"type":"string","description":"Platform of the asset (aws, azure, on_prem)"},"subscription":{"type":"string","nullable":true,"description":"Subscription ID (AWS account ID, Azure subscription ID, OVA account ID)"},"region":{"type":"string"},"scan_sources":{"type":"string"},"severity":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"backup_policy_names":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized policy display names (AWS only; often empty for other platforms)."},"policies":{"type":"array","description":"Direct active policy memberships for this asset.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"asset_state":{"type":"string","description":"Current state of the asset (e.g., running, stopped, available, etc.)","example":"running"},"storage_account":{"type":"string","nullable":true,"description":"Storage account name (only present for Azure blob containers)"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/threats/definitions":{"get":{"operationId":"list_threat_definitions_v2","summary":"Get supported finding definitions","tags":["Threats"],"description":"Returns the catalog of supported v2 threat kinds with human titles and source labels.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"threat_kind":{"type":"string","enum":["ransomware","malware","encryption","filesystem_error","pursuit","custom"]},"title":{"type":"string"},"source":{"type":"string"}},"required":["threat_kind","title","source"]}}},"required":["data"]}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/threats":{"get":{"operationId":"list_threats_v2","summary":"List findings (v2)","tags":["Threats"],"description":"Returns hunt-style threat rows for live assets only. Omitted ?status= is open; acknowledged, suppressed and resolved are included when those values (or all) are passed. A virtual machine is hunted through its attached volumes and disks, so their threats are reported on the parent VM row and the attached volume/disk does not get a row of its own; asset_id, asset_kind and search also match the folded volumes and disks. Custom hunt findings are one row per (asset, hunt rule) with threat_kind custom; omitted/open includes acknowledged custom rows. Use GET /api/v2/assets/{assetId}/threats for the per-volume breakdown.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error,pursuit,custom)"},{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"Comma-separated asset IDs (use when expanding an asset group)"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string","enum":["open","acknowledged","suppressed","resolved","all"]},"in":"query","name":"status","required":false,"description":"Filter rows by lifecycle status. Omitted means `open`, at parity with GET /api/v2/violations. `open` matches detections stored as `detected` or `open`. `acknowledged`, `suppressed` (also stored as `ignored`) and `resolved` match those statuses. Pass `all` for every status."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Finding identity. Elastio hunts and pursuit: `threat:{asset_id}:{threat_kind}`. Custom hunts: `threat:{asset_id}:custom:{finding_id}` because one asset can have many custom findings. Pass it to /api/v2/findings/{findingId}."},"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account (blob/file share). IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"kind":{"type":"string","enum":["hunt"]},"threat_kind":{"type":"string","enum":["ransomware","malware","encryption","filesystem_error","pursuit","custom"]},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"count":{"type":"number"},"latest_scan_at":{"type":"string","nullable":true},"attached_assets":{"type":"array","description":"Attached volumes / disks whose threats are reported on this row (VM rows only; empty otherwise). The scan report, the infected files and the underlying threat rows live under these asset ids.","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"}}}},"files_affected":{"type":"number","nullable":true,"description":"True affected-artifact total for this (asset, threat_kind), counted from the detections that back the row rather than from the rollup counters. Counts the detections whose status is open or acknowledged (an expired suppression counts as open) and that carry no unexpired suppressed_until, including a per-file suppression that leaves the status open. Null when no such detection backs the pair, in which case the consumer falls back to `count`."},"signature":{"type":"string","nullable":true,"description":"The detection name those rows recorded, when they agree on exactly one. Null when they carry no name or carry several (see `signatures`). Never the scan-engine vendor or version."},"signatures":{"type":"array","description":"Every distinct name of the detections counted in `files_affected`, most frequent first, capped at 5. Empty when those detections carry no name.","items":{"type":"string"}},"report_id":{"type":"string","nullable":true,"description":"Pursuit only: the report ID, the same ID `GET /api/v1/pursuit/reports` serves and `GET /api/v1/pursuit/reports/{report_id}` resolves. Null for every other `threat_kind`."},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"For Pursuit, the investigation's overall_assessment. For custom hunts, hunt_rule_id and hunt_scan_id. Null for Elastio hunts. Never includes raw hunt query output."},"status":{"type":"string","enum":["open","acknowledged","suppressed","resolved"],"description":"Lifecycle status of the finding."},"status_changed_at":{"type":"string","format":"date-time","nullable":true,"description":"When the status last changed (RFC3339 UTC)."},"suppressed_until":{"type":"string","format":"date-time","nullable":true,"description":"Expiry of an active suppression (RFC3339 UTC); null if not suppressed."},"suppression_reason":{"type":"string","nullable":true,"description":"Reason recorded for an active suppression; null if not suppressed."},"resolved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was resolved (RFC3339 UTC); null if not resolved."},"resolved_by":{"type":"string","nullable":true,"description":"Actor who resolved the finding; null if not resolved."},"resolve_note":{"type":"string","nullable":true,"description":"Optional note recorded at resolve time; null if absent."},"acknowledged_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was acknowledged (RFC3339 UTC); null if not acknowledged."},"acknowledged_by":{"type":"string","nullable":true,"description":"Actor who acknowledged the finding; null if not acknowledged."}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/threats/groups":{"get":{"operationId":"list_threats_v2_groups","summary":"Get v2 finding group summaries","tags":["Threats"],"description":"Lists threat groups with a count per group (for example one row per asset or per severity). Set group_by to choose the grouping. To load the full threat details for a group, call GET /api/v2/threats with the same search and filters, and add the filter for that group (such as asset_id, severity, or policy_id=<group.key>). Groups count the same rows GET /api/v2/threats returns under the same ?status=, so a virtual machine's attached volumes and disks are counted on the VM.","parameters":[{"schema":{"type":"string","enum":["asset","severity","platform","asset_kind","threat_kind","policy"]},"in":"query","name":"group_by","required":true,"description":"Dimension to group by"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error,pursuit,custom)"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string","enum":["open","acknowledged","suppressed","resolved","all"]},"in":"query","name":"status","required":false,"description":"Filter rows by lifecycle status. Omitted means `open`, at parity with GET /api/v2/violations. `open` matches detections stored as `detected` or `open`. `acknowledged`, `suppressed` (also stored as `ignored`) and `resolved` match those statuses. Pass `all` for every status."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size (groups per page)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"group_by":{"type":"string","enum":["asset","severity","platform","asset_kind","threat_kind","policy"]},"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"count":{"type":"number"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/threats/filters":{"get":{"operationId":"list_threats_v2_filters","summary":"Get filter options for v2 findings","tags":["Threats"],"description":"Lists available threat filter options and result counts based on your current search and filter selections. Counts follow GET /api/v2/threats under the same ?status=, so a virtual machine's attached volumes and disks count towards the VM's asset kind.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error,pursuit,custom)"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string","enum":["open","acknowledged","suppressed","resolved","all"]},"in":"query","name":"status","required":false,"description":"Filter rows by lifecycle status. Omitted means `open`, at parity with GET /api/v2/violations. `open` matches detections stored as `detected` or `open`. `acknowledged`, `suppressed` (also stored as `ignored`) and `resolved` match those statuses. Pass `all` for every status."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"severity":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of hunt rows matching this option given all other active filters."}},"required":["value","label","count"]}},"platform":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of hunt rows matching this option given all other active filters."}},"required":["value","label","count"]}},"asset_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of hunt rows matching this option given all other active filters."}},"required":["value","label","count"]}},"threat_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of hunt rows matching this option given all other active filters."}},"required":["value","label","count"]}},"policy_id":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of hunt rows matching this option given all other active filters."}},"required":["value","label","count"]}}},"required":["severity","platform","asset_kind","threat_kind","policy_id"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets":{"get":{"operationId":"list_assets_v2","summary":"Get list of v2 assets (live inventory)","tags":["Assets"],"description":"Returns live assets with health, threats, scans, tags, and policy membership. By default show_attachments is true (attached EBS volumes and Azure disks also appear as top-level rows). Set show_attachments=false to hide attached volumes/disks from the top-level list (they remain nested under EC2/Azure VM parents).","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search by asset name or UUID"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem,gcp)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds. azure_gallery_image and azure_managed_image match only when Azure machine images are enabled for your tenant."},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Comma-separated health states (infected,at_risk,clean)"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error)"},{"schema":{"type":"string"},"in":"query","name":"scan_coverage","required":false,"description":"Comma-separated scan coverage states (covered,not_covered)"},{"schema":{"type":"string"},"in":"query","name":"clean_backup","required":false,"description":"Comma-separated clean backup states (has,missing). has = known clean backup in cache; missing = no known clean backup"},{"schema":{"type":"string"},"in":"query","name":"trigger_sources","required":false,"description":"Comma-separated scan trigger sources (scheduled,event,vendor,guardduty,threat-hunt,wiz,s3-threat-hunt)"},{"schema":{"type":"string"},"in":"query","name":"tags","required":false,"description":"JSON array of tag filters, e.g. [{\"key\":\"Environment\",\"value\":\"prod\"}]"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced for assets with no active policy"},{"schema":{"type":"string"},"in":"query","name":"policy_kind","required":false,"description":"Comma-separated policy kinds (scheduled, event)"},{"schema":{"type":"string"},"in":"query","name":"policy_source","required":false,"description":"Comma-separated event policy sources (e.g. aws.guardduty.finding_raised, wiz.finding_raised)"},{"schema":{"type":"string"},"in":"query","name":"region","required":false,"description":"Comma-separated regions"},{"schema":{"type":"string"},"in":"query","name":"account","required":false,"description":"Comma-separated account identifiers (AWS account id, Azure subscription id, IBM scope, OVA account id)"},{"schema":{"type":"string"},"in":"query","name":"os_kind","required":false,"description":"Comma-separated RAW os_kind values, exact match (e.g. Linux/UNIX,Windows). EC2 and Azure VM rows carry an os_kind; prefer os_family for Windows/Linux bucketing."},{"schema":{"type":"string"},"in":"query","name":"os_family","required":false,"description":"Comma-separated normalized OS families, OR semantics: windows,linux,other,unknown. Any other value is a 400. Only VM rows (ec2_instance, azure_compute_vm) can match; every other kind is excluded when this is set."},{"schema":{"type":"string"},"in":"query","name":"source_image_id","required":false,"description":"Comma-separated AWS AMI ids (each must match ^ami-[0-9a-z]+$, else 400), OR semantics. Returns the instances launched from any of those images: rows whose source_image.image_id is in the list. Only kinds that carry a source image can match (ec2_instance today); every other kind is excluded when this is set. AMI family uuids are NOT accepted: resolve a family to its version AMI ids via GET /api/v2/assets/{id}/machine-image (lineage), or use that response's derived_instances for a single image."},{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"Comma-separated asset UUIDs (use when expanding a group)"},{"schema":{"type":"boolean"},"in":"query","name":"show_attachments","required":false,"description":"When false, hides attached EBS volumes and Azure disks from the top-level list. Defaults to true."},{"schema":{"type":"string"},"in":"query","name":"attachment_status","required":false,"description":"Comma-separated. Only ebs_volume and azure_compute_disk. Possible values: attached, unattached. Independent of show_attachments. Both values together is a no-op. Does not apply to fsx_ontap_volume."},{"schema":{"type":"boolean"},"in":"query","name":"excluded","required":false,"description":"true = assets the data plane skips for inspection; false = the inverse. An asset is excluded when it carries one of the four builtin exclusion tags with any value except exactly 'false' (case-sensitive: an empty or key-only value excludes, and so does 'False'): elastio:exclude (set by the customer), elastio:resource (set by Elastio on its own infrastructure), awsbackup-restore-test (set by AWS Backup restore testing) and elastio:nobackup (deprecated, still honoured). Each key also matches with '.' or '_' in place of ':' (elastio.exclude, elastio_exclude), for GCP and Azure resources that cannot use ':'. elastio:action=scan does not override an exclusion tag. An EBS volume attached to an EC2 instance that carries one of these tags is excluded too. Each row's excluded_reason says which rule applies. Tags are read from the asset's inventoried tags, which today arrive only for AWS (EC2, EBS, S3, EFS, FSx for ONTAP), Azure and GCP assets. On-prem servers (generic hosts, vSphere/OVA servers) and IBM COS buckets currently arrive with no tags, so they never match true and always match false, even when tagged at the source. Also, AWS inventory ingest currently drops an asset tagged elastio:exclude=true or elastio:resource=true from the catalog, so only other values of those two tags (for example key-only) are listed today."},{"schema":{"type":"boolean"},"in":"query","name":"has_pursuit_exception","required":false,"description":"true = only assets that currently have an active Pursuit exception; false = only assets that do not. Omitted = no filter. Honored only when Pursuit exceptions are enabled for your tenant; otherwise the parameter is ignored."},{"schema":{"type":"string"},"in":"query","name":"sort_by","required":false,"description":"Single sort field. Defaults to health descending. Values: ASSET_NAME_ASC, ASSET_NAME_DESC, ASSET_KIND_ASC, ASSET_KIND_DESC, ACCOUNT_ASC, ACCOUNT_DESC, LAST_CLEAN_BACKUP_ASC, LAST_CLEAN_BACKUP_DESC"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location, location_kind and size_bytes (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"},"size_bytes":{"type":"number"}},"additionalProperties":false},"health":{"type":"string","enum":["infected","at_risk","clean"]},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string","nullable":true}}}},"threats":{"type":"object","properties":{"malware":{"type":"number"},"ransomware":{"type":"number"},"encryption":{"type":"number"},"filesystem_error":{"type":"number"},"pursuit":{"type":"number","description":"Current-snapshot pursuit findings with suspicion low/medium/high/critical. Loaded after pagination."},"custom":{"type":"number","description":"Custom hunt match_count summed across this asset's custom hunt findings (detected and acknowledged; expired mutes count as open). Loaded after pagination. VM rows sum attached volumes/disks."}}},"latest_scans":{"type":"object","properties":{"malware":{"type":"string","nullable":true},"ransomware":{"type":"string","nullable":true},"encryption":{"type":"string","nullable":true},"filesystem_check":{"type":"string","nullable":true},"pursuit":{"type":"string","nullable":true,"description":"Latest pursuit snapshot scanned_at for this asset, or null when none exists."},"custom":{"type":"string","nullable":true,"description":"Latest last_detected_at among inbox custom hunt findings for this asset, or null when none exist."}}},"region":{"type":"string","nullable":true},"os_kind":{"type":"string","nullable":true,"description":"RAW OS string off the VM's image: the AWS Image.platform_details value, passed through verbatim. Null on asset kinds that carry no OS of their own (volumes, disks, buckets) and on VMs whose image could not be resolved. This is the same column the os_kind facet and filter read, so the row and the filter always agree. OPEN SET, not an enum: values observed live are Linux/UNIX, Windows, Red Hat Enterprise Linux, Red Hat Enterprise Linux with High Availability and SQL Server Standard, and anything else AWS returns is passed through unchanged. Note a Windows value need not start with \"Windows\" (SQL Server Standard is Windows), so match on the known set rather than a prefix. Bucketing into Windows/Linux is the client's job. azure_compute_vm carries the Azure os disk osType (Windows/Linux); gcp_compute_vm carries the boot disk's license name (e.g. ubuntu-2404-lts, windows-server-2022-dc), else its image project.","example":"Linux/UNIX"},"os_family":{"type":"string","nullable":true,"enum":["windows","linux","other","unknown",null],"description":"Normalized OS family of a VM, derived server-side from os_kind: windows | linux | other | unknown on ec2_instance, azure_compute_vm and gcp_compute_vm rows, null on every kind that has no OS of its own (volumes, disks, buckets, file shares, on-prem servers) and on attachments. unknown means the row IS a VM but its OS string is empty (image unresolved, or the catalog has no OS for it yet); do not read it as Linux. The same SQL expression feeds this column, the os_family facet on /api/v2/assets/filters and the os_family query param, so the row and the filter always agree. Rules: an empty os_kind is unknown; a value containing 'windows' (or starting with 'win') is windows; a value containing linux, unix, ubuntu, suse, red hat, rhel, debian, centos or fedora is linux; a bare 'SQL Server …' value is windows (AWS bills it as Windows); anything else is other. Azure VMs carry the Azure os disk osType (Windows/Linux) in os_kind once the catalog column is populated."},"pursuit_supported":{"type":"boolean","nullable":true,"description":"Whether Pursuit can run on this asset: Windows on AWS, and on Azure VMs for tenants with Pursuit on Azure enabled; Linux coming soon. On ec2_instance rows: true only when os_family is windows, false for linux, other and unknown. On azure_compute_vm rows: the same rule when Pursuit on Azure is enabled for the tenant, otherwise always false. On aws_ami_family, azure_gallery_image and azure_managed_image rows: machine_image.pursuit_supported (always false for Azure images). Null on every other kind and on attachments (no OS of their own). POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows EC2 instance, AMI or Azure VM (400 pursuit_not_supported); without Pursuit on Azure, Azure on-demand scans refuse Pursuit on every OS."},"excluded_reason":{"type":"string","nullable":true,"enum":["elastio_resource","customer_excluded","restore_test","legacy_nobackup","parent_excluded",null],"description":"Why the data plane skips this asset for inspection, or null when it does not. Same rule as the excluded query param. elastio_resource = tagged elastio:resource (Elastio-managed infrastructure); customer_excluded = tagged elastio:exclude; restore_test = tagged awsbackup-restore-test; legacy_nobackup = tagged elastio:nobackup (deprecated); parent_excluded = an EBS volume with no exclusion tag of its own, attached to an EC2 instance that has one. When an asset carries several tags, the first in that order wins."},"ami_details":{"type":"object","nullable":true,"description":"Machine image the VM was launched from. Same shape v1 serves on /assets-list, so a caller can drop the batched v1 lookup. Null on asset kinds with no image and on VMs whose image could not be resolved; populated on exactly the rows that carry an os_kind, since both come from the same image lookup.","properties":{"aws_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"The AMI name, which is NOT an OS name: it is uncontrolled text chosen by whoever built the image (observed live: \"ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-...\", and also \"ntfs3\"). Render it as image provenance, never as the OS."},"location":{"type":"string","nullable":true}}},"source_image":{"type":"object","nullable":true,"description":"Machine image the VM was launched from, with provenance and tracking. Served for ec2_instance, azure_compute_vm (from the VM's storage profile image reference) and gcp_compute_vm (from the boot disk's source image). On ec2_instance it is the same image as ami_details (which stays for compatibility and is AWS only). Null on asset kinds with no image, on attachments, and on VMs whose image is unknown (an Azure VM not inventoried since the image reference was added fills on its next inventory run; a GCP VM booted from a snapshot has no image). No version field yet: a version needs the AMI family lineage, which only exists for images Elastio has scanned; use GET /api/v2/assets/{id}/machine-image on the family for that.","required":["image_id","name","location","provenance","tracked"],"properties":{"image_id":{"type":"string","nullable":true,"description":"AWS: the AMI id (ami-...). Azure: the image ARM id (gallery or managed image), else the marketplace URN publisher:offer:sku:version. GCP: projects/<project>/global/images/<name>."},"name":{"type":"string","nullable":true,"description":"The AMI name: uncontrolled text chosen by the image builder, not an OS name."},"location":{"type":"string","nullable":true,"description":"<owner>/<name>. Owner is the AMI owner on AWS; on Azure the image's subscription id, azure-marketplace, shared-gallery or community-gallery; on GCP the image project."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"Read off the owner segment of location (text before the first '/'): aws-marketplace or azure-marketplace is marketplace; the VM's own AWS account id, Azure subscription or GCP project is owned; amazon or any other owner is public (an image shared privately by another account is indistinguishable from a public one here, so it is also public). Null when location is missing or has no owner segment."},"tracked":{"type":"boolean","description":"True when this image id is a live member of an image family in this tenant: a non-deregistered, non-Elastio aws_ami_family version, or a non-deleted gcp_compute_images row. False for Azure, for a public GCP image we do not inventory, and for a GCP VM booted from a snapshot."}}},"machine_image":{"type":"object","nullable":true,"description":"Rollup of an aws_ami_family row, so the Machine Images table needs no per-row call. Null on every other asset kind and on attachments. Derived with the same rules as the lineage of GET /api/v2/assets/{id}/machine-image: versions are the family's live (not deregistered), non-Elastio AMIs. Also set on azure_gallery_image and azure_managed_image rows (listed only when Azure machine images are enabled for your tenant): versions are the image's live (not deleted) versions, current_image_id is the newest one's ARM id, provenance is owned (the image is in the customer's subscription) and in_use_count is 0, since Azure VM inventory records no source image.","required":["provenance","in_use_count","current_image_id","current_version","version_count","hunt_status","last_hunted_at","last_known_clean_version","last_known_clean_image_id","pursuit_assessed","pursuit_suspicion","last_pursuit_at","os_family","pursuit_supported"],"properties":{"discovered_by":{"type":"array","items":{"type":"string","enum":["cloud_connector","aws_iam_role"]},"description":"Every way Elastio inventoried this image's live versions, in a fixed order (cloud_connector first). cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Both when a role-inventoried AMI was also scanned through a connector."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"From the newest version's AMI location, by the same rule as source_image.provenance (aws-marketplace owner is marketplace, the AMI's own account is owned, any other owner is public). With no usable location it is owned: a family only exists for an AMI found in the customer's own account."},"in_use_count":{"type":"integer","description":"Non-terminated EC2 instances in the tenant whose image id is any version of the family (deregistered versions included). Same account inventory only: launch templates, ASGs and other accounts are not counted."},"current_image_id":{"type":"string","description":"AMI id (ami-...) of the newest live version."},"current_version":{"type":"string","description":"Label of the newest live version: the AMI name, or its id when the name is empty (lineage[].version)."},"version_count":{"type":"integer","description":"Number of live versions (lineage length)."},"hunt_status":{"type":"string","enum":["clean","threat","never"],"description":"Verdict of the newest live version, by the lineage rule: any check bad is threat, else malware and ransomware each good or not applicable is clean (the clean-backup rule), else never (lineage baseline)."},"last_hunted_at":{"type":"string","format":"date-time","nullable":true,"description":"Newest hunted_at across the live versions (the completion time of the latest scan of any version). Null when none was scanned."},"last_known_clean_version":{"type":"string","nullable":true,"description":"Label of the newest live version whose hunt_status is clean."},"last_known_clean_image_id":{"type":"string","nullable":true,"description":"AMI id of last_known_clean_version."},"pursuit_assessed":{"type":"boolean","description":"True when the newest live version (current_image_id) has a readable Pursuit report (the newest completed scan whose report parses). False means no readable Pursuit report: Pursuit never ran, or its report could not be read (a coverage gap, not clean). Always false for azure_gallery_image and azure_managed_image: Pursuit does not run on Azure images."},"pursuit_suspicion":{"type":"string","nullable":true,"enum":["none","low","medium","high","critical",null],"description":"Suspicion from the newest readable Pursuit report of the newest live version (current_image_id): its overall_assessment.suspicion_level, the level GET /api/v2/pursuit/reports serves. none when that report says none; null when not assessed. Medium and above is a compromise (the Pursuit timeline threshold); low folds into clean. This is the report-level verdict. The per-finding view is the asset's threats.pursuit / latest_scans.pursuit and GET /api/v2/assets/{id}/threats/pursuit/findings, both read from the findings extracted from that same report, so a compromised verdict normally has findings there too."},"last_pursuit_at":{"type":"string","format":"date-time","nullable":true,"description":"When the newest completed Pursuit scan of the newest live version (current_image_id) was ingested; null when not assessed."},"os_family":{"type":"string","enum":["windows","linux","other","unknown"],"description":"OS family of the newest live version (current_image_id), bucketed by the same rules as the VM row os_family. AMIs: the image's PlatformDetails as posture inventoried it (aws_amis.platform, else a described aws_ami_in_use.platform; e.g. Windows, Linux/UNIX, Windows BYOL). Azure images: the image definition's os_type (Windows/Linux). An AMI posture does not inventory falls back to the PlatformDetails the Cloud Connector reported. unknown when no OS could be read; do not read it as Linux."},"os_source":{"type":"string","nullable":true,"enum":["cloud_connector","aws_iam_role",null],"description":"Where the newest live version (current_image_id)'s os_family was read from: cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Recorded by whoever stored the OS, never guessed: null when os_family is unknown or the source is not recorded."},"pursuit_supported":{"type":"boolean","description":"True only when the newest live version (current_image_id) is an AMI whose os_family is windows: Pursuit runs on Windows on AWS only; Linux and Azure coming soon. False for linux, other and unknown, and always false on Azure images (os_family is still served). An unsupported image is always served pursuit_assessed false and pursuit_suspicion null, so pursuit_supported false tells \"not supported\" apart from \"not yet run\". POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows AMI (400 pursuit_not_supported)."}}},"last_clean_backup":{"type":"object","nullable":true,"description":"Most recent known clean backup for this asset, or null when none exists.","properties":{"backup_id":{"type":"string","format":"uuid"},"kind":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}},"required":["backup_id","kind","timestamp"]},"source_machine_image":{"type":"object","nullable":true,"description":"Machine image a gcp_compute_vm was created from (projects/<project>/global/machineImages/<name>). Null on every other asset kind and on a VM that was not created from a machine image.","required":["image_id","name","tracked"],"properties":{"image_id":{"type":"string"},"name":{"type":"string","nullable":true},"tracked":{"type":"boolean","description":"True when a live gcp_compute_machine_images row has this resource name."}}},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"attachments":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location, location_kind and size_bytes (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"},"size_bytes":{"type":"number"}},"additionalProperties":false},"health":{"type":"string","enum":["infected","at_risk","clean"]},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string","nullable":true}}}},"threats":{"type":"object","properties":{"malware":{"type":"number"},"ransomware":{"type":"number"},"encryption":{"type":"number"},"filesystem_error":{"type":"number"},"pursuit":{"type":"number","description":"Current-snapshot pursuit findings with suspicion low/medium/high/critical. Loaded after pagination."},"custom":{"type":"number","description":"Custom hunt match_count summed across this asset's custom hunt findings (detected and acknowledged; expired mutes count as open). Loaded after pagination. VM rows sum attached volumes/disks."}}},"latest_scans":{"type":"object","properties":{"malware":{"type":"string","nullable":true},"ransomware":{"type":"string","nullable":true},"encryption":{"type":"string","nullable":true},"filesystem_check":{"type":"string","nullable":true},"pursuit":{"type":"string","nullable":true,"description":"Latest pursuit snapshot scanned_at for this asset, or null when none exists."},"custom":{"type":"string","nullable":true,"description":"Latest last_detected_at among inbox custom hunt findings for this asset, or null when none exist."}}},"region":{"type":"string","nullable":true},"os_kind":{"type":"string","nullable":true,"description":"RAW OS string off the VM's image: the AWS Image.platform_details value, passed through verbatim. Null on asset kinds that carry no OS of their own (volumes, disks, buckets) and on VMs whose image could not be resolved. This is the same column the os_kind facet and filter read, so the row and the filter always agree. OPEN SET, not an enum: values observed live are Linux/UNIX, Windows, Red Hat Enterprise Linux, Red Hat Enterprise Linux with High Availability and SQL Server Standard, and anything else AWS returns is passed through unchanged. Note a Windows value need not start with \"Windows\" (SQL Server Standard is Windows), so match on the known set rather than a prefix. Bucketing into Windows/Linux is the client's job. azure_compute_vm carries the Azure os disk osType (Windows/Linux); gcp_compute_vm carries the boot disk's license name (e.g. ubuntu-2404-lts, windows-server-2022-dc), else its image project.","example":"Linux/UNIX"},"os_family":{"type":"string","nullable":true,"enum":["windows","linux","other","unknown",null],"description":"Normalized OS family of a VM, derived server-side from os_kind: windows | linux | other | unknown on ec2_instance, azure_compute_vm and gcp_compute_vm rows, null on every kind that has no OS of its own (volumes, disks, buckets, file shares, on-prem servers) and on attachments. unknown means the row IS a VM but its OS string is empty (image unresolved, or the catalog has no OS for it yet); do not read it as Linux. The same SQL expression feeds this column, the os_family facet on /api/v2/assets/filters and the os_family query param, so the row and the filter always agree. Rules: an empty os_kind is unknown; a value containing 'windows' (or starting with 'win') is windows; a value containing linux, unix, ubuntu, suse, red hat, rhel, debian, centos or fedora is linux; a bare 'SQL Server …' value is windows (AWS bills it as Windows); anything else is other. Azure VMs carry the Azure os disk osType (Windows/Linux) in os_kind once the catalog column is populated."},"pursuit_supported":{"type":"boolean","nullable":true,"description":"Whether Pursuit can run on this asset: Windows on AWS, and on Azure VMs for tenants with Pursuit on Azure enabled; Linux coming soon. On ec2_instance rows: true only when os_family is windows, false for linux, other and unknown. On azure_compute_vm rows: the same rule when Pursuit on Azure is enabled for the tenant, otherwise always false. On aws_ami_family, azure_gallery_image and azure_managed_image rows: machine_image.pursuit_supported (always false for Azure images). Null on every other kind and on attachments (no OS of their own). POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows EC2 instance, AMI or Azure VM (400 pursuit_not_supported); without Pursuit on Azure, Azure on-demand scans refuse Pursuit on every OS."},"excluded_reason":{"type":"string","nullable":true,"enum":["elastio_resource","customer_excluded","restore_test","legacy_nobackup","parent_excluded",null],"description":"Why the data plane skips this asset for inspection, or null when it does not. Same rule as the excluded query param. elastio_resource = tagged elastio:resource (Elastio-managed infrastructure); customer_excluded = tagged elastio:exclude; restore_test = tagged awsbackup-restore-test; legacy_nobackup = tagged elastio:nobackup (deprecated); parent_excluded = an EBS volume with no exclusion tag of its own, attached to an EC2 instance that has one. When an asset carries several tags, the first in that order wins."},"ami_details":{"type":"object","nullable":true,"description":"Machine image the VM was launched from. Same shape v1 serves on /assets-list, so a caller can drop the batched v1 lookup. Null on asset kinds with no image and on VMs whose image could not be resolved; populated on exactly the rows that carry an os_kind, since both come from the same image lookup.","properties":{"aws_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"The AMI name, which is NOT an OS name: it is uncontrolled text chosen by whoever built the image (observed live: \"ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-...\", and also \"ntfs3\"). Render it as image provenance, never as the OS."},"location":{"type":"string","nullable":true}}},"source_image":{"type":"object","nullable":true,"description":"Machine image the VM was launched from, with provenance and tracking. Served for ec2_instance, azure_compute_vm (from the VM's storage profile image reference) and gcp_compute_vm (from the boot disk's source image). On ec2_instance it is the same image as ami_details (which stays for compatibility and is AWS only). Null on asset kinds with no image, on attachments, and on VMs whose image is unknown (an Azure VM not inventoried since the image reference was added fills on its next inventory run; a GCP VM booted from a snapshot has no image). No version field yet: a version needs the AMI family lineage, which only exists for images Elastio has scanned; use GET /api/v2/assets/{id}/machine-image on the family for that.","required":["image_id","name","location","provenance","tracked"],"properties":{"image_id":{"type":"string","nullable":true,"description":"AWS: the AMI id (ami-...). Azure: the image ARM id (gallery or managed image), else the marketplace URN publisher:offer:sku:version. GCP: projects/<project>/global/images/<name>."},"name":{"type":"string","nullable":true,"description":"The AMI name: uncontrolled text chosen by the image builder, not an OS name."},"location":{"type":"string","nullable":true,"description":"<owner>/<name>. Owner is the AMI owner on AWS; on Azure the image's subscription id, azure-marketplace, shared-gallery or community-gallery; on GCP the image project."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"Read off the owner segment of location (text before the first '/'): aws-marketplace or azure-marketplace is marketplace; the VM's own AWS account id, Azure subscription or GCP project is owned; amazon or any other owner is public (an image shared privately by another account is indistinguishable from a public one here, so it is also public). Null when location is missing or has no owner segment."},"tracked":{"type":"boolean","description":"True when this image id is a live member of an image family in this tenant: a non-deregistered, non-Elastio aws_ami_family version, or a non-deleted gcp_compute_images row. False for Azure, for a public GCP image we do not inventory, and for a GCP VM booted from a snapshot."}}},"machine_image":{"type":"object","nullable":true,"description":"Rollup of an aws_ami_family row, so the Machine Images table needs no per-row call. Null on every other asset kind and on attachments. Derived with the same rules as the lineage of GET /api/v2/assets/{id}/machine-image: versions are the family's live (not deregistered), non-Elastio AMIs. Also set on azure_gallery_image and azure_managed_image rows (listed only when Azure machine images are enabled for your tenant): versions are the image's live (not deleted) versions, current_image_id is the newest one's ARM id, provenance is owned (the image is in the customer's subscription) and in_use_count is 0, since Azure VM inventory records no source image.","required":["provenance","in_use_count","current_image_id","current_version","version_count","hunt_status","last_hunted_at","last_known_clean_version","last_known_clean_image_id","pursuit_assessed","pursuit_suspicion","last_pursuit_at","os_family","pursuit_supported"],"properties":{"discovered_by":{"type":"array","items":{"type":"string","enum":["cloud_connector","aws_iam_role"]},"description":"Every way Elastio inventoried this image's live versions, in a fixed order (cloud_connector first). cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Both when a role-inventoried AMI was also scanned through a connector."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"From the newest version's AMI location, by the same rule as source_image.provenance (aws-marketplace owner is marketplace, the AMI's own account is owned, any other owner is public). With no usable location it is owned: a family only exists for an AMI found in the customer's own account."},"in_use_count":{"type":"integer","description":"Non-terminated EC2 instances in the tenant whose image id is any version of the family (deregistered versions included). Same account inventory only: launch templates, ASGs and other accounts are not counted."},"current_image_id":{"type":"string","description":"AMI id (ami-...) of the newest live version."},"current_version":{"type":"string","description":"Label of the newest live version: the AMI name, or its id when the name is empty (lineage[].version)."},"version_count":{"type":"integer","description":"Number of live versions (lineage length)."},"hunt_status":{"type":"string","enum":["clean","threat","never"],"description":"Verdict of the newest live version, by the lineage rule: any check bad is threat, else malware and ransomware each good or not applicable is clean (the clean-backup rule), else never (lineage baseline)."},"last_hunted_at":{"type":"string","format":"date-time","nullable":true,"description":"Newest hunted_at across the live versions (the completion time of the latest scan of any version). Null when none was scanned."},"last_known_clean_version":{"type":"string","nullable":true,"description":"Label of the newest live version whose hunt_status is clean."},"last_known_clean_image_id":{"type":"string","nullable":true,"description":"AMI id of last_known_clean_version."},"pursuit_assessed":{"type":"boolean","description":"True when the newest live version (current_image_id) has a readable Pursuit report (the newest completed scan whose report parses). False means no readable Pursuit report: Pursuit never ran, or its report could not be read (a coverage gap, not clean). Always false for azure_gallery_image and azure_managed_image: Pursuit does not run on Azure images."},"pursuit_suspicion":{"type":"string","nullable":true,"enum":["none","low","medium","high","critical",null],"description":"Suspicion from the newest readable Pursuit report of the newest live version (current_image_id): its overall_assessment.suspicion_level, the level GET /api/v2/pursuit/reports serves. none when that report says none; null when not assessed. Medium and above is a compromise (the Pursuit timeline threshold); low folds into clean. This is the report-level verdict. The per-finding view is the asset's threats.pursuit / latest_scans.pursuit and GET /api/v2/assets/{id}/threats/pursuit/findings, both read from the findings extracted from that same report, so a compromised verdict normally has findings there too."},"last_pursuit_at":{"type":"string","format":"date-time","nullable":true,"description":"When the newest completed Pursuit scan of the newest live version (current_image_id) was ingested; null when not assessed."},"os_family":{"type":"string","enum":["windows","linux","other","unknown"],"description":"OS family of the newest live version (current_image_id), bucketed by the same rules as the VM row os_family. AMIs: the image's PlatformDetails as posture inventoried it (aws_amis.platform, else a described aws_ami_in_use.platform; e.g. Windows, Linux/UNIX, Windows BYOL). Azure images: the image definition's os_type (Windows/Linux). An AMI posture does not inventory falls back to the PlatformDetails the Cloud Connector reported. unknown when no OS could be read; do not read it as Linux."},"os_source":{"type":"string","nullable":true,"enum":["cloud_connector","aws_iam_role",null],"description":"Where the newest live version (current_image_id)'s os_family was read from: cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Recorded by whoever stored the OS, never guessed: null when os_family is unknown or the source is not recorded."},"pursuit_supported":{"type":"boolean","description":"True only when the newest live version (current_image_id) is an AMI whose os_family is windows: Pursuit runs on Windows on AWS only; Linux and Azure coming soon. False for linux, other and unknown, and always false on Azure images (os_family is still served). An unsupported image is always served pursuit_assessed false and pursuit_suspicion null, so pursuit_supported false tells \"not supported\" apart from \"not yet run\". POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows AMI (400 pursuit_not_supported)."}}}}}}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}":{"get":{"operationId":"get_asset_v2","summary":"Get a single live inventory asset by ID","tags":["Assets"],"description":"Returns details for the specified asset, including health, threats, scans, tags, policy membership, and attached volumes and disks for virtual machines.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location, location_kind and size_bytes (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"},"size_bytes":{"type":"number"}},"additionalProperties":false},"health":{"type":"string","enum":["infected","at_risk","clean"]},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string","nullable":true}}}},"threats":{"type":"object","properties":{"malware":{"type":"number"},"ransomware":{"type":"number"},"encryption":{"type":"number"},"filesystem_error":{"type":"number"},"pursuit":{"type":"number","description":"Current-snapshot pursuit findings with suspicion low/medium/high/critical. Loaded after pagination."},"custom":{"type":"number","description":"Custom hunt match_count summed across this asset's custom hunt findings (detected and acknowledged; expired mutes count as open). Loaded after pagination. VM rows sum attached volumes/disks."}}},"latest_scans":{"type":"object","properties":{"malware":{"type":"string","nullable":true},"ransomware":{"type":"string","nullable":true},"encryption":{"type":"string","nullable":true},"filesystem_check":{"type":"string","nullable":true},"pursuit":{"type":"string","nullable":true,"description":"Latest pursuit snapshot scanned_at for this asset, or null when none exists."},"custom":{"type":"string","nullable":true,"description":"Latest last_detected_at among inbox custom hunt findings for this asset, or null when none exist."}}},"region":{"type":"string","nullable":true},"os_kind":{"type":"string","nullable":true,"description":"RAW OS string off the VM's image: the AWS Image.platform_details value, passed through verbatim. Null on asset kinds that carry no OS of their own (volumes, disks, buckets) and on VMs whose image could not be resolved. This is the same column the os_kind facet and filter read, so the row and the filter always agree. OPEN SET, not an enum: values observed live are Linux/UNIX, Windows, Red Hat Enterprise Linux, Red Hat Enterprise Linux with High Availability and SQL Server Standard, and anything else AWS returns is passed through unchanged. Note a Windows value need not start with \"Windows\" (SQL Server Standard is Windows), so match on the known set rather than a prefix. Bucketing into Windows/Linux is the client's job. azure_compute_vm carries the Azure os disk osType (Windows/Linux); gcp_compute_vm carries the boot disk's license name (e.g. ubuntu-2404-lts, windows-server-2022-dc), else its image project.","example":"Linux/UNIX"},"os_family":{"type":"string","nullable":true,"enum":["windows","linux","other","unknown",null],"description":"Normalized OS family of a VM, derived server-side from os_kind: windows | linux | other | unknown on ec2_instance, azure_compute_vm and gcp_compute_vm rows, null on every kind that has no OS of its own (volumes, disks, buckets, file shares, on-prem servers) and on attachments. unknown means the row IS a VM but its OS string is empty (image unresolved, or the catalog has no OS for it yet); do not read it as Linux. The same SQL expression feeds this column, the os_family facet on /api/v2/assets/filters and the os_family query param, so the row and the filter always agree. Rules: an empty os_kind is unknown; a value containing 'windows' (or starting with 'win') is windows; a value containing linux, unix, ubuntu, suse, red hat, rhel, debian, centos or fedora is linux; a bare 'SQL Server …' value is windows (AWS bills it as Windows); anything else is other. Azure VMs carry the Azure os disk osType (Windows/Linux) in os_kind once the catalog column is populated."},"pursuit_supported":{"type":"boolean","nullable":true,"description":"Whether Pursuit can run on this asset: Windows on AWS, and on Azure VMs for tenants with Pursuit on Azure enabled; Linux coming soon. On ec2_instance rows: true only when os_family is windows, false for linux, other and unknown. On azure_compute_vm rows: the same rule when Pursuit on Azure is enabled for the tenant, otherwise always false. On aws_ami_family, azure_gallery_image and azure_managed_image rows: machine_image.pursuit_supported (always false for Azure images). Null on every other kind and on attachments (no OS of their own). POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows EC2 instance, AMI or Azure VM (400 pursuit_not_supported); without Pursuit on Azure, Azure on-demand scans refuse Pursuit on every OS."},"excluded_reason":{"type":"string","nullable":true,"enum":["elastio_resource","customer_excluded","restore_test","legacy_nobackup","parent_excluded",null],"description":"Why the data plane skips this asset for inspection, or null when it does not. Same rule as the excluded query param. elastio_resource = tagged elastio:resource (Elastio-managed infrastructure); customer_excluded = tagged elastio:exclude; restore_test = tagged awsbackup-restore-test; legacy_nobackup = tagged elastio:nobackup (deprecated); parent_excluded = an EBS volume with no exclusion tag of its own, attached to an EC2 instance that has one. When an asset carries several tags, the first in that order wins."},"ami_details":{"type":"object","nullable":true,"description":"Machine image the VM was launched from. Same shape v1 serves on /assets-list, so a caller can drop the batched v1 lookup. Null on asset kinds with no image and on VMs whose image could not be resolved; populated on exactly the rows that carry an os_kind, since both come from the same image lookup.","properties":{"aws_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"The AMI name, which is NOT an OS name: it is uncontrolled text chosen by whoever built the image (observed live: \"ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-...\", and also \"ntfs3\"). Render it as image provenance, never as the OS."},"location":{"type":"string","nullable":true}}},"source_image":{"type":"object","nullable":true,"description":"Machine image the VM was launched from, with provenance and tracking. Served for ec2_instance, azure_compute_vm (from the VM's storage profile image reference) and gcp_compute_vm (from the boot disk's source image). On ec2_instance it is the same image as ami_details (which stays for compatibility and is AWS only). Null on asset kinds with no image, on attachments, and on VMs whose image is unknown (an Azure VM not inventoried since the image reference was added fills on its next inventory run; a GCP VM booted from a snapshot has no image). No version field yet: a version needs the AMI family lineage, which only exists for images Elastio has scanned; use GET /api/v2/assets/{id}/machine-image on the family for that.","required":["image_id","name","location","provenance","tracked"],"properties":{"image_id":{"type":"string","nullable":true,"description":"AWS: the AMI id (ami-...). Azure: the image ARM id (gallery or managed image), else the marketplace URN publisher:offer:sku:version. GCP: projects/<project>/global/images/<name>."},"name":{"type":"string","nullable":true,"description":"The AMI name: uncontrolled text chosen by the image builder, not an OS name."},"location":{"type":"string","nullable":true,"description":"<owner>/<name>. Owner is the AMI owner on AWS; on Azure the image's subscription id, azure-marketplace, shared-gallery or community-gallery; on GCP the image project."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"Read off the owner segment of location (text before the first '/'): aws-marketplace or azure-marketplace is marketplace; the VM's own AWS account id, Azure subscription or GCP project is owned; amazon or any other owner is public (an image shared privately by another account is indistinguishable from a public one here, so it is also public). Null when location is missing or has no owner segment."},"tracked":{"type":"boolean","description":"True when this image id is a live member of an image family in this tenant: a non-deregistered, non-Elastio aws_ami_family version, or a non-deleted gcp_compute_images row. False for Azure, for a public GCP image we do not inventory, and for a GCP VM booted from a snapshot."}}},"machine_image":{"type":"object","nullable":true,"description":"Rollup of an aws_ami_family row, so the Machine Images table needs no per-row call. Null on every other asset kind and on attachments. Derived with the same rules as the lineage of GET /api/v2/assets/{id}/machine-image: versions are the family's live (not deregistered), non-Elastio AMIs. Also set on azure_gallery_image and azure_managed_image rows (listed only when Azure machine images are enabled for your tenant): versions are the image's live (not deleted) versions, current_image_id is the newest one's ARM id, provenance is owned (the image is in the customer's subscription) and in_use_count is 0, since Azure VM inventory records no source image.","required":["provenance","in_use_count","current_image_id","current_version","version_count","hunt_status","last_hunted_at","last_known_clean_version","last_known_clean_image_id","pursuit_assessed","pursuit_suspicion","last_pursuit_at","os_family","pursuit_supported"],"properties":{"discovered_by":{"type":"array","items":{"type":"string","enum":["cloud_connector","aws_iam_role"]},"description":"Every way Elastio inventoried this image's live versions, in a fixed order (cloud_connector first). cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Both when a role-inventoried AMI was also scanned through a connector."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"From the newest version's AMI location, by the same rule as source_image.provenance (aws-marketplace owner is marketplace, the AMI's own account is owned, any other owner is public). With no usable location it is owned: a family only exists for an AMI found in the customer's own account."},"in_use_count":{"type":"integer","description":"Non-terminated EC2 instances in the tenant whose image id is any version of the family (deregistered versions included). Same account inventory only: launch templates, ASGs and other accounts are not counted."},"current_image_id":{"type":"string","description":"AMI id (ami-...) of the newest live version."},"current_version":{"type":"string","description":"Label of the newest live version: the AMI name, or its id when the name is empty (lineage[].version)."},"version_count":{"type":"integer","description":"Number of live versions (lineage length)."},"hunt_status":{"type":"string","enum":["clean","threat","never"],"description":"Verdict of the newest live version, by the lineage rule: any check bad is threat, else malware and ransomware each good or not applicable is clean (the clean-backup rule), else never (lineage baseline)."},"last_hunted_at":{"type":"string","format":"date-time","nullable":true,"description":"Newest hunted_at across the live versions (the completion time of the latest scan of any version). Null when none was scanned."},"last_known_clean_version":{"type":"string","nullable":true,"description":"Label of the newest live version whose hunt_status is clean."},"last_known_clean_image_id":{"type":"string","nullable":true,"description":"AMI id of last_known_clean_version."},"pursuit_assessed":{"type":"boolean","description":"True when the newest live version (current_image_id) has a readable Pursuit report (the newest completed scan whose report parses). False means no readable Pursuit report: Pursuit never ran, or its report could not be read (a coverage gap, not clean). Always false for azure_gallery_image and azure_managed_image: Pursuit does not run on Azure images."},"pursuit_suspicion":{"type":"string","nullable":true,"enum":["none","low","medium","high","critical",null],"description":"Suspicion from the newest readable Pursuit report of the newest live version (current_image_id): its overall_assessment.suspicion_level, the level GET /api/v2/pursuit/reports serves. none when that report says none; null when not assessed. Medium and above is a compromise (the Pursuit timeline threshold); low folds into clean. This is the report-level verdict. The per-finding view is the asset's threats.pursuit / latest_scans.pursuit and GET /api/v2/assets/{id}/threats/pursuit/findings, both read from the findings extracted from that same report, so a compromised verdict normally has findings there too."},"last_pursuit_at":{"type":"string","format":"date-time","nullable":true,"description":"When the newest completed Pursuit scan of the newest live version (current_image_id) was ingested; null when not assessed."},"os_family":{"type":"string","enum":["windows","linux","other","unknown"],"description":"OS family of the newest live version (current_image_id), bucketed by the same rules as the VM row os_family. AMIs: the image's PlatformDetails as posture inventoried it (aws_amis.platform, else a described aws_ami_in_use.platform; e.g. Windows, Linux/UNIX, Windows BYOL). Azure images: the image definition's os_type (Windows/Linux). An AMI posture does not inventory falls back to the PlatformDetails the Cloud Connector reported. unknown when no OS could be read; do not read it as Linux."},"os_source":{"type":"string","nullable":true,"enum":["cloud_connector","aws_iam_role",null],"description":"Where the newest live version (current_image_id)'s os_family was read from: cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Recorded by whoever stored the OS, never guessed: null when os_family is unknown or the source is not recorded."},"pursuit_supported":{"type":"boolean","description":"True only when the newest live version (current_image_id) is an AMI whose os_family is windows: Pursuit runs on Windows on AWS only; Linux and Azure coming soon. False for linux, other and unknown, and always false on Azure images (os_family is still served). An unsupported image is always served pursuit_assessed false and pursuit_suspicion null, so pursuit_supported false tells \"not supported\" apart from \"not yet run\". POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows AMI (400 pursuit_not_supported)."}}},"last_clean_backup":{"type":"object","nullable":true,"description":"Most recent known clean backup for this asset, or null when none exists.","properties":{"backup_id":{"type":"string","format":"uuid"},"kind":{"type":"string"},"timestamp":{"type":"string","format":"date-time"}},"required":["backup_id","kind","timestamp"]},"source_machine_image":{"type":"object","nullable":true,"description":"Machine image a gcp_compute_vm was created from (projects/<project>/global/machineImages/<name>). Null on every other asset kind and on a VM that was not created from a machine image.","required":["image_id","name","tracked"],"properties":{"image_id":{"type":"string"},"name":{"type":"string","nullable":true},"tracked":{"type":"boolean","description":"True when a live gcp_compute_machine_images row has this resource name."}}},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"attachments":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location, location_kind and size_bytes (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"},"size_bytes":{"type":"number"}},"additionalProperties":false},"health":{"type":"string","enum":["infected","at_risk","clean"]},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string","nullable":true}}}},"threats":{"type":"object","properties":{"malware":{"type":"number"},"ransomware":{"type":"number"},"encryption":{"type":"number"},"filesystem_error":{"type":"number"},"pursuit":{"type":"number","description":"Current-snapshot pursuit findings with suspicion low/medium/high/critical. Loaded after pagination."},"custom":{"type":"number","description":"Custom hunt match_count summed across this asset's custom hunt findings (detected and acknowledged; expired mutes count as open). Loaded after pagination. VM rows sum attached volumes/disks."}}},"latest_scans":{"type":"object","properties":{"malware":{"type":"string","nullable":true},"ransomware":{"type":"string","nullable":true},"encryption":{"type":"string","nullable":true},"filesystem_check":{"type":"string","nullable":true},"pursuit":{"type":"string","nullable":true,"description":"Latest pursuit snapshot scanned_at for this asset, or null when none exists."},"custom":{"type":"string","nullable":true,"description":"Latest last_detected_at among inbox custom hunt findings for this asset, or null when none exist."}}},"region":{"type":"string","nullable":true},"os_kind":{"type":"string","nullable":true,"description":"RAW OS string off the VM's image: the AWS Image.platform_details value, passed through verbatim. Null on asset kinds that carry no OS of their own (volumes, disks, buckets) and on VMs whose image could not be resolved. This is the same column the os_kind facet and filter read, so the row and the filter always agree. OPEN SET, not an enum: values observed live are Linux/UNIX, Windows, Red Hat Enterprise Linux, Red Hat Enterprise Linux with High Availability and SQL Server Standard, and anything else AWS returns is passed through unchanged. Note a Windows value need not start with \"Windows\" (SQL Server Standard is Windows), so match on the known set rather than a prefix. Bucketing into Windows/Linux is the client's job. azure_compute_vm carries the Azure os disk osType (Windows/Linux); gcp_compute_vm carries the boot disk's license name (e.g. ubuntu-2404-lts, windows-server-2022-dc), else its image project.","example":"Linux/UNIX"},"os_family":{"type":"string","nullable":true,"enum":["windows","linux","other","unknown",null],"description":"Normalized OS family of a VM, derived server-side from os_kind: windows | linux | other | unknown on ec2_instance, azure_compute_vm and gcp_compute_vm rows, null on every kind that has no OS of its own (volumes, disks, buckets, file shares, on-prem servers) and on attachments. unknown means the row IS a VM but its OS string is empty (image unresolved, or the catalog has no OS for it yet); do not read it as Linux. The same SQL expression feeds this column, the os_family facet on /api/v2/assets/filters and the os_family query param, so the row and the filter always agree. Rules: an empty os_kind is unknown; a value containing 'windows' (or starting with 'win') is windows; a value containing linux, unix, ubuntu, suse, red hat, rhel, debian, centos or fedora is linux; a bare 'SQL Server …' value is windows (AWS bills it as Windows); anything else is other. Azure VMs carry the Azure os disk osType (Windows/Linux) in os_kind once the catalog column is populated."},"pursuit_supported":{"type":"boolean","nullable":true,"description":"Whether Pursuit can run on this asset: Windows on AWS, and on Azure VMs for tenants with Pursuit on Azure enabled; Linux coming soon. On ec2_instance rows: true only when os_family is windows, false for linux, other and unknown. On azure_compute_vm rows: the same rule when Pursuit on Azure is enabled for the tenant, otherwise always false. On aws_ami_family, azure_gallery_image and azure_managed_image rows: machine_image.pursuit_supported (always false for Azure images). Null on every other kind and on attachments (no OS of their own). POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows EC2 instance, AMI or Azure VM (400 pursuit_not_supported); without Pursuit on Azure, Azure on-demand scans refuse Pursuit on every OS."},"excluded_reason":{"type":"string","nullable":true,"enum":["elastio_resource","customer_excluded","restore_test","legacy_nobackup","parent_excluded",null],"description":"Why the data plane skips this asset for inspection, or null when it does not. Same rule as the excluded query param. elastio_resource = tagged elastio:resource (Elastio-managed infrastructure); customer_excluded = tagged elastio:exclude; restore_test = tagged awsbackup-restore-test; legacy_nobackup = tagged elastio:nobackup (deprecated); parent_excluded = an EBS volume with no exclusion tag of its own, attached to an EC2 instance that has one. When an asset carries several tags, the first in that order wins."},"ami_details":{"type":"object","nullable":true,"description":"Machine image the VM was launched from. Same shape v1 serves on /assets-list, so a caller can drop the batched v1 lookup. Null on asset kinds with no image and on VMs whose image could not be resolved; populated on exactly the rows that carry an os_kind, since both come from the same image lookup.","properties":{"aws_id":{"type":"string","nullable":true},"name":{"type":"string","nullable":true,"description":"The AMI name, which is NOT an OS name: it is uncontrolled text chosen by whoever built the image (observed live: \"ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-amd64-server-...\", and also \"ntfs3\"). Render it as image provenance, never as the OS."},"location":{"type":"string","nullable":true}}},"source_image":{"type":"object","nullable":true,"description":"Machine image the VM was launched from, with provenance and tracking. Served for ec2_instance, azure_compute_vm (from the VM's storage profile image reference) and gcp_compute_vm (from the boot disk's source image). On ec2_instance it is the same image as ami_details (which stays for compatibility and is AWS only). Null on asset kinds with no image, on attachments, and on VMs whose image is unknown (an Azure VM not inventoried since the image reference was added fills on its next inventory run; a GCP VM booted from a snapshot has no image). No version field yet: a version needs the AMI family lineage, which only exists for images Elastio has scanned; use GET /api/v2/assets/{id}/machine-image on the family for that.","required":["image_id","name","location","provenance","tracked"],"properties":{"image_id":{"type":"string","nullable":true,"description":"AWS: the AMI id (ami-...). Azure: the image ARM id (gallery or managed image), else the marketplace URN publisher:offer:sku:version. GCP: projects/<project>/global/images/<name>."},"name":{"type":"string","nullable":true,"description":"The AMI name: uncontrolled text chosen by the image builder, not an OS name."},"location":{"type":"string","nullable":true,"description":"<owner>/<name>. Owner is the AMI owner on AWS; on Azure the image's subscription id, azure-marketplace, shared-gallery or community-gallery; on GCP the image project."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"Read off the owner segment of location (text before the first '/'): aws-marketplace or azure-marketplace is marketplace; the VM's own AWS account id, Azure subscription or GCP project is owned; amazon or any other owner is public (an image shared privately by another account is indistinguishable from a public one here, so it is also public). Null when location is missing or has no owner segment."},"tracked":{"type":"boolean","description":"True when this image id is a live member of an image family in this tenant: a non-deregistered, non-Elastio aws_ami_family version, or a non-deleted gcp_compute_images row. False for Azure, for a public GCP image we do not inventory, and for a GCP VM booted from a snapshot."}}},"machine_image":{"type":"object","nullable":true,"description":"Rollup of an aws_ami_family row, so the Machine Images table needs no per-row call. Null on every other asset kind and on attachments. Derived with the same rules as the lineage of GET /api/v2/assets/{id}/machine-image: versions are the family's live (not deregistered), non-Elastio AMIs. Also set on azure_gallery_image and azure_managed_image rows (listed only when Azure machine images are enabled for your tenant): versions are the image's live (not deleted) versions, current_image_id is the newest one's ARM id, provenance is owned (the image is in the customer's subscription) and in_use_count is 0, since Azure VM inventory records no source image.","required":["provenance","in_use_count","current_image_id","current_version","version_count","hunt_status","last_hunted_at","last_known_clean_version","last_known_clean_image_id","pursuit_assessed","pursuit_suspicion","last_pursuit_at","os_family","pursuit_supported"],"properties":{"discovered_by":{"type":"array","items":{"type":"string","enum":["cloud_connector","aws_iam_role"]},"description":"Every way Elastio inventoried this image's live versions, in a fixed order (cloud_connector first). cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Both when a role-inventoried AMI was also scanned through a connector."},"provenance":{"type":"string","nullable":true,"enum":["owned","public","marketplace",null],"description":"From the newest version's AMI location, by the same rule as source_image.provenance (aws-marketplace owner is marketplace, the AMI's own account is owned, any other owner is public). With no usable location it is owned: a family only exists for an AMI found in the customer's own account."},"in_use_count":{"type":"integer","description":"Non-terminated EC2 instances in the tenant whose image id is any version of the family (deregistered versions included). Same account inventory only: launch templates, ASGs and other accounts are not counted."},"current_image_id":{"type":"string","description":"AMI id (ami-...) of the newest live version."},"current_version":{"type":"string","description":"Label of the newest live version: the AMI name, or its id when the name is empty (lineage[].version)."},"version_count":{"type":"integer","description":"Number of live versions (lineage length)."},"hunt_status":{"type":"string","enum":["clean","threat","never"],"description":"Verdict of the newest live version, by the lineage rule: any check bad is threat, else malware and ransomware each good or not applicable is clean (the clean-backup rule), else never (lineage baseline)."},"last_hunted_at":{"type":"string","format":"date-time","nullable":true,"description":"Newest hunted_at across the live versions (the completion time of the latest scan of any version). Null when none was scanned."},"last_known_clean_version":{"type":"string","nullable":true,"description":"Label of the newest live version whose hunt_status is clean."},"last_known_clean_image_id":{"type":"string","nullable":true,"description":"AMI id of last_known_clean_version."},"pursuit_assessed":{"type":"boolean","description":"True when the newest live version (current_image_id) has a readable Pursuit report (the newest completed scan whose report parses). False means no readable Pursuit report: Pursuit never ran, or its report could not be read (a coverage gap, not clean). Always false for azure_gallery_image and azure_managed_image: Pursuit does not run on Azure images."},"pursuit_suspicion":{"type":"string","nullable":true,"enum":["none","low","medium","high","critical",null],"description":"Suspicion from the newest readable Pursuit report of the newest live version (current_image_id): its overall_assessment.suspicion_level, the level GET /api/v2/pursuit/reports serves. none when that report says none; null when not assessed. Medium and above is a compromise (the Pursuit timeline threshold); low folds into clean. This is the report-level verdict. The per-finding view is the asset's threats.pursuit / latest_scans.pursuit and GET /api/v2/assets/{id}/threats/pursuit/findings, both read from the findings extracted from that same report, so a compromised verdict normally has findings there too."},"last_pursuit_at":{"type":"string","format":"date-time","nullable":true,"description":"When the newest completed Pursuit scan of the newest live version (current_image_id) was ingested; null when not assessed."},"os_family":{"type":"string","enum":["windows","linux","other","unknown"],"description":"OS family of the newest live version (current_image_id), bucketed by the same rules as the VM row os_family. AMIs: the image's PlatformDetails as posture inventoried it (aws_amis.platform, else a described aws_ami_in_use.platform; e.g. Windows, Linux/UNIX, Windows BYOL). Azure images: the image definition's os_type (Windows/Linux). An AMI posture does not inventory falls back to the PlatformDetails the Cloud Connector reported. unknown when no OS could be read; do not read it as Linux."},"os_source":{"type":"string","nullable":true,"enum":["cloud_connector","aws_iam_role",null],"description":"Where the newest live version (current_image_id)'s os_family was read from: cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Recorded by whoever stored the OS, never guessed: null when os_family is unknown or the source is not recorded."},"pursuit_supported":{"type":"boolean","description":"True only when the newest live version (current_image_id) is an AMI whose os_family is windows: Pursuit runs on Windows on AWS only; Linux and Azure coming soon. False for linux, other and unknown, and always false on Azure images (os_family is still served). An unsupported image is always served pursuit_assessed false and pursuit_suspicion null, so pursuit_supported false tells \"not supported\" apart from \"not yet run\". POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows AMI (400 pursuit_not_supported)."}}}}}}}}},"required":["data"]}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/machine-image":{"get":{"operationId":"get_asset_machine_image_v2","summary":"Get a machine image's lineage and derived instances","tags":["Assets"],"description":"Machine-image details for one aws_ami_family asset: its versions oldest to newest with a hunt verdict each, and the live EC2 instances launched from any of them. Same RBAC as GET /api/v2/assets/{assetId}. 404 when the asset does not exist or is not a machine image. A family exists only once one of its AMIs has been scanned. Azure machine images (azure_gallery_image: a Compute Gallery image definition; azure_managed_image: a managed image, which has exactly one version, itself) are served the same way when Azure machine images are enabled for your tenant (404 otherwise). For them: lineage holds the image versions (version = the gallery version name such as 1.0.0, or the managed image name; image_id = the version's ARM id; created_at = its publish time, or when Elastio first saw it; state = the Azure provisioning state; deleted versions are left out). derived_instances is always empty, because Azure VM inventory does not record the image a VM was created from, and pending_launch_sources is empty with launch_sources_status unavailable, because VM scale sets are not collected yet. Pursuit does not run on Azure images, so their lineage is always pursuit_assessed false. Each lineage version carries os_family and pursuit_supported (Windows on AWS only; Linux and Azure coming soon): AMI OS from posture's PlatformDetails, Azure OS from the definition's os_type; pursuit_supported is always false on Azure.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","required":["asset_id","lineage","derived_instances","pending_launch_sources","launch_sources_status"],"properties":{"discovered_by":{"type":"array","items":{"type":"string","enum":["cloud_connector","aws_iam_role"]},"description":"Every way Elastio inventoried this image's live versions, in a fixed order (cloud_connector first). cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Both when a role-inventoried AMI was also scanned through a connector."},"asset_id":{"type":"string","format":"uuid","description":"The aws_ami_family, azure_gallery_image, azure_managed_image, gcp_compute_image_family, or gcp_compute_machine_image_family asset id."},"lineage":{"type":"array","description":"The family's versions (one AMI each), oldest to newest by AWS creation time. Deregistered and Elastio technical AMIs are left out, as on the asset list.","items":{"type":"object","required":["version","image_id","created_at","hunt_status","threats","hunted_at","state","pursuit_assessed","pursuit_suspicion","last_pursuit_at","os_family","pursuit_supported"],"properties":{"version":{"type":"string","description":"The AMI name, or its AMI id when the name is empty."},"image_id":{"type":"string","description":"AWS AMI id, the ARM id of an Azure image version, or a GCP resource name (projects/P/global/images/N or projects/P/global/machineImages/N)."},"created_at":{"type":"string","format":"date-time","description":"When AWS created the AMI."},"hunt_status":{"type":"string","enum":["baseline","clean","threat"],"description":"threat when any of the malware / ransomware / encryption / filesystem checks on this AMI is bad; otherwise clean when the malware and ransomware checks are each good or not applicable (the rule a clean backup follows); otherwise baseline (never checked, or only partly checked)."},"threats":{"type":"integer","description":"Active detections (open, acknowledged, or a lapsed suppression) recorded against this AMI version."},"hunted_at":{"type":"string","format":"date-time","nullable":true,"description":"Newest scan result ingested for this AMI version; null when no scan row targets it."},"state":{"type":"string","description":"AWS AMI state, Azure version state, or GCP image state."},"backup_kind":{"type":"string","enum":["gcp_compute_image","gcp_compute_machine_image"],"description":"Set on GCP lineage entries. Omitted for AWS and Azure."},"pursuit_assessed":{"type":"boolean","description":"True when the version has a readable Pursuit report (the newest completed scan whose report parses). False means no readable Pursuit report: Pursuit never ran, or its report could not be read (a coverage gap, not clean). Always false for azure_gallery_image and azure_managed_image: Pursuit does not run on Azure images."},"pursuit_suspicion":{"type":"string","nullable":true,"enum":["none","low","medium","high","critical",null],"description":"Suspicion from the newest readable Pursuit report of the version: its overall_assessment.suspicion_level, the level GET /api/v2/pursuit/reports serves. none when that report says none; null when not assessed. Medium and above is a compromise (the Pursuit timeline threshold); low folds into clean. This is the report-level verdict. The per-finding view is the asset's threats.pursuit / latest_scans.pursuit and GET /api/v2/assets/{id}/threats/pursuit/findings, both read from the findings extracted from that same report, so a compromised verdict normally has findings there too."},"last_pursuit_at":{"type":"string","format":"date-time","nullable":true,"description":"When the newest completed Pursuit scan of the version was ingested; null when not assessed."},"os_family":{"type":"string","enum":["windows","linux","other","unknown"],"description":"OS family of the version, bucketed by the same rules as the VM row os_family. AMIs: the image's PlatformDetails as posture inventoried it (aws_amis.platform, else a described aws_ami_in_use.platform; e.g. Windows, Linux/UNIX, Windows BYOL). Azure images: the image definition's os_type (Windows/Linux). An AMI posture does not inventory falls back to the PlatformDetails the Cloud Connector reported. unknown when no OS could be read; do not read it as Linux."},"os_source":{"type":"string","nullable":true,"enum":["cloud_connector","aws_iam_role",null],"description":"Where the version's os_family was read from: cloud_connector = the Elastio Cloud Connector deployed in the account; aws_iam_role = a read-only IAM role the customer registered for posture, read by Elastio directly without a connector. Recorded by whoever stored the OS, never guessed: null when os_family is unknown or the source is not recorded."},"pursuit_supported":{"type":"boolean","description":"True only when the version is an AMI whose os_family is windows: Pursuit runs on Windows on AWS only; Linux and Azure coming soon. False for linux, other and unknown, and always false on Azure images (os_family is still served). An unsupported image is always served pursuit_assessed false and pursuit_suspicion null, so pursuit_supported false tells \"not supported\" apart from \"not yet run\". POST /api/v1/scans/schedule refuses Pursuit on a known non-Windows AMI (400 pursuit_not_supported)."}}}},"derived_instances":{"type":"array","description":"Live instances launched from any version of the family, including a version since deleted. AWS: non-terminated EC2. GCP: VMs that are not deleted or terminated, matched by boot-disk source image or source machine image. aws_id is the cloud id (instance id, or projects/P/zones/Z/instances/N).","items":{"type":"object","required":["asset_id","aws_id","name","image_id","version","state","pursuit_state","hunt_state"],"properties":{"asset_id":{"type":"string","format":"uuid","description":"The ec2_instance asset id."},"aws_id":{"type":"string","description":"Cloud id of the instance: an AWS instance id, or a GCP resource name projects/P/zones/Z/instances/N."},"name":{"type":"string","description":"The Name tag, or the instance id without one."},"image_id":{"type":"string","description":"AWS AMI id."},"version":{"type":"string","description":"The version label of the AMI it runs."},"state":{"type":"string","enum":["infected","clean","stale"],"description":"Legacy/drift field, kept for compatibility: infected when the instance or an attached volume is infected; otherwise stale when it runs a version older than the family's newest clean version; otherwise clean. Read the verdict from pursuit_state and hunt_state; use stale only as the drift signal."},"pursuit_state":{"type":"string","enum":["compromised","clean","not_assessed"],"description":"From the latest completed Pursuit scan of the instance and of each volume attached to it: compromised when any of those reports' suspicion_level is medium, high or critical (the Pursuit timeline threshold, the same one images use); clean when assessed and all are none or low; not_assessed when Pursuit never scanned it."},"hunt_state":{"type":"string","enum":["infected","clean","not_assessed"],"description":"infected when the instance or an attached volume is infected (the rule behind state=infected); otherwise clean when either was ever hunted; otherwise not_assessed."}}}},"pending_launch_sources":{"type":"array","description":"Live Auto Scaling groups and launch templates in this tenant that launch any version of the family now (deregistered versions included), from the posture sweep. Empty when none, or when launch_sources_status is unavailable.","items":{"type":"object","required":["id","type","name","image_ref","resolves_to_image_id","resolves_to_version"],"properties":{"id":{"type":"string","description":"Auto Scaling group: its name. Launch template: its id (lt-...), or lt-...:$Latest for a $Latest version whose image differs from $Default."},"type":{"type":"string","enum":["auto_scaling_group","launch_template"]},"name":{"type":"string"},"image_ref":{"type":"string","description":"How the source picks its image: $Default, $Latest, a launch template version number, or launch_configuration."},"resolves_to_image_id":{"type":"string","description":"The AMI id the source launches now."},"resolves_to_version":{"type":"string","nullable":true,"description":"The family version label of that AMI; null when it is not a version of this family."}}}},"launch_sources_status":{"type":"string","enum":["complete","partial","unavailable"],"description":"Coverage of pending_launch_sources over the account/regions the family's versions live in. complete: every one was last listed completely. partial: at least one was denied, failed, or never listed, so sources may be missing. unavailable: no launch-source data (not collected yet, or the posture data could not be read); an empty list then means unknown, not none."}}}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/threats":{"get":{"operationId":"get_asset_threats_v2","summary":"List Hunt findings for an asset","tags":["Threats"],"description":"Lists threats associated with the specified asset. For virtual machines, results include threats on attached volumes and disks, one row per volume or disk (unlike GET /api/v2/threats, which folds them onto the VM). Custom hunt findings are one row per hunt rule. Omitted ?status= is open; pass acknowledged, suppressed, resolved, or all to include disposed hunt rows.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error,pursuit,custom)"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string","enum":["open","acknowledged","suppressed","resolved","all"]},"in":"query","name":"status","required":false,"description":"Filter rows by lifecycle status. Omitted means `open`, at parity with GET /api/v2/violations. `open` matches detections stored as `detected` or `open`. `acknowledged`, `suppressed` (also stored as `ignored`) and `resolved` match those statuses. Pass `all` for every status."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Finding identity. Elastio hunts and pursuit: `threat:{asset_id}:{threat_kind}`. Custom hunts: `threat:{asset_id}:custom:{finding_id}` because one asset can have many custom findings. Pass it to /api/v2/findings/{findingId}."},"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account (blob/file share). IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"kind":{"type":"string","enum":["hunt"]},"threat_kind":{"type":"string","enum":["ransomware","malware","encryption","filesystem_error","pursuit","custom"]},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"count":{"type":"number"},"latest_scan_at":{"type":"string","nullable":true},"attached_assets":{"type":"array","description":"Attached volumes / disks whose threats are reported on this row (VM rows only; empty otherwise). The scan report, the infected files and the underlying threat rows live under these asset ids.","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"}}}},"files_affected":{"type":"number","nullable":true,"description":"True affected-artifact total for this (asset, threat_kind), counted from the detections that back the row rather than from the rollup counters. Counts the detections whose status is open or acknowledged (an expired suppression counts as open) and that carry no unexpired suppressed_until, including a per-file suppression that leaves the status open. Null when no such detection backs the pair, in which case the consumer falls back to `count`."},"signature":{"type":"string","nullable":true,"description":"The detection name those rows recorded, when they agree on exactly one. Null when they carry no name or carry several (see `signatures`). Never the scan-engine vendor or version."},"signatures":{"type":"array","description":"Every distinct name of the detections counted in `files_affected`, most frequent first, capped at 5. Empty when those detections carry no name.","items":{"type":"string"}},"report_id":{"type":"string","nullable":true,"description":"Pursuit only: the report ID, the same ID `GET /api/v1/pursuit/reports` serves and `GET /api/v1/pursuit/reports/{report_id}` resolves. Null for every other `threat_kind`."},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"For Pursuit, the investigation's overall_assessment. For custom hunts, hunt_rule_id and hunt_scan_id. Null for Elastio hunts. Never includes raw hunt query output."},"status":{"type":"string","enum":["open","acknowledged","suppressed","resolved"],"description":"Lifecycle status of the finding."},"status_changed_at":{"type":"string","format":"date-time","nullable":true,"description":"When the status last changed (RFC3339 UTC)."},"suppressed_until":{"type":"string","format":"date-time","nullable":true,"description":"Expiry of an active suppression (RFC3339 UTC); null if not suppressed."},"suppression_reason":{"type":"string","nullable":true,"description":"Reason recorded for an active suppression; null if not suppressed."},"resolved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was resolved (RFC3339 UTC); null if not resolved."},"resolved_by":{"type":"string","nullable":true,"description":"Actor who resolved the finding; null if not resolved."},"resolve_note":{"type":"string","nullable":true,"description":"Optional note recorded at resolve time; null if absent."},"acknowledged_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was acknowledged (RFC3339 UTC); null if not acknowledged."},"acknowledged_by":{"type":"string","nullable":true,"description":"Actor who acknowledged the finding; null if not acknowledged."}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/threats/pursuit/findings":{"get":{"operationId":"list_asset_pursuit_findings_v2","summary":"List the latest Pursuit findings for an asset","tags":["Threats"],"description":"Returns the latest-only pursuit findings for the asset. A virtual machine includes findings on attached volumes and disks. Only snapshots whose report-level suspicion_level is low, medium, high, or critical are included (same as GET /api/v2/threats?threat_kind=pursuit). Returns 404 when the asset has no qualifying pursuit threat. These are the per-finding records extracted from the asset's newest Pursuit report; the report-level verdict is machine_image.pursuit_suspicion (and the Pursuit report itself). The two come from the same report, so a verdict of medium or above has findings here.","parameters":[{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Pursuit finding ID (UUID)"},"asset_id":{"type":"string"},"pursuit_scan_id":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string","enum":["none","low","medium","high","critical"]},"confidence":{"type":"string","enum":["low","medium","high"]},"details":{"type":"string"},"persistence_type":{"type":"string","nullable":true},"lol_bin":{"type":"object","additionalProperties":true,"nullable":true},"credential_assessment":{"type":"object","additionalProperties":true,"nullable":true},"evidence":{"type":"array"},"extra":{"type":"object","additionalProperties":true},"scanned_at":{"type":"string"}},"required":["id","asset_id","pursuit_scan_id","title","category","severity","confidence","details","evidence","extra","scanned_at"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}},"required":["total","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/threats/custom/findings/{findingId}":{"get":{"operationId":"get_asset_custom_hunt_finding_v2","summary":"Get one custom hunt finding and its query hit envelopes","tags":["Threats"],"description":"Returns one custom hunt finding for the asset (including findings on attached volumes and disks), plus one hit envelope per matched file. Missing hit rows yield hits: [].","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"findingId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"hunt_rule_id":{"type":"string","format":"uuid","nullable":true},"hunt_rule_name":{"type":"string"},"hunt_scan_id":{"type":"string","format":"uuid"},"severity":{"type":"string","enum":["low","medium","high","critical"]},"count":{"type":"number"},"latest_scan_at":{"type":"string"},"status":{"type":"string","enum":["open","acknowledged","suppressed","resolved"]},"acknowledged_at":{"type":"string","nullable":true},"acknowledged_by":{"type":"string","nullable":true},"suppressed_until":{"type":"string","nullable":true},"suppression_reason":{"type":"string","nullable":true},"hits":{"type":"array","items":{"type":"object","properties":{"query":{"type":"string"},"envelope":{"type":"object","additionalProperties":true}},"required":["query","envelope"]}}},"required":["id","asset_id","hunt_rule_name","hunt_scan_id","severity","count","hits"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/threats/{threatKind}":{"get":{"operationId":"get_asset_threat_detail_v2","summary":"Get finding detail for an asset by hunt kind","tags":["Threats"],"description":"Returns threat details for a specific asset and threat kind, including the latest scan and hunt report, in any lifecycle status. Returns 404 if no matching threat is found. custom is not unique per asset; use GET /api/v2/assets/{assetId}/threats/custom/findings/{findingId}.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true},{"schema":{"type":"string","enum":["ransomware","malware","encryption","filesystem_error","pursuit","custom"]},"in":"path","name":"threatKind","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account (blob/file share). IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"kind":{"type":"string","enum":["hunt"]},"threat_kind":{"type":"string","enum":["ransomware","malware","encryption","filesystem_error","pursuit","custom"]},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"count":{"type":"number"},"latest_scan_at":{"type":"string","nullable":true},"attached_assets":{"type":"array","description":"Attached volumes / disks whose threats are reported on this row (VM rows only; empty otherwise).","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"}}}},"details":{"type":"object","nullable":true,"additionalProperties":true,"description":"For Pursuit, the investigation's overall_assessment. For custom hunts, hunt_rule_id and hunt_scan_id. Null for Elastio hunts. Never includes raw hunt query output."},"latest_scan":{"type":"object","description":"Latest scan of the matching kind for this asset and threat.","properties":{"scan_id":{"type":"string"},"scan_job_id":{"type":"string"},"kind":{"type":"string","enum":["ransomware_scan","malware_scan","entropy_scan","fs_check","pursuit"]},"status":{"type":"string","nullable":true},"type":{"type":"string","nullable":true},"target":{"type":"object","properties":{"id":{"type":"string"},"kind_tag":{"type":"string","enum":["asset","asset_item","backup"]},"asset_id":{"type":"string","description":"Parent asset ID when kind_tag is asset_item"},"resource":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"kind_tag":{"type":"string","enum":["asset","asset_item"]},"asset_id":{"type":"string","description":"Parent asset ID for asset_item targets"}}}}},"created_at":{"type":"string"},"updated_at":{"type":"string"},"scan_created_ebs_snapshot_id":{"type":"string","nullable":true},"scan_created_ami_id":{"type":"string","nullable":true},"report":{"type":"object","nullable":true,"description":"Full report for this scan when available, including timestamps, nested hunt report_data, and scan_target.","additionalProperties":true}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/violations":{"get":{"operationId":"get_asset_violations_v2","summary":"Get open violations for a specific asset","tags":["Violations"],"description":"Lists open violations associated with the specified asset. For virtual machines, results include violations on attached volumes and disks.","parameters":[{"schema":{"type":"string"},"in":"query","name":"violation_code","required":false,"description":"Comma-separated violation codes"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Comma-separated violation categories"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string","enum":["open","acknowledged","suppressed","resolved","all"]},"in":"query","name":"status","required":false,"description":"Filter rows by lifecycle status. Omitted means `open`, the default this list has always had; pass `all` explicitly for every status."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size (default 10, max 100)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"violation_code":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"details":{"type":"object"},"last_evaluated_at":{"type":"string"},"created_at":{"type":"string"},"status":{"type":"string","enum":["open","acknowledged","suppressed","resolved"],"description":"Lifecycle status of the finding."},"status_changed_at":{"type":"string","format":"date-time","nullable":true,"description":"When the status last changed (RFC3339 UTC)."},"suppressed_until":{"type":"string","format":"date-time","nullable":true,"description":"Expiry of an active suppression (RFC3339 UTC); null if not suppressed."},"suppression_reason":{"type":"string","nullable":true,"description":"Reason recorded for an active suppression; null if not suppressed."},"resolved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was resolved (RFC3339 UTC); null if not resolved."},"resolved_by":{"type":"string","nullable":true,"description":"Actor who resolved the finding; null if not resolved."},"resolve_note":{"type":"string","nullable":true,"description":"Optional note recorded at resolve time; null if absent."},"acknowledged_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was acknowledged (RFC3339 UTC); null if not acknowledged."},"acknowledged_by":{"type":"string","nullable":true,"description":"Actor who acknowledged the finding; null if not acknowledged."}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/{assetId}/recovery-points":{"get":{"operationId":"list_asset_recovery_points_v2","summary":"Get asset recovery points (v2)","tags":["Assets"],"description":"Lists recovery points for the specified asset, including health checks and storage details.","parameters":[{"schema":{"type":"number","default":10,"minimum":1,"maximum":100},"in":"query","name":"page_size","required":false},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false},{"schema":{"type":"number","default":365,"minimum":1},"in":"query","name":"days","required":false,"description":"Time window on backup timestamp"},{"schema":{"type":"string"},"in":"query","name":"kind","required":false,"description":"Comma-separated BackupKind values"},{"schema":{"type":"string"},"in":"query","name":"backup_type","required":false,"description":"User-facing backup type label filter"},{"schema":{"type":"string"},"in":"query","name":"checks_fs","required":false,"description":"Filter by filesystem check status"},{"schema":{"type":"string"},"in":"query","name":"checks_ransomware","required":false,"description":"Filter by ransomware check status"},{"schema":{"type":"string"},"in":"query","name":"checks_malware","required":false,"description":"Filter by malware check status"},{"schema":{"type":"string"},"in":"query","name":"checks_encryption","required":false,"description":"Filter by encryption check status"},{"schema":{"type":"string"},"examples":{"infected":{"value":"infected"},"clean,at_risk":{"value":"clean,at_risk"}},"in":"query","name":"health","required":false,"description":"Comma-separated effective health values: clean, infected, at_risk"},{"schema":{"type":"string"},"examples":{"backup":{"value":"backup"},"logically_air_gapped_backup":{"value":"logically_air_gapped_backup"}},"in":"query","name":"aws_vault_type","required":false,"description":"Comma-separated AWS Backup vault types. Applies to AWS Backup recovery points only."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"timestamp":{"type":"string","format":"date-time"},"kind":{"type":"string"},"backup_type":{"type":"string"},"provider":{"type":"string"},"source_asset_id":{"type":"string","format":"uuid"},"protected_asset_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"health":{"type":"string","enum":["clean","infected","at_risk"]},"checks":{"type":"object","properties":{"fs":{"type":"string","enum":["good","bad","not_applicable","unchecked"]},"ransomware":{"type":"string","enum":["good","bad","not_applicable","unchecked"]},"malware":{"type":"string","enum":["good","bad","not_applicable","unchecked"]},"encryption":{"type":"string","enum":["good","bad","not_applicable","unchecked"]}},"required":["fs","ransomware","malware","encryption"]},"replicated":{"type":"boolean"},"drs_source_server_id":{"type":"string","format":"uuid","nullable":true},"storage":{"type":"object","description":"Kind-relevant storage fields only. Omitted keys are not applicable to this backup kind.","properties":{"storage_class":{"type":"string","nullable":true,"enum":["warm","cold","deleted","unknown",null],"description":"AWS Backup (awsb_*) only"},"storage_tier":{"type":"string","nullable":true,"enum":["standard","archive",null],"description":"EBS snapshot only"},"size_bytes":{"type":"number","nullable":true,"description":"AWS Backup, EBS snapshot, OVA"},"region":{"type":"string","nullable":true,"description":"AWS Backup, EBS snapshot, Azure disk snapshot"},"encrypted":{"type":"boolean","nullable":true,"description":"AWS Backup and EBS snapshot only"},"vault":{"type":"object","properties":{"id":{"type":"string","format":"uuid","nullable":true},"name":{"type":"string","nullable":true},"vault_type":{"type":"string","nullable":true,"enum":["backup","logically_air_gapped_backup",null],"description":"AWS Backup only"},"region":{"type":"string","nullable":true}},"description":"AWS Backup and Azure RS/DP recovery points"}},"additionalProperties":false}},"required":["id","timestamp","kind","backup_type","provider","source_asset_id","protected_asset_ids","health","checks","replicated","drs_source_server_id","storage"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string","description":"Next page token"},"prev_page_token":{"type":"string","description":"Prev page token"}},"required":["next_page_token","prev_page_token"]}},"required":["total","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/filters":{"get":{"operationId":"list_assets_v2_filters","summary":"Get contextual filter options for v2 assets","tags":["Assets"],"description":"Returns filter option values that exist in the current filtered inventory, with a count per option. Accepts the same query params as GET /api/v2/assets (except pagination and asset_id). Each facet omits its own filter when computing options so users can change selections without dead ends.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search by asset name or UUID"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Comma-separated health states (infected,at_risk,clean)"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error)"},{"schema":{"type":"string"},"in":"query","name":"scan_coverage","required":false,"description":"Comma-separated scan coverage states (covered,not_covered)"},{"schema":{"type":"string"},"in":"query","name":"clean_backup","required":false,"description":"Comma-separated clean backup states (has,missing). has = known clean backup in cache; missing = no known clean backup"},{"schema":{"type":"string"},"in":"query","name":"trigger_sources","required":false,"description":"Comma-separated scan trigger sources (scheduled,event,vendor,guardduty,threat-hunt,wiz,s3-threat-hunt)"},{"schema":{"type":"string"},"in":"query","name":"tags","required":false,"description":"JSON array of tag filters, e.g. [{\"key\":\"Environment\",\"value\":\"prod\"}]"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string"},"in":"query","name":"policy_kind","required":false,"description":"Comma-separated policy kinds (scheduled, event)"},{"schema":{"type":"string"},"in":"query","name":"policy_source","required":false,"description":"Comma-separated event policy sources (e.g. aws.guardduty.finding_raised, wiz.finding_raised)"},{"schema":{"type":"string"},"in":"query","name":"region","required":false,"description":"Comma-separated regions"},{"schema":{"type":"string"},"in":"query","name":"account","required":false,"description":"Comma-separated account identifiers (AWS account id, Azure subscription id, IBM scope, OVA account id)"},{"schema":{"type":"string"},"in":"query","name":"os_kind","required":false,"description":"Comma-separated RAW os_kind values, exact match (e.g. Linux/UNIX,Windows). EC2 and Azure VM rows carry an os_kind; prefer os_family for Windows/Linux bucketing."},{"schema":{"type":"string"},"in":"query","name":"os_family","required":false,"description":"Comma-separated normalized OS families, OR semantics: windows,linux,other,unknown. Any other value is a 400. Only VM rows (ec2_instance, azure_compute_vm) can match; every other kind is excluded when this is set."},{"schema":{"type":"string"},"in":"query","name":"source_image_id","required":false,"description":"Comma-separated AWS AMI ids (^ami-[0-9a-z]+$, else 400), OR semantics. Facet counts are computed with it applied; only ec2_instance rows can match and every other kind is excluded. AMI family uuids are not accepted (resolve via GET /api/v2/assets/{id}/machine-image lineage)."},{"schema":{"type":"boolean"},"in":"query","name":"show_attachments","required":false,"description":"When false, attached EBS volumes and Azure disks are excluded from facet counts. Defaults to true."},{"schema":{"type":"string"},"in":"query","name":"attachment_status","required":false,"description":"Comma-separated. Only ebs_volume and azure_compute_disk. Possible values: attached, unattached. Independent of show_attachments. Both values together is a no-op. Does not apply to fsx_ontap_volume."},{"schema":{"type":"boolean"},"in":"query","name":"excluded","required":false,"description":"true = assets the data plane skips for inspection; false = the inverse. An asset is excluded when it carries one of the four builtin exclusion tags with any value except exactly 'false' (case-sensitive: an empty or key-only value excludes, and so does 'False'): elastio:exclude (set by the customer), elastio:resource (set by Elastio on its own infrastructure), awsbackup-restore-test (set by AWS Backup restore testing) and elastio:nobackup (deprecated, still honoured). Each key also matches with '.' or '_' in place of ':' (elastio.exclude, elastio_exclude), for GCP and Azure resources that cannot use ':'. elastio:action=scan does not override an exclusion tag. An EBS volume attached to an EC2 instance that carries one of these tags is excluded too. Each row's excluded_reason says which rule applies. Tags are read from the asset's inventoried tags, which today arrive only for AWS (EC2, EBS, S3, EFS, FSx for ONTAP), Azure and GCP assets. On-prem servers (generic hosts, vSphere/OVA servers) and IBM COS buckets currently arrive with no tags, so they never match true and always match false, even when tagged at the source. Also, AWS inventory ingest currently drops an asset tagged elastio:exclude=true or elastio:resource=true from the catalog, so only other values of those two tags (for example key-only) are listed today."},{"schema":{"type":"boolean"},"in":"query","name":"has_pursuit_exception","required":false,"description":"true = only assets that currently have an active Pursuit exception; false = only assets that do not. Omitted = no filter. Honored only when Pursuit exceptions are enabled for your tenant; otherwise the parameter is ignored."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"platform":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"asset_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"health":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"threat_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"scan_coverage":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"clean_backup":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"region":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"os_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]},"description":"RAW os_kind values with counts. label repeats the raw value; use os_family for the Windows/Linux buckets."},"os_family":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]},"description":"Normalized OS family with counts, VM rows only, in the canonical order windows, linux, other, unknown; zero-count entries are omitted. Labels are Windows / Linux / Other / Unknown. Cross-filtered by the other active filters and exclude-self like every other facet."},"account":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"platform":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","platform","count"]}},"policy_id":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"policy_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"policy_source":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"values":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]}}},"required":["key","values"]}},"has_pursuit_exception":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of assets matching this option given all other active filters."}},"required":["value","label","count"]},"description":"Active Pursuit exception facet: value \"true\" / \"false\" with counts, zero counts omitted, labels Has Pursuit exception / No Pursuit exception. Cross-filtered by the other active filters and exclude-self like every other facet. Present only when Pursuit exceptions are enabled for your tenant."}},"required":["platform","asset_kind","health","threat_kind","scan_coverage","clean_backup","region","os_kind","os_family","account","policy_id","policy_kind","policy_source","tags"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/groups":{"get":{"operationId":"list_assets_v2_groups","summary":"Get v2 asset group summaries","tags":["Assets"],"description":"Lists asset groups with a count per group (policy, asset_kind, account, or coverage). To load full asset details for a group, call GET /api/v2/assets with the same filters and add the matching filter (such as policy_id, asset_kind, or account). When group_by=policy, use policy_id=<group.key> (or policy_id=unpoliced for the unpoliced bucket). When group_by=coverage, keys are scheduled, event, and unpoliced. An asset covered by both scheduled and event policies appears in both buckets, so coverage counts are not additive. Expand a coverage group with policy_kind=scheduled, policy_kind=event, or policy_id=unpoliced.","parameters":[{"schema":{"type":"string","enum":["policy","asset_kind","account","coverage"]},"in":"query","name":"group_by","required":true,"description":"Dimension to group by. coverage buckets: scheduled, event, unpoliced (no active policy)."},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"health","required":false,"description":"Comma-separated health states (infected,at_risk,clean)"},{"schema":{"type":"string"},"in":"query","name":"threat_kind","required":false,"description":"Comma-separated threat kinds (ransomware,malware,encryption,filesystem_error)"},{"schema":{"type":"string"},"in":"query","name":"clean_backup","required":false,"description":"Comma-separated clean backup states (has,missing). has = known clean backup in cache; missing = no known clean backup"},{"schema":{"type":"string"},"in":"query","name":"tags","required":false,"description":"JSON array of tag filters, e.g. [{\"key\":\"Environment\",\"value\":\"prod\"}]"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string"},"in":"query","name":"policy_kind","required":false,"description":"Comma-separated policy kinds (scheduled, event)"},{"schema":{"type":"string"},"in":"query","name":"policy_source","required":false,"description":"Comma-separated event policy sources (e.g. aws.guardduty.finding_raised, wiz.finding_raised)"},{"schema":{"type":"string"},"in":"query","name":"region","required":false,"description":"Comma-separated regions"},{"schema":{"type":"string"},"in":"query","name":"account","required":false,"description":"Comma-separated account identifiers"},{"schema":{"type":"string"},"in":"query","name":"os_kind","required":false,"description":"Comma-separated RAW os_kind values, exact match (EC2 and Azure VM rows, )"},{"schema":{"type":"string"},"in":"query","name":"os_family","required":false,"description":"Comma-separated normalized OS families: windows,linux,other,unknown. Only VM rows can match."},{"schema":{"type":"string"},"in":"query","name":"source_image_id","required":false,"description":"Comma-separated AWS AMI ids (^ami-[0-9a-z]+$, else 400). Only ec2_instance rows can match."},{"schema":{"type":"boolean"},"in":"query","name":"show_attachments","required":false,"description":"When false, hides attached EBS volumes and Azure disks from counts. Defaults to true."},{"schema":{"type":"string"},"in":"query","name":"attachment_status","required":false,"description":"Comma-separated. Only ebs_volume and azure_compute_disk. Possible values: attached, unattached. Independent of show_attachments. Both values together is a no-op. Does not apply to fsx_ontap_volume."},{"schema":{"type":"boolean"},"in":"query","name":"excluded","required":false,"description":"true = assets the data plane skips for inspection; false = the inverse. An asset is excluded when it carries one of the four builtin exclusion tags with any value except exactly 'false' (case-sensitive: an empty or key-only value excludes, and so does 'False'): elastio:exclude (set by the customer), elastio:resource (set by Elastio on its own infrastructure), awsbackup-restore-test (set by AWS Backup restore testing) and elastio:nobackup (deprecated, still honoured). Each key also matches with '.' or '_' in place of ':' (elastio.exclude, elastio_exclude), for GCP and Azure resources that cannot use ':'. elastio:action=scan does not override an exclusion tag. An EBS volume attached to an EC2 instance that carries one of these tags is excluded too. Each row's excluded_reason says which rule applies. Tags are read from the asset's inventoried tags, which today arrive only for AWS (EC2, EBS, S3, EFS, FSx for ONTAP), Azure and GCP assets. On-prem servers (generic hosts, vSphere/OVA servers) and IBM COS buckets currently arrive with no tags, so they never match true and always match false, even when tagged at the source. Also, AWS inventory ingest currently drops an asset tagged elastio:exclude=true or elastio:resource=true from the catalog, so only other values of those two tags (for example key-only) are listed today."},{"schema":{"type":"boolean"},"in":"query","name":"has_pursuit_exception","required":false,"description":"true = only assets that currently have an active Pursuit exception; false = only assets that do not. Omitted = no filter. Honored only when Pursuit exceptions are enabled for your tenant; otherwise the parameter is ignored."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"group_by":{"type":"string","enum":["policy","asset_kind","account","coverage"]},"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"count":{"type":"number"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/tags":{"get":{"operationId":"list_tags","summary":"List distinct asset tag keys","tags":["Tags"],"description":"Returns the distinct tag keys present on the tenant's assets, with per-key asset and value counts. Use GET /api/v2/assets?tags=[...] to list the assets carrying a tag.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Case-insensitive substring match on the tag key"},{"schema":{"type":"number"},"in":"query","name":"page_size","required":false,"description":"Number of keys per page (max 100, default 10)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"asset_count":{"type":"number","description":"Distinct assets carrying this tag key"},"value_count":{"type":"number","description":"Distinct values recorded for this tag key"}},"required":["key","asset_count","value_count"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}},"required":["total","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/tags/values":{"get":{"operationId":"list_tag_values","summary":"List distinct values for an asset tag key","tags":["Tags"],"description":"Returns the distinct values recorded for one tag key on the tenant's assets, with per-value asset counts. A null value means the tag exists key-only.","parameters":[{"schema":{"type":"string"},"in":"query","name":"key","required":true,"description":"The tag key whose values are listed"},{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Case-insensitive substring match on the tag value"},{"schema":{"type":"number"},"in":"query","name":"page_size","required":false,"description":"Number of values per page (max 100, default 10)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string"},"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","nullable":true,"description":"null when the tag exists key-only"},"asset_count":{"type":"number","description":"Distinct assets carrying this key/value pair"}},"required":["value","asset_count"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}},"required":["key","total","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/summary":{"get":{"operationId":"get_assets_summary","summary":"Get scoped live-asset dashboard summary","tags":["Assets"],"description":"Returns aggregated threats, sensitive data, coverage, protection, and recovery metrics for live inventory assets in the current X-Effective-Scope context.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"object","properties":{"mode":{"type":"string","enum":["all_live_inventory","policy_members","unpoliced"]},"scope_id":{"type":"string"}},"required":["mode"]},"live_asset_count":{"type":"number"},"threats":{"type":"object","properties":{"assets_with_threats":{"type":"number"},"total_threats":{"type":"number"},"by_threat_kind":{"type":"object","properties":{"malware":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]},"ransomware":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]},"filesystem_error":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]},"encryption":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]}},"required":["malware","ransomware","filesystem_error","encryption"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]}},"required":["critical","high","medium","low"]}},"required":["assets_with_threats","total_threats","by_threat_kind","by_severity"]},"sensitive_data":{"type":"object","properties":{"assets_scanned_for_sensitive_data":{"type":"number"},"assets_with_sensitive_data":{"type":"number"},"total_findings":{"type":"number"},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]}},"required":["critical","high","medium","low"]}},"required":["assets_scanned_for_sensitive_data","assets_with_sensitive_data","total_findings","by_severity"]},"coverage":{"type":"object","properties":{"non_compliant_assets":{"type":"number","description":"Distinct DASHBOARD assets with at least one open violation in this pillar. An attached EBS volume or Azure disk is folded into its parent instance here, the same rollup the threat and health metrics apply, so this is a narrower population than by_violation_code[code].assets."},"total_violations":{"type":"number"},"by_violation_code":{"type":"object","properties":{"no_policy_coverage":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"ebs_volume_unattached":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"azure_disk_unattached":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]}},"required":["no_policy_coverage","ebs_volume_unattached","azure_disk_unattached"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"info":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]}},"required":["critical","high","medium","low","info"]}},"required":["non_compliant_assets","total_violations","by_violation_code","by_severity"]},"protection":{"type":"object","properties":{"non_compliant_assets":{"type":"number","description":"Distinct DASHBOARD assets with at least one open violation in this pillar. An attached EBS volume or Azure disk is folded into its parent instance here, the same rollup the threat and health metrics apply, so this is a narrower population than by_violation_code[code].assets."},"total_violations":{"type":"number"},"by_violation_code":{"type":"object","properties":{"no_backup":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"backup_stale":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]}},"required":["no_backup","backup_stale"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"info":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]}},"required":["critical","high","medium","low","info"]}},"required":["non_compliant_assets","total_violations","by_violation_code","by_severity"]},"recovery":{"type":"object","properties":{"non_compliant_assets":{"type":"number","description":"Distinct DASHBOARD assets with at least one open violation in this pillar. An attached EBS volume or Azure disk is folded into its parent instance here, the same rollup the threat and health metrics apply, so this is a narrower population than by_violation_code[code].assets."},"total_violations":{"type":"number"},"by_violation_code":{"type":"object","properties":{"no_clean_backup":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"r_rpo_exceeded":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"no_backup":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"backup_stale":{"type":"object","properties":{"assets":{"type":"number","description":"Distinct assets that actually carry this violation code, identical to the distinct asset count of GET /api/v2/violations and to GET /api/v2/violations/groups?group_by=violation_code for the same scope. An attached EBS volume or Azure disk counts as its own asset here. This is a DIFFERENT population from the sibling non_compliant_assets, which folds children into their parent: the two must never be compared or summed."},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]}},"required":["no_clean_backup","r_rpo_exceeded","no_backup","backup_stale"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"info":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]}},"required":["critical","high","medium","low","info"]}},"required":["non_compliant_assets","total_violations","by_violation_code","by_severity"]}},"required":["scope","live_asset_count","threats","sensitive_data","coverage","protection","recovery"]}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/r-rpo":{"get":{"operationId":"get_assets_r_rpo","summary":"Get fleet R-RPO","tags":["Assets"],"description":"Returns the 95th percentile age of the last clean recovery point across scoped live assets, plus asset counts for context.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"object","properties":{"mode":{"type":"string","enum":["all_live_inventory","policy_members","unpoliced"]},"scope_id":{"type":"string"}},"required":["mode"]},"data":{"type":"object","properties":{"value_seconds":{"type":"number","nullable":true,"description":"Fleet R-RPO in seconds (p95 of per-asset last clean recovery point age)"},"aggregation":{"type":"string","enum":["p95"]},"total_assets":{"type":"number","description":"Live assets in the current scope"},"assets_with_clean_recovery_point":{"type":"number","description":"Scoped assets that have at least one clean recovery point"}},"required":["value_seconds","aggregation","total_assets","assets_with_clean_recovery_point"]}},"required":["scope","data"]}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/policies/summary":{"get":{"operationId":"get_policies_summary","summary":"Get per-policy live-asset dashboard summaries","tags":["Assets"],"description":"Returns threats, sensitive data, coverage, protection, and recovery metrics for each policy and for assets without a policy.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"policy_id":{"type":"string"},"policy_name":{"type":"string"},"policy_kind":{"type":"string","nullable":true,"enum":["scheduled","event",null],"description":"Whether the policy is schedule-driven or event-driven. Null for the unpoliced bucket."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies. Null for scheduled policies and the unpoliced bucket."},"live_asset_count":{"type":"number"},"total_threats":{"type":"number","description":"Open threats on assets covered by this policy."},"total_violations":{"type":"number","description":"Distinct open violations on assets covered by this policy, each counted once. Includes violation codes outside the coverage / protection / recovery pillar breakdown (whose blocks overlap by design: recovery repeats the protection codes), so it reconciles with the violations list for the same scope."},"health":{"type":"object","description":"Covered-asset health split; clean + at_risk + infected = live_asset_count.","properties":{"clean":{"type":"number"},"at_risk":{"type":"number"},"infected":{"type":"number"}},"required":["clean","at_risk","infected"]},"threats":{"type":"object","properties":{"assets_with_threats":{"type":"number"},"total_threats":{"type":"number"},"by_threat_kind":{"type":"object","properties":{"malware":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]},"ransomware":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]},"filesystem_error":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]},"encryption":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"},"severity":{"type":"string"}},"required":["assets","threats","severity"]}},"required":["malware","ransomware","filesystem_error","encryption"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"threats":{"type":"number"}},"required":["assets","threats"]}},"required":["critical","high","medium","low"]}},"required":["assets_with_threats","total_threats","by_threat_kind","by_severity"]},"sensitive_data":{"type":"object","properties":{"assets_scanned_for_sensitive_data":{"type":"number"},"assets_with_sensitive_data":{"type":"number"},"total_findings":{"type":"number"},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"findings":{"type":"number"}},"required":["assets","findings"]}},"required":["critical","high","medium","low"]}},"required":["assets_scanned_for_sensitive_data","assets_with_sensitive_data","total_findings","by_severity"]},"coverage":{"type":"object","properties":{"non_compliant_assets":{"type":"number"},"total_violations":{"type":"number"},"by_violation_code":{"type":"object","properties":{"no_policy_coverage":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"ebs_volume_unattached":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"azure_disk_unattached":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]}},"required":["no_policy_coverage","ebs_volume_unattached","azure_disk_unattached"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"info":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]}},"required":["critical","high","medium","low","info"]}},"required":["non_compliant_assets","total_violations","by_violation_code","by_severity"]},"protection":{"type":"object","properties":{"non_compliant_assets":{"type":"number"},"total_violations":{"type":"number"},"by_violation_code":{"type":"object","properties":{"no_backup":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"backup_stale":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]}},"required":["no_backup","backup_stale"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"info":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]}},"required":["critical","high","medium","low","info"]}},"required":["non_compliant_assets","total_violations","by_violation_code","by_severity"]},"recovery":{"type":"object","properties":{"non_compliant_assets":{"type":"number"},"total_violations":{"type":"number"},"by_violation_code":{"type":"object","properties":{"no_clean_backup":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"r_rpo_exceeded":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"no_backup":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]},"backup_stale":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"},"severity":{"type":"string"}},"required":["assets","violations","severity"]}},"required":["no_clean_backup","r_rpo_exceeded","no_backup","backup_stale"]},"by_severity":{"type":"object","properties":{"critical":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"high":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"medium":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"low":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]},"info":{"type":"object","properties":{"assets":{"type":"number"},"violations":{"type":"number"}},"required":["assets","violations"]}},"required":["critical","high","medium","low","info"]}},"required":["non_compliant_assets","total_violations","by_violation_code","by_severity"]}},"required":["policy_id","policy_name","live_asset_count","total_threats","total_violations","health","threats","sensitive_data","coverage","protection","recovery"]}}},"required":["total","data"]}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/assets/coverage-by-platform":{"get":{"operationId":"get_coverage_by_platform","summary":"Get scoped policy coverage grouped by platform","tags":["Assets"],"description":"Returns live-inventory asset counts and policy-covered counts per platform for the current X-Effective-Scope context. Covered means active policy membership on the asset or all attached volumes/disks for VMs.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"object","properties":{"mode":{"type":"string","enum":["all_live_inventory","policy_members","unpoliced"]},"scope_id":{"type":"string"}},"required":["mode"]},"platforms":{"type":"array","items":{"type":"object","properties":{"platform":{"type":"string"},"label":{"type":"string"},"total_assets":{"type":"number"},"covered_assets":{"type":"number"}},"required":["platform","label","total_assets","covered_assets"]}}},"required":["scope","platforms"]}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/count":{"get":{"operationId":"get_findings_count_v2","summary":"Get findings counts","tags":["Findings"],"description":"Returns counts of threats, open violations, and assets with sensitive data findings for your current access and policy scope, plus unique affected assets per bucket.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"threats":{"type":"number","description":"Number of threat findings."},"violations":{"type":"number","description":"Number of open policy violations."},"data_classification":{"type":"number","description":"Number of assets with sensitive data findings."},"affected_assets":{"type":"object","description":"Unique display assets with at least one finding. Attached volumes and disks count on the parent VM when the parent is in scope; unattached children and children whose parent is out of scope count as themselves.","properties":{"threats":{"type":"number","description":"Unique assets with an open threat finding."},"violations":{"type":"number","description":"Unique assets with an open policy violation."},"data_classification":{"type":"number","description":"Unique assets with sensitive data findings. Matches `data_classification`."},"total":{"type":"number","description":"Unique assets with any of the above. An asset in more than one bucket counts once."}},"required":["threats","violations","data_classification","total"]}},"required":["threats","violations","data_classification","affected_assets"]}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/{findingId}/acknowledge":{"post":{"operationId":"acknowledge_finding_v2","summary":"Acknowledge a finding","tags":["Findings"],"description":"Marks that an analyst owns the finding (the OCSF In-Progress analog). Sets status to acknowledged and records who and when. Optional in the workflow: no transition requires passing through it.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":1024,"description":"Optional note (<= 1024 chars)."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^(threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:custom:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:[a-z_]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"},"in":"path","name":"findingId","required":true,"description":"Finding identity: `threat:{asset_id}:{hunt}` for Elastio hunts and pursuit, `threat:{asset_id}:custom:{finding_id}` for custom hunts, the api/v2/violations row id (a uuid) for violations."}],"responses":{"204":{"description":"No Content. The transition was applied."},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/{findingId}/suppress":{"post":{"operationId":"suppress_finding_v2","summary":"Suppress a finding","tags":["Findings"],"description":"Silences a finding judged not actionable (false positive, benign, accepted risk, duplicate). Carries a reason and a required expiry; while suppressed the finding stays quiet on every channel and does not re-alert. Suppressing does not fix anything. Unifies both finding classes; the served scoped violation-suppressions family stays the scoped-exception surface.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"description":"Required, non-empty. Convention '<disposition>: <note>'; stored verbatim."},"until":{"type":"string","format":"date-time","description":"Required. RFC3339 UTC; must be later than now."}},"required":["reason","until"],"additionalProperties":false}}},"required":true},"parameters":[{"schema":{"type":"string","pattern":"^(threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:custom:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:[a-z_]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"},"in":"path","name":"findingId","required":true,"description":"Finding identity: `threat:{asset_id}:{hunt}` for Elastio hunts and pursuit, `threat:{asset_id}:custom:{finding_id}` for custom hunts, the api/v2/violations row id (a uuid) for violations."}],"responses":{"204":{"description":"No Content. The transition was applied."},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/{findingId}/resolve":{"post":{"operationId":"resolve_finding_v2","summary":"Resolve a finding","tags":["Findings"],"description":"Records that the underlying problem is fixed (threat remediated or config corrected). If a resolved finding is detected again it reopens automatically and re-alerts loudly (a regression, not noise). Violations are evaluator-resolved, so this verb returns 409 UNSUPPORTED_FINDING_CLASS for violation-class ids.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","maxLength":1024,"description":"Optional note (<= 1024 chars)."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^(threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:custom:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:[a-z_]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"},"in":"path","name":"findingId","required":true,"description":"Finding identity: `threat:{asset_id}:{hunt}` for Elastio hunts and pursuit, `threat:{asset_id}:custom:{finding_id}` for custom hunts, the api/v2/violations row id (a uuid) for violations."}],"responses":{"204":{"description":"No Content. The transition was applied."},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/{findingId}/recover":{"post":{"operationId":"recover_finding_v2","summary":"Recover a finding by restoring from a clean recovery point","tags":["Findings"],"description":"Schedules a restore of the finding's asset from a clean recovery point and returns a job handle (202). Preconditions: the recovery point protects the finding's asset and reads health: clean. On job success the finding is resolved automatically with the restore recorded in its history. Threat-class only; violation-class ids return 409 UNSUPPORTED_FINDING_CLASS.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"recovery_point_id":{"type":"string","format":"uuid","description":"Required. Recovery point to restore the asset from."},"note":{"type":"string","maxLength":1024,"description":"Optional note (<= 1024 chars)."}},"required":["recovery_point_id"],"additionalProperties":false}}},"required":true},"parameters":[{"schema":{"type":"string","pattern":"^(threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:custom:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:[a-z_]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"},"in":"path","name":"findingId","required":true,"description":"Finding identity: `threat:{asset_id}:{hunt}` for Elastio hunts and pursuit, `threat:{asset_id}:custom:{finding_id}` for custom hunts, the api/v2/violations row id (a uuid) for violations."}],"responses":{"202":{"description":"Accepted. A restore job was scheduled.","content":{"application/json":{"schema":{"type":"object","description":"Accepted. A restore job was scheduled.","properties":{"job_id":{"type":"string","format":"uuid"},"finding_id":{"type":"string"},"recovery_point_id":{"type":"string"},"state":{"type":"string","enum":["scheduled"]}},"required":["job_id","finding_id","recovery_point_id","state"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/{findingId}/reopen":{"post":{"operationId":"reopen_finding_v2","summary":"Reopen a finding","tags":["Findings"],"description":"Puts a suppressed or resolved finding back to open by hand. Legal from suppressed | resolved; from open | acknowledged returns 409. Automatic reopen on re-detection of a resolved finding is handled server-side, not through this endpoint.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","maxLength":1024,"description":"Optional reason (<= 1024 chars)."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^(threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:custom:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:[a-z_]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"},"in":"path","name":"findingId","required":true,"description":"Finding identity: `threat:{asset_id}:{hunt}` for Elastio hunts and pursuit, `threat:{asset_id}:custom:{finding_id}` for custom hunts, the api/v2/violations row id (a uuid) for violations."}],"responses":{"204":{"description":"No Content. The transition was applied."},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/suppressions":{"get":{"operationId":"list_finding_suppressions_v2","summary":"List suppressed findings","tags":["Findings"],"description":"Returns one row per currently-suppressed finding across both classes. The served rule-level violation-suppressions read remains as-is; this projection is what finding surfaces render.","parameters":[{"schema":{"type":"string","enum":["threat","violation","data_classification"]},"in":"query","name":"class","required":false,"description":"Optional. Restrict to one finding class."},{"schema":{"type":"boolean","default":false},"in":"query","name":"include_expired","required":false,"description":"Optional. Include suppressions whose expiry has passed."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size."},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token."},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"finding_id":{"type":"string"},"finding_class":{"type":"string","enum":["threat","violation","data_classification"]},"reason":{"type":"string"},"until":{"type":"string","format":"date-time","nullable":true,"description":"Expiry (RFC3339); null only for scoped rules without expiry."},"suppressed_by":{"type":"string"},"suppressed_at":{"type":"string","format":"date-time"},"source":{"type":"string","enum":["finding","scoped_rule"]},"scoped_rule_id":{"type":"string","format":"uuid","nullable":true,"description":"violation-suppressions rule id when source is scoped_rule."}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/resolutions":{"get":{"operationId":"list_finding_resolutions_v2","summary":"List resolved findings","tags":["Findings"],"description":"Returns one row per currently-resolved finding across both classes, distinguishing manual resolves from recover-driven ones.","parameters":[{"schema":{"type":"string","enum":["threat","violation","data_classification"]},"in":"query","name":"class","required":false,"description":"Optional. Restrict to one finding class."},{"schema":{"type":"string","enum":["manual","recover"]},"in":"query","name":"source","required":false,"description":"Optional. Restrict to manual or recover-driven resolves."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size."},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token."},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"finding_id":{"type":"string"},"finding_class":{"type":"string","enum":["threat","violation","data_classification"]},"resolved_at":{"type":"string","format":"date-time"},"resolved_by":{"type":"string"},"note":{"type":"string","nullable":true},"source":{"type":"string","nullable":true,"enum":["manual","recover"]},"job_id":{"type":"string","format":"uuid","nullable":true,"description":"Restore job id when source is recover."},"recovery_point_id":{"type":"string","format":"uuid","nullable":true,"description":"Recovery point restored from when source is recover."}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/findings/{findingId}/status-log":{"get":{"operationId":"get_finding_status_log_v2","summary":"Get a finding's status log","tags":["Findings"],"description":"Returns the append-only audit of every status transition for a finding, newest first, including automatic transitions (expiry, redetection, recover completion).","parameters":[{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size."},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token."},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token."},{"schema":{"type":"string","pattern":"^(threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:custom:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|threat:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}:[a-z_]+|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"},"in":"path","name":"findingId","required":true,"description":"Finding identity: `threat:{asset_id}:{hunt}` for Elastio hunts and pursuit, `threat:{asset_id}:custom:{finding_id}` for custom hunts, the api/v2/violations row id (a uuid) for violations."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"at":{"type":"string","format":"date-time"},"actor":{"type":"string","description":"User identity, or 'system'."},"from":{"type":"string","enum":["open","acknowledged","suppressed","resolved"]},"to":{"type":"string","enum":["open","acknowledged","suppressed","resolved"]},"verb":{"type":"string","enum":["acknowledge","suppress","resolve","recover","reopen","unsuppress","expire","redetect"]},"source":{"type":"string","enum":["manual","expiry","redetection","recover"]},"reason":{"type":"string","nullable":true},"until":{"type":"string","format":"date-time","nullable":true},"note":{"type":"string","nullable":true},"job_id":{"type":"string","format":"uuid","nullable":true},"recovery_point_id":{"type":"string","format":"uuid","nullable":true}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"501":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/data-classification/definitions":{"get":{"operationId":"list_data_classification_definitions_v2","summary":"Get default severities for data classification types","tags":["Data Classification"],"description":"Returns every data classification definition. This is the Default column in the policy editor. Severities are critical, high, medium, or low.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"ccl_type":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low"]}},"required":["ccl_type","severity"]}}},"required":["data"]}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/data-classification/findings":{"get":{"operationId":"list_data_classification_findings_v2","summary":"List assets with sensitive data classification findings","tags":["Data Classification"],"description":"Returns display assets that currently have sensitive findings. Volume/disk findings are rolled up to attached EC2 instances / Azure VMs. Unattached volumes/disks appear as their own rows. Empty classification rows are excluded.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"findings_category","required":false,"description":"Comma-separated finding categories (asset matches if any listed category has count > 0)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated display asset kinds (after volume/disk rollup)"},{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"Comma-separated asset IDs"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical, high, medium, low). An asset matches when its highest severity is one of them."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account (blob/file share). IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"findings_by_category":{"type":"object","additionalProperties":{"type":"number"},"description":"Category name to finding count map"},"findings_by_category_severity":{"type":"object","additionalProperties":{"type":"string","enum":["critical","high","medium","low"]},"description":"Severity for rollup keys that are known CCL types with count greater than 0"},"highest_severity":{"type":"string","nullable":true,"enum":["critical","high","medium","low"],"description":"Worst severity among known CCL types on this asset. Null when none of the rollup keys are known types."},"updated_at":{"type":"string","nullable":true,"description":"Latest classification update across the display asset and contributing volumes/disks"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/data-classification/findings/filters":{"get":{"operationId":"list_data_classification_findings_v2_filters","summary":"Get contextual filter options for v2 data classification findings","tags":["Data Classification"],"description":"Lists available filter options and result counts based on your current search and filter selections.","parameters":[{"schema":{"type":"string"},"in":"query","name":"search","required":false,"description":"Free-text search"},{"schema":{"type":"string"},"in":"query","name":"findings_category","required":false,"description":"Comma-separated finding categories"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws,azure,ibm,on_prem)"},{"schema":{"type":"string"},"in":"query","name":"asset_kind","required":false,"description":"Comma-separated asset kinds"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical, high, medium, low)"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"findings_category":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of display assets matching this option given all other active filters."}},"required":["value","label","count"]}},"asset_kind":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of display assets matching this option given all other active filters."}},"required":["value","label","count"]}},"policy_id":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of display assets matching this option given all other active filters."}},"required":["value","label","count"]}},"severity":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of display assets matching this option given all other active filters."}},"required":["value","label","count"]}}},"required":["findings_category","asset_kind","policy_id","severity"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/violations/definitions":{"get":{"operationId":"list_violation_definitions_v2","summary":"Get supported violation definitions","tags":["Violations"],"description":"Returns the catalog of supported violation types with code, title, category, and severity.","parameters":[{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Comma-separated categories to filter by"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]}}}}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/violations":{"get":{"operationId":"list_violations_v2","summary":"Get list of open asset violations","tags":["Violations"],"description":"Returns open violations for accessible live assets in the tenant.","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_id","required":false,"description":"Comma-separated asset IDs (use when expanding an asset group)"},{"schema":{"type":"string"},"in":"query","name":"violation_code","required":false,"description":"Comma-separated violation codes"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Comma-separated violation categories"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"string","enum":["open","acknowledged","suppressed","resolved","all"]},"in":"query","name":"status","required":false,"description":"Filter rows by lifecycle status. Omitted means `open`, the default this list has always had; pass `all` explicitly for every status."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size (default 10, max 100)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"violation_code":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"details":{"type":"object"},"last_evaluated_at":{"type":"string"},"created_at":{"type":"string"},"status":{"type":"string","enum":["open","acknowledged","suppressed","resolved"],"description":"Lifecycle status of the finding."},"status_changed_at":{"type":"string","format":"date-time","nullable":true,"description":"When the status last changed (RFC3339 UTC)."},"suppressed_until":{"type":"string","format":"date-time","nullable":true,"description":"Expiry of an active suppression (RFC3339 UTC); null if not suppressed."},"suppression_reason":{"type":"string","nullable":true,"description":"Reason recorded for an active suppression; null if not suppressed."},"resolved_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was resolved (RFC3339 UTC); null if not resolved."},"resolved_by":{"type":"string","nullable":true,"description":"Actor who resolved the finding; null if not resolved."},"resolve_note":{"type":"string","nullable":true,"description":"Optional note recorded at resolve time; null if absent."},"acknowledged_at":{"type":"string","format":"date-time","nullable":true,"description":"When the finding was acknowledged (RFC3339 UTC); null if not acknowledged."},"acknowledged_by":{"type":"string","nullable":true,"description":"Actor who acknowledged the finding; null if not acknowledged."}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/violations/groups":{"get":{"operationId":"list_violations_v2_groups","summary":"Get v2 violation group summaries","tags":["Violations"],"description":"Lists violation groups with a count per group (for example one row per asset or per severity). Set group_by to choose the grouping. To load full violation details for a group, call GET /api/v2/violations with the same filters and add the filter for that group (such as asset_id, severity, category, or policy_id=<group.key>).","parameters":[{"schema":{"type":"string","enum":["asset","violation_code","severity","category","policy"]},"in":"query","name":"group_by","required":true,"description":"Dimension to group by"},{"schema":{"type":"string"},"in":"query","name":"violation_code","required":false,"description":"Comma-separated violation codes"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Comma-separated violation categories"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size (groups per page, default 10, max 100)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"group_by":{"type":"string","enum":["asset","violation_code","severity","category","policy"]},"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"count":{"type":"number"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/violations/filters":{"get":{"operationId":"list_violations_v2_filters","summary":"Get contextual filter options for v2 violations","tags":["Violations"],"description":"Lists available violation filter options and result counts based on your current search and filter selections.","parameters":[{"schema":{"type":"string"},"in":"query","name":"violation_code","required":false,"description":"Comma-separated violation codes"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severities (critical,high,medium,low,info)"},{"schema":{"type":"string"},"in":"query","name":"category","required":false,"description":"Comma-separated violation categories"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Comma-separated policy UUIDs from policy membership, or unpoliced"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"violation_code":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of violation rows matching this option given all other active filters."}},"required":["value","label","count"]}},"severity":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of violation rows matching this option given all other active filters."}},"required":["value","label","count"]}},"category":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of violation rows matching this option given all other active filters."}},"required":["value","label","count"]}},"policy_id":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"count":{"type":"number","description":"Number of violation rows matching this option given all other active filters."}},"required":["value","label","count"]}}},"required":["violation_code","severity","category","policy_id"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v2/violations/{violationId}":{"get":{"operationId":"get_violation_v2","summary":"Get a violation by ID","tags":["Violations"],"description":"Returns a single violation by ID for an accessible live asset in the tenant, in any lifecycle status. Returns 404 if the violation is not found or outside the caller's scope.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"violationId","required":true,"description":"Violation ID"}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_kind":{"type":"string"},"platform":{"type":"string","description":"aws|azure|ibm|on_prem|gcp"},"platform_details":{"type":"object","description":"Platform-specific context. AWS: account_id + region. Azure: subscription_id, resource_group, optional region and storage_account. IBM: scope, optional location and bucket_crn. On-prem: account_id only. GCP: project_id, plus zone (VM), location and location_kind (disk), or location and storage_class (bucket).","properties":{"account_id":{"type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"storage_account":{"type":"string"},"scope":{"type":"string"},"location":{"type":"string"},"bucket_crn":{"type":"string"},"project_id":{"type":"string"},"zone":{"type":"string"},"location_kind":{"type":"string","enum":["zonal","regional"]},"storage_class":{"type":"string"}},"additionalProperties":false},"policies":{"type":"array","description":"Effective policy coverage for this asset (direct memberships plus implied parent coverage for attached volumes/disks), sorted by policy name.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}},"violation_code":{"type":"string"},"title":{"type":"string"},"category":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"details":{"type":"object"},"last_evaluated_at":{"type":"string"},"created_at":{"type":"string"}}}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/threats-issues-infectedfiles-count":{"get":{"operationId":"threats_issues_infectedfiles_count","summary":"Count findings, issues and files with findings","tags":["Threats"],"description":"Get threats,Issues and Infected files count","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"threats":{"type":"number"},"issues":{"type":"number"},"infected_files":{"type":"number"}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/issues-filters":{"get":{"operationId":"issues_filters","summary":"Get issues filters","tags":["Issues"],"description":"Get issues filters","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"cached":{"type":"boolean"},"expiresInMs":{"type":"number","nullable":true},"data":{"type":"object","properties":{"severity":{"type":"array","items":{"type":"string"}},"issue_types":{"type":"array","items":{"type":"string"}},"asset_types":{"type":"array","items":{"type":"string"}},"platforms":{"type":"array","items":{"type":"string"}},"names":{"type":"array","items":{"type":"string"}},"asset_ids":{"type":"array","items":{"type":"string"}},"account_ids":{"type":"array","items":{"type":"string"}}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/threats-filters":{"get":{"operationId":"threats_filters","summary":"Get finding filters","tags":["Threats"],"description":"Get threats filters","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"cached":{"type":"boolean"},"expiresInMs":{"type":"number","nullable":true},"data":{"type":"object","properties":{"severity":{"type":"array","items":{"type":"string"}},"threat_kinds":{"type":"array","items":{"type":"string"}},"asset_kinds":{"type":"array","items":{"type":"string"}},"names":{"type":"array","items":{"type":"string"}},"asset_ids":{"type":"array","items":{"type":"string"}},"account_ids":{"type":"array","items":{"type":"string"}},"platforms":{"type":"array","items":{"type":"string"}}}},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/filters":{"get":{"operationId":"get_cloud_connector_jobs_filters","summary":"Get Cloud Connector job filters","tags":["Jobs"],"description":"Get available filter options for Cloud Connector jobs including assets","parameters":[{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering (ISO format: YYYY-MM-DD)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"kinds":{"type":"array","items":{"type":"string"},"description":"Available job kinds"},"statuses":{"type":"array","items":{"type":"string","enum":["scheduled","starting","in_progress","failed","succeeded","aborted"]},"description":"Available job statuses (JobStatus enum values)"},"assets":{"type":"array","nullable":true,"items":{"type":"object","properties":{"id":{"type":"string","description":"Asset ID"},"name":{"type":"string","description":"Asset name"}},"required":["id","name"]},"description":"Available assets for filtering"},"cloud_connectors":{"type":"array","nullable":true,"items":{"oneOf":[{"type":"object","description":"Classic AWS cloud-connector stack","properties":{"id":{"type":"string","description":"Cloud connector ID"},"deployment":{"type":"string","enum":["cloud_connector"]},"aws_account_id":{"type":"string","description":"AWS account ID"},"aws_region":{"type":"string","description":"AWS region"}},"required":["id","deployment","aws_account_id","aws_region"],"additionalProperties":false},{"type":"object","description":"Decoupled scan-cluster connector","properties":{"id":{"type":"string","description":"Scan cluster ID"},"deployment":{"type":"string","enum":["decoupled"]},"cluster_name":{"type":"string","description":"Scan cluster name"},"cluster_kind":{"type":"string","enum":["azure","ibm","on_prem","gcp"],"description":"Scan cluster platform kind"},"cluster_type":{"type":"string","enum":["self_managed","elastio_managed"],"description":"Scan cluster management type"}},"required":["id","deployment","cluster_name","cluster_kind","cluster_type"],"additionalProperties":false}]},"description":"Available Cloud Connectors for filtering (AWS Cloud Connectors and standalone deployments)"},"asset_accounts":{"type":"array","nullable":true,"items":{"type":"object","properties":{"account_id":{"type":"string","description":"The asset's own account identity"},"region":{"type":"string","nullable":true,"description":"The asset's region; null when it has none"}},"required":["account_id"]},"description":"Accounts the jobs' ASSETS live in, which is what the Account/Region column reports. Includes Protected Accounts, which the cloud_connectors facet cannot represent. Filter with assetAccountIds."},"trigger_sources":{"type":"array","nullable":true,"items":{"type":"string","enum":["guardduty","threat-hunt","wiz","s3-threat-hunt"]},"description":"Available scan trigger sources for filtering (if present in range)"}},"required":["kinds","statuses"]},"cached":{"type":"boolean","description":"Whether response came from cache"},"expiresInMs":{"type":"number","nullable":true,"description":"Cache expiration time in milliseconds"},"message":{"type":"string","example":"Cloud connector job filters retrieved successfully"}},"required":["status","data","cached","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/groups":{"get":{"operationId":"list_cloud_connector_jobs_groups","summary":"Get Cloud Connector job group summaries","tags":["Jobs"],"description":"Lists Cloud Connector job groups with a count per group (asset or policy). To load full job details for a group, call GET /api/v1/jobs/cloud-connector with the same filters and add assetIds=<group.key> when group_by=asset, or policy_id=<group.key> when group_by=policy. For the unpoliced policy bucket, use X-Effective-Scope unpoliced mode on the list endpoint.","parameters":[{"schema":{"type":"string","enum":["asset","policy"]},"in":"query","name":"group_by","required":true,"description":"Dimension to group by"},{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"kinds","required":false,"description":"Comma-separated list of job kinds to filter by"},{"schema":{"type":"string"},"in":"query","name":"statuses","required":false,"description":"Comma-separated list of job statuses to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetIds","required":false,"description":"Comma-separated list of asset IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"cloudConnectorIds","required":false,"description":"Comma-separated list of Cloud Connector IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"triggerSources","required":false,"description":"Comma-separated list of trigger sources to filter by (guardduty, threat-hunt)"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Only jobs whose asset(s) are currently covered by this policy's scope (asset-membership semantics, not trigger attribution). policyId is accepted as an alias."},{"schema":{"type":"string"},"in":"query","name":"policyId","required":false,"description":"CamelCase alias of policy_id."},{"schema":{"type":"string","enum":["aws","azure"]},"in":"query","name":"platform","required":false,"description":"Only jobs of this platform, derived from the job kind prefix (aws_* / azure_*)."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kindScope","required":false,"description":"Jobs Kind chip, the same classification as hunt_count / deployment_count / system_count on GET /jobs/count. kind_scope is accepted as an alias."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kind_scope","required":false,"description":"Snake_case alias of kindScope."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size (groups per page)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"group_by":{"type":"string","enum":["asset","policy"]},"total":{"type":"number"},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"count":{"type":"number"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/groups":{"get":{"operationId":"list_jobs_groups","summary":"Get job group summaries across Cloud Connector and tenant jobs","tags":["Jobs"],"description":"Lists job groups with a count per group (asset or policy) across BOTH job sources (Cloud Connector and tenant (deployment/system)) for the Jobs 'All' surface. Pagination pages over GROUPS, not jobs, so a group is never split across pages and its count is always the group's full total. To load a group's jobs, call GET /jobs with the same filters plus assetIds=<group.key> when group_by=asset, or policy_id=<group.key> when group_by=policy. Grouping semantics: a Cloud Connector job counts under every asset it touched and every policy covering those assets (membership semantics, so counts may sum above the job total). Tenant jobs have no asset of their own and all collapse into the single 'no-asset' bucket under group_by=asset; under group_by=policy each counts exactly once, under the same policy the jobs list displays for it. Because tenant jobs carry no asset, no trigger source and are not filterable by policy, they are excluded entirely when assetIds, triggerSources or policy_id is supplied.","parameters":[{"schema":{"type":"string","enum":["asset","policy"]},"in":"query","name":"group_by","required":true,"description":"Dimension to group by"},{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"kinds","required":false,"description":"Comma-separated list of job kinds to filter by. Matched against each source's own kind column, so a kind that exists only on one side simply matches nothing on the other."},{"schema":{"type":"string"},"in":"query","name":"statuses","required":false,"description":"Comma-separated list of job statuses to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetIds","required":false,"description":"Comma-separated list of asset IDs to filter by. Excludes tenant jobs, which carry no asset."},{"schema":{"type":"string"},"in":"query","name":"cloudConnectorIds","required":false,"description":"Comma-separated list of Cloud Connector IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"triggerSources","required":false,"description":"Comma-separated list of trigger sources to filter by (guardduty, threat-hunt). Excludes tenant jobs, which have no trigger source."},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Only jobs whose asset(s) are currently covered by this policy's scope (asset-membership semantics, not trigger attribution). policyId is accepted as an alias. Excludes tenant jobs, which the jobs list does not filter by policy."},{"schema":{"type":"string"},"in":"query","name":"policyId","required":false,"description":"CamelCase alias of policy_id."},{"schema":{"type":"string","enum":["aws","azure"]},"in":"query","name":"platform","required":false,"description":"Only jobs of this platform, derived from the job kind prefix (aws_* / azure_*)."},{"schema":{"type":"integer"},"in":"query","name":"page_size","required":false,"description":"Page size (groups per page)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Prev page token"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"group_by":{"type":"string","enum":["asset","policy"]},"total":{"type":"number","description":"Total number of GROUPS matching the filters"},"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"count":{"type":"number"}}}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/count":{"get":{"operationId":"get_jobs_count","summary":"Count Cloud Connector and tenant jobs in the unified catalog","tags":["Jobs"],"description":"Same filters as GET /jobs, no pagination and no row hydration. Returns the filtered union total, the contribution of each source, and Kind-chip counts (hunt / deployment / system). Every parent job is in exactly one chip, so the three add up to total_count. Call once without kindScope to fill the nav chips. kindScope narrows both the totals and the chip numbers to that chip. Pursuit is a name heuristic, not a count facet.","parameters":[{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"kinds","required":false,"description":"Comma-separated list of job kinds. Matched against each source's own kind column."},{"schema":{"type":"string"},"in":"query","name":"statuses","required":false,"description":"Comma-separated list of job statuses to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetIds","required":false,"description":"Comma-separated list of asset IDs. Excludes tenant jobs, which carry no asset."},{"schema":{"type":"string"},"in":"query","name":"cloudConnectorIds","required":false,"description":"Comma-separated list of Cloud Connector IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetAccountIds","required":false,"description":"Comma-separated list of ASSET account IDs. Excludes tenant jobs, which have no asset."},{"schema":{"type":"string"},"in":"query","name":"triggerSources","required":false,"description":"Comma-separated list of trigger sources (guardduty, threat-hunt). Excludes tenant jobs."},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Only jobs whose asset(s) are currently covered by this policy's scope. policyId is accepted as an alias. Excludes tenant jobs."},{"schema":{"type":"string"},"in":"query","name":"policyId","required":false,"description":"CamelCase alias of policy_id."},{"schema":{"type":"string","enum":["aws","azure"]},"in":"query","name":"platform","required":false,"description":"Only jobs of this platform, derived from the job kind prefix (aws_* / azure_*)."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kindScope","required":false,"description":"Jobs Kind chip. hunt / deployment / system use the same classification as hunt_count / deployment_count / system_count on GET /jobs/count. kind_scope is accepted as an alias. Pursuit is not a server facet."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kind_scope","required":false,"description":"Snake_case alias of kindScope."},{"schema":{"type":"string"},"in":"query","name":"jobId","required":false,"description":"Human-readable cloud-connector Job ID (`cc_job_id`, e.g. `j-01m09zvyyfcgx4ynp40x4e4rej`). Prefix match, case-insensitive. Excludes tenant jobs, which have no human-readable job id."},{"schema":{"type":"string"},"in":"query","name":"noCache","required":false,"description":"Set to 'true' to bypass the jobs cache"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"total_count":{"type":"number","description":"Parent jobs matching the filters across both sources"},"cloud_connector_count":{"type":"number","description":"Matching Cloud Connector parent jobs"},"tenant_count":{"type":"number","description":"Matching tenant parent jobs"},"hunt_count":{"type":"number","description":"Cloud-connector parents whose kind is a scan or hunt (`…_scan`, `…_scan_trigger`, `iscan`, `…_hunt`) or `unknown`. Matches the Hunt chip."},"deployment_count":{"type":"number","description":"Tenant parents whose kind is install/vault/connector lifecycle, plus cloud-connector region-stack parents. Matches the Deployment chip."},"system_count":{"type":"number","description":"Every other parent: tenant jobs outside Deployment and cloud-connector jobs that are neither hunts nor region stacks (inventory, backups, maintenance). Matches the System chip."}},"required":["total_count","cloud_connector_count","tenant_count","hunt_count","deployment_count","system_count"]},"cached":{"type":"boolean","description":"Whether response came from cache"},"expiresInMs":{"type":"number","nullable":true,"description":"Cache expiration time in milliseconds"},"message":{"type":"string","example":"Job counts retrieved successfully"}},"required":["status","data","cached","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs":{"get":{"operationId":"list_jobs","summary":"List Cloud Connector and tenant jobs in one catalog","tags":["Jobs"],"description":"Cloud Connector and tenant parent jobs, filtered with the same predicates as GET /jobs/cloud-connector and GET /jobs/tenant, unioned, sorted, and paginated as one list. Each row is the existing cloud-connector or tenant job object plus `source`. Filters the tenant list cannot honor (assetIds, assetAccountIds, triggerSources, policy_id) drop the tenant branch. kindScope keeps the jobs of one Kind chip from both sources (hunt has no tenant jobs). Order is newest first using each source's existing list sort key. To load a group's jobs from GET /jobs/groups, pass the same filters plus assetIds=<group.key> or policy_id=<group.key>.","parameters":[{"schema":{"type":"string"},"in":"query","name":"pageToken","required":false,"description":"Pagination token for next/previous page. Base64 JSON `{ offset }`, the same encoding as /jobs/cloud-connector and /jobs/tenant."},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page (1–100)"},{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"kinds","required":false,"description":"Comma-separated list of job kinds. Matched against each source's own kind column."},{"schema":{"type":"string"},"in":"query","name":"statuses","required":false,"description":"Comma-separated list of job statuses to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetIds","required":false,"description":"Comma-separated list of asset IDs. Excludes tenant jobs, which carry no asset."},{"schema":{"type":"string"},"in":"query","name":"cloudConnectorIds","required":false,"description":"Comma-separated list of Cloud Connector IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetAccountIds","required":false,"description":"Comma-separated list of ASSET account IDs. Excludes tenant jobs, which have no asset."},{"schema":{"type":"string"},"in":"query","name":"triggerSources","required":false,"description":"Comma-separated list of trigger sources (guardduty, threat-hunt). Excludes tenant jobs."},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Only jobs whose asset(s) are currently covered by this policy's scope. policyId is accepted as an alias. Excludes tenant jobs."},{"schema":{"type":"string"},"in":"query","name":"policyId","required":false,"description":"CamelCase alias of policy_id."},{"schema":{"type":"string","enum":["aws","azure"]},"in":"query","name":"platform","required":false,"description":"Only jobs of this platform, derived from the job kind prefix (aws_* / azure_*)."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kindScope","required":false,"description":"Jobs Kind chip. hunt / deployment / system use the same classification as hunt_count / deployment_count / system_count on GET /jobs/count. kind_scope is accepted as an alias. Pursuit is not a server facet."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kind_scope","required":false,"description":"Snake_case alias of kindScope."},{"schema":{"type":"string"},"in":"query","name":"jobId","required":false,"description":"Human-readable cloud-connector Job ID (`cc_job_id`, e.g. `j-01m09zvyyfcgx4ynp40x4e4rej`). Prefix match, case-insensitive. Excludes tenant jobs, which have no human-readable job id."},{"schema":{"type":"string"},"in":"query","name":"noCache","required":false,"description":"Set to 'true' to bypass the jobs cache"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"jobsList":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"source":{"type":"string","enum":["cloud-connector","tenant"],"description":"Which catalog this row came from. The remaining fields match GET /jobs/cloud-connector or GET /jobs/tenant exactly."},"id":{"type":"string","description":"Job ID"},"status":{"type":"string","description":"Job status"},"kind":{"type":"string","description":"Job kind"},"created_at":{"type":"string","description":"Creation timestamp"},"updated_at":{"type":"string","description":"Last update timestamp"},"tenant_name":{"type":"string","description":"Tenant name"},"childrenList":{"type":"array","description":"Child jobs (stages)","items":{"type":"object"}}},"required":["source","id","status","kind","created_at","updated_at","tenant_name","childrenList"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string","nullable":true,"description":"Token for next page"},"prev_page_token":{"type":"string","nullable":true,"description":"Token for previous page"},"total_count":{"type":"number","description":"Total parent jobs in the filtered union"}},"required":["total_count"]}},"required":["jobsList","pagination"]},"cached":{"type":"boolean","description":"Whether response came from cache"},"expiresInMs":{"type":"number","nullable":true,"description":"Cache expiration time in milliseconds"},"message":{"type":"string","example":"Jobs retrieved successfully"}},"required":["status","data","cached","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/{jobId}":{"get":{"operationId":"get_cloud_connector_job","summary":"Get Cloud Connector job by id","tags":["Jobs"],"description":"Returns a single Cloud Connector job by id","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"jobId","required":true,"description":"Parent job UUID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","description":"Cloud connector job object","additionalProperties":true},"message":{"type":"string","example":"Cloud connector job retrieved successfully"}},"required":["status","data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/{jobId}/scans":{"get":{"operationId":"get_cloud_connector_job_scans","summary":"List the hunts in a Cloud Connector job","tags":["Jobs"],"description":"Returns all scans for a given Cloud Connector job, including threat_count per scan","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"jobId","required":true,"description":"Cloud connector job UUID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true},"job_id":{"type":"string","format":"uuid"},"kind":{"type":"string"},"status":{"type":"string","enum":["good","bad"]},"type":{"type":"string","enum":["direct","backup"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"scan_created_ebs_snapshot_id":{"type":"string","format":"uuid","nullable":true},"scan_created_ami_id":{"type":"string","format":"uuid","nullable":true},"threat_count":{"type":"number"},"target_asset_details":{"type":"array","description":"Assets for the UUIDs derived from target (display name uses the same rules as Cloud Connector job list)","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Asset UUID"},"name":{"type":"string","description":"Resolved display name"},"kind":{"type":"string","enum":["ec2","ebs","s3","efs","generic_host","server","fsx","azure_vm","azure_disk","azure_blob","azure_file_share","ibm_cos_bucket"],"description":"API asset kind"}},"required":["id","name","kind"]}}},"required":["id","tenant_name","cc_id","target","job_id","kind","status","type","created_at","updated_at","scan_created_ebs_snapshot_id","scan_created_ami_id","threat_count"]}},"message":{"type":"string","example":"Cloud connector job scans retrieved successfully"}},"required":["status","data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/{jobId}/raw-data":{"get":{"operationId":"get_cloud_connector_job_raw_data","summary":"Get Cloud Connector job raw data by id","tags":["Jobs"],"description":"Returns the raw_data JSONB column for a parent Cloud Connector job","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"jobId","required":true,"description":"Parent job UUID"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","nullable":true,"description":"Raw job data","additionalProperties":true},"message":{"type":"string","example":"Cloud connector job raw data retrieved successfully"}},"required":["status","data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-classifications/assets/{assetId}":{"get":{"operationId":"list_data_classifications","summary":"List data classifications by asset","tags":["Data Classification"],"description":"Returns paginated data classification records for an asset within the requested day window.","parameters":[{"schema":{"type":"string","default":"365"},"in":"query","name":"days","required":false,"description":"Lookback window in days."},{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"assetId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"asset_id":{"type":"string","format":"uuid"},"days":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Data classification record id."},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true,"description":"Scan target (classified resource) for this run."},"report_location":{"type":"object","additionalProperties":true,"description":"Location of the classification report artifact."},"total":{"type":"number","description":"Files in scan scope for this data classification run."},"analyzed":{"type":"number","description":"Files analyzed in this data classification run."},"containing_sensitive_info":{"type":"number","description":"Sensitive files detected in this scan only. Excludes carry-forward paths from prior runs."},"triggered_ccls":{"type":"number","description":"Number of content classifiers (CCLs) triggered during this scan."},"errors":{"type":"object","additionalProperties":true,"description":"Scan errors keyed by path or error type."},"inaccessible_directories":{"type":"object","additionalProperties":true,"description":"Directories the scanner could not access."},"previously_sensitive_files":{"type":"array","items":{"type":"string"},"description":"Paths still sensitive from prior scans but not re-analyzed this run. Array length is not the full inventory count; on get-by-id use total_sensitive_files instead."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","tenant_name","cc_id","job_id","target","report_location","total","analyzed","containing_sensitive_info","triggered_ccls","errors","inaccessible_directories","previously_sensitive_files","created_at","updated_at"]}}},"required":["asset_id","days","items"]},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number","description":"Total data classification records matching the query."}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-classifications/findings":{"get":{"operationId":"list_data_classification_findings_by_ids","summary":"List combined sensitive files for multiple data classifications","tags":["Data Classification"],"description":"Returns paginated sensitive files across the given data classification ids, ordered by path ascending.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string"},"in":"query","name":"path","required":false,"description":"Optional case-insensitive substring filter on file path."},{"schema":{"type":"string"},"in":"query","name":"categories","required":false,"description":"Optional comma-separated category names. Returns findings matching any category."},{"schema":{"type":"string","format":"uuid"},"in":"query","name":"assetId","required":false,"description":"Optional classified resource id. Restricts findings to that scan target."},{"schema":{"type":"string"},"in":"query","name":"dataClassificationIds","required":true,"description":"Required comma-separated data classification UUIDs (max 50, deduplicated server-side)."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"data_classification_id":{"type":"string","format":"uuid","description":"Data classification this sensitive file belongs to."},"path":{"type":"string","description":"Sensitive file path."},"categories":{"type":"array","items":{"type":"string"},"description":"Detected CCL categories for this file."},"kind":{"type":"string","enum":["data","container"],"description":"data: a single file. container: an archive or container with nested_files."},"nested_files":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Path of a file inside a container or archive."},"categories":{"type":"array","items":{"type":"string"},"description":"Detected CCL categories in this nested file."}},"required":["path","categories"]},"description":"Present when kind is container. Per-file breakdown inside the archive."},"asset_id":{"type":"string","format":"uuid","description":"Classified resource id (volume, VM, bucket, etc.)."},"asset_name":{"type":"string","description":"Display name of the classified resource."}},"required":["data_classification_id","path","categories","kind","asset_id","asset_name"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-classifications/findings/filter-options":{"get":{"operationId":"get_data_classification_findings_filter_options_by_ids","summary":"Get filter options for combined data classification findings by ids","tags":["Data Classification"],"description":"Returns distinct categories and classified resources for findings across the given data classification ids.","parameters":[{"schema":{"type":"string"},"in":"query","name":"dataClassificationIds","required":true,"description":"Required comma-separated data classification UUIDs (max 50, deduplicated server-side)."},{"schema":{"type":"string","format":"uuid"},"in":"query","name":"assetId","required":false,"description":"Optional classified resource id. Narrows categories and assets to that scan target."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"string"},"description":"Distinct CCL category values available for filtering."},"assets":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string","format":"uuid"},"label":{"type":"string"}},"required":["value","label"]},"description":"Classified resources available for the assetId filter."}},"required":["categories","assets"]}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-classifications/{dataClassificationId}":{"get":{"operationId":"get_data_classification_by_id","summary":"Get data classification by id","tags":["Data Classification"],"description":"Returns a specific data classification record by id.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"dataClassificationId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Data classification record id."},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"job_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true,"description":"Scan target (classified resource) for this run."},"report_location":{"type":"object","additionalProperties":true,"description":"Location of the classification report artifact."},"total":{"type":"number","description":"Files in scan scope for this data classification run."},"analyzed":{"type":"number","description":"Files analyzed in this data classification run."},"containing_sensitive_info":{"type":"number","description":"Sensitive files detected in this scan only. Excludes carry-forward paths from prior runs."},"triggered_ccls":{"type":"number","description":"Number of content classifiers (CCLs) triggered during this scan."},"errors":{"type":"object","additionalProperties":true,"description":"Scan errors keyed by path or error type."},"inaccessible_directories":{"type":"object","additionalProperties":true,"description":"Directories the scanner could not access."},"previously_sensitive_files":{"type":"array","items":{"type":"string"},"description":"Paths still sensitive from prior scans but not re-analyzed this run. Array length is not the full inventory count; on get-by-id use total_sensitive_files instead."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"total_sensitive_files":{"type":"number","description":"Total sensitive files in the current inventory (this scan plus carry-forward paths with resolved categories)."}},"required":["id","tenant_name","cc_id","job_id","target","report_location","total","analyzed","containing_sensitive_info","triggered_ccls","errors","inaccessible_directories","previously_sensitive_files","created_at","updated_at","total_sensitive_files"],"nullable":true}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-classifications/{dataClassificationId}/findings/filter-options":{"get":{"operationId":"get_data_classification_findings_filter_options","summary":"Get filter options for data classification sensitive files","tags":["Data Classification"],"description":"Returns distinct category values for sensitive files in a data classification.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"dataClassificationId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"data_classification_id":{"type":"string","format":"uuid"},"categories":{"type":"array","items":{"type":"string"},"description":"Distinct category names across the data classification sensitive-file inventory."}},"required":["data_classification_id","categories"]}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/data-classifications/{dataClassificationId}/findings":{"get":{"operationId":"list_data_classification_findings","summary":"List sensitive files for a data classification","tags":["Data Classification"],"description":"Returns paginated sensitive files for a data classification, ordered by path ascending.","parameters":[{"schema":{"type":"string","default":""},"in":"query","name":"pageToken","required":false},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false},{"schema":{"type":"string"},"in":"query","name":"path","required":false,"description":"Optional case-insensitive substring filter on file path."},{"schema":{"type":"string"},"in":"query","name":"categories","required":false,"description":"Optional comma-separated category names. Returns findings matching any category."},{"schema":{"type":"string","format":"uuid"},"in":"path","name":"dataClassificationId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"data_classification_id":{"type":"string","format":"uuid","description":"Data classification this sensitive file belongs to."},"path":{"type":"string","description":"Sensitive file path."},"categories":{"type":"array","items":{"type":"string"},"description":"Detected CCL categories for this file."},"kind":{"type":"string","enum":["data","container"],"description":"data: a single file. container: an archive or container with nested_files."},"nested_files":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","description":"Path of a file inside a container or archive."},"categories":{"type":"array","items":{"type":"string"},"description":"Detected CCL categories in this nested file."}},"required":["path","categories"]},"description":"Present when kind is container. Per-file breakdown inside the archive."}},"required":["data_classification_id","path","categories","kind"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"},"total_count":{"type":"number"}},"required":["next_page_token","prev_page_token","total_count"]}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/aws-threat-hunts/{threatHuntJobId}/jobs":{"get":{"operationId":"list_aws_threat_hunt_related_jobs","summary":"List related jobs for an AWS hunt","tags":["Jobs"],"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"threatHuntJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"message":{"type":"string"}},"required":["status","data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/aws-threat-hunts/{threatHuntJobId}/latest-healthy-related-job":{"get":{"operationId":"get_aws_threat_hunt_latest_healthy_related_job","summary":"Get the latest healthy related job for an AWS hunt","tags":["Jobs"],"description":"Returns the latest healthy related Cloud Connector job (if any) and scans for that job.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"threatHuntJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string"},"data":{"type":"object","properties":{"threat_hunt_job_id":{"type":"string","format":"uuid"},"cc_job":{"type":"object","additionalProperties":true,"nullable":true},"scans":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"cc_id":{"type":"string","format":"uuid"},"target":{"type":"object","additionalProperties":true},"job_id":{"type":"string","format":"uuid"},"kind":{"type":"string"},"status":{"type":"string"},"type":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"scan_created_ebs_snapshot_id":{"type":"string","format":"uuid","nullable":true},"scan_created_ami_id":{"type":"string","format":"uuid","nullable":true}},"required":["id","tenant_name","cc_id","target","job_id","kind","status","type","created_at","updated_at"]}}},"required":["threat_hunt_job_id","cc_job","scans"]}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/aws-s3-threat-hunts/{s3ThreatHuntJobId}/jobs":{"get":{"operationId":"list_aws_s3_threat_hunt_related_jobs","summary":"List related jobs for an AWS S3 hunt","tags":["Jobs"],"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"s3ThreatHuntJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"message":{"type":"string"}},"required":["status","data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector/ibm-cos-bucket-threat-hunts/{ibmCosBucketThreatHuntJobId}/jobs":{"get":{"operationId":"list_ibm_cos_bucket_threat_hunt_related_jobs","summary":"List related jobs for an IBM COS bucket hunt","tags":["Jobs"],"parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"ibmCosBucketThreatHuntJobId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"message":{"type":"string"}},"required":["status","data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/cloud-connector":{"get":{"operationId":"list_cloud_connector_jobs","summary":"List Cloud Connector jobs","tags":["Jobs"],"description":"Get list of Cloud Connector jobs with filtering and pagination","parameters":[{"schema":{"type":"string"},"in":"query","name":"pageToken","required":false,"description":"Pagination token for next/previous page"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"},{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"kinds","required":false,"description":"Comma-separated list of job kinds to filter by"},{"schema":{"type":"string"},"in":"query","name":"statuses","required":false,"description":"Comma-separated list of job statuses to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetIds","required":false,"description":"Comma-separated list of asset IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"cloudConnectorIds","required":false,"description":"Comma-separated list of Cloud Connector IDs to filter by"},{"schema":{"type":"string"},"in":"query","name":"assetAccountIds","required":false,"description":"Comma-separated list of ASSET account IDs to filter by. Distinct from cloudConnectorIds: an asset in a Protected Account is covered by a connector in a different account, so the connector filter can never select it. Pairs with the asset_accounts facet on /filters."},{"schema":{"type":"string"},"in":"query","name":"triggerSources","required":false,"description":"Comma-separated list of trigger sources to filter by (guardduty, threat-hunt)"},{"schema":{"type":"string"},"in":"query","name":"policy_id","required":false,"description":"Only jobs whose asset(s) are currently covered by this policy's scope (asset-membership semantics, not trigger attribution). policyId is accepted as an alias."},{"schema":{"type":"string"},"in":"query","name":"policyId","required":false,"description":"CamelCase alias of policy_id."},{"schema":{"type":"string","enum":["aws","azure"]},"in":"query","name":"platform","required":false,"description":"Only jobs of this platform, derived from the job kind prefix (aws_* / azure_*)."},{"schema":{"type":"string"},"in":"query","name":"jobId","required":false,"description":"Human-readable cloud-connector Job ID (`cc_job_id`, e.g. `j-01m09zvyyfcgx4ynp40x4e4rej`). Prefix match, case-insensitive."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kindScope","required":false,"description":"Jobs Kind chip, the same classification as hunt_count / deployment_count / system_count on GET /jobs/count. kind_scope is accepted as an alias."},{"schema":{"type":"string","enum":["hunt","deployment","system"]},"in":"query","name":"kind_scope","required":false,"description":"Snake_case alias of kindScope."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"jobsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Job ID"},"cc_job_id":{"type":"string","description":"Cloud Connector's human-readable ID","nullable":true},"cc_id":{"type":"string","description":"Cloud Connector ID where job is running","nullable":true},"parent_id":{"type":"string","description":"Parent job ID","nullable":true},"name":{"type":"string","description":"Customer facing job name","nullable":true},"status_message":{"type":"string","description":"User-visible status message","nullable":true},"status":{"type":"string","description":"Job status"},"childrenList":{"type":"array","description":"Child jobs","items":{"type":"object"}},"kind":{"type":"string","description":"Job kind"},"progress":{"type":"object","nullable":true,"description":"Progress information","properties":{"percentage":{"type":"object","nullable":true,"properties":{"fraction":{"type":"object","properties":{"value":{"type":"number"}}}}},"units":{"type":"object","nullable":true,"properties":{"measurement":{"type":"number"}}}}},"target_asset_details":{"type":"object","nullable":true,"description":"Target asset details","properties":{"id":{"type":"string","description":"Asset UUID"},"kind":{"type":"string","enum":["ec2","ebs","s3","efs","generic_host","server","fsx","azure_vm","azure_disk","azure_blob","azure_file_share","ibm_cos_bucket"],"description":"Asset kind"},"aws_id":{"type":"string","nullable":true,"description":"Display resource id (can be empty for server and generic_host)"},"account_id":{"type":"string","nullable":true,"description":"Account ID"},"region":{"type":"string","nullable":true,"description":"Region"},"cc_asset_id":{"type":"string","nullable":true,"description":"Elastio cc_asset_id"}},"required":["id","kind"]},"asset_details":{"type":"array","nullable":true,"description":"All asset details from asset_ids array","items":{"type":"object","properties":{"id":{"type":"string","description":"Asset UUID"},"kind":{"type":"string","enum":["ec2","ebs","s3","efs","generic_host","server","fsx","azure_vm","azure_disk","azure_blob","azure_file_share","ibm_cos_bucket"],"description":"Asset kind"},"aws_id":{"type":"string","nullable":true,"description":"Display resource id (can be empty for server and generic_host)"},"account_id":{"type":"string","nullable":true,"description":"Account ID"},"region":{"type":"string","nullable":true,"description":"Region"},"cc_asset_id":{"type":"string","nullable":true,"description":"Elastio cc_asset_id"}},"required":["id","kind"]}},"scanIdsList":{"type":"array","description":"Related scan IDs","items":{"type":"string"}},"backupIdsList":{"type":"array","description":"Related backup IDs","items":{"type":"string"}},"abort_requested":{"type":"boolean","description":"Abort requested flag"},"finalized":{"type":"boolean","description":"Job finished and won't be retried"},"started_at":{"type":"string","nullable":true,"description":"When job started (ISO8601 timestamp)"},"finished_at":{"type":"string","nullable":true,"description":"When job finished (ISO8601 timestamp)"},"created_at":{"type":"string","description":"Creation timestamp"},"updated_at":{"type":"string","description":"Last update timestamp"},"cc_aws_id":{"type":"string","nullable":true,"description":"Cloud Connector AWS account ID (null for decoupled deployments)"},"cc_aws_region":{"type":"string","nullable":true,"description":"Cloud Connector AWS region (null for decoupled deployments)"},"scan_cluster":{"type":"object","nullable":true,"description":"Standalone scan cluster context for the job. Null for AWS Cloud Connectors.","properties":{"id":{"type":"string","description":"Scan cluster ID (same as cc_id)"},"cluster_name":{"type":"string","description":"Cluster name"},"cluster_kind":{"type":"string","enum":["azure","ibm","on_prem","gcp"],"description":"Cluster platform kind"},"cluster_type":{"type":"string","enum":["self_managed","elastio_managed"],"description":"Cluster management type"},"azure":{"type":"object","nullable":true,"properties":{"subscription_id":{"type":"string"},"tenant_id":{"type":"string"},"region":{"type":"string"}},"required":["subscription_id","tenant_id","region"]},"ibm":{"type":"object","nullable":true,"properties":{"account_id":{"type":"string"},"region":{"type":"string"}},"required":["account_id","region"]},"on_prem":{"type":"object","nullable":true,"properties":{"stack_id":{"type":"string"},"stack_name":{"type":"string"},"stack_account":{"type":"string"}},"required":["stack_id","stack_name","stack_account"]},"gcp":{"type":"object","nullable":true,"properties":{"project_id":{"type":"string"},"region":{"type":"string"}},"required":["project_id","region"]}},"required":["id","cluster_name","cluster_kind","cluster_type","azure","ibm","on_prem","gcp"]},"tenant_name":{"type":"string","description":"Tenant name"},"error_message":{"type":"string","nullable":true,"description":"Error message if failed (REST convenience field)"},"fingerprint":{"type":"string","nullable":true,"description":"Job fingerprint (REST convenience field)"},"heartbeat_at":{"type":"string","nullable":true,"description":"Last heartbeat timestamp (REST convenience field)"},"triggered_by_sources":{"type":"array","nullable":true,"description":"Information about what triggered this job (e.g., GuardDuty event); a scan can have multiple triggers","items":{"type":"object","properties":{"source":{"type":"string","enum":["guardduty","threat-hunt","wiz","s3-threat-hunt"],"description":"Source that triggered the job"},"event_type":{"type":"string","nullable":true,"description":"Event type that triggered the job (e.g., GuardDuty finding type)"},"job_id":{"type":"string","nullable":true,"description":"Hunt job ID that triggered the job"},"human_readable_cc_job_id":{"type":"string","nullable":true,"description":"Hunt job's human-readable ID that triggered the job"}},"required":["source"]}},"triggered_by":{"type":"object","nullable":true,"deprecated":true,"description":"Deprecated. Use triggered_by_sources instead. Always null."},"threat_hunt_jobs":{"type":"array","nullable":true,"description":"For threat-hunt parent jobs only: related jobs launched by the hunt","items":{"type":"object","description":"Related Cloud Connector job"}},"policy_ids":{"type":"array","description":"IDs of the job's policies. When the job carries a trigger tag (elastio:scan_policies from the multicloud scheduler, or elastio:plan from a Cloud Connector policy run) naming a known policy, these are the policies that triggered it (policies_source = triggered); otherwise the policies whose scope currently covers the job's asset(s) (policies_source = covering); for an aggregate bucket hunt (aws_s3_threat_hunt, ibm_cos_bucket_threat_hunt) the asset is the bucket of its related scan jobs. [] when neither applies.","items":{"type":"string"}},"policies":{"type":"array","description":"The job's policies, name-sorted and deduped by id. Triggering policies from the elastio:scan_policies or elastio:plan job tag when present, else the policies whose scope currently covers the job's asset(s), for an aggregate bucket hunt the bucket of its related scan jobs; see policies_source. [] when neither applies.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy ID"},"name":{"type":"string","description":"Policy name"}},"required":["id","name"]}},"policies_source":{"type":"string","enum":["triggered","covering"],"description":"How policies / policy_ids were produced: 'triggered' = from the job's trigger tag, elastio:scan_policies (multicloud scheduler) or elastio:plan (Cloud Connector policy run), i.e. the policies whose run launched this job, reported under their current name and resolved even if since deleted or no longer covering the asset; 'covering' = asset-membership fallback, used when no trigger tag is present, or it names no policy the tenant has ever had."},"duration_sec":{"type":"number","nullable":true,"description":"Whole seconds between started_at and finished_at; null while running."}},"required":["id","status","kind","created_at","updated_at","tenant_name","childrenList","scanIdsList","backupIdsList","abort_requested","finalized"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string","nullable":true,"description":"Token for next page"},"prev_page_token":{"type":"string","nullable":true,"description":"Token for previous page"},"total_count":{"type":"number","description":"Total number of jobs"}},"required":["total_count"]}},"required":["jobsList","pagination"]},"cached":{"type":"boolean","description":"Whether response came from cache"},"expiresInMs":{"type":"number","nullable":true,"description":"Cache expiration time in milliseconds"},"message":{"type":"string","example":"Cloud connector jobs retrieved successfully"}},"required":["status","data","cached","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/tenant":{"get":{"operationId":"list_tenant_jobs","summary":"List tenant jobs","tags":["Jobs"],"description":"Get list of tenant jobs (deployment and system jobs) with filtering and pagination","parameters":[{"schema":{"type":"string"},"in":"query","name":"pageToken","required":false,"description":"Pagination token for next/previous page"},{"schema":{"type":"string","default":"10"},"in":"query","name":"pageSize","required":false,"description":"Number of results per page"},{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering jobs (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"kinds","required":false,"description":"Comma-separated list of job kinds to filter by (use to differentiate deployment vs system jobs)"},{"schema":{"type":"string"},"in":"query","name":"statuses","required":false,"description":"Comma-separated list of job statuses to filter by"},{"schema":{"type":"string"},"in":"query","name":"cloudConnectorIds","required":false,"description":"Comma-separated list of Cloud Connector IDs to filter by"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"jobsList":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Job ID"},"parent_id":{"type":"string","description":"Parent job ID","nullable":true},"name":{"type":"string","description":"Human readable job name","nullable":true},"cc_id":{"type":"string","description":"CloudConnector ID context","nullable":true},"status_message":{"type":"string","description":"Status message","nullable":true},"status":{"type":"string","description":"Job status"},"childrenList":{"type":"array","description":"Child jobs (stages)","items":{"type":"object"}},"kind":{"type":"string","description":"Job kind (deployment, system, etc.)"},"started_at":{"type":"string","nullable":true,"description":"When entered running state"},"finished_at":{"type":"string","nullable":true,"description":"When entered finished state"},"created_at":{"type":"string","description":"Creation timestamp"},"updated_at":{"type":"string","description":"Last update timestamp"},"cc_aws_id":{"type":"string","nullable":true,"description":"Cloud Connector AWS account ID (null for decoupled deployments)"},"cc_aws_region":{"type":"string","nullable":true,"description":"Cloud Connector AWS region (null for decoupled deployments)"},"scan_cluster":{"type":"object","nullable":true,"description":"Standalone scan cluster context for the job. Null for AWS Cloud Connectors.","properties":{"id":{"type":"string","description":"Scan cluster ID (same as cc_id)"},"cluster_name":{"type":"string","description":"Cluster name"},"cluster_kind":{"type":"string","enum":["azure","ibm","on_prem","gcp"],"description":"Cluster platform kind"},"cluster_type":{"type":"string","enum":["self_managed","elastio_managed"],"description":"Cluster management type"},"azure":{"type":"object","nullable":true,"properties":{"subscription_id":{"type":"string"},"tenant_id":{"type":"string"},"region":{"type":"string"}},"required":["subscription_id","tenant_id","region"]},"ibm":{"type":"object","nullable":true,"properties":{"account_id":{"type":"string"},"region":{"type":"string"}},"required":["account_id","region"]},"on_prem":{"type":"object","nullable":true,"properties":{"stack_id":{"type":"string"},"stack_name":{"type":"string"},"stack_account":{"type":"string"}},"required":["stack_id","stack_name","stack_account"]},"gcp":{"type":"object","nullable":true,"properties":{"project_id":{"type":"string"},"region":{"type":"string"}},"required":["project_id","region"]}},"required":["id","cluster_name","cluster_kind","cluster_type","azure","ibm","on_prem","gcp"]},"policy_id":{"type":"string","nullable":true,"description":"First policy ID associated with this job's Cloud Connector assets"},"policy_name":{"type":"string","nullable":true,"description":"First policy name associated with this job's Cloud Connector assets"},"policy_ids":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Policy IDs associated with this job's Cloud Connector assets"},"policy_names":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Policy names associated with this job's Cloud Connector assets"},"tenant_name":{"type":"string","description":"Tenant name"},"heartbeat_at":{"type":"string","nullable":true,"description":"Last heartbeat timestamp (REST convenience field)"},"progress":{"type":"object","nullable":true,"description":"Progress object or string (currently missing)"},"error_message":{"type":"string","nullable":true,"description":"Error message if failed (REST convenience field)"}},"required":["id","status","kind","created_at","updated_at","tenant_name","childrenList"]}},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string","nullable":true,"description":"Token for next page"},"prev_page_token":{"type":"string","nullable":true,"description":"Token for previous page"},"total_count":{"type":"number","description":"Total number of jobs"}},"required":["total_count"]}},"required":["jobsList","pagination"]},"cached":{"type":"boolean","description":"Whether response came from cache"},"expiresInMs":{"type":"number","nullable":true,"description":"Cache expiration time in milliseconds"},"message":{"type":"string","example":"Tenant jobs retrieved successfully"}},"required":["status","data","cached","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/jobs/tenant/filters":{"get":{"operationId":"get_tenant_jobs_filters","summary":"Get tenant job filters","tags":["Jobs"],"description":"Get available filter options for tenant jobs (deployment and system jobs)","parameters":[{"schema":{"type":"string"},"in":"query","name":"startDate","required":true,"description":"Start date for filtering (ISO format: YYYY-MM-DD)"},{"schema":{"type":"string"},"in":"query","name":"endDate","required":true,"description":"End date for filtering (ISO format: YYYY-MM-DD)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number","example":200},"data":{"type":"object","properties":{"kinds":{"type":"array","items":{"type":"string"},"description":"Available job kinds (deployment, system, etc.)"},"statuses":{"type":"array","items":{"type":"string","enum":["scheduled","starting","in_progress","failed","succeeded","aborted"]},"description":"Available job statuses (JobStatus enum values)"},"cloud_connectors":{"type":"array","nullable":true,"items":{"oneOf":[{"type":"object","description":"Classic AWS cloud-connector stack","properties":{"id":{"type":"string","description":"Cloud connector ID"},"deployment":{"type":"string","enum":["cloud_connector"]},"aws_account_id":{"type":"string","description":"AWS account ID"},"aws_region":{"type":"string","description":"AWS region"}},"required":["id","deployment","aws_account_id","aws_region"],"additionalProperties":false},{"type":"object","description":"Decoupled scan-cluster connector","properties":{"id":{"type":"string","description":"Scan cluster ID"},"deployment":{"type":"string","enum":["decoupled"]},"cluster_name":{"type":"string","description":"Scan cluster name"},"cluster_kind":{"type":"string","enum":["azure","ibm","on_prem","gcp"],"description":"Scan cluster platform kind"},"cluster_type":{"type":"string","enum":["self_managed","elastio_managed"],"description":"Scan cluster management type"}},"required":["id","deployment","cluster_name","cluster_kind","cluster_type"],"additionalProperties":false}]},"description":"Available Cloud Connectors for filtering (AWS Cloud Connectors and standalone scan clusters)"}},"required":["kinds","statuses"]},"cached":{"type":"boolean","description":"Whether response came from cache"},"expiresInMs":{"type":"number","nullable":true,"description":"Cache expiration time in milliseconds"},"message":{"type":"string","example":"Tenant job filters retrieved successfully"}},"required":["status","data","cached","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/compliance/status":{"get":{"operationId":"getComplianceStatus","summary":"Get compliance status across all frameworks","tags":["Compliance"],"description":"Retrieve compliance status for NYDFS 23 NYCRR 500.16, NIST Cybersecurity Framework, PCI DSS v4.0, ISO 27001:2022, and DORA EU 2022/2554 frameworks. Tenant is determined from authority header.","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"start_date","required":false,"description":"Start date for compliance assessment (YYYY-MM-DD)"},{"schema":{"type":"string","format":"date"},"in":"query","name":"end_date","required":false,"description":"End date for compliance assessment (YYYY-MM-DD)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful compliance status response","content":{"application/json":{"schema":{"description":"Successful compliance status response","type":"object","properties":{"data":{"type":"array","description":"Array of compliance frameworks with their controls","items":{"type":"object","properties":{"framework":{"type":"string","description":"Compliance framework identifier"},"controls":{"type":"array","description":"Array of compliance controls for this framework","items":{"type":"object","properties":{"name":{"type":"string","description":"Name of the compliance control"},"description":{"type":"string","description":"Description of what the control validates"},"isPassed":{"type":"boolean","description":"Whether the compliance control passes or fails"}},"required":["name","description","isPassed"]}}},"required":["framework","controls"]}},"message":{"type":"string","description":"Summary message with compliance statistics"}},"required":["data","message"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/reports/compliance/dora":{"get":{"operationId":"getDORAReport","summary":"Generate DORA Compliance Report","tags":["Reports"],"description":"Generates a PDF compliance report for DORA (Digital Operational Resilience Act) framework","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"start_date","required":false,"description":"Start date for the report period (ISO date string). If not provided, defaults to first day of current month (month-to-date)."},{"schema":{"type":"string","format":"date"},"in":"query","name":"end_date","required":false,"description":"End date for the report period (ISO date string). If not provided, defaults to today (month-to-date)."},{"schema":{"type":"string","enum":["json","pdf"],"default":"pdf"},"in":"query","name":"type","required":false,"description":"Response format: 'pdf' for downloadable report (default) or 'json' for compliance data"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"PDF file download","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/reports/compliance/iso27001":{"get":{"operationId":"getISO27001Report","summary":"Generate ISO 27001 Compliance Report","tags":["Reports"],"description":"Generates a PDF compliance report for ISO/IEC 27001:2022 framework","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"start_date","required":false,"description":"Start date for the report period (ISO date string). If not provided, defaults to first day of current month (month-to-date)."},{"schema":{"type":"string","format":"date"},"in":"query","name":"end_date","required":false,"description":"End date for the report period (ISO date string). If not provided, defaults to today (month-to-date)."},{"schema":{"type":"string","enum":["json","pdf"],"default":"pdf"},"in":"query","name":"type","required":false,"description":"Response format: 'pdf' for downloadable report (default) or 'json' for compliance data"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"PDF file download","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/reports/compliance/nist":{"get":{"operationId":"getNISTReport","summary":"Generate NIST CSF Compliance Report","tags":["Reports"],"description":"Generates a PDF compliance report for NIST Cybersecurity Framework","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"start_date","required":false,"description":"Start date for the report period (ISO date string). If not provided, defaults to first day of current month (month-to-date)."},{"schema":{"type":"string","format":"date"},"in":"query","name":"end_date","required":false,"description":"End date for the report period (ISO date string). If not provided, defaults to today (month-to-date)."},{"schema":{"type":"string","enum":["json","pdf"],"default":"pdf"},"in":"query","name":"type","required":false,"description":"Response format: 'pdf' for downloadable report (default) or 'json' for compliance data"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"PDF file download","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/reports/compliance/nydfs":{"get":{"operationId":"getNYDFSReport","summary":"Generate NYDFS Compliance Report","tags":["Reports"],"description":"Generates a PDF compliance report for NYDFS 23 NYCRR 500 framework","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"start_date","required":false,"description":"Start date for the report period (ISO date string). If not provided, defaults to first day of current month (month-to-date)."},{"schema":{"type":"string","format":"date"},"in":"query","name":"end_date","required":false,"description":"End date for the report period (ISO date string). If not provided, defaults to today (month-to-date)."},{"schema":{"type":"string","enum":["json","pdf"],"default":"pdf"},"in":"query","name":"type","required":false,"description":"Response format: 'pdf' for downloadable report (default) or 'json' for compliance data"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"PDF file download","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/reports/compliance/pci":{"get":{"operationId":"getPCIDSSReport","summary":"Generate PCI DSS Compliance Report","tags":["Reports"],"description":"Generates a PDF compliance report for PCI DSS v4.0 framework","parameters":[{"schema":{"type":"string","format":"date"},"in":"query","name":"start_date","required":false,"description":"Start date for the report period (ISO date string). If not provided, defaults to first day of current month (month-to-date)."},{"schema":{"type":"string","format":"date"},"in":"query","name":"end_date","required":false,"description":"End date for the report period (ISO date string). If not provided, defaults to today (month-to-date)."},{"schema":{"type":"string","enum":["json","pdf"],"default":"pdf"},"in":"query","name":"type","required":false,"description":"Response format: 'pdf' for downloadable report (default) or 'json' for compliance data"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"PDF file download","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/plan/{name}":{"get":{"operationId":"get_plan","summary":"Get plan","tags":["Plan"],"description":"Get plan","parameters":[{"schema":{"type":"string"},"in":"path","name":"name","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"tenant_name":{"type":"string"},"name":{"type":"string"},"frequency":{"type":"object","additionalProperties":true,"description":"Frequency configuration object with dynamic structure"},"status":{"type":"string"},"selectors":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"Selectors configuration object with dynamic structure"}},"tags":{"type":"object","additionalProperties":true,"description":"Tags configuration object with dynamic structure"},"integrity_check":{"type":"string"},"iscan":{"type":"object","additionalProperties":true,"description":"Iscan configuration object with dynamic structure"},"paused_until":{"type":"string","nullable":true},"kind":{"type":"string"},"vaults":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"Vaults configuration object with dynamic structure"}},"created_at":{"type":"string"},"updated_at":{"type":"string"},"snapshot_import":{"type":"string"},"protect_new_immediately":{"type":"string"},"skip_ebs_backup":{"type":"boolean"},"account_region_selectors":{"type":"array","items":{"type":"object","additionalProperties":true,"description":"Account region selectors configuration object with dynamic structure"}},"mode":{"type":"object","additionalProperties":true,"description":"Mode configuration object with dynamic structure"}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets-list":{"get":{"operationId":"list_assets_by_ids","summary":"List assets by ids","tags":["Assets"],"description":"List assets by ids","parameters":[{"schema":{"type":"string"},"in":"query","name":"asset_ids","required":false}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"ec2_instances":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"aws_id":{"type":"string"},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"started_at":{"type":"string"},"state":{"type":"string"},"type":{"type":"object","properties":{"family":{"type":"string"},"size":{"type":"string"},"spot":{"type":"boolean"}}},"ami_details":{"type":"object","properties":{"aws_id":{"type":"string"},"name":{"type":"string"},"location":{"type":"string"}}},"aws_vpc_id":{"type":"string"},"os_kind":{"type":"string"},"ebs_ids":{"type":"array","items":{"type":"string"}},"backup_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized policy display names."},"retention_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized retention policy display names."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"has_replicated_backups":{"type":"boolean"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"ebs_volumes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"aws_id":{"type":"string"},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"aws_az":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"non_recognized_volume_type":{"type":"string"},"state":{"type":"string"},"encryption_details":{"type":"object","properties":{"encrypted":{"type":"boolean"},"encrypted_with_cmk":{"type":"boolean"}}},"performance_characteristics":{"type":"object","properties":{"iops":{"type":"string"},"throughput":{"type":"string"}}},"size":{"type":"string","description":"Volume size in BYTES. The inventory multiplies the AWS GiB figure by 1024^3 before storing it; rows written before that conversion landed can still carry a raw GiB figure."},"attached_instance_ids":{"type":"array","items":{"type":"string"},"description":"Asset ids of the EC2 instances this volume is attached to, excluding terminated instances. Use `attachments` when the device name is needed too."},"attachments":{"type":"array","description":"One entry per live EC2 attachment of this volume. `device_name` is the device the volume is attached under inside the instance (e.g. `/dev/xvda`); it is null when AWS reported no device, or when the attachment predates the inventory recording it.","items":{"type":"object","properties":{"instance_id":{"type":"string","format":"uuid"},"device_name":{"type":"string","nullable":true}}}},"filesystems":{"type":"array","items":{"type":"string"},"description":"Filesystems detected on this volume by its most recent FS check (e.g. `[\"xfs\"]`, or several entries for a multi-partition volume). Empty when the volume has never been FS-checked or no partition reported a filesystem."},"backup_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized policy display names."},"retention_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized retention policy display names."},"created_by_aws_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"type":{"type":"string"},"has_replicated_backups":{"type":"boolean"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"efs_filesystems":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"aws_id":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"state":{"type":"string"},"backup_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized policy display names."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"s3_buckets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"aws_id":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"object_count":{"type":"string"},"size":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"state":{"type":"string"},"object_versioning_enabled":{"type":"boolean","nullable":true,"description":"Whether S3 object versioning is enabled for this bucket"},"backup_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized policy display names."},"retention_policies":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized retention policy display names."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"ova_servers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ova_account_id":{"type":"string"},"cc_asset_id":{"type":"string"},"backup_provider":{"type":"string"},"backup_provider_asset_id":{"type":"string"},"name":{"type":"string"},"os_name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"fsx_ontap_volumes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"cc_asset_id":{"type":"string"},"aws_volume_id":{"type":"string"},"ontap_volume_name":{"type":"string"},"aws_file_system_id":{"type":"string"},"aws_svm_id":{"type":"string"},"junction_path":{"type":"string"},"size":{"type":"string"},"root":{"type":"boolean"},"created_by_aws_at":{"type":"string","format":"date-time"},"state":{"type":"string"},"state_transition_reason":{"type":"string"},"arn":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"backup_policy_names":{"type":"array","items":{"type":"string"},"deprecated":true,"description":"Deprecated. Use `policies` instead. Legacy denormalized policy display names."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"azure_vms":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"region":{"type":"string"},"name":{"type":"string"},"state":{"type":"string"},"disk_ids":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"created_in_azure_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"has_replicated_backups":{"type":"boolean"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"azure_disks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"subscription_id":{"type":"string"},"attached_vm_ids":{"type":"array","items":{"type":"string"}},"resource_group":{"type":"string"},"region":{"type":"string"},"name":{"type":"string"},"state":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"availability_zones":{"type":"array","items":{"type":"string"}},"created_in_azure_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"has_replicated_backups":{"type":"boolean"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"azure_blobs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"cc_asset_id":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"region":{"type":"string"},"state":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"storage_account":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"has_replicated_backups":{"type":"boolean"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"azure_file_shares":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"cc_asset_id":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"region":{"type":"string"},"state":{"type":"string"},"tags":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"value":{"type":"string"}}}},"storage_account":{"type":"string"},"share_quota":{"type":"number","nullable":true},"enabled_protocol":{"type":"string","nullable":true},"root_squash":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"has_replicated_backups":{"type":"boolean"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}},"ibm_cos_buckets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_asset_id":{"type":"string"},"name":{"type":"string"},"location":{"type":"string"},"scope":{"type":"string"},"service_instance_id":{"type":"string"},"service_instance_ibm_id":{"type":"string"},"objects_count":{"type":"number"},"bytes_used":{"type":"number"},"archived_object_count":{"type":"number"},"archived_bytes_used":{"type":"number"},"restored_object_count":{"type":"number"},"restored_bytes_used":{"type":"number"},"accelerated_object_count":{"type":"number"},"accelerated_bytes_used":{"type":"number"},"state":{"type":"string"},"created_in_ibm_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"health":{"type":"string"},"has_pursuit_exception":{"type":"boolean","description":"True when the asset currently has an active Pursuit exception. Present only when Pursuit exceptions are enabled for your tenant; treat an absent value as unknown rather than false."},"policies":{"type":"array","description":"Direct active policy memberships for this asset (no implied parent coverage). Sorted by policy name. Empty when unpoliced.","items":{"type":"object","properties":{"id":{"type":"string","description":"Policy UUID"},"name":{"type":"string","description":"Policy display name"},"coverage_source":{"type":"string","enum":["direct","implied"],"description":"Whether coverage comes from an active membership on this asset (direct) or from a parent EC2/Azure VM (implied)."},"policy_kind":{"type":"string","enum":["scheduled","event"],"description":"Whether the policy is schedule-driven or event-driven."},"policy_source":{"type":"string","nullable":true,"description":"Event trigger source for event policies (e.g. aws.guardduty.finding_raised, wiz.finding_raised). Null for scheduled policies."},"scan_types":{"type":"object","nullable":true,"description":"Scan kinds this covering policy is configured to run.","properties":{"ransomware":{"type":"boolean"},"malware":{"type":"boolean"},"encryption_detection":{"type":"boolean"},"data_classification":{"type":"boolean"},"hunt":{"type":"boolean"},"pursuit":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"additionalProperties":false}},"required":["id","name","coverage_source","policy_kind","policy_source","scan_types"]}}}}}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true},"message":{"type":"string"}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/health-summary":{"get":{"operationId":"getAssetHealthSummary","summary":"Get asset health summary","tags":["Assets"],"description":"Retrieves a summary of asset health status across all platforms, categorizing assets as clean, infected, or at risk.","parameters":[{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated list of platforms to filter (aws,azure,on_prem,ibm)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"clean_assets":{"type":"number","description":"Number of assets that are clean (no threats or only encryption threats)"},"infected_assets":{"type":"number","description":"Number of assets that are infected (malware, ransomware, filesystem errors)"},"at_risk_assets":{"type":"number","description":"Number of assets that are at risk (unscanned or unknown status)"}},"required":["clean_assets","infected_assets","at_risk_assets"]},"cached":{"type":"boolean","description":"Whether the response was served from cache"},"expires_in_ms":{"type":"number","description":"Cache expiration time in milliseconds"}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/coverage-summary":{"get":{"operationId":"getCoverageSummary","summary":"Get asset coverage summary","tags":["Assets"],"description":"Retrieves a detailed coverage summary across all platforms and asset types, showing covered and not covered counts for each asset type.","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"aws":{"type":"object","properties":{"ec2":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"ebs":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"s3":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"efs":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"fsx":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]}},"required":["ec2","ebs","s3","efs","fsx"]},"azure":{"type":"object","properties":{"vm":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"blob":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"file_share":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]},"disk":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]}},"required":["vm","blob","file_share","disk"]},"on_prem":{"type":"object","properties":{"server":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]}},"required":["server"]},"ibm":{"type":"object","properties":{"cos_bucket":{"type":"object","properties":{"covered":{"type":"number"},"not_covered":{"type":"number"}},"required":["covered","not_covered"]}},"required":["cos_bucket"]}},"required":["aws","azure","on_prem","ibm"]},"cached":{"type":"boolean","description":"Whether the response was served from cache"},"expires_in_ms":{"type":"number","description":"Cache expiration time in milliseconds"}},"required":["status","message","data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/recovery-assurance":{"get":{"operationId":"getRecoveryAssurance","summary":"Get recovery assurance data","tags":["Assets"],"description":"Retrieves recovery assurance data including RPO compliance counts and recovery points across all platforms.","parameters":[{"schema":{"type":"string"},"in":"query","name":"rpo_hours","required":false,"description":"Recovery Point Objective in hours (default: 24)"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated list of platforms to filter (aws,azure,on_prem,ibm)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"assets_under_rpo":{"type":"number","description":"Number of assets that meet the RPO requirement"},"assets_outside_rpo":{"type":"number","description":"Number of assets that do not meet the RPO requirement"},"recovery_points":{"type":"array","description":"List of recovery points sorted by timestamp (newest first)","items":{"type":"object","properties":{"timestamp":{"type":"string","format":"date-time","description":"ISO timestamp of the recovery point"}},"required":["timestamp"]}}},"required":["assets_under_rpo","assets_outside_rpo","recovery_points"]},"cached":{"type":"boolean","description":"Whether the response was served from cache"},"expires_in_ms":{"type":"number","description":"Cache expiration time in milliseconds"}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/encryption-summary":{"get":{"operationId":"getAssetEncryptionSummary","summary":"Get asset encryption summary","tags":["Assets"],"description":"Retrieves a summary of asset encryption status across all platforms and asset types.","security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"aws":{"type":"object","properties":{"ec2":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"ebs":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"s3":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"efs":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"fsx":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]}},"required":["ec2","ebs","s3","efs","fsx"]},"azure":{"type":"object","properties":{"vm":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"blob":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"file_share":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]},"disk":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]}},"required":["vm","blob","file_share","disk"]},"on_prem":{"type":"object","properties":{"server":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]}},"required":["server"]},"ibm":{"type":"object","properties":{"cos_bucket":{"type":"object","properties":{"encrypted":{"type":"number"},"not_encrypted":{"type":"number"},"unscanned":{"type":"number"}},"required":["encrypted","not_encrypted","unscanned"]}},"required":["cos_bucket"]}},"required":["aws","azure","on_prem","ibm"]},"cached":{"type":"boolean"},"expires_in_ms":{"type":"number"}},"required":["status","message","data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/storage-vulnerability":{"get":{"operationId":"getStorageVulnerabilitySummary","summary":"Get storage vulnerability summary","tags":["Assets"],"description":"Retrieves a summary of storage vulnerabilities categorized by severity level (high, medium, low) across all platforms.","parameters":[{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated list of platforms to filter (aws,azure)"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"high":{"type":"number","description":"Number of high severity storage vulnerabilities"},"medium":{"type":"number","description":"Number of medium severity storage vulnerabilities"},"low":{"type":"number","description":"Number of low severity storage vulnerabilities"}},"required":["high","medium","low"]},"cached":{"type":"boolean"},"expires_in_ms":{"type":"number"}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/storage-vulnerability/issues":{"get":{"operationId":"listStorageVulnerabilityIssues","summary":"List storage vulnerability issues","tags":["Assets"],"description":"Returns a paginated list of storage health issues (one row per asset per issue) for EBS volumes, EBS snapshots, and Azure compute disks.","parameters":[{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws, azure)"},{"schema":{"type":"string"},"in":"query","name":"asset_type","required":false,"description":"Comma-separated asset types (ebs_volume, ebs_snapshot, azure_compute_disk)"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severity levels (high, medium, low)"},{"schema":{"type":"string"},"in":"query","name":"storage_health_issue","required":false,"description":"Comma-separated storage health issue slugs"},{"schema":{"type":"string","maxLength":256},"in":"query","name":"search","required":false,"description":"Case-insensitive search by asset name or asset id (max 256 characters)"},{"schema":{"type":"string"},"in":"query","name":"account_id","required":false,"description":"Comma-separated AWS account ids or Azure subscription ids"},{"schema":{"type":"integer","minimum":1,"maximum":100},"in":"query","name":"page_size","required":false,"description":"Page size (1–100, default 10)"},{"schema":{"type":"string"},"in":"query","name":"next_page_token","required":false,"description":"Next page token"},{"schema":{"type":"string"},"in":"query","name":"prev_page_token","required":false,"description":"Previous page token"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"total":{"type":"number"},"issues":{"type":"array","items":{"type":"object","properties":{"asset_id":{"type":"string"},"asset_name":{"type":"string"},"asset_type":{"type":"string","enum":["ebs_volume","ebs_snapshot","azure_compute_disk"]},"platform":{"type":"string","enum":["aws","azure"]},"region":{"type":"string","nullable":true},"platform_details":{"oneOf":[{"type":"object","properties":{"account_id":{"type":"string"},"region":{"type":"string"}},"required":["account_id","region"]},{"type":"object","properties":{"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"region":{"type":"string"}},"required":["subscription_id","resource_group"]}]},"severity":{"type":"string","enum":["high","medium","low"]},"storage_health_issue":{"type":"string"},"parent_asset_id":{"type":"string","nullable":true}},"required":["asset_id","asset_name","asset_type","platform","platform_details","severity","storage_health_issue","parent_asset_id"]}}},"required":["total","issues"]},"pagination":{"type":"object","properties":{"next_page_token":{"type":"string"},"prev_page_token":{"type":"string"}}}},"required":["status","message","data","pagination"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/assets/storage-vulnerability/filters":{"get":{"operationId":"getStorageVulnerabilityIssuesFilters","summary":"Get contextual filter options for storage vulnerability issues","tags":["Assets"],"description":"Returns filter option values present in the currently filtered issue set. Accepts the same query params as the issues list endpoint (except pagination).","parameters":[{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated platforms (aws, azure)"},{"schema":{"type":"string"},"in":"query","name":"asset_type","required":false,"description":"Comma-separated asset types (ebs_volume, ebs_snapshot, azure_compute_disk)"},{"schema":{"type":"string"},"in":"query","name":"severity","required":false,"description":"Comma-separated severity levels (high, medium, low)"},{"schema":{"type":"string"},"in":"query","name":"storage_health_issue","required":false,"description":"Comma-separated storage health issue slugs"},{"schema":{"type":"string","maxLength":256},"in":"query","name":"search","required":false,"description":"Case-insensitive search by asset name or asset id (max 256 characters)"},{"schema":{"type":"string"},"in":"query","name":"account_id","required":false,"description":"Comma-separated AWS account ids or Azure subscription ids"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"message":{"type":"string"},"data":{"type":"object","properties":{"severity":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]}},"asset_type":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]}},"storage_health_issue":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]}},"platform":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]}},"account":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"},"platform":{"type":"string"}},"required":["value","label","platform"]}},"asset_name":{"type":"array","items":{"type":"object","properties":{"value":{"type":"string"},"label":{"type":"string"}},"required":["value","label"]}}},"required":["severity","asset_type","storage_health_issue","platform","account","asset_name"]}},"required":["status","message","data"]}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/asset/{assetId}/last-clean-backup":{"get":{"operationId":"last_clean_backup","summary":"Get last clean backup","tags":["Backup"],"description":"Get last clean backup","parameters":[{"schema":{"type":"string"},"in":"path","name":"assetId","required":true}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"number"},"data":{"type":"object","properties":{"erp":{"type":"object","properties":{"id":{"type":"string"},"cc_rp_id":{"type":"string"},"cc_id":{"type":"string"},"vault":{"type":"object","properties":{"name":{"type":"string"},"shard":{"type":"string"}}},"job_id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"deletion_status":{"type":"string"},"source_asset_id":{"type":"string"},"backup_entities":{"type":"array"},"corresponding_backup":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{}},"backup_policy_names":{"type":"array","items":{"type":"string"}},"retention_policy_name":{"type":"string"},"threat_id_list":{"type":"array","items":{"type":"string"}},"scan_id_list":{"type":"array","items":{"type":"string"}},"size_info":{"type":"number"},"timestamp":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"}}},"ebs_snapshots":{"type":"object","properties":{"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_id":{"type":"string"},"aws_region":{"type":"string"},"backup_policy_names":{"type":"array"},"created_at":{"type":"string"},"description":{"type":"string"},"encrypted":{"type":"boolean"},"fs_check_status":{"type":"string"},"id":{"type":"string"},"job_id":{"type":"string"},"malware_check_status":{"type":"string"},"publicly_shared":{"type":"boolean"},"ransomware_check_status":{"type":"string"},"scan_id_list":{"type":"array"},"size":{"type":"number"},"status":{"type":"string"},"storage_tier":{"type":"string"},"tags":{"type":"array"},"threat_id_list":{"type":"array"},"timestamp":{"type":"string"},"updated_at":{"type":"string"},"volume_id":{"type":"string"}}},"awsb_rps":{"type":"object","properties":{"account_id":{"type":"string"},"arn":{"type":"string"},"calculated_lifecycle":{"type":"object"},"created_at":{"type":"string"},"created_by":{"type":"object","properties":{"backup_plan_arn":{"type":"string"},"backup_plan_id":{"type":"string"},"backup_plan_version":{"type":"string"},"backup_rule_id":{"type":"string"}}},"encrypted":{"type":"boolean"},"encryption_key_arn":{"type":"string"},"fs_check_status":{"type":"string"},"id":{"type":"string"},"import_job_id":{"type":"string"},"kind":{"type":"string"},"lifecycle":{"type":"object"},"malware_check_status":{"type":"string"},"parent_recovery_point_arn":{"type":"string"},"ransomware_check_status":{"type":"string"},"region":{"type":"string"},"scan_id_list":{"type":"array"},"size":{"type":"number"},"source_asset_id":{"type":"string"},"source_backup_vault_arn":{"type":"string"},"status":{"type":"string"},"storage_class":{"type":"string"},"tags":{"type":"array"},"threat_id_list":{"type":"array"},"timestamp":{"type":"string"},"updated_at":{"type":"string"},"vault":{"type":"object","properties":{"arn":{"type":"string"},"created_at":{"type":"string"},"name":{"type":"string"}}}}},"aws_ami":{"type":"object","properties":{"id":{"type":"string"},"arn":{"type":"string"},"account_id":{"type":"string"},"region":{"type":"string"},"aws_ami_id":{"type":"string"},"source_instance_id":{"type":"string"},"ebs_volume_ids":{"type":"array"},"state":{"type":"string"},"type":{"type":"string"},"location":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"has_public_permissions":{"type":"boolean"},"tags":{"type":"array"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"},"timestamp":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"}}},"ova_backups":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"cc_backup_id":{"type":"string"},"backup_provider_backup_id":{"type":"string"},"source_asset_id":{"type":"string"},"snapshots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ova_volume_id":{"type":"string"},"cc_volume_id":{"type":"string"},"backup_provider_volume_id":{"type":"string"},"total_size":{"type":"number"},"allocated_size":{"type":"number"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}}},"timestamp":{"type":"string"},"total_size":{"type":"number"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"}}},"aws_drs":{"type":"object","properties":{"id":{"type":"string"},"account_id":{"type":"string"},"region":{"type":"string"},"status":{"type":"string"},"instance_id":{"type":"string"},"volume_ids":{"type":"array"},"pit_snapshot_id":{"type":"string"},"timestamp":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"},"source_server_id":{"type":"string"}}},"gcp_compute_image":{"type":"object","properties":{"id":{"type":"string"},"family_id":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"resource_name":{"type":"string"},"state":{"type":"string"},"description":{"type":"string","nullable":true},"labels":{},"storage_locations":{"type":"array"},"created_in_gcp_at":{"type":"string"},"timestamp":{"type":"string"},"architecture":{"type":"string","nullable":true},"disk_size_gb":{"type":"number","nullable":true},"archive_size_bytes":{"type":"number","nullable":true},"image_family":{"type":"string","nullable":true},"source_kind":{"type":"string","nullable":true},"licenses":{"type":"array"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}},"gcp_compute_machine_image":{"type":"object","properties":{"id":{"type":"string"},"family_id":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"resource_name":{"type":"string"},"state":{"type":"string"},"description":{"type":"string","nullable":true},"labels":{},"storage_locations":{"type":"array"},"created_in_gcp_at":{"type":"string"},"timestamp":{"type":"string"},"machine_type":{"type":"string","nullable":true},"source_instance":{"type":"string","nullable":true},"total_storage_bytes":{"type":"number","nullable":true},"saved_disks":{"type":"array"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}},"gcp_compute_disk_snapshots":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"source_disk_id":{"type":"string"},"labels":{},"storage_bytes":{"type":"number","nullable":true},"disk_size_gb":{"type":"number"},"size_bytes":{"type":"number"},"created_in_gcp_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"}}},"gcp_backup_dr_recovery_points":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"project_id":{"type":"string"},"location":{"type":"string"},"vault_name":{"type":"string"},"data_source":{"type":"string"},"backup_name":{"type":"string"},"device_name":{"type":"string","nullable":true},"asset_kind":{"type":"string"},"asset_id":{"type":"string"},"additional_asset_ids":{"type":"array"},"resource_size_bytes":{"type":"number","nullable":true},"expire_time":{"type":"string","nullable":true},"enforced_retention_end_time":{"type":"string","nullable":true},"consistency_time":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"}}},"azure_snapshots":{"type":"object","properties":{"id":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"name":{"type":"string"},"source_disk_id":{"type":"string"},"status":{"type":"string"},"tags":{"type":"array"},"created_in_azure_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"region":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"}}},"azure_recovery_services_recovery_point_vm":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"vault_subscription_id":{"type":"string"},"vault_resource_group":{"type":"string"},"vault_name":{"type":"string"},"rp_name":{"type":"string"},"rp_azure_id":{"type":"string"},"asset_kind":{"type":"string"},"asset_id":{"type":"string"},"additional_asset_ids":{"type":"array"},"status":{"type":"string"},"created_in_azure_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array","items":{"type":"string"}},"scan_id_list":{"type":"array","items":{"type":"string"}}}},"azure_data_protection_recovery_points":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"vault_subscription_id":{"type":"string"},"vault_resource_group":{"type":"string"},"vault_name":{"type":"string"},"rp_name":{"type":"string"},"rp_azure_id":{"type":"string"},"asset_kind":{"type":"string"},"asset_id":{"type":"string"},"additional_asset_ids":{"type":"array"},"status":{"type":"string"},"created_in_azure_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array","items":{"type":"string"}},"scan_id_list":{"type":"array","items":{"type":"string"}}}},"fsx_ontap_volume_snapshots":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"snapshot_id":{"type":"string"},"arn":{"type":"string"},"fsx_ontap_volume_id":{"type":"string"},"snapshot_kind":{"type":"string"},"backup_id":{"type":"string","nullable":true},"tags":{"type":"array"},"created_in_aws_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array","items":{"type":"string"}},"scan_id_list":{"type":"array","items":{"type":"string"}}}}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/backups-list-by-ids":{"get":{"operationId":"backup_by_ids","summary":"Get backup by ids","tags":["Backup"],"description":"Get backup by ids","parameters":[{"schema":{"type":"string"},"in":"query","name":"backup_ids","required":false}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"number"},"data":{"type":"object","properties":{"erps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"cc_rp_id":{"type":"string"},"cc_id":{"type":"string"},"vault":{"type":"object","properties":{"name":{"type":"string"},"shard":{"type":"string"}}},"job_id":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"deletion_status":{"type":"string"},"source_asset_id":{"type":"string"},"backup_entities":{"type":"array"},"corresponding_backup":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{}},"backup_policy_names":{"type":"array","items":{"type":"string"}},"retention_policy_name":{"type":"string"},"size_info":{"type":"number"},"timestamp":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"}}}},"ebs_snapshots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"arn":{"type":"string"},"aws_account_id":{"type":"string"},"aws_id":{"type":"string"},"aws_region":{"type":"string"},"backup_policy_names":{"type":"array"},"created_at":{"type":"string"},"description":{"type":"string"},"encrypted":{"type":"boolean"},"fs_check_status":{"type":"string"},"job_id":{"type":"string"},"malware_check_status":{"type":"string"},"publicly_shared":{"type":"boolean"},"ransomware_check_status":{"type":"string"},"size":{"type":"number"},"status":{"type":"string"},"storage_tier":{"type":"string"},"tags":{"type":"array"},"timestamp":{"type":"string"},"updated_at":{"type":"string"},"volume_id":{"type":"string"}}}},"awsb_rps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"aws_vault_id":{"type":"string"},"aws_account_id":{"type":"string"},"arn":{"type":"string"},"calculated_lifecycle":{"type":"object"},"created_at":{"type":"string"},"encrypted":{"type":"boolean"},"encryption_key_arn":{"type":"string"},"fs_check_status":{"type":"string"},"import_job_id":{"type":"string"},"kind":{"type":"string"},"lifecycle":{"type":"object"},"malware_check_status":{"type":"string"},"parent_recovery_point_arn":{"type":"string"},"ransomware_check_status":{"type":"string"},"region":{"type":"string"},"size":{"type":"number"},"source_asset_id":{"type":"string"},"source_vault_arn":{"type":"string"},"status":{"type":"string"},"storage_class":{"type":"string"},"tags":{"type":"array"},"timestamp":{"type":"string"},"updated_at":{"type":"string"},"vault":{"type":"object","properties":{"arn":{"type":"string"},"created_at":{"type":"string"},"name":{"type":"string"}}}}}},"aws_amis":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"arn":{"type":"string"},"account_id":{"type":"string"},"region":{"type":"string"},"aws_ami_id":{"type":"string"},"source_instance_id":{"type":"string"},"ebs_volume_ids":{"type":"array"},"state":{"type":"string"},"type":{"type":"string"},"location":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"has_public_permissions":{"type":"boolean"},"tags":{"type":"array"},"timestamp":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"}}}},"ova_backups":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"provider":{"type":"string"},"cc_backup_id":{"type":"string"},"backup_provider_backup_id":{"type":"string"},"source_asset_id":{"type":"string"},"snapshots":{"type":"object","properties":{"id":{"type":"string"},"ova_volume_id":{"type":"string"},"cc_volume_id":{"type":"string"},"backup_provider_volume_id":{"type":"string"},"total_size":{"type":"number"},"allocated_size":{"type":"number"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}}},"timestamp":{"type":"string"},"total_size":{"type":"number"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"}}}},"aws_drs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"account_id":{"type":"string"},"region":{"type":"string"},"status":{"type":"string"},"instance_id":{"type":"string"},"volume_ids":{"type":"array"},"pit_snapshot_id":{"type":"string"},"timestamp":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"source_server_id":{"type":"string"}}}},"gcp_compute_images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"family_id":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"resource_name":{"type":"string"},"state":{"type":"string"},"description":{"type":"string","nullable":true},"labels":{},"storage_locations":{"type":"array"},"created_in_gcp_at":{"type":"string"},"timestamp":{"type":"string"},"architecture":{"type":"string","nullable":true},"disk_size_gb":{"type":"number","nullable":true},"archive_size_bytes":{"type":"number","nullable":true},"image_family":{"type":"string","nullable":true},"source_kind":{"type":"string","nullable":true},"licenses":{"type":"array"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}}},"gcp_compute_machine_images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"family_id":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"resource_name":{"type":"string"},"state":{"type":"string"},"description":{"type":"string","nullable":true},"labels":{},"storage_locations":{"type":"array"},"created_in_gcp_at":{"type":"string"},"timestamp":{"type":"string"},"machine_type":{"type":"string","nullable":true},"source_instance":{"type":"string","nullable":true},"total_storage_bytes":{"type":"number","nullable":true},"saved_disks":{"type":"array"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}}},"gcp_compute_disk_snapshots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"source_disk_id":{"type":"string"},"labels":{},"storage_bytes":{"type":"number","nullable":true},"disk_size_gb":{"type":"number"},"size_bytes":{"type":"number"},"created_in_gcp_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}}},"gcp_backup_dr_recovery_points":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"project_id":{"type":"string"},"location":{"type":"string"},"vault_name":{"type":"string"},"data_source":{"type":"string"},"backup_name":{"type":"string"},"device_name":{"type":"string","nullable":true},"asset_kind":{"type":"string"},"asset_id":{"type":"string"},"additional_asset_ids":{"type":"array"},"resource_size_bytes":{"type":"number","nullable":true},"expire_time":{"type":"string","nullable":true},"enforced_retention_end_time":{"type":"string","nullable":true},"consistency_time":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}}},"azure_snapshots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"subscription_id":{"type":"string"},"resource_group":{"type":"string"},"name":{"type":"string"},"source_disk_id":{"type":"string"},"status":{"type":"string"},"tags":{"type":"array"},"created_in_azure_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"region":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"threat_id_list":{"type":"array"},"scan_id_list":{"type":"array"}}}},"azure_recovery_services_recovery_point_vm":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"vault_subscription_id":{"type":"string"},"vault_resource_group":{"type":"string"},"vault_name":{"type":"string"},"rp_name":{"type":"string"},"rp_azure_id":{"type":"string"},"asset_kind":{"type":"string"},"asset_id":{"type":"string"},"additional_asset_ids":{"type":"array"},"status":{"type":"string"},"created_in_azure_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"},"backup_fabric":{"type":"string"},"protection_container":{"type":"string"},"protected_item":{"type":"string"}}}},"azure_data_protection_recovery_points":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"vault_subscription_id":{"type":"string"},"vault_resource_group":{"type":"string"},"vault_name":{"type":"string"},"rp_name":{"type":"string"},"rp_azure_id":{"type":"string"},"asset_kind":{"type":"string"},"asset_id":{"type":"string"},"additional_asset_ids":{"type":"array"},"status":{"type":"string"},"created_in_azure_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}}},"fsx_ontap_volume_snapshots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"tenant_name":{"type":"string"},"aws_account_id":{"type":"string"},"aws_region":{"type":"string"},"snapshot_id":{"type":"string"},"arn":{"type":"string"},"fsx_ontap_volume_id":{"type":"string"},"snapshot_kind":{"type":"string"},"backup_id":{"type":"string","nullable":true},"tags":{"type":"array"},"created_in_aws_at":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"},"fs_check_status":{"type":"string"},"malware_check_status":{"type":"string"},"ransomware_check_status":{"type":"string"},"encryption_check_status":{"type":"string"}}}}}},"cached":{"type":"boolean","description":"Indicates whether the data was served from cache (true) or fetched fresh (false)","example":true},"expiresInMs":{"type":"number","description":"If cached is true, indicates the time in milliseconds until the cache expires. Undefined if not cached.","example":240000,"nullable":true}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/security-metrics":{"get":{"operationId":"get_security_metrics","summary":"Get security metrics","tags":["Security Metrics"],"description":"Provides detailed security metrics across multiple dimensions with dynamic RPO support","parameters":[{"schema":{"type":"number"},"in":"query","name":"rpo_hours","required":false,"description":"Recovery Point Objective in hours for dynamic calculation"},{"schema":{"type":"string"},"in":"query","name":"platform","required":false,"description":"Comma-separated list of platforms to filter by. Options: aws, azure, on_prem, ibm"},{"schema":{"type":"boolean"},"in":"query","name":"exclude_at_risk","required":false,"description":"If true, excludes at-risk assets from the storage health and recovery assurance security metrics calculations. Defaults to false."}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Security metrics fetched successfully","content":{"application/json":{"schema":{"description":"Security metrics fetched successfully","type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Security metrics fetched successfully"},"data":{"type":"object","properties":{"ransomware_safety":{"type":"object","properties":{"clean_assets":{"type":"number","example":13},"infected_assets":{"type":"number","example":3},"at_risk_assets":{"type":"number","example":2}}},"encryption_safety":{"type":"object","properties":{"encrypted_assets":{"type":"number","example":3},"unencrypted_assets":{"type":"number","example":12},"unscanned_assets":{"type":"number","example":5}}},"storage_health":{"type":"object","properties":{"unhealthy_storage":{"type":"number","example":1},"total_storage":{"type":"number","example":6}}},"recovery_assurance":{"type":"object","properties":{"assets_under_rpo":{"type":"number","example":10},"assets_outside_rpo":{"type":"number","example":6}}},"asset_coverage":{"type":"object","properties":{"covered_assets":{"type":"number","example":7},"uncovered_assets":{"type":"number","example":2},"platforms_covered":{"type":"array","description":"Distinct platforms that have at least one covered asset","items":{"type":"string","enum":["aws","azure","on_prem","ibm"]},"example":["aws","azure"]}}}}}}}}}},"400":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/api/v1/recovery-analytics/backup-age-percentiles":{"get":{"operationId":"get_backup_age_percentiles","summary":"Get backup age percentiles","tags":["Recovery Analytics"],"description":"Provides percentiles of backup ages to understand distribution across assets","parameters":[{"schema":{"type":"string","enum":["aws","azure","on_prem","ibm"]},"in":"query","name":"platform","required":false,"description":"Platform to filter by. Options: aws, azure, on_prem, ibm"}],"security":[{"authorization":[]}],"responses":{"200":{"description":"Backup age percentiles fetched successfully","content":{"application/json":{"schema":{"description":"Backup age percentiles fetched successfully","type":"object","properties":{"status":{"type":"number","example":200},"message":{"type":"string","example":"Backup age percentiles fetched successfully"},"data":{"type":"object","properties":{"min":{"type":"number","description":"Minimum backup age in seconds","example":3600},"max":{"type":"number","description":"Maximum backup age in seconds","example":86400},"top_20":{"type":"number","description":"20th percentile backup age in seconds","example":7200},"top_40":{"type":"number","description":"40th percentile backup age in seconds","example":14400},"top_50":{"type":"number","description":"50th percentile (top_50) backup age in seconds","example":21600},"top_60":{"type":"number","description":"60th percentile backup age in seconds","example":28800},"top_80":{"type":"number","description":"80th percentile backup age in seconds","example":43200},"top_100":{"type":"number","description":"100th percentile backup age in seconds","example":86400}},"required":["min","max","top_20","top_40","top_50","top_60","top_80","top_100"]}},"required":["status","message","data"]}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"4XX":{"description":"Client error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"5XX":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/rbac/api/v1/users":{"get":{"tags":["Users"],"summary":"List all users","operationId":"listUsers","parameters":[{"name":"q","in":"query","description":"Search query to filter users by email, name, status, or role","required":false,"schema":{"type":"string"}},{"name":"search_query","in":"query","description":"Alternative parameter name for search query (for backward compatibility)","required":false,"schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter users by status. By default, deleted users are excluded. Use 'all' to include deleted users.","required":false,"schema":{"type":"string","enum":["all"],"default":"active"}}],"responses":{"200":{"description":"Array of users","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}},"post":{"tags":["Users"],"summary":"Create a new user","operationId":"createUser","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDetail"}}}},"responses":{"200":{"description":"Creation status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/users/byIds":{"post":{"tags":["Users"],"summary":"Get user objects by ID list (bulk)","operationId":"getUsersByIds","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserIdArray"}}}},"responses":{"200":{"description":"Array of user detail objects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserDetail"}}}}}}}},"/rbac/api/v1/users/disable":{"patch":{"tags":["Users"],"summary":"Disable one or many users by ID","operationId":"disableUsers","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableUsersRequest"}}}},"responses":{"200":{"description":"Status per user","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"status":{"type":"string"}}}}}}}}}},"/rbac/api/v1/users/enable":{"patch":{"tags":["Users"],"summary":"Enable one or many users by ID","operationId":"enableUsers","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableUsersRequest"}}}},"responses":{"200":{"description":"Status per user","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"status":{"type":"string"}}}}}}}}}},"/rbac/api/v1/users/{id}":{"patch":{"tags":["Users"],"summary":"Update user attributes","operationId":"updateUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDetail"}}}},"responses":{"200":{"description":"Update status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}},"delete":{"tags":["Users"],"summary":"Delete a user","operationId":"deleteUser","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"User deleted successfully"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}}}},"/rbac/api/v1/users/{id}/role":{"get":{"tags":["Users"],"summary":"Get user's current role","operationId":"getUserRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"User's current role","content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["admin","viewer"]}},"required":["user_id","role"]}}}},"404":{"description":"User not found"}}}},"/rbac/api/v1/users/role":{"get":{"tags":["Users"],"summary":"Get current authenticated user's role","operationId":"getCurrentUserRole","responses":{"200":{"description":"Current user's role","content":{"application/json":{"schema":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["admin","viewer"]}},"required":["user_id","role"]}}}},"401":{"description":"Unauthorized - authentication required"},"404":{"description":"User not found"}}}},"/rbac/api/v1/users/resend-invite":{"post":{"tags":["Users"],"summary":"Resend an invitation email","operationId":"resendUserInvite","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendInviteRequest"}}}},"responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/users/search":{"get":{"tags":["Users"],"summary":"Search users by free‑text query","operationId":"searchUsers","parameters":[{"name":"search_query","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Array of users matching query","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"}}}}}}}},"/rbac/api/v1/userGroups":{"get":{"tags":["User Groups"],"summary":"List user groups","operationId":"listUserGroups","responses":{"200":{"description":"Array of user groups","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserGroup"}}}}}}},"post":{"tags":["User Groups"],"summary":"Create a user group","operationId":"createUserGroup","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserGroupCreate"}}}},"responses":{"201":{"description":"Created user group with user details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserGroup"}}}}}}},"/rbac/api/v1/userGroups/byIds":{"post":{"tags":["User Groups"],"summary":"Get user groups by IDs (bulk)","operationId":"getUserGroupsByIds","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserIdArray"}}}},"responses":{"200":{"description":"Array of user group objects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserGroup"}}}}}}}},"/rbac/api/v1/userGroups/{id}":{"patch":{"tags":["User Groups"],"summary":"Update a user group","operationId":"editUserGroup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserGroupUpdate"}}}},"responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}},"delete":{"tags":["User Groups"],"summary":"Delete a user group","operationId":"deleteUserGroup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deletion status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/userGroups/search":{"get":{"tags":["User Groups"],"summary":"Search user groups","operationId":"searchUserGroups","parameters":[{"name":"search_query","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Array of user groups","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserGroup"}}}}}}}},"/rbac/api/v1/accountGroups":{"get":{"tags":["Account Groups"],"summary":"List account groups","operationId":"listAccountGroups","responses":{"200":{"description":"Array of account groups","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountGroup"}}}}}}},"post":{"tags":["Account Groups"],"summary":"Create an account group","operationId":"createAccountGroup","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountGroupCreate"}}}},"responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/accountGroups/byIds":{"post":{"tags":["Account Groups"],"summary":"Get account groups by IDs (bulk)","operationId":"getAccountGroupsByIds","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserIdArray"}}}},"responses":{"200":{"description":"Array of account group objects","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountGroup"}}}}}}}},"/rbac/api/v1/accountGroups/{id}":{"patch":{"tags":["Account Groups"],"summary":"Update an account group","operationId":"editAccountGroup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountGroupUpdate"}}}},"responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}},"delete":{"tags":["Account Groups"],"summary":"Delete an account group","operationId":"deleteAccountGroup","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deletion status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/accountGroups/search":{"get":{"tags":["Account Groups"],"summary":"Search account groups","operationId":"searchAccountGroups","parameters":[{"name":"search_query","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Array of account groups","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountGroup"}}}}}}}},"/rbac/api/v1/accounts/{id}":{"get":{"tags":["Account Groups"],"summary":"Get raw cloud account ID mapping for an Elastio account group","operationId":"getAccountIdMapping","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"JSON payload with accountId mapping","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"account_id":{"type":"string"}}}}}}}}},"/rbac/api/v1/users/{userId}":{"get":{"tags":["Users"],"summary":"Get a specific user by ID","operationId":"getUserByID","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"User details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"404":{"description":"User not found"}}}},"/rbac/api/v1/userGroups/{userGroupId}":{"get":{"tags":["User Groups"],"summary":"Get a specific user group by ID","operationId":"getUserGroupByID","parameters":[{"name":"userGroupId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"User group details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserGroup"}}}},"404":{"description":"User group not found"}}}},"/rbac/api/v1/accountGroups/{accountGroupId}":{"get":{"tags":["Account Groups"],"summary":"Get a specific account group by ID","operationId":"getAccountGroupByID","parameters":[{"name":"accountGroupId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Account group details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountGroup"}}}},"404":{"description":"Account group not found"}}}},"/rbac/api/v1/roles":{"get":{"tags":["Roles"],"summary":"List all roles for the tenant","operationId":"listRoles","responses":{"200":{"description":"Array of roles","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Role"}}}}}}},"post":{"tags":["Roles"],"summary":"Create a new role","operationId":"createRole","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleCreate"}}}},"responses":{"201":{"description":"Created role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}}}}},"/rbac/api/v1/roles/{id}":{"get":{"tags":["Roles"],"summary":"Get a specific role by ID","operationId":"getRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Role details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}},"404":{"description":"Role not found"}}},"patch":{"tags":["Roles"],"summary":"Update a specific role by ID","operationId":"updateRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoleUpdate"}}}},"responses":{"200":{"description":"Update status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}},"delete":{"tags":["Roles"],"summary":"Delete a specific role by ID","operationId":"deleteRole","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deletion status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/users/{userId}/roles":{"get":{"tags":["Users"],"summary":"List roles for a user","operationId":"listUserRoles","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Array of roles assigned to the user","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Role"}}}}}}},"post":{"tags":["Users"],"summary":"Assign role to user","operationId":"assignRoleToUser","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignRoleRequest"}}}},"responses":{"200":{"description":"Assignment status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/users/{userId}/roles/{roleId}":{"delete":{"tags":["Users"],"summary":"Revoke role from user","operationId":"revokeRoleFromUser","parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"roleId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Revocation status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/rbac/api/v1/audit-logs":{"get":{"tags":["Audit Logs"],"summary":"Retrieve audit logs with filtering and pagination","operationId":"listAuditLogs","parameters":[{"in":"query","name":"start_date","required":true,"schema":{"type":"string","format":"date"},"description":"Start date (inclusive) for filtering audit logs (YYYY-MM-DD)"},{"in":"query","name":"end_date","required":true,"schema":{"type":"string","format":"date"},"description":"End date (inclusive) for filtering audit logs (YYYY-MM-DD)"},{"name":"search","in":"query","schema":{"type":"string"},"description":"Search term to filter logs by content"},{"name":"category","in":"query","schema":{"type":"string"},"description":"Filter logs by category"},{"name":"generated_by","in":"query","schema":{"type":"string"},"description":"Filter logs by the user who generated them"},{"name":"offset","in":"query","schema":{"type":"integer","default":0},"description":"Number of records to skip for pagination"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":1000},"description":"Maximum number of records to return"}],"responses":{"200":{"description":"Paginated list of audit logs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogResponse"}}}},"400":{"description":"Invalid query parameters"},"401":{"description":"Unauthorized - missing or invalid authentication"},"500":{"description":"Internal server error"}}}},"/rbac/api/v1/audit-logs/filters":{"get":{"tags":["Audit Logs"],"summary":"Get available filter options for audit logs","operationId":"getAuditLogFilters","responses":{"200":{"description":"Available filter options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLogFilters"}}}},"401":{"description":"Unauthorized - missing or invalid authentication"},"500":{"description":"Internal server error"}}}},"/gateway/ingestion/v1/accounts":{"get":{"tags":["GuardDuty"],"summary":"List AWS accounts for a tenant","description":"Returns all active AWS accounts associated with the specified tenant. Includes both Cloud Connectors and asset accounts (protected accounts). Each account includes its type to distinguish between connectors and asset accounts.","operationId":"listAccounts","responses":{"200":{"description":"Successfully retrieved accounts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountsResponse"},"example":{"accounts":[{"account_id":"123456789012","region":"us-east-1","type":"cloud_connector"},{"account_id":"987654321098","region":"eu-west-1","type":"protected_account"}]}}}},"400":{"description":"Bad request"},"500":{"description":"Internal server error"}}}},"/gateway/ingestion/v1/enable":{"post":{"tags":["GuardDuty"],"summary":"Enable GuardDuty integration for an AWS account","description":"Creates an EventBridge event bus and rule to route GuardDuty findings from the specified AWS account to the ingestion service's SQS queue. If integration is already enabled, returns the existing configuration.","operationId":"enableIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableRequest"},"example":{"integration":"guardduty","account_id":"123456789012","region":"us-east-1"}}}},"responses":{"200":{"description":"Integration enabled successfully (or already enabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableResponse"},"examples":{"new":{"summary":"Newly enabled","value":{"event_bus_name":"elastio-acme-corp-123456789012","rule_name":"elastio-acme-corp-123456789012-guardduty","eventbridge_rule_name":"elastio-acme-corp-123456789012-guardduty","status":"enabled","message":"ok"}},"existing":{"summary":"Already enabled","value":{"event_bus_name":"elastio-acme-corp-123456789012","rule_name":"elastio-acme-corp-123456789012-guardduty","eventbridge_rule_name":"elastio-acme-corp-123456789012-guardduty","status":"enabled","message":"Event bus is already enabled"}}}}}},"400":{"description":"Invalid request (missing fields or unsupported integration)"},"404":{"description":"Account not found for the specified tenant"},"500":{"description":"Internal server error (AWS or database failure)"}}}},"/gateway/ingestion/v1/disable":{"post":{"tags":["GuardDuty"],"summary":"Disable GuardDuty integration for an AWS account","description":"Removes the EventBridge event bus, rule, and targets for the specified AWS account. Deletes the integration record from the database.","operationId":"disableIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableRequest"},"example":{"integration":"guardduty","account_id":"123456789012","region":"us-east-1"}}}},"responses":{"200":{"description":"Integration disabled successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisableResponse"},"example":{"event_bus_name":"elastio-acme-corp-123456789012","rule_name":"elastio-acme-corp-123456789012-guardduty","status":"deleted","message":"Integration deleted successfully"}}}},"400":{"description":"Invalid request (missing fields or unsupported integration)"},"404":{"description":"Integration not found for the specified account"},"500":{"description":"Internal server error (AWS or database failure)"}}}},"/gateway/ingestion/v1/guardduty/{hub_account_id}/{hub_region}/linked-accounts":{"post":{"tags":["GuardDuty"],"summary":"Add linked accounts to a hub","description":"Adds one or more spoke accounts to a hub account's linked_account_ids. Linked accounts can forward GuardDuty events through the hub to Elastio. Validates that each account exists in active Cloud Connectors or asset accounts.","operationId":"addLinkedAccounts","parameters":[{"name":"hub_account_id","in":"path","required":true,"description":"AWS account ID of the hub (12 digits)","schema":{"type":"string","pattern":"^[0-9]{12}$"},"example":"111111111111"},{"name":"hub_region","in":"path","required":true,"description":"AWS region where the hub is deployed","schema":{"type":"string"},"example":"us-east-1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedAccountsRequest"},"example":{"account_ids":["222222222222","333333333333"]}}}},"responses":{"200":{"description":"Accounts linked successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedAccountsResponse"},"examples":{"all_added":{"summary":"All accounts added","value":{"hub_account_id":"111111111111","linked_account_ids":["222222222222","333333333333"],"added":["222222222222","333333333333"],"message":"Accounts linked successfully"}},"partial_already_linked":{"summary":"Some already linked","value":{"hub_account_id":"111111111111","linked_account_ids":["222222222222","333333333333"],"added":["333333333333"],"already_linked":["222222222222"],"message":"Accounts linked successfully"}},"partial_with_errors":{"summary":"Some accounts failed validation","value":{"hub_account_id":"111111111111","linked_account_ids":["222222222222"],"added":["222222222222"],"failed":["444444444444"],"validation_errors":["account 444444444444 not found in tenant's AWS accounts"],"message":"Accounts linked with some errors"}}}}}},"400":{"description":"Invalid request (missing fields or empty account_ids)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"account_ids is required and must not be empty","code":"BAD_REQUEST"}}}},"404":{"description":"Hub account not found for this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"hub account 111111111111 not found for this tenant","code":"NOT_FOUND"}}}},"409":{"description":"All accounts failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"validation failed: account 222222222222 is already configured as a hub","code":"VALIDATION_ERROR"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"failed to validate accounts","code":"INTERNAL_ERROR"}}}}}},"delete":{"tags":["GuardDuty"],"summary":"Remove linked accounts from a hub","description":"Removes one or more spoke accounts from a hub account's linked_account_ids. Accounts not currently linked are reported in the not_found field but do not cause an error (idempotent operation).","operationId":"removeLinkedAccounts","parameters":[{"name":"hub_account_id","in":"path","required":true,"description":"AWS account ID of the hub (12 digits)","schema":{"type":"string","pattern":"^[0-9]{12}$"},"example":"111111111111"},{"name":"hub_region","in":"path","required":true,"description":"AWS region where the hub is deployed","schema":{"type":"string"},"example":"us-east-1"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedAccountsRequest"},"example":{"account_ids":["222222222222"]}}}},"responses":{"200":{"description":"Accounts unlinked successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedAccountsResponse"},"examples":{"all_removed":{"summary":"All accounts removed","value":{"hub_account_id":"111111111111","linked_account_ids":["333333333333"],"removed":["222222222222"],"message":"Accounts unlinked successfully"}},"partial":{"summary":"Some not found","value":{"hub_account_id":"111111111111","linked_account_ids":["333333333333"],"removed":["222222222222"],"not_found":["999999999999"],"message":"Accounts unlinked successfully"}}}}}},"400":{"description":"Invalid request (missing fields or empty account_ids)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"account_ids is required and must not be empty","code":"BAD_REQUEST"}}}},"404":{"description":"Hub account not found for this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"hub account 111111111111 not found for this tenant","code":"NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"failed to remove linked accounts","code":"INTERNAL_ERROR"}}}}}}},"/gateway/ingestion/v1/status":{"get":{"tags":["GuardDuty"],"summary":"Get GuardDuty integration status for a tenant","description":"Returns the status of all GuardDuty integrations for the tenant. If any accounts have integrations enabled, returns 'enabled' with account details. Otherwise returns 'disabled'. Each enabled account also carries its ingested-findings activity (`last_event_at`, `events_last_24h`, `scans_scheduled_last_24h`), folded across the hub account and every currently linked spoke.","operationId":"getIntegrationStatus","responses":{"200":{"description":"Integration status retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse1"},"examples":{"enabled_with_linked":{"summary":"Hub with linked spoke accounts","value":{"status":"enabled","accounts":[{"account_id":"123456789012","region":"us-east-1","event_bus_name":"gd-123456789012-uat-development","elastio_event_bus_arn":"arn:aws:events:eu-central-1:937593779230:event-bus/gd-123456789012-uat-development","hub_event_bus_arn":"arn:aws:events:us-east-1:123456789012:event-bus/gd-123456789012-uat-development","eventbridge_rule_name":"gd-123456789012-uat-development","linked_account_ids":["222222222222","333333333333"],"last_event_at":"2026-09-01T11:10:02Z","events_last_24h":3,"scans_scheduled_last_24h":3}]}},"enabled_no_linked":{"summary":"Hub without linked accounts","value":{"status":"enabled","accounts":[{"account_id":"123456789012","region":"us-east-1","event_bus_name":"gd-123456789012-uat-development","elastio_event_bus_arn":"arn:aws:events:eu-central-1:937593779230:event-bus/gd-123456789012-uat-development","hub_event_bus_arn":"arn:aws:events:us-east-1:123456789012:event-bus/gd-123456789012-uat-development","eventbridge_rule_name":"gd-123456789012-uat-development","last_event_at":null,"events_last_24h":0,"scans_scheduled_last_24h":0}]}},"disabled":{"summary":"No integrations enabled","value":{"status":"disabled"}}}}}},"400":{"description":"Bad request"},"500":{"description":"Internal server error"}}}},"/gateway/integration/v1/alerts":{"get":{"tags":["Alerts"],"summary":"List leftover unlabeled alerts (v1)","description":"Returns a paginated list of alert configurations for the authenticated tenant. Supports filtering and pagination via query parameters. This list returns only alerts whose matching_semantics is not yet assigned (v1 leftovers until cutover). Labeled alerts are served by the v2 list and GET endpoints. Fetching a labeled alert by id on v1 returns 404.","operationId":"listAlerts","parameters":[{"name":"pageSize","in":"query","description":"Maximum number of alerts to return per page","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination (from previous response)","required":false,"schema":{"type":"string"},"example":"eyJzb3J0Ijp7ImZpZWxkIjoiY3JlYXRlZF9hdCJ9fQ=="},{"name":"status","in":"query","description":"Filter alerts by status","required":false,"schema":{"type":"string","enum":["active","inactive","suppressed"]},"example":"active"},{"name":"severities","in":"query","required":false,"description":"Severity filter, comma-separated and repeatable (critical, high, medium, low, info). Keeps alerts that route any of the given severities: an alert whose criteria.severities overlaps the list, or an unrestricted alert (no selection), which routes every severity. An unknown value returns 400 validation_error.","schema":{"type":"string"},"example":"critical,high"}],"responses":{"200":{"description":"Successfully retrieved alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAlertsResponse"},"example":{"alerts":[{"id":"123e4567-e89b-12d3-a456-426614174000","tenant_name":"acme-corp.elastio.us","name":"Critical Scan Failures","description":"Notify when critical scan failures occur","mode":{"kind_tag":"notify"},"status":"enabled","criteria":{"asset_ids":null,"aws_account_id_regions":[{"account_id":"123456789012","region":"us-east-1"},{"account_id":"123456789012","region":"us-west-2"}],"ova_account_id_providers":null,"azure_subscription_id_resource_groups":null,"ibm_scopes":null,"tags":null,"event_kinds":{"kind_tag":"exact_events","event_kinds":["elastio:asset:threat:detected","elastio:asset:iscan:succeeded"]}},"channels":{"webhooks":[{"webhook_id":"550e8400-e29b-41d4-a716-446655440000"}],"tenant_members":[],"emails":[{"email":"security@company.com"}],"slack":[]},"created_at":"2026-01-23T10:30:00Z","updated_at":"2026-01-23T10:30:00Z"}],"pagination":{"next_page_token":"eyJzb3J0Ijp7ImZpZWxkIjoiY3JlYXRlZF9hdCIsImRpcmVjdGlvbiI6ImRlc2MifX0=","prev_page_token":null,"total_count":42}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to list alerts","code":"INTERNAL_ERROR"}}}}}},"post":{"tags":["Alerts"],"summary":"Create a new alert","description":"Creates a new alert configuration for the authenticated tenant. Alert names must be unique per tenant. Format is compatible with Rust notifications-service.","operationId":"createAlert","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertRequest"},"example":{"name":"Critical Scan Failures","description":"Notify when critical scan failures occur","mode":{"kind_tag":"notify"},"status":"enabled","criteria":{"asset_ids":null,"aws_account_id_regions":[{"account_id":"123456789012","region":"us-east-1"},{"account_id":"123456789012","region":"us-west-2"}],"ova_account_id_providers":null,"azure_subscription_id_resource_groups":null,"ibm_scopes":null,"tags":null,"event_kinds":{"kind_tag":"exact_events","event_kinds":["elastio:asset:threat:detected","elastio:asset:iscan:succeeded"]}},"channels":{"webhooks":[{"webhook_id":"550e8400-e29b-41d4-a716-446655440000"}],"tenant_members":[],"emails":[{"email":"security@company.com"}],"slack":[]}}}}},"responses":{"201":{"description":"Alert created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertResponse"},"example":{"id":"123e4567-e89b-12d3-a456-426614174000","tenant_name":"acme-corp.elastio.us","name":"Critical Scan Failures","description":"Notify when critical scan failures occur","mode":{"kind_tag":"notify"},"status":"enabled","criteria":{"asset_ids":null,"aws_account_id_regions":[{"account_id":"123456789012","region":"us-east-1"},{"account_id":"123456789012","region":"us-west-2"}],"ova_account_id_providers":null,"azure_subscription_id_resource_groups":null,"ibm_scopes":null,"tags":null,"event_kinds":{"kind_tag":"exact_events","event_kinds":["elastio:asset:threat:detected","elastio:asset:iscan:succeeded"]}},"channels":{"webhooks":[{"webhook_id":"550e8400-e29b-41d4-a716-446655440000"}],"tenant_members":[],"emails":[{"email":"security@company.com"}],"slack":[]},"created_at":"2026-01-23T10:30:00Z","updated_at":"2026-01-23T10:30:00Z"}}}},"400":{"description":"Invalid request (validation errors)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_name":{"summary":"Missing required field","value":{"error":"name is required","code":"BAD_REQUEST"}},"invalid_mode":{"summary":"Invalid mode format","value":{"error":"mode.kind_tag must be 'notify' or 'suppress'","code":"BAD_REQUEST"}}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"409":{"description":"Alert name already exists for this tenant. Codes: `duplicate_name` (another unlabeled alert), or `duplicate_name_labeled` (a v2 labeled alert owns the name; rename or delete it in the new alerts experience, or choose a different name).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Conflict","code":"duplicate_name","details":"An alert with this name already exists"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to create alert","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/alerts/{alert_id}":{"get":{"tags":["Alerts"],"summary":"Get leftover unlabeled alert by ID","description":"Returns an unlabeled leftover alert (matching_semantics not assigned). Labeled alerts are not found on v1; use the v2 GET. Missing and labeled-on-the-other-surface both return 404.","operationId":"getAlert","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"},"example":"123e4567-e89b-12d3-a456-426614174000"}],"responses":{"200":{"description":"Alert found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertResponse"},"example":{"id":"123e4567-e89b-12d3-a456-426614174000","tenant_name":"acme-corp.elastio.us","name":"Critical Scan Failures","description":"Notify when critical scan failures occur","mode":{"kind_tag":"notify"},"status":"enabled","criteria":{"asset_ids":null,"aws_account_id_regions":[{"account_id":"123456789012","region":"us-east-1"},{"account_id":"123456789012","region":"us-west-2"}],"ova_account_id_providers":null,"azure_subscription_id_resource_groups":null,"ibm_scopes":null,"tags":null,"event_kinds":{"kind_tag":"exact_events","event_kinds":["elastio:asset:threat:detected","elastio:asset:iscan:succeeded"]}},"channels":{"webhooks":[{"webhook_id":"550e8400-e29b-41d4-a716-446655440000"}],"tenant_members":[],"emails":[{"email":"security@company.com"}],"slack":[]},"created_at":"2026-01-23T10:30:00Z","updated_at":"2026-01-23T10:30:00Z"}}}},"400":{"description":"Invalid alert ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"invalid alert ID format","code":"BAD_REQUEST"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Alert not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"alert not found","code":"NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to get alert","code":"INTERNAL_ERROR"}}}}}},"put":{"tags":["Alerts"],"summary":"Update leftover unlabeled alert","description":"Updates an unlabeled leftover alert. All fields are optional; only provided fields will be updated (partial update). Labeled alerts are not found on v1; use the v2 PUT. Format is compatible with Rust notifications-service.","operationId":"updateAlert","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"},"example":"123e4567-e89b-12d3-a456-426614174000"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertRequest"},"examples":{"suppress_alert":{"summary":"Suppress an alert temporarily","value":{"description":"Temporarily suppressed for maintenance","mode":{"kind_tag":"suppress","reason":"Maintenance window","until":"2026-02-01T00:00:00Z"}}},"update_channels":{"summary":"Update notification channels","value":{"channels":{"webhooks":[{"webhook_id":"660e8400-e29b-41d4-a716-446655440001"}],"tenant_members":[],"emails":[{"email":"new-email@company.com"}],"slack":[{"slack_id":"880e8400-e29b-41d4-a716-446655440000"}]}}},"disable_alert":{"summary":"Disable an alert","value":{"status":"disabled"}}}}}},"responses":{"200":{"description":"Alert updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertResponse"},"example":{"id":"123e4567-e89b-12d3-a456-426614174000","tenant_name":"acme-corp.elastio.us","name":"Critical Scan Failures","description":"Temporarily suppressed for maintenance","mode":{"kind_tag":"suppress","reason":"Maintenance window","until":"2026-02-01T00:00:00Z"},"status":"enabled","criteria":{"asset_ids":null,"aws_account_id_regions":[{"account_id":"123456789012","region":"us-east-1"},{"account_id":"123456789012","region":"us-west-2"}],"ova_account_id_providers":null,"azure_subscription_id_resource_groups":null,"ibm_scopes":null,"tags":null,"event_kinds":{"kind_tag":"exact_events","event_kinds":["elastio:asset:threat:detected","elastio:asset:iscan:succeeded"]}},"channels":{"webhooks":[{"webhook_id":"550e8400-e29b-41d4-a716-446655440000"}],"tenant_members":[],"emails":[{"email":"security@company.com"}],"slack":[]},"created_at":"2026-01-23T10:30:00Z","updated_at":"2026-01-23T14:20:00Z"}}}},"400":{"description":"Invalid request (validation errors)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"invalid_mode":{"summary":"Invalid mode format","value":{"error":"mode.kind_tag must be 'notify' or 'suppress'","code":"BAD_REQUEST"}},"no_fields":{"summary":"No fields to update","value":{"error":"at least one field must be provided for update","code":"BAD_REQUEST"}}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Alert not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"alert not found","code":"NOT_FOUND"}}}},"409":{"description":"Alert name already exists when updating name. Codes: `duplicate_name` or `duplicate_name_labeled` (see createAlert).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Conflict","code":"duplicate_name","details":"An alert with this name already exists"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to update alert","code":"INTERNAL_ERROR"}}}}}},"delete":{"tags":["Alerts"],"summary":"Delete an alert","description":"Deletes an unlabeled leftover alert (soft delete). Labeled alerts are not found on v1. The row is marked as deleted but retained in the database for audit purposes.","operationId":"deleteAlert","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"},"example":"123e4567-e89b-12d3-a456-426614174000"}],"responses":{"204":{"description":"Alert deleted successfully (no content)"},"400":{"description":"Invalid alert ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"invalid alert ID format","code":"BAD_REQUEST"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Alert not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"alert not found","code":"NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to delete alert","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v2/alerts":{"get":{"tags":["Alerts"],"summary":"List all alerts for a tenant (v2)","description":"Returns a paginated list of alert configurations including policy-only (no_events) alerts.","operationId":"listAlertsV2","parameters":[{"name":"pageSize","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"pageToken","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["active","inactive","suppressed"]}},{"name":"scope","in":"query","description":"Matching-semantics scope. `policy` (the default) returns labeled policy alerts, `system` returns labeled system alerts, and `all` returns every labeled alert. Alerts whose `matching_semantics` is null are not returned; those leftovers are the v1 list until cutover.","schema":{"type":"string","enum":["policy","system","all"],"default":"policy"}},{"name":"policy_ids","in":"query","description":"Comma-separated recovery policy UUIDs. Scopes the result to alerts bound to any of the given policies plus all unbound alerts. Valid only with `scope=policy` (or `scope` omitted): combining it with `scope=system` or `scope=all` returns 400 `validation_error`.","schema":{"type":"string"}},{"name":"severities","in":"query","required":false,"description":"Severity filter, comma-separated and repeatable (critical, high, medium, low, info). Keeps alerts that route any of the given severities: an alert whose criteria.severities overlaps the list, or an unrestricted alert (no selection), which routes every severity. An unknown value returns 400 validation_error.","schema":{"type":"string"},"example":"critical,high"}],"responses":{"200":{"description":"Successfully retrieved alerts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAlertsV2Response"}}}},"400":{"description":"Validation error: unknown `scope` value, invalid `policy_ids`, or `policy_ids` combined with `scope=system` or `scope=all`."},"401":{"description":"Missing or invalid tenant authentication"},"404":{"description":"Feature not enabled for tenant"},"500":{"description":"Internal server error"}}},"post":{"tags":["Alerts"],"summary":"Create a policy-aware alert (v2)","description":"Creates an alert with optional recovery policy bindings. `matching_semantics` is required (`system` or `policy`) and is persisted even before cutover. Omit `criteria` to store `no_events`. Policy creates must use `no_events` (or omit criteria) and may omit `policy_ids`; `all_events` / `exact_events` or any scope fields on a policy alert are rejected (`scope_not_allowed_on_policy_alert`). System creates cannot include `policy_ids` and may set asset/account/tag/DC scope on `criteria`, including on a `no_events` draft. Returns 409 if a policy would lose its last alert on delete/update.","operationId":"createAlertV2","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertV2Request"}}}},"responses":{"201":{"description":"Alert created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertV2Response"}}}},"400":{"description":"Validation error"},"401":{"description":"Missing tenant authentication"},"409":{"description":"Conflict. Stable error codes: `duplicate_name` (another labeled alert already uses this name), `duplicate_name_unlabeled` (a classic/v1 leftover with null matching_semantics owns the name; rename or delete it in classic alerts, or choose a different name), or `policy_last_alert`."},"500":{"description":"Internal server error"}}}},"/gateway/integration/v2/alerts/{alert_id}":{"get":{"tags":["Alerts"],"summary":"Get alert by ID (v2)","description":"Returns a labeled alert. Unlabeled leftovers (matching_semantics null) are not found on v2; use v1 until cutover.","operationId":"getAlertV2","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Alert details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertV2Response"}}}},"404":{"description":"Alert not found"}}},"put":{"tags":["Alerts"],"summary":"Update alert (v2)","operationId":"updateAlertV2","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertV2Request"}}}},"responses":{"200":{"description":"Alert updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertV2Response"}}}},"409":{"description":"Conflict. Stable error codes: `policy_last_alert` (removing the last alert of a bound policy that still exists in pechkin; orphaned bindings to deleted policies do not veto the update), `duplicate_name`, `duplicate_name_unlabeled` (a classic/v1 leftover owns the name), `ALERT_MIGRATION_IN_PROGRESS` (retry after the tenant's alert migration operation finishes), and `alert_not_policy_scoped`; the request sent a non-empty `policy_ids` for a system-wide alert on a migrated tenant; system alerts cannot be bound to recovery policies (send `policy_ids: []` to clear bindings, which is always allowed)."}}},"delete":{"tags":["Alerts"],"summary":"Delete leftover unlabeled alert","description":"Deletes a labeled alert. Unlabeled leftovers are not found on v2; use v1 until cutover. Returns 409 if deleting would leave a still-existing bound policy without any alerts. Bindings to policies absent from pechkin do not veto the delete.","operationId":"deleteAlertV2","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Alert deleted"},"409":{"description":"Policy last-alert conflict (`policy_last_alert`) for a still-existing bound policy. Orphaned bindings do not produce this conflict."}}}},"/gateway/integration/v2/alerts/{alert_id}/activity":{"get":{"tags":["Alerts"],"summary":"List alert activity (v2)","description":"Returns paginated rows of events that matched this labeled alert (matching_semantics is system or policy), with linked channel delivery rows. Same listing as GET /integration/v1/alerts/{alert_id}/activity. Unlabeled leftovers are not found on v2; use v1 until cutover.","operationId":"getAlertActivityV2","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"pageToken","in":"query","required":false,"schema":{"type":"string"}},{"name":"period","in":"query","required":false,"description":"Rolling window for event_time, same style as GET /integration/v1/alerts/statistics (e.g. 1d, 7d, 30d). Defaults to 7d. Values must be between 1d and 30d inclusive.","schema":{"type":"string","default":"7d","example":"7d"}},{"name":"event_kind","in":"query","required":false,"description":"Optional filter by event kind. May be repeated (?event_kind=a&event_kind=b) or comma-separated (?event_kind=a,b). Allowed values come from GET.../activity/options.","explode":true,"schema":{"type":"array","items":{"type":"string"}},"example":["elastio:asset:iscan:succeeded"]}],"responses":{"200":{"description":"Activity page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertActivityResponse"}}}},"400":{"description":"Invalid query or page token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Alert not found, unlabeled leftover, or feature disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Activity storage not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v2/alerts/{alert_id}/activity/options":{"get":{"tags":["Alerts"],"summary":"Filter options for alert activity (v2)","description":"Returns selectable filter values for the alert activity UI: supported period choices and distinct event kinds seen for this labeled alert within the maximum window (30d). Unlabeled leftovers are not found on v2; use v1 until cutover.","operationId":"getAlertActivityOptionsV2","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertActivityOptionsResponse"}}}},"401":{"description":"Missing tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Alert not found, unlabeled leftover, or feature disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/alerts/{alert_id}/activity":{"get":{"tags":["Alerts"],"summary":"List alert activity (matched events and channel deliveries)","description":"Returns paginated rows of events that matched this unlabeled leftover alert (notify rule), with linked channel delivery rows and best-effort status/channel names from legacy delivery tables. Labeled alerts are not found on v1; use GET /integration/v2/alerts/{alert_id}/activity.","operationId":"getAlertActivity","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"}},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"pageToken","in":"query","required":false,"schema":{"type":"string"}},{"name":"period","in":"query","required":false,"description":"Rolling window for event_time, same style as GET /integration/v1/alerts/statistics (e.g. 1d, 7d, 30d). Defaults to 7d. Values must be between 1d and 30d inclusive.","schema":{"type":"string","default":"7d","example":"7d"}},{"name":"event_kind","in":"query","required":false,"description":"Optional filter by event kind. May be repeated (?event_kind=a&event_kind=b) or comma-separated (?event_kind=a,b). Allowed values come from GET.../activity/options.","explode":true,"schema":{"type":"array","items":{"type":"string"}},"example":["elastio:asset:iscan:succeeded"]}],"responses":{"200":{"description":"Activity page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertActivityResponse"}}}},"400":{"description":"Invalid query or page token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Alert not found or feature disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Activity storage not available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/alerts/{alert_id}/activity/options":{"get":{"tags":["Alerts"],"summary":"Filter options for alert activity","description":"Returns selectable filter values for the alert activity UI: supported period choices and distinct event kinds seen for this unlabeled leftover alert within the maximum window (30d). Labeled alerts are not found on v1; use GET /integration/v2/alerts/{alert_id}/activity/options.","operationId":"getAlertActivityOptions","parameters":[{"name":"alert_id","in":"path","required":true,"description":"Alert unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Options","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertActivityOptionsResponse"}}}},"401":{"description":"Missing tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Alert not found or feature disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/channels":{"get":{"tags":["Alerts"],"summary":"Get available notification channels","description":"Returns grouped notification channels (webhooks, etc.) for the tenant","operationId":"getChannels","responses":{"200":{"description":"Successfully retrieved channels","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelsResponse"},"example":{"webhooks":[{"id":"550e8400-e29b-41d4-a716-446655440000","name":"Production Webhook","type":"webhook","direction":"outgoing","description":"Main production webhook","created_at":"2026-01-23T10:30:00Z"}],"splunk":[]}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/alerts/emails":{"get":{"tags":["Alerts"],"summary":"Get available email addresses","description":"Returns active tenant user email addresses from the users database. Only returns users with status='active' and invitation_status='accepted' for the tenant.","operationId":"getEmails","responses":{"200":{"description":"Successfully retrieved emails","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EmailResponse"}},"example":[{"customer_id":"550e8400-e29b-41d4-a716-446655440000","email":"john.doe@company.com","name":"John Doe"},{"customer_id":"660e8400-e29b-41d4-a716-446655440001","email":"jane.smith@company.com","name":"Jane Smith"}]}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/alerts/events":{"get":{"tags":["Alerts"],"summary":"Get available event types","description":"Returns list of event kinds that can be used in alert criteria","operationId":"getEvents","responses":{"200":{"description":"Successfully retrieved events","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventKindCatalogEntry"}},"example":[{"event_kind":"elastio:asset:threat:resolved","description":"Threat resolved","category":"security"},{"event_kind":"elastio:asset:threat:detected","description":"Threat detected","category":"security"},{"event_kind":"elastio:asset:iscan:succeeded","description":"Hunt Job Succeeded","category":"operational"}]}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v2/alerts/events":{"get":{"tags":["Alerts"],"summary":"Get available event types (v2)","description":"Returns the full event catalog for v2 alert criteria.","operationId":"getEventsV2","responses":{"200":{"description":"Successfully retrieved events","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EventKindCatalogEntry"}},"example":[{"event_kind":"elastio:asset:threat:resolved","description":"Threat resolved","category":"security"},{"event_kind":"elastio:asset:threat:suppressed","description":"Threat suppressed","category":"security"},{"event_kind":"elastio:asset:violation:detected","description":"Violation detected","category":"recovery"},{"event_kind":"elastio:asset:violation:resolved","description":"Violation resolved","category":"recovery"}]}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/alerts/accounts":{"get":{"tags":["Alerts"],"summary":"Get available accounts by platform","description":"Returns accounts grouped by platform (AWS, Azure, OVA) for use in alert criteria","operationId":"getAccounts","responses":{"200":{"description":"Successfully retrieved accounts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MultiPlatformAccountsResponse"},"example":{"aws":{"accounts":[{"account_id":"123456789012","regions":["us-east-1","us-west-2"]},{"account_id":"987654321098","regions":["us-east-1"]}]},"azure":{"subscriptions":[{"subscription_id":"123e4567-e89b-12d3-a456-426614174000","name":"Production Subscription","azure_tenant_id":"tenant-12345"}]},"ova":{"accounts":[{"id":"123e4567-e89b-12d3-a456-426614174000","name":"Production OVA","custom_name":"My Custom Name","backup_providers":["veeam","commvault"]},{"id":"223e4567-e89b-12d3-a456-426614174001","name":"Development OVA","backup_providers":[]}]}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/wiz/webhook":{"post":{"tags":["Wiz"],"summary":"Receive incoming Wiz event","operationId":"receiveWizWebhookEvent","description":"Endpoint called by Wiz to deliver threat and asset events. The gateway validates the Authorization header and injects the Authority (tenant) header. On the first call from a new Wiz source (identified by wiz_source_id in the payload), a channel is automatically created. Subsequent calls from the same source route to the existing channel.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Raw Wiz threat/asset payload (stored verbatim)"},"example":{"subscriptionId":"sub-abc123","subscriptionName":"Production Wiz Org","severity":"HIGH","findings":[]}}}},"responses":{"200":{"description":"Event received and stored","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"received"},"id":{"type":"string","format":"uuid","example":"8f14e45f-ceea-467a-a866-92405cc08e17"},"scan_status":{"type":"string","enum":["scheduled","not_scheduled","unsupported"],"description":"scheduled: a scan job was created. not_scheduled: the event names an asset\nElastio scans, but no scan job was created (the reason is logged).\nunsupported: the event names no asset Elastio scans.\n","example":"scheduled"},"scan_job_id":{"type":"string","description":"Present only when scan_status is scheduled","example":"07fb3384-93e5-5359-bd41-c9ed9d02d865"}}}}}},"400":{"description":"Invalid JSON payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid authorization","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Wiz channel is set to inactive","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/wiz":{"get":{"tags":["Wiz"],"summary":"List Wiz channels","operationId":"listWizChannels","description":"Returns a paginated list of Wiz channels for the authenticated tenant.","security":[{"bearerAuth":[]}],"parameters":[{"name":"page_token","in":"query","schema":{"type":"string"},"description":"Cursor token for pagination"}],"responses":{"200":{"description":"List of Wiz channels","content":{"application/json":{"schema":{"type":"object","properties":{"configs":{"type":"array","items":{"$ref":"#/components/schemas/WizChannel"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/wiz/{id}":{"get":{"tags":["Wiz"],"summary":"Get a Wiz channel","operationId":"getWizChannel","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Wiz channel details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizChannel"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Wiz channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Wiz"],"summary":"Update a Wiz channel","operationId":"updateWizChannel","description":"Update the name, description, or status. Only provided fields are changed.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWizRequest"}}}},"responses":{"200":{"description":"Updated Wiz channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WizChannel"}}}},"400":{"description":"Invalid request body or status value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Wiz channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Channel with this name already exists","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Wiz"],"summary":"Delete a Wiz channel","operationId":"deleteWizChannel","description":"Soft-deletes the channel. Events already stored are retained.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Channel deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Wiz channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/webhooks":{"get":{"tags":["Webhooks"],"summary":"List all webhooks for a tenant","description":"Returns a paginated list of webhook configurations. Uses cursor-based pagination with pageSize and pageToken parameters.","operationId":"listWebhooks","parameters":[{"name":"pageSize","in":"query","description":"Number of items per page (1-100, default 50)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination (from previous response)","required":false,"schema":{"type":"string"},"example":"eyJzb3J0Ijp7ImZpZWxkIjoiY3JlYXRlZF9hdCIsImRpcmVjdGlvbiI6ImRlc2MifX0="}],"responses":{"200":{"description":"Successfully retrieved webhooks","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListWebhooksResponse"},"example":{"webhooks":[{"id":"660e8400-e29b-41d4-a716-446655440000","name":"Production Webhook","endpoint":"https://api.example.com/webhooks/production","description":"System Default","status":"active","authentication":{"type":"basic_auth","username":"product@test.com"},"used_in_alert_rules":3,"success_rate":98.5,"last_triggered_at":"2026-01-19T10:28:00Z","created_at":"2026-01-19T10:30:00Z","updated_at":"2026-01-19T10:30:00Z"}],"pagination":{"next_page_token":"eyJzb3J0Ijp7ImZpZWxkIjoiY3JlYXRlZF9hdCIsImRpcmVjdGlvbiI6ImRlc2MifX0=","prev_page_token":null,"total_count":1}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to list webhooks","code":"INTERNAL_ERROR"}}}}}},"post":{"tags":["Webhooks"],"summary":"Create a new webhook","description":"Creates a new webhook configuration for the authenticated tenant. Webhook names must be unique per tenant. Sensitive authentication fields (passwords, tokens) are never returned in responses.","operationId":"createWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateWebhookRequest"},"example":{"name":"Production Webhook","description":"System Default","endpoint":"https://api.example.com/webhook","authentication":{"type":"basic_auth","username":"product@test.com","password":"******"}}}}},"responses":{"201":{"description":"Webhook created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"integer","example":201},"data":{"$ref":"#/components/schemas/WebhookResponse"}}},"example":{"status":201,"data":{"id":"660e8400-e29b-41d4-a716-446655440000","name":"Production Webhook","endpoint":"https://api.example.com/webhook","description":"System Default","status":"active","authentication":{"type":"basic_auth","username":"product@test.com"},"created_at":"2026-01-19T10:30:00Z"}}}}},"400":{"description":"Invalid request (validation errors)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"examples":{"missing_name":{"summary":"Missing required field","value":{"error":"name is required","code":"BAD_REQUEST"}},"invalid_endpoint":{"summary":"Invalid endpoint URL","value":{"error":"invalid endpoint URL format","code":"BAD_REQUEST"}}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"409":{"description":"Webhook name already exists for this tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Webhook with name 'Production Webhook' already exists","code":"CONFLICT"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to create webhook","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/webhooks/statistics":{"get":{"tags":["Webhooks"],"summary":"Get webhook delivery statistics","description":"Returns aggregate statistics for all webhooks including total counts, active/inactive webhooks, and delivery success/failure metrics.","operationId":"getWebhookStatistics","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","schema":{"type":"string","default":"7d","example":"7d"}}],"responses":{"200":{"description":"Successfully retrieved statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookStatisticsResponse"},"example":{"data":{"total_webhooks":3,"active_webhooks":2,"inactive_webhooks":1,"total_deliveries":4,"successful_deliveries":2,"failed_deliveries":1,"period_days":7}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to get webhook statistics","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/webhooks/invocations":{"get":{"tags":["Webhooks"],"summary":"Get webhook invocation history (all webhooks)","description":"Returns delivery history for all webhooks. Supports filtering by period, name, and status. Includes request/response payloads for debugging.","operationId":"listAllWebhookInvocations","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"name","in":"query","description":"Filter by webhook name (or 'all')","required":false,"schema":{"type":"string","default":"all"},"example":"all"},{"name":"status","in":"query","description":"Filter by delivery status (or 'all')","required":false,"schema":{"type":"string","enum":["all","delivered","failed","in_progress","scheduled","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of invocations per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"},"example":"eyJvZmZzZXQiOjUwLCJpZCI6Imludl8xMjMiLCJkaXIiOiJuZXh0In0"}],"responses":{"200":{"description":"Successfully retrieved invocations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInvocationsResponse"},"example":{"invocations":[{"id":"inv_123","webhook_name":"Production Webhook","event_type":"user.created","created_at":"2026-01-19T10:28:00Z","response_time_ms":245,"http_status_code":200,"status":"delivered","request_payload":{"event":"user.created","data":{"id":"usr_123456","email":"john@example.com"}},"response_body":{"success":true,"message":"User created successfully"}},{"id":"inv_456","webhook_name":"Production Webhook","event_type":"account.created","created_at":"2026-01-19T10:15:00Z","response_time_ms":5000,"http_status_code":500,"status":"failed","request_payload":{"event":"account.created"},"response_body":{"error":"Internal server error"}}],"pagination":{"next_page_token":"eyJvZmZzZXQiOjUwLCJpZCI6Imludl80NTYiLCJkaXIiOiJuZXh0In0","prev_page_token":null,"total_count":150}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to list invocations","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/webhooks/deliveries/filter-options":{"get":{"tags":["Webhooks"],"summary":"Get filter options for webhook deliveries list","description":"Returns webhook names and status values to populate the name and status filters for GET.../deliveries (e.g. dropdowns or multi-select). Accepts the same period (time filter) as the deliveries list; default 7d.","operationId":"listWebhookDeliveryFilterOptions","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d); same as deliveries list, default 7d","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"}],"responses":{"200":{"description":"Filter options for the tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryFilterOptionsResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/webhooks/deliveries":{"get":{"tags":["Webhooks"],"summary":"Get webhook delivery history (all webhooks)","description":"Returns delivery history from ingestion tables for all webhooks. Same query params and pagination as list invocations (period, name, status, pageSize, pageToken).","operationId":"listAllWebhookDeliveries","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"name","in":"query","description":"Filter by webhook name (or 'all')","required":false,"schema":{"type":"string","default":"all"},"example":"all"},{"name":"status","in":"query","description":"Filter by delivery status (or 'all')","required":false,"schema":{"type":"string","enum":["all","delivered","failed","in_progress","scheduled","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of deliveries per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDeliveriesResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/webhooks/{webhook_id}":{"get":{"tags":["Webhooks"],"summary":"Get webhook by ID","description":"Returns a single webhook configuration with statistics","operationId":"getWebhook","parameters":[{"name":"webhook_id","in":"path","required":true,"description":"Webhook unique identifier (UUID)","schema":{"type":"string","format":"uuid"},"example":"660e8400-e29b-41d4-a716-446655440000"}],"responses":{"200":{"description":"Webhook found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"},"example":{"id":"660e8400-e29b-41d4-a716-446655440000","name":"Production Webhook","endpoint":"https://api.example.com/webhook","description":"System Default","status":"active","authentication":{"type":"basic_auth","username":"product@test.com"},"used_in_alert_rules":3,"success_rate":98.5,"last_triggered_at":"2026-01-19T10:28:00Z","created_at":"2026-01-19T10:30:00Z","updated_at":"2026-01-19T10:30:00Z"}}}},"400":{"description":"Invalid webhook ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"invalid webhook ID format","code":"BAD_REQUEST"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"webhook not found","code":"NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to get webhook","code":"INTERNAL_ERROR"}}}}}},"put":{"tags":["Webhooks"],"summary":"Update a webhook","description":"Updates an existing webhook configuration. All fields are optional; only provided fields will be updated (partial update).","operationId":"updateWebhook","parameters":[{"name":"webhook_id","in":"path","required":true,"description":"Webhook unique identifier (UUID)","schema":{"type":"string","format":"uuid"},"example":"660e8400-e29b-41d4-a716-446655440000"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateWebhookRequest"},"example":{"description":"Updated webhook description","endpoint":"https://api.example.com/webhook/v2"}}}},"responses":{"200":{"description":"Webhook updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookResponse"},"example":{"id":"660e8400-e29b-41d4-a716-446655440000","name":"Production Webhook","endpoint":"https://api.example.com/webhook/v2","description":"Updated webhook description","status":"active","authentication":{"type":"basic_auth","username":"product@test.com"},"created_at":"2026-01-19T10:30:00Z","updated_at":"2026-01-19T14:20:00Z"}}}},"400":{"description":"Invalid request (validation errors)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"invalid endpoint URL format","code":"BAD_REQUEST"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"webhook not found","code":"NOT_FOUND"}}}},"409":{"description":"Webhook name already exists (when updating name)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Webhook with name 'New Name' already exists","code":"CONFLICT"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to update webhook","code":"INTERNAL_ERROR"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","description":"Deletes a webhook configuration (soft delete). The webhook is marked as deleted but retained in the database for audit purposes.","operationId":"deleteWebhook","parameters":[{"name":"webhook_id","in":"path","required":true,"description":"Webhook unique identifier (UUID)","schema":{"type":"string","format":"uuid"},"example":"660e8400-e29b-41d4-a716-446655440000"}],"responses":{"204":{"description":"Webhook deleted successfully (no content)"},"400":{"description":"Invalid webhook ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"invalid webhook ID format","code":"BAD_REQUEST"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"webhook not found","code":"NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to delete webhook","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/webhooks/{webhook_id}/invocations":{"get":{"tags":["Webhooks"],"summary":"Get invocation history for a specific webhook","description":"Returns delivery history for a specific webhook. Supports filtering by period and status. Includes request/response payloads for debugging.","operationId":"listWebhookInvocations","parameters":[{"name":"webhook_id","in":"path","required":true,"description":"Webhook unique identifier (UUID)","schema":{"type":"string","format":"uuid","example":"660e8400-e29b-41d4-a716-446655440000"}},{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"status","in":"query","description":"Filter by delivery status (or 'all')","required":false,"schema":{"type":"string","enum":["all","delivered","failed","in_progress","scheduled","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of invocations per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"},"example":"eyJvZmZzZXQiOjUwLCJpZCI6Imludl8xMjMiLCJkaXIiOiJuZXh0In0"}],"responses":{"200":{"description":"Successfully retrieved invocations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListInvocationsResponse"},"example":{"invocations":[{"id":"inv_123","webhook_name":"Production Webhook","event_type":"user.created","created_at":"2026-01-19T10:28:00Z","response_time_ms":245,"http_status_code":200,"status":"delivered","request_payload":{"event":"user.created","data":{"id":"usr_123456"}},"response_body":{"success":true}}],"pagination":{"next_page_token":null,"prev_page_token":null,"total_count":50}}}}},"400":{"description":"Invalid webhook ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"invalid webhook ID format","code":"BAD_REQUEST"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"webhook not found","code":"NOT_FOUND"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to list invocations","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/webhooks/{webhook_id}/deliveries":{"get":{"tags":["Webhooks"],"summary":"Get delivery history for a specific webhook","description":"Returns delivery history from ingestion tables for a specific webhook. Same query params and pagination as list invocations (period, status, pageSize, pageToken).","operationId":"listWebhookDeliveries","parameters":[{"name":"webhook_id","in":"path","required":true,"description":"Webhook unique identifier (UUID)","schema":{"type":"string","format":"uuid","example":"660e8400-e29b-41d4-a716-446655440000"}},{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"status","in":"query","description":"Filter by delivery status (or 'all')","required":false,"schema":{"type":"string","enum":["all","delivered","failed","in_progress","scheduled","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of deliveries per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved deliveries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListDeliveriesResponse"}}}},"400":{"description":"Invalid webhook ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/splunk/statistics":{"get":{"tags":["Splunk"],"summary":"Get Splunk delivery statistics","description":"Returns aggregate statistics for all Splunk configs including total counts, active/inactive configs, and delivery success/failure metrics. Mirrors webhook statistics API.","operationId":"getSplunkStatistics","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","schema":{"type":"string","default":"7d","example":"7d"}}],"responses":{"200":{"description":"Successfully retrieved statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplunkStatisticsResponse"},"example":{"status":200,"data":{"total_splunk_configs":3,"active_splunk_configs":2,"inactive_splunk_configs":1,"total_deliveries":4,"successful_deliveries":2,"failed_deliveries":1,"period_days":7},"message":"success"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing tenant name in Authority header","code":"UNAUTHORIZED"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Failed to get Splunk statistics","code":"INTERNAL_ERROR"}}}}}}},"/gateway/integration/v1/slack":{"get":{"tags":["Slack"],"summary":"List Slack integrations","description":"Every Slack workspace connection for the tenant. Tokens are masked.","operationId":"listSlackIntegrations","responses":{"200":{"description":"Successfully retrieved integrations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSlackIntegrationsResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}},"post":{"tags":["Slack"],"summary":"Create a Slack integration from a bot token","description":"Registers a workspace from a bot token obtained out of band. Admin only. The normal path is the OAuth install (GET /integration/v1/slack/oauth/authorize), which creates the integration from Slack's callback instead.","operationId":"createSlackIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSlackIntegrationRequest"}}}},"responses":{"201":{"description":"Integration created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackIntegration"}}}},"400":{"description":"Invalid payload, or bot_token does not start with \"xoxb-\"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/status":{"get":{"tags":["Slack"],"summary":"Slack service readiness","description":"Whether this cell can run the OAuth install. Read it before offering a \"Connect\" action so an unconfigured cell can explain itself instead of surfacing a control that returns 503.","operationId":"getSlackStatus","responses":{"200":{"description":"Successfully retrieved status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackServiceStatusResponse"},"example":{"oauth_available":true,"oauth_configured":true,"redis_available":true,"crud_available":true,"test_available":true}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/oauth/authorize":{"get":{"tags":["Slack"],"summary":"Mint the Slack consent URL","description":"Returns the Slack authorize URL to open in a browser, carrying a signed state stored in Redis for 10 minutes. Slack then calls /integration/v1/slack/oauth/callback, which finishes the install, so the caller learns the result by re-reading GET /integration/v1/slack rather than from this response.","operationId":"slackOAuthAuthorize","responses":{"200":{"description":"Authorize URL generated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackOAuthAuthorizeResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Failed to generate or store the OAuth state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"503":{"description":"Slack OAuth is not configured, or Redis is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"oauth_not_configured","message":"Slack OAuth is not configured"}}}}}}}},"/gateway/integration/v1/slack/test":{"post":{"tags":["Slack"],"summary":"Post a test message","description":"Admin only. The bot token is resolved server-side. Without integration_id the tenant's FIRST integration is used, which is the wrong workspace on any tenant with more than one, so prefer POST /integration/v1/slack/{slack_id}/test.","operationId":"testSlackIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSlackRequest"}}}},"responses":{"200":{"description":"Test attempted. Check `success` for the outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSlackResponse"}}}},"400":{"description":"channel_id missing, invalid integration_id, or the integration has no token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"No Slack integration for this tenant, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/{slack_id}":{"parameters":[{"name":"slack_id","in":"path","required":true,"description":"Slack integration unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Slack"],"summary":"Get a Slack integration","operationId":"getSlackIntegration","responses":{"200":{"description":"Successfully retrieved integration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackIntegrationDetailResponse"}}}},"400":{"description":"Invalid Slack integration ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}},"put":{"tags":["Slack"],"summary":"Update a Slack integration","description":"Admin only. Partial update of name, description and newly_created. The workspace, tokens and channel_id are set by the install and are not writable here.","operationId":"updateSlackIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSlackIntegrationRequest"}}}},"responses":{"200":{"description":"Integration updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackIntegration"}}}},"400":{"description":"Invalid payload or ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}},"delete":{"tags":["Slack"],"summary":"Delete a Slack integration","description":"Admin only. Soft-deletes the integration; delivery history is kept.","operationId":"deleteSlackIntegration","responses":{"204":{"description":"Integration deleted"},"400":{"description":"Invalid Slack integration ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/{slack_id}/test":{"post":{"tags":["Slack"],"summary":"Post a test message with this integration","description":"Admin only. Resolves the bot token from this integration. With no channel_id in the body, the integration's own channel_id is used.","operationId":"testSlackIntegrationById","parameters":[{"name":"slack_id","in":"path","required":true,"description":"Slack integration unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSlackByIdRequest"}}}},"responses":{"200":{"description":"Test attempted. Check `success` for the outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestSlackResponse"},"example":{"success":true,"status_code":200,"latency_ms":246}}}},"400":{"description":"Invalid ID format, the integration has no token, or no channel_id was given and the integration has no default channel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/{slack_id}/channels":{"get":{"tags":["Slack"],"summary":"List the workspace's channels","description":"Conversations the integration's bot can see, fetched live from Slack (conversations.list).","operationId":"listSlackChannels","parameters":[{"name":"slack_id","in":"path","required":true,"description":"Slack integration unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Successfully retrieved channels","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSlackChannelsResponse"}}}},"400":{"description":"Invalid ID format, or the integration has no token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"502":{"description":"Slack rejected the channel listing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"slack_api_error","message":"Failed to fetch channels: invalid_auth"}}}}}}}},"/gateway/integration/v1/slack/{slack_id}/channel-mappings":{"parameters":[{"name":"slack_id","in":"path","required":true,"description":"Slack integration unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"get":{"tags":["Slack"],"summary":"List channel mappings","description":"Channels this integration may deliver to, default first.","operationId":"listSlackChannelMappings","responses":{"200":{"description":"Successfully retrieved mappings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSlackChannelMappingsResponse"}}}},"400":{"description":"Invalid Slack integration ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}},"post":{"tags":["Slack"],"summary":"Add a channel mapping","description":"Admin only. A live mapping is unique per (integration, channel): adding one for a channel that already has a live mapping fails with 500. Delete the existing mapping first. There is no update verb, so making an existing mapping the default means deleting and re-adding it.","operationId":"saveSlackChannelMapping","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSlackChannelMappingRequest"}}}},"responses":{"201":{"description":"Mapping created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackChannelMapping"}}}},"400":{"description":"channel_id missing, or invalid ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Integration not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Persistence failed, including the unique-constraint conflict when the channel already has a live mapping","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"database_error","message":"Failed to save channel mapping"}}}}}}}},"/gateway/integration/v1/slack/{slack_id}/channel-mappings/{mapping_id}":{"delete":{"tags":["Slack"],"summary":"Remove a channel mapping","description":"Admin only. Soft-deletes the mapping, freeing the channel to be mapped again.","operationId":"deleteSlackChannelMapping","parameters":[{"name":"slack_id","in":"path","required":true,"description":"Slack integration unique identifier (UUID)","schema":{"type":"string","format":"uuid"}},{"name":"mapping_id","in":"path","required":true,"description":"Channel mapping unique identifier (UUID)","schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Mapping removed"},"400":{"description":"Invalid ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"403":{"description":"Caller is not an admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Mapping not found, or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/statistics":{"get":{"tags":["Slack"],"summary":"Get Slack delivery statistics","description":"Returns aggregate statistics for all Slack integrations including total counts, active/inactive configs, and delivery success/failure metrics. Mirrors Splunk/webhook statistics API.","operationId":"getSlackStatistics","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","schema":{"type":"string","default":"7d","example":"7d"}}],"responses":{"200":{"description":"Successfully retrieved statistics","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackStatisticsResponse"},"example":{"status":200,"data":{"total_slack_configs":2,"active_slack_configs":1,"inactive_slack_configs":1,"total_deliveries":10,"successful_deliveries":8,"failed_deliveries":1,"period_days":7},"message":"success"}}}},"400":{"description":"Invalid `period` format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"invalid_period","message":"Invalid period format: 7x"}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"internal_error","message":"Failed to get Slack statistics"}}}}}}}},"/gateway/integration/v1/slack/invocations/filter-options":{"get":{"tags":["Slack"],"summary":"Get filter options for Slack invocations list","description":"Returns Slack integration names and status values to populate the name and status filters for GET.../invocations (e.g. dropdowns or multi-select). Accepts the same period (time filter) as the invocations list; default 7d.","operationId":"listSlackInvocationFilterOptions","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d); same as invocations list, default 7d","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"}],"responses":{"200":{"description":"Filter options for the tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackInvocationFilterOptionsResponse"}}}},"400":{"description":"Invalid `period` format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"invalid_period","message":"Invalid period format: 7x"}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/invocations":{"get":{"tags":["Slack"],"summary":"Get Slack invocation history (all integrations)","description":"Returns invocation/delivery history for all Slack integrations. Supports filtering by period, name, and status. Mirrors Splunk invocations API.","operationId":"listAllSlackInvocations","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"name","in":"query","description":"Filter by Slack integration name (or 'all')","required":false,"schema":{"type":"string","default":"all"},"example":"all"},{"name":"status","in":"query","description":"Filter by status (or 'all')","required":false,"schema":{"type":"string","enum":["all","scheduled","in_progress","delivered","failed","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of invocations per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved invocations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSlackInvocationsResponse"}}}},"400":{"description":"Invalid `period` format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"},"example":{"error":{"code":"invalid_period","message":"Invalid period format: 7x"}}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/slack/{slack_id}/invocations":{"get":{"tags":["Slack"],"summary":"Get Slack invocation history for an integration","description":"Returns invocation/delivery history for a specific Slack integration. Supports filtering by period and status.","operationId":"listSlackConfigInvocations","parameters":[{"name":"slack_id","in":"path","required":true,"description":"Slack integration unique identifier (UUID)","schema":{"type":"string","format":"uuid"}},{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"status","in":"query","description":"Filter by status (or 'all')","required":false,"schema":{"type":"string","enum":["all","scheduled","in_progress","delivered","failed","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of invocations per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved invocations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSlackInvocationsResponse"}}}},"400":{"description":"Invalid Slack integration ID format, or invalid `period` format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"404":{"description":"Slack integration not found or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SlackErrorResponse"}}}}}}},"/gateway/integration/v1/splunk/invocations/filter-options":{"get":{"tags":["Splunk"],"summary":"Get filter options for Splunk invocations list","description":"Returns Splunk config names and status values to populate the name and status filters for GET.../invocations (e.g. dropdowns or multi-select). Accepts the same period (time filter) as the invocations list; default 7d.","operationId":"listSplunkInvocationFilterOptions","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d); same as invocations list, default 7d","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"}],"responses":{"200":{"description":"Filter options for the tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplunkInvocationFilterOptionsResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/splunk/invocations":{"get":{"tags":["Splunk"],"summary":"Get Splunk invocation history (all configs)","description":"Returns invocation/delivery history for all Splunk configs. Supports filtering by period, name, and status. Mirrors webhook invocations API.","operationId":"listAllSplunkInvocations","parameters":[{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"name","in":"query","description":"Filter by Splunk config name (or 'all')","required":false,"schema":{"type":"string","default":"all"},"example":"all"},{"name":"status","in":"query","description":"Filter by status (or 'all')","required":false,"schema":{"type":"string","enum":["all","scheduled","in_progress","delivered","failed","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of invocations per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved invocations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSplunkInvocationsResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"New alerts feature not enabled for tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/splunk/{splunk_id}/invocations":{"get":{"tags":["Splunk"],"summary":"Get Splunk invocation history for a config","description":"Returns invocation/delivery history for a specific Splunk config. Supports filtering by period and status.","operationId":"listSplunkConfigInvocations","parameters":[{"name":"splunk_id","in":"path","required":true,"description":"Splunk config unique identifier (UUID)","schema":{"type":"string","format":"uuid"}},{"name":"period","in":"query","description":"Time period filter (e.g., 7d, 24h, 30d)","required":false,"schema":{"type":"string","default":"7d"},"example":"7d"},{"name":"status","in":"query","description":"Filter by status (or 'all')","required":false,"schema":{"type":"string","enum":["all","scheduled","in_progress","delivered","failed","retryable"],"default":"all"},"example":"all"},{"name":"pageSize","in":"query","description":"Number of invocations per page (1-100)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"example":50},{"name":"pageToken","in":"query","description":"Cursor token for pagination","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successfully retrieved invocations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSplunkInvocationsResponse"}}}},"400":{"description":"Invalid Splunk config ID format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid tenant authentication","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Splunk config not found or feature not enabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/virustotal":{"get":{"tags":["VirusTotal"],"summary":"Get VirusTotal integration","description":"Returns the VirusTotal integration for the authenticated tenant and user (from Authority and X-User-Id). At most one integration per tenant/user. api_key is never returned.","operationId":"getVirusTotalIntegration","responses":{"200":{"description":"Integration found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirusTotalResponse"}}}},"401":{"description":"Unauthorized (missing or invalid Authority / X-User-Id)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No integration found for this tenant/user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable (e.g. users DB not configured)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["VirusTotal"],"summary":"Create VirusTotal integration","description":"Creates a VirusTotal integration for the authenticated tenant and user. Only one integration per tenant/user; use PUT to update.","operationId":"createVirusTotalIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVirusTotalRequest"}}}},"responses":{"201":{"description":"Integration created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VirusTotalResponse"}}}},"400":{"description":"Invalid request (e.g. api_key missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Integration already exists for this tenant/user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["VirusTotal"],"summary":"Update VirusTotal integration","description":"Updates the VirusTotal API key for the authenticated tenant and user.","operationId":"updateVirusTotalIntegration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVirusTotalRequest"}}}},"responses":{"204":{"description":"Integration updated (no body)"},"400":{"description":"Invalid request (e.g. api_key missing)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["VirusTotal"],"summary":"Delete VirusTotal integration","description":"Deletes the VirusTotal integration for the authenticated tenant and user.","operationId":"deleteVirusTotalIntegration","responses":{"204":{"description":"Integration deleted (no body)"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/integration/v1/virustotal/files/{fileHash}":{"get":{"tags":["VirusTotal"],"summary":"Get VirusTotal file report by hash","description":"Fetches the VirusTotal file report for the given file hash (MD5, SHA-1, or SHA-256) using the tenant/user's stored API key. Requires a VirusTotal integration to exist.","operationId":"getVirusTotalFileReport","parameters":[{"name":"fileHash","in":"path","required":true,"description":"File hash - MD5 (32 hex), SHA-1 (40 hex), or SHA-256 (64 hex), lowercase","schema":{"type":"string","pattern":"^[a-f0-9]{32}$|^[a-f0-9]{40}$|^[a-f0-9]{64}$","example":"131f95c51cc819465fa1797f6ccacf9d494aaaff46fa3eac73ae63ffbdfd8267"}}],"responses":{"200":{"description":"VirusTotal file report (raw JSON from VirusTotal API)","content":{"application/json":{"schema":{"type":"object","description":"VirusTotal API v3 file report object"}}}},"400":{"description":"Invalid hash format","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Integration not found or file report not found on VirusTotal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"VirusTotal rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Service unavailable (client not configured or VirusTotal error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Request timeout to VirusTotal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/gateway/scans/v1/threat-hunt":{"post":{"tags":["Scans"],"summary":"Start a hunt across recovery points","description":"Starts a hunt that looks back in time across the recovery points of AWS resources (EC2 instances, EBS volumes) for ransomware, malware, and corrupted files. The hunt runs asynchronously.","operationId":"startThreatHunt","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatHuntRequest"},"examples":{"ec2_backup":{"summary":"Scan EC2 AWS Backup recovery points","value":{"tenant_name":"acme-corp","cloud_connector":{"aws_account_id":"123456789012","aws_region":"us-east-1"},"asset_kind":{"ec2_backup":{"instance_id":"i-1234567890abcdef0"}},"scan_type":"full"}},"ebs_with_options":{"summary":"Scan EBS snapshots with options","value":{"tenant_name":"acme-corp","cloud_connector":{"aws_account_id":"123456789012","aws_region":"us-east-1"},"asset_kind":{"ebs":{"volume_id":"vol-1234567890abcdef0"}},"scan_type":"malware","oldest_timestamp":"2024-01-01T00:00:00Z","max_parallel_scan_jobs":5}}}}}},"responses":{"200":{"description":"Hunt job submitted successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatHuntResponse"},"example":{"success":true,"message":"Threat-hunt job submitted successfully","job_id":"01234567-89ab-cdef-0123-456789abcdef","aws_backup_vault":"Default","timestamp":"2024-01-15T10:30:00Z"}}}},"400":{"description":"Invalid request (validation errors)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatHuntResponse"},"examples":{"missing_tenant":{"summary":"Missing tenant_name","value":{"success":false,"message":"tenant_name is required","timestamp":"2024-01-15T10:30:00Z"}},"invalid_asset_kind":{"summary":"Invalid asset kind","value":{"success":false,"message":"asset_kind is required (must specify one of: ec2_backup, ec2_drs, ebs, ebs_backup)","timestamp":"2024-01-15T10:30:00Z"}},"invalid_instance_id":{"summary":"Invalid EC2 instance ID","value":{"success":false,"message":"invalid EC2 instance ID format (expected: i-[a-f0-9]{8,17})","timestamp":"2024-01-15T10:30:00Z"}}}}}},"405":{"description":"Method not allowed (use POST)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatHuntResponse"},"example":{"success":false,"message":"Method not allowed. Use POST.","timestamp":"2024-01-15T10:30:00Z"}}}},"500":{"description":"Internal server error (job submission failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatHuntResponse"},"example":{"success":false,"message":"Failed to submit threat-hunt job","error":"connection refused","timestamp":"2024-01-15T10:30:00Z"}}}}}}},"/gateway/ingestion/v1/posture/overview":{"get":{"tags":["Posture"],"summary":"Get the cloud configuration overview","description":"Returns high-level posture metrics including overall compliance score, per-service breakdown, violation severity counts, score trend, and latest sync status. Data is collected by scanning AWS resources directly (S3, EBS, RDS, IAM, GuardDuty, CloudTrail, Backup vaults).","operationId":"getPostureOverview","responses":{"200":{"description":"Posture overview retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureOverview"},"example":{"total_resources":47,"compliant":31,"non_compliant":16,"score":65.96,"trend":[{"score":55,"captured_at":"2026-04-20T06:00:00Z"},{"score":65.96,"captured_at":"2026-04-25T06:00:00Z"}],"by_service":{"s3_bucket":{"total":8,"compliant":3,"non_compliant":5},"ebs_volume":{"total":15,"compliant":12,"non_compliant":3}},"by_severity":{"critical":4,"high":8,"medium":3},"last_sync":{"id":"a1b2c3d4-0000-0000-0000-000000000001","status":"completed","trigger_type":"scheduled","accounts_scanned":3,"regions_scanned":5,"resources_found":47,"findings_found":16}}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/resources":{"get":{"tags":["Posture"],"summary":"List cloud configuration resources","description":"Returns cloud resources with their posture assessment status. Supports filtering by resource type, status, AWS account, and region. Resources are UPSERTED on each sync: the latest assessment is always returned.","operationId":"listPostureResources","parameters":[{"name":"type","in":"query","schema":{"type":"string","enum":["aurora_cluster","aws_config_recorder","backup_job","backup_plan","backup_vault","cloudtrail_trail","cloudwatch_alarm","cloudwatch_log_group","dynamodb_table","ebs_snapshot","ebs_volume","ec2_instance","ecr_repository","ecs_task_definition","efs_filesystem","guardduty_detector","iam_user","kms_key","lambda_function","rds_instance","rds_snapshot","s3_bucket","secret","security_group","security_hub_account","sns_topic","sqs_queue","ssm_session_manager","vpc_flow_logs"]},"description":"Filter by resource type. `security_service` is no longer used; filter by `guardduty_detector` or `cloudtrail_trail` instead."},{"name":"status","in":"query","schema":{"type":"string","enum":["compliant","non_compliant","error","unknown"]},"description":"Filter by posture status"},{"name":"account_id","in":"query","schema":{"type":"string"},"description":"Filter by AWS account ID"},{"name":"region","in":"query","schema":{"type":"string"},"description":"Filter by AWS region"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":1000},"description":"Maximum number of resources to return. Non-positive values fall back to the default of 50; values above 1000 are clamped to 1000 and the response echoes the effective limit."},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0},"description":"Number of resources to skip for pagination"},{"name":"resource_id","in":"query","schema":{"type":"string"},"description":"Filter to a specific cloud-native resource ID (exact match)"}],"responses":{"200":{"description":"Resources retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureResourceListResponse"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/findings":{"get":{"tags":["Posture"],"summary":"List cloud configuration findings (violations)","description":"Returns posture violations: instances where a cloud resource fails a compliance rule. Each finding includes the rule details, severity, category, and the affected resource. Results are sorted by severity (critical first). Defaults to open violations only.","operationId":"listPostureFindings","parameters":[{"name":"severity","in":"query","style":"form","explode":true,"schema":{"type":"array","items":{"type":"string","enum":["critical","high","medium","low","info"]}},"description":"Filter by rule severity. Repeat the parameter to combine values, e.g. `?severity=critical&severity=high` returns findings whose severity is in the supplied set."},{"name":"category","in":"query","style":"form","explode":true,"schema":{"type":"array","items":{"type":"string"}},"description":"Filter by category. Repeat the parameter to combine values, e.g. `?category=Immutability&category=Cryptographic`. Known categories: Immutability, Cryptographic, RPO/RTO, Identity, Platform & Integrity, Access Control."},{"name":"status","in":"query","schema":{"type":"string","enum":["open","resolved","suppressed"],"default":"open"},"description":"Filter by violation status (defaults to open)"},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":1000},"description":"Maximum number of findings to return. Values above 1000 are clamped to 1000 and the response echoes the effective limit."},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0}},{"name":"resource_id","in":"query","schema":{"type":"string"},"description":"Filter findings to a specific cloud-native resource ID (e.g. vol-xxx, my-bucket)"}],"responses":{"200":{"description":"Findings retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureViolationListResponse"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/compliance":{"get":{"tags":["Posture"],"summary":"Get compliance framework scores","description":"Returns per-framework compliance assessment across ISO 27001, NIST CSF, SOC2, NYDFS, and DORA. Each framework includes a score, status (Healthy/At Risk/Failing), and per-control pass/fail breakdown with the names of failing assets.","operationId":"getPostureCompliance","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100},"description":"Max number of frameworks to return."},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0},"description":"Frameworks to skip (for pagination)."}],"responses":{"200":{"description":"Compliance scores retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComplianceResponse"},"example":{"frameworks":[{"framework":"ISO27001","score":50,"status":"At Risk","controls":[{"control_id":"A.10.1.1","control_title":"Cryptographic Controls","status":"Failed","assets":["production-data-bucket"]},{"control_id":"A.12.4.1","control_title":"Forensic Logging","status":"Passed","assets":[]}]}]}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/lineage":{"get":{"tags":["Posture"],"summary":"Get asset relationship graph","description":"Returns a graph of cloud configuration resources with their finding counts, organized by AWS account. Use it to render an asset lineage view. Resources are matched to Elastio assets by account, region, and resource ID.","operationId":"getPostureLineage","parameters":[{"name":"affected","in":"query","schema":{"type":"boolean"},"description":"When `true`, return only resources with at least one open violation (drives the FE lineage sidebar's \"Affected Only\" toggle). Default: no filter, all resources are returned."},{"name":"limit","in":"query","schema":{"type":"integer","default":100,"maximum":1000},"description":"Max number of nodes to return. Values above 1000 are clamped to 1000 and the response echoes the effective limit."},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0},"description":"Nodes to skip (for pagination)."}],"responses":{"200":{"description":"Lineage data retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LineageResponse"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/lineage/count":{"get":{"tags":["Posture"],"summary":"Count lineage resources (total and affected)","description":"Returns the total resource count for the tenant and the affected subset (resources with at least one open violation) in a single round-trip. Drives the lineage sidebar's \"X of Y affected\" counter. Both values come from one SQL row so they cannot drift across sync boundaries the way two separate count calls could.","operationId":"getPostureLineageCount","responses":{"200":{"description":"Counts retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureResourceCounts"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/sync":{"post":{"tags":["Posture"],"summary":"Run configuration checks now","description":"Starts an asynchronous configuration check for the tenant. Elastio assumes a role into each of the tenant's AWS accounts through the Cloud Connectors and runs every configuration check. Returns immediately with a sync_id for polling. Returns 409 if a check is already in progress.","operationId":"triggerPostureSync","responses":{"202":{"description":"Sync started successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureSyncTriggerResponse"},"example":{"message":"posture sync started","sync_id":"a1b2c3d4-0000-0000-0000-000000000002","status":"pending"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"409":{"description":"Sync already in progress for this tenant (status is either 'pending' or 'in_progress'). The response includes the sync_id of the currently-active row so the caller can poll /posture/sync/status instead of retrying.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureSyncTriggerResponse"},"example":{"message":"sync already in progress","sync_id":"a1b2c3d4-0000-0000-0000-000000000001","status":"in_progress"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/sync/status":{"get":{"tags":["Posture"],"summary":"Get configuration check status","description":"Returns the status of the most recent posture sync for the tenant, including progress metrics (accounts/regions scanned, resources and findings found).","operationId":"getPostureSyncStatus","responses":{"200":{"description":"Sync status retrieved. When no sync has run yet, the response has a different shape with `status: \"none\"` and a `message` field.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/PostureSyncStatus"},{"type":"object","properties":{"message":{"type":"string"},"status":{"type":"string","enum":["none"]}},"required":["message","status"]}]},"examples":{"completed":{"summary":"Completed sync","value":{"id":"a1b2c3d4-0000-0000-0000-000000000001","status":"completed","trigger_type":"scheduled","started_at":"2026-04-25T06:00:00Z","completed_at":"2026-04-25T06:03:45Z","accounts_scanned":3,"regions_scanned":5,"resources_found":47,"findings_found":16}},"none":{"summary":"No sync has run yet","value":{"message":"no posture sync found","status":"none"}}}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/connection-status":{"get":{"tags":["Posture"],"summary":"Validate stored AWS credentials for configuration checks","description":"Calls `sts:GetCallerIdentity` with the tenant's stored AWS credentials and returns the resolved account/ARN on success. Returns `connected: false` with a friendly message when no credentials are configured (HTTP 200, not 404) so the FE can render a single \"Not connected yet\" tile in Settings → Posture.","operationId":"getPostureConnectionStatus","responses":{"200":{"description":"Connection status retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureConnectionStatusResponse"},"examples":{"connected":{"summary":"Credentials valid","value":{"connected":true,"account_id":"123456789012","user_arn":"arn:aws:iam::123456789012:user/posture-svc","default_region":"us-east-1","access_key_id":"AKIAIOSFODNN7EXAMPLE"}},"disconnected":{"summary":"No credentials configured","value":{"connected":false,"error":"no posture credentials configured"}}}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error (e.g., decrypt failure)","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gateway/ingestion/v1/posture/syncs":{"get":{"tags":["Posture"],"summary":"List configuration check history","description":"Returns a paginated list of recent posture sync records for the tenant, most recent first. Useful for an audit/timeline view.","operationId":"listPostureSyncs","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","default":20,"maximum":100}},{"name":"offset","in":"query","schema":{"type":"integer","default":0,"minimum":0}}],"responses":{"200":{"description":"Sync history retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureSyncListResponse"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"},"example":"missing Authority header\n"}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"},"example":"internal server error\n"}}}}}},"/gateway/ingestion/v1/posture/credentials/role":{"post":{"tags":["Posture"],"summary":"Connect a tenant's AWS account by assuming a role (preferred)","description":"Stores (or replaces) role-based posture credentials for the tenant. Preferred over POST /ingestion/v1/posture/credentials, which stores long-lived secrets at rest.\n\nThe role is assumed and sts:GetCallerIdentity is called before anything is persisted, so a missing or wrong trust policy is reported here rather than discovered as an empty posture report later. Writing a role row clears any static keys previously stored for the same (tenant, account) pair: a row is exactly one of the two modes.","operationId":"upsertPostureRoleCredentials","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureAWSRoleCredentialsRequest"}}}},"responses":{"200":{"description":"Role credentials saved and verified","content":{"application/json":{"schema":{"type":"object","required":["message","auth_mode","role_arn","default_region","has_external_id"],"properties":{"message":{"type":"string"},"auth_mode":{"type":"string","enum":["role"]},"role_arn":{"type":"string"},"aws_account_id":{"type":"string"},"default_region":{"type":"string"},"has_external_id":{"type":"boolean"}}},"example":{"message":"posture role credentials saved","auth_mode":"role","role_arn":"arn:aws:iam::123456789012:role/ElastioPosture","aws_account_id":"123456789012","default_region":"us-east-1","has_external_id":true}}}},"400":{"description":"Missing Authority header, invalid body, malformed role_arn, missing default_region, the role could not be assumed, or the supplied aws_account_id disagrees with the assumed session.","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error (encryption or storage failure)","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gateway/ingestion/v1/posture/credentials":{"post":{"tags":["Posture"],"summary":"Save AWS credentials for configuration checks","description":"Stores (or replaces) the AWS access key, optional session token and default region for the tenant. Secret material is encrypted at rest with AWS KMS; only the non-secret metadata can be read back via GET.","operationId":"upsertPostureCredentials","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureAWSCredentialsRequest"}}}},"responses":{"200":{"description":"Credentials saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureAWSCredentialsUpsertResponse"},"example":{"message":"posture aws credentials saved","access_key_id":"AKIAIOSFODNN7EXAMPLE","default_region":"us-east-1","has_session_token":false}}}},"400":{"description":"Missing Authority header or invalid request body","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error (encryption or storage failure)","content":{"text/plain":{"schema":{"type":"string"}}}}}},"get":{"tags":["Posture"],"summary":"Get stored AWS credential metadata","description":"Returns the access key ID, default region, and a flag indicating whether a session token is on file. Secret material is never returned.","operationId":"getPostureCredentials","responses":{"200":{"description":"Credential metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostureAWSCredentialsResponse"}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"No posture credentials configured for this tenant","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"tags":["Posture"],"summary":"Delete stored AWS credentials","description":"Clears the stored AWS posture credentials for the tenant.","operationId":"deletePostureCredentials","responses":{"200":{"description":"Credentials deleted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"No posture credentials configured for this tenant","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gateway/ingestion/v1/posture/rules":{"get":{"tags":["Posture"],"summary":"List enabled configuration rules","description":"Returns all enabled posture rules. Optionally filtered by resource_type. Used by the FE to populate the rule_code dropdown when creating a suppression and to render rule descriptions in the findings detail panel.","operationId":"listPostureRules","parameters":[{"name":"resource_type","in":"query","schema":{"type":"string"},"description":"Filter rules to a specific resource type (e.g. s3_bucket, ebs_volume)"}],"responses":{"200":{"description":"Rules retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/PostureRule"}},"total":{"type":"integer"}}}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string","example":"missing Authority header\n"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gateway/ingestion/v1/posture/violation-suppressions":{"post":{"tags":["Posture"],"summary":"Create a violation suppression","description":"Creates a suppression rule that prevents matching violations from being emitted during future scans. At least one scope field must be provided. The reason field is required for audit trail purposes. Requires RBAC (Authority header).","operationId":"createPostureSuppression","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionRequest"}}}},"responses":{"201":{"description":"Suppression created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionResponse"}}}},"400":{"description":"Missing Authority header, invalid body, or no scope field set","content":{"text/plain":{"schema":{"type":"string"}}}},"409":{"description":"Rule has been deprecated; suppressions disallowed","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"rule_deprecated"},"rule_code":{"type":"string"},"message":{"type":"string"}}}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}},"get":{"tags":["Posture"],"summary":"List active violation suppressions","description":"Returns all active (non-expired) suppressions for the tenant.","operationId":"listPostureSuppressions","responses":{"200":{"description":"Suppressions retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"suppressions":{"type":"array","items":{"$ref":"#/components/schemas/SuppressionResponse"}}}}}}},"400":{"description":"Missing Authority header","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gateway/ingestion/v1/posture/violation-suppressions/{id}":{"get":{"tags":["Posture"],"summary":"Get a single violation suppression","description":"Fetches a suppression by its UUID. Returns 404 if not found or owned by a different tenant.","operationId":"getPostureSuppression","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Suppression UUID"}],"responses":{"200":{"description":"Suppression retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionResponse"}}}},"400":{"description":"Missing Authority header or id","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Suppression not found","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}},"delete":{"tags":["Posture"],"summary":"Delete a violation suppression","description":"Removes a suppression. Violations that were suppressed by this rule will be re-emitted on the next sync. Requires RBAC.","operationId":"deletePostureSuppression","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Suppression UUID"}],"responses":{"204":{"description":"Suppression deleted"},"400":{"description":"Missing Authority header or id","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"Suppression not found","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Internal server error","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/gateway/shared-services/v1/assets/{asset_id}/evidence":{"get":{"description":"200 with `degraded` populated rather than 5xx when a single upstream section fails, so one flaky read never costs the reader the whole document. 404 means the tenant has no such live asset, distinct from \"the asset has no evidence\".\n","operationId":"getAssetEvidence","parameters":[{"in":"path","name":"asset_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetEvidence"}}},"description":"Asset evidence envelope"},"400":{"$ref":"#/components/responses/EvidenceBadRequestError"},"404":{"$ref":"#/components/responses/EvidenceNotFoundError"},"500":{"$ref":"#/components/responses/EvidenceInternalError"}},"summary":"Get the aggregated evidence envelope for one asset","tags":["Evidence"]}},"/gateway/shared-services/v1/deployments/asset-accounts":{"get":{"operationId":"listAssetAccounts","parameters":[{"description":"Optional AWS account id filters (12-digit strings)","explode":true,"in":"query","name":"account_id","schema":{"items":{"type":"string"},"type":"array"},"style":"form"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAssetAccountsResponse"}}},"description":"Asset accounts list"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"List deployment asset accounts","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/asset-accounts/{asset_account_id}/region-stacks/{region}":{"delete":{"description":"Schedules deletion of the **asset region stack** for the given asset account and AWS region.\nThe stack must not be in `install_pending` or `deletion_pending` state; otherwise the server\nresponds with a precondition error.\n","operationId":"deleteAssetRegionStack","parameters":[{"description":"12-digit AWS account ID of the asset account","in":"path","name":"asset_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}},{"description":"AWS region where the asset region stack exists (e.g. us-east-1)","in":"path","name":"region","required":true,"schema":{"pattern":"^[a-z]{2}(-gov)?-[a-z]+-\\d$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAssetRegionStackResponse"}}},"description":"Deletion job scheduled; returns connector job identifiers"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"412":{"$ref":"#/components/responses/DeploymentsPreconditionFailedError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Delete an asset region stack","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/asset-accounts/{asset_account_id}/unlink":{"post":{"description":"Removes the **asset account** link for the given 12-digit AWS account id. Regional stacks must be\ndestroyed first; otherwise the server responds with a precondition error.\n","operationId":"unlinkAssetAccount","parameters":[{"description":"12-digit AWS account ID of the asset account to unlink","in":"path","name":"asset_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}}],"responses":{"204":{"description":"Unlink accepted; no response body"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"412":{"$ref":"#/components/responses/DeploymentsPreconditionFailedError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Unlink an asset account","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/asset-accounts/link":{"post":{"description":"Registers the given AWS account as an **asset account** linked to the specified **connector account**,\nand schedules regional deployment jobs as returned in `linking_jobs`.\n","operationId":"linkAssetAccount","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkAssetAccountRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkAssetAccountResponse"}}},"description":"Linking jobs started"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict (e.g. asset account id is an existing connector account)"},"412":{"$ref":"#/components/responses/DeploymentsPreconditionFailedError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Link an asset account to a connector account","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/aws-accounts/{aws_account_id}":{"patch":{"description":"Updates the friendly **alias** and **description** shown for a linked AWS account in your tenant.\n","operationId":"patchAwsAccount","parameters":[{"description":"12-digit AWS account ID","in":"path","name":"aws_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchAwsAccountBody"}}},"required":true},"responses":{"204":{"description":"Update accepted; no response body"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Update AWS account display metadata","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/aws-accounts/{aws_account_id}/connector-account-install-flow":{"get":{"description":"Returns the **connector account install flow** for the given 12-digit AWS account id\n(autoinstall regions, VPC template permissions flag, and current state).\n","operationId":"getConnectorAccountInstallFlow","parameters":[{"description":"12-digit AWS account ID (connector account)","in":"path","name":"aws_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetConnectorAccountInstallFlowResponse"}}},"description":"Install flow for the account (flow may be null if none exists)"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Get connector account install flow","tags":["Deployments"]},"patch":{"description":"Updates install-flow settings for the connector AWS account: optionally enable VPC permissions on\ngenerated CloudFormation templates, and/or append AWS regions for autoinstall. If no flow exists yet,\nthe server creates one. Send at least `enable_vpc_permissions: true` or a non-empty\n`add_aws_regions_to_autoinstall` array.\n","operationId":"patchConnectorAccountInstallFlow","parameters":[{"description":"12-digit AWS account ID (connector account)","in":"path","name":"aws_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchConnectorAccountInstallFlowBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetConnectorAccountInstallFlowResponse"}}},"description":"Updated install flow"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Update connector account install flow","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/aws-accounts/{aws_account_id}/upgrade":{"post":{"description":"Schedules the upgrade of the given regions to `target_version`: Elastio applies\nTerraform in the customer's account through the role the account template grants,\nthen upgrades the Elastio vaults in those regions. The request is the tenant's\napproval, so `target_version` must be the plan's current target; a plan that moved\non answers `409` and must be reviewed again.\n\nElastio records the approval in the audit log (`connector.upgrade.approved`) before it\nschedules anything, and answers `503` without scheduling when it cannot. One job is\nreturned per region.\n","operationId":"upgradeAwsRegionStacks","parameters":[{"description":"12-digit AWS account ID (connector account)","in":"path","name":"aws_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeAwsRegionStacksRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpgradeAwsRegionStacksResponse"}}},"description":"Upgrade jobs scheduled, one per region"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"409":{"$ref":"#/components/responses/DeploymentsUpgradeNotAllowedError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"},"501":{"$ref":"#/components/responses/DeploymentsNotImplementedError"},"503":{"$ref":"#/components/responses/DeploymentsServiceUnavailableError"}},"summary":"Upgrade an Elastio-managed Cloud Connector","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/aws-accounts/{aws_account_id}/upgrade-plan":{"get":{"description":"Returns, for every region stack of the account, the version it would be upgraded\nto, the migration steps on the way, and why a region cannot be upgraded.\nNothing is scheduled.\n\nThe target is the newest version enabled for the tenant (within its pin) that the\naccount-level CloudFormation template allows. `latest_version` above\n`target_version` means the template must be updated before the account can reach it.\n\nReturns `501` when an upgrade plan is not available.\n","operationId":"getAwsAccountUpgradePlan","parameters":[{"description":"12-digit AWS account ID (connector account)","in":"path","name":"aws_account_id","required":true,"schema":{"pattern":"^\\d{12}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AwsAccountUpgradePlanResponse"}}},"description":"The upgrade plan"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"},"501":{"$ref":"#/components/responses/DeploymentsNotImplementedError"},"503":{"$ref":"#/components/responses/DeploymentsServiceUnavailableError"}},"summary":"Plan an upgrade of an Elastio-managed Cloud Connector","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/aws-vpcs":{"get":{"operationId":"listAwsVpcs","parameters":[{"in":"query","name":"account_id","required":true,"schema":{"type":"string"}},{"in":"query","name":"region_name","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListAwsVpcsResponse"}}},"description":"AWS VPCs list"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"List AWS VPCs for an account and region","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/cloudformation-link":{"get":{"description":"Optional query parameter `account_id` is the 12-digit **Cloud Connector** AWS account ID.\nWhen provided, the template link is tailored to that account. When omitted, a generic\naccount-agnostic template link is returned.\n","operationId":"getCloudFormationLink","parameters":[{"description":"Optional 12-digit Cloud Connector AWS account ID","in":"query","name":"account_id","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCloudFormationLinkResponse"}}},"description":"Template URL"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Get link to CloudFormation template (S3)","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/discover-installed-cfn":{"post":{"description":"Checks whether the Elastio CloudFormation stack is installed for the given AWS account and returns its status.\nThis call can update stored deployment state for your tenant.\n","operationId":"discoverInstalledCfn","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverInstalledCfnRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverInstalledCfnResponse"}}},"description":"Discovery result"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Discover installed CloudFormation stack for an AWS account","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/red-stacks":{"get":{"description":"Returns Cloud Connectors visible to the tenant, with optional pagination.\nOmit `page_size` to use the default page size (50). Results are ordered by the server.\n","operationId":"listRedStacks","parameters":[{"description":"Maximum number of Cloud Connectors to return in this page (1–500). If omitted, defaults to 50.\n","in":"query","name":"page_size","schema":{"maximum":500,"minimum":1,"type":"integer"}},{"description":"Zero-based page index (first page is 0).","in":"query","name":"page_index","schema":{"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRedStacksResponse"}}},"description":"Paginated list of Cloud Connectors"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"List Cloud Connectors","tags":["Deployments"]},"post":{"description":"Starts Cloud Connector installation for an AWS account. You supply the account ID and,\nfor each target AWS region, how the stack should be deployed (region, optional VPC and subnets, safety lock).\nThe response lists **job identifiers** you can use to track installation progress.\n","operationId":"createRedStack","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallRedstackRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallRedstackResponse"}}},"description":"Scheduled job IDs"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Install the Cloud Connector","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/red-stacks/{red_stack_id}":{"delete":{"description":"Permanently removes a **deactivated** Cloud Connector. The instance must already be deactivated.\n","operationId":"deleteRedStack","parameters":[{"description":"Cloud Connector identifier (must be deactivated)","in":"path","name":"red_stack_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRedstackResponse"}}},"description":"Deletion job scheduled"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Delete a deactivated Cloud Connector","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/red-stacks/{red_stack_id}/deactivate":{"post":{"description":"Deactivates an existing Cloud Connector identified by `red_stack_id`. The instance is no longer active after this succeeds.\n","operationId":"deactivateRedStack","parameters":[{"description":"Cloud Connector identifier","in":"path","name":"red_stack_id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Deactivation accepted; no response body"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Deactivate a Cloud Connector","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/red-stacks/{red_stack_id}/rescan":{"post":{"description":"Schedules a refresh of a **self-managed** (customer-deployed) Cloud Connector region stack.\n\nNothing is deployed: Elastio re-reads the stack's version and resources from your account. Use it after you apply a new version yourself (for example with Terraform) so Elastio sees that version.\n\nReturns `400` for an Elastio-managed Cloud Connector, which refreshes through its own upgrade job instead.\n","operationId":"rescanRedStack","parameters":[{"description":"Cloud Connector identifier","in":"path","name":"red_stack_id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescanRedstackResponse"}}},"description":"Re-scan job scheduled"},"400":{"$ref":"#/components/responses/DeploymentsBadRequestError"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"404":{"$ref":"#/components/responses/DeploymentsNotFoundError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Refresh a self-managed Cloud Connector","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/red-stacks/latest-version":{"get":{"description":"Returns the newest enabled, non-deprecated Cloud Connector version. Generated Terraform module sources are pinned to this version so you always deploy the current release. The value is cached server-side for up to 30 minutes.","operationId":"getLatestRedStackVersion","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LatestRedStackVersionResponse"}}},"description":"Latest enabled Cloud Connector version"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"Get the latest enabled Cloud Connector version","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/scan-clusters":{"get":{"description":"Returns the tenant's standalone (decoupled) scan clusters: Azure, IBM and on-prem\nclusters registered against the tenant through the public-api\n`/public-api/v1/scan-cluster/{kind}/{name}` attachment flow. These clusters are\ntenant-scoped and carry no Cloud Connector binding, so they are never present in the\n`Cloud Connectors` listing's `multicloud_clusters` (which only covers legacy\nCloud Connector-attached clusters). The list is not paginated; results are ordered by\nregistration time, newest first.\n","operationId":"listScanClusters","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListScanClustersResponse"}}},"description":"The tenant's standalone scan clusters"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"List standalone scan clusters","tags":["Deployments"]}},"/gateway/shared-services/v1/deployments/supported-aws-regions":{"get":{"operationId":"listSupportedAwsRegions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSupportedAwsRegionsResponse"}}},"description":"Supported AWS regions list"},"401":{"$ref":"#/components/responses/DeploymentsUnauthorizedError"},"403":{"$ref":"#/components/responses/DeploymentsForbiddenError"},"500":{"$ref":"#/components/responses/DeploymentsInternalError"}},"summary":"List supported AWS regions for deployments","tags":["Deployments"]}},"/gateway/shared-services/v1/documents/pdf":{"post":{"description":"Tenant-admin endpoint, gated by eql-reporting or documents-pdf. No HTML, executable templates or external resources. Maximum 8 MiB, 10000 table rows and 512 pages.","operationId":"renderStructuredDocumentPDF","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ElastioPDFDocument"}}},"required":true},"responses":{"200":{"content":{"application/pdf":{"schema":{"format":"binary","type":"string"}}},"description":"PDF document"},"400":{"description":"Invalid structured document"},"401":{"description":"Missing or invalid signed gateway identity"},"403":{"description":"Tenant administrator required"},"404":{"description":"Rendering disabled"},"422":{"description":"Content exceeds rendering limits or unsupported font glyphs"},"429":{"description":"Renderer busy; retry later"}},"summary":"Render a structured document as a PDF","tags":["Reports"]}},"/gateway/shared-services/v1/evidence/ledger":{"get":{"description":"`coverage` and `population` describe the whole scope, not the page; `records` is the page. Inconclusive and errored analyses are never folded into ran/expected.\n","operationId":"getEvidenceLedger","parameters":[{"in":"query","name":"offset","schema":{"default":0,"type":"integer"}},{"in":"query","name":"page_size","schema":{"default":500,"type":"integer"}},{"description":"Opaque paging cursor; today carries the record offset.","in":"query","name":"next_page_token","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LedgerResponse"}}},"description":"One page of the evidence ledger"},"500":{"$ref":"#/components/responses/EvidenceInternalError"}},"summary":"Get one page of the fleet-wide evidence ledger","tags":["Evidence"]}},"/gateway/shared-services/v1/personal-access-tokens":{"get":{"description":"Returns the active personal access tokens issued by the requesting user.","operationId":"listPersonalAccessTokens","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/UserRoleAdmin"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPATsResponse"}}},"description":"Tokens issued by the requesting user, with a total count."},"400":{"$ref":"#/components/responses/PATBadRequestError"},"401":{"$ref":"#/components/responses/PATUnauthorizedError"},"403":{"$ref":"#/components/responses/PATForbiddenError"},"500":{"$ref":"#/components/responses/PATInternalError"}},"summary":"List personal access tokens","tags":["Personal Access Tokens"]},"post":{"description":"Generates a new personal access token for the requesting user. The raw token value is included in the response and is not shown again.","operationId":"issuePersonalAccessToken","parameters":[{"$ref":"#/components/parameters/UserRoleAdmin"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuePATRequestBody"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuePATResponse"}}},"description":"Token issued. The body includes the raw token and its details."},"400":{"$ref":"#/components/responses/PATBadRequestError"},"401":{"$ref":"#/components/responses/PATUnauthorizedError"},"403":{"$ref":"#/components/responses/PATForbiddenError"},"500":{"$ref":"#/components/responses/PATInternalError"}},"summary":"Issue a personal access token","tags":["Personal Access Tokens"]}},"/gateway/shared-services/v1/personal-access-tokens/{token_id}":{"patch":{"description":"Updates a previously issued personal access token. Omitting both `all_scopes` and `grants` leaves permissions unchanged (a name-only rename). Omitting `expires_at` leaves expiry unchanged.","operationId":"updatePersonalAccessToken","parameters":[{"description":"UUID of the token to update.","in":"path","name":"token_id","required":true,"schema":{"format":"uuid","type":"string"}},{"$ref":"#/components/parameters/UserRoleAdmin"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePATRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenDetails"}}},"description":"Updated token details."},"400":{"$ref":"#/components/responses/PATBadRequestError"},"401":{"$ref":"#/components/responses/PATUnauthorizedError"},"403":{"$ref":"#/components/responses/PATForbiddenError"},"404":{"$ref":"#/components/responses/PATNotFoundError"},"500":{"$ref":"#/components/responses/PATInternalError"}},"summary":"Update a personal access token","tags":["Personal Access Tokens"]}},"/gateway/shared-services/v1/personal-access-tokens/revoke":{"post":{"description":"Revokes one or more personal access tokens belonging to the requesting user.","operationId":"revokePersonalAccessTokens","parameters":[{"$ref":"#/components/parameters/UserRoleAdmin"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokePATRequestBody"}}},"required":true},"responses":{"204":{"description":"Tokens revoked. There is no response body."},"400":{"$ref":"#/components/responses/PATBadRequestError"},"401":{"$ref":"#/components/responses/PATUnauthorizedError"},"403":{"$ref":"#/components/responses/PATForbiddenError"},"404":{"$ref":"#/components/responses/PATNotFoundError"},"500":{"$ref":"#/components/responses/PATInternalError"}},"summary":"Revoke personal access tokens","tags":["Personal Access Tokens"]}},"/gateway/shared-services/v1/personal-access-tokens/revoked":{"get":{"description":"Returns revoked personal access tokens issued by the requesting user.","operationId":"listRevokedPersonalAccessTokens","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/UserRoleAdmin"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPATsResponse"}}},"description":"Revoked tokens issued by the requesting user, with a total count."},"400":{"$ref":"#/components/responses/PATBadRequestError"},"401":{"$ref":"#/components/responses/PATUnauthorizedError"},"403":{"$ref":"#/components/responses/PATForbiddenError"},"500":{"$ref":"#/components/responses/PATInternalError"}},"summary":"List revoked personal access tokens","tags":["Personal Access Tokens"]}},"/gateway/shared-services/v1/policies":{"get":{"operationId":"listPolicies","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPoliciesResponse"}}},"description":"Policies list"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"List tenant policies","tags":["Policies"]},"post":{"description":"Admin only. Creates a new policy for the tenant.\n\nOn AWS, `selectors` are capped at 300 KiB serialized; over that the request is rejected with 400 `POLICY_TOO_LARGE`. A larger policy cannot be delivered to the Cloud Connectors and would stop every policy in the tenant from syncing. Only enumerated (`assets`) selectors can reach this size; `is_type` and `has_tags` are constant-size however many assets they match.","operationId":"createPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicyRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyResponse"}}},"description":"Created policy"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"$ref":"#/components/responses/ConflictError"},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Create policy (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v1/policies/{name}":{"delete":{"description":"Admin only. Deletes an existing policy by name.","operationId":"deletePolicy","responses":{"204":{"description":"Policy deleted"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; or `COMMIT_OUTCOME_UNKNOWN` when the AWS delete transaction's commit outcome could not be resolved; nothing is claimed destroyed and nothing was compensated (a retry converges: it can 404 if the first attempt actually committed)."}},"summary":"Delete policy by name (Admin only)","tags":["Policies"]},"get":{"operationId":"getPolicy","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyResponse"}}},"description":"Policy"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Get policy by name","tags":["Policies"]},"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"put":{"description":"Admin only. Updates an existing policy by name.\n\nOn AWS, `selectors` are capped at 300 KiB serialized; over that the request is rejected with 400 `POLICY_TOO_LARGE`. A larger policy cannot be delivered to the Cloud Connectors and would stop every policy in the tenant from syncing. Only enumerated (`assets`) selectors can reach this size; `is_type` and `has_tags` are constant-size however many assets they match.","operationId":"updatePolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePolicyRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyResponse"}}},"description":"Updated policy"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Update policy by name (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v1/policies/{name}/pause":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Pauses the specified policy.","operationId":"pausePolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseRequest"}}},"required":true},"responses":{"204":{"description":"Policy paused"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Pause policy (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v1/policies/{name}/resume":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Resumes the specified policy.","operationId":"resumePolicy","responses":{"204":{"description":"Policy resumed"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Resume policy (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v1/recovery-verdict":{"get":{"description":"The recovery verdict counted over the whole live estate, for Posture's Recovery axis (`counts.proven_count / estate_total`), served with or without a committed Program. Program-excluded assets are part of the estate, so they are counted here on their policy or default target. Live AWS AMI families are part of the estate and never of the Program, so they too are counted on their policy or default target only. The counts are read from the last evaluation (`evaluated_at`) and grouped by each asset's live class; a live asset with no evaluated verdict yet counts as unproven with no reason and under no target source. A tenant-scoped read for any role, like the snapshot.\n","operationId":"getRecoveryVerdictSummary","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryVerdictSummary"}}},"description":"The estate-wide recovery verdict summary"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"404":{"$ref":"#/components/responses/RecoveryVerdictNotServedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"Estate-wide recovery verdict summary","tags":["Recovery Verdict"]}},"/gateway/shared-services/v1/recovery-verdict/assets":{"get":{"description":"Per-asset recovery verdicts for the Posture drill-down, the board work lists and MCP, ordered by asset name. Filters combine with AND. `total` is the unpaged count for the filters, so `scope=program&verdict=proven` equals the snapshot's `totals.proven_count` and `scope=program&verdict=unproven` its `totals.unproven_count`. A live asset with no evaluated verdict yet is listed with `recovery` null and matches `verdict=unproven` and `with_exceptions=false`. A tenant-scoped read for any role, like the snapshot.\n","operationId":"listRecoveryVerdictAssets","parameters":[{"description":"`estate` (default) lists every live asset, Program-excluded ones and live AWS AMI families included; both are evaluated on their policy or default target only. `program` lists the snapshot's promised population: the committed Program's assets whose live class is not `excluded`, never an AMI family; empty when no Program is committed.\n","in":"query","name":"scope","schema":{"enum":["estate","program"],"type":"string"}},{"in":"query","name":"verdict","schema":{"$ref":"#/components/schemas/RecoveryVerdict"}},{"description":"One unproven or at-risk reason code. An unproven code matches unproven assets carrying it; an at-risk code matches at-risk proven assets carrying it.\n","in":"query","name":"reason","schema":{"enum":["no_recovery_point","no_scanned_point","no_clean_point","r_rpo_exceeded","missing_immutable_copy","missing_air_gapped_copy","missing_cross_region_copy","immutable_copy_not_observable","air_gapped_copy_not_observable","cross_region_copy_not_observable","no_enabled_policy","plan_not_activated","near_expiry","policy_looser_than_target"],"type":"string"}},{"description":"The asset's live resilience class.","in":"query","name":"class","schema":{"$ref":"#/components/schemas/ResilienceProgramTier"}},{"description":"`true` lists the assets proven with exceptions; `false` lists every other asset.\n","in":"query","name":"with_exceptions","schema":{"type":"boolean"}},{"description":"1-based page number (default 1).","in":"query","name":"page","schema":{"minimum":1,"type":"integer"}},{"description":"Page size, default and cap 500.","in":"query","name":"page_size","schema":{"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryVerdictAssetPage"}}},"description":"One page of per-asset verdicts plus the unpaged total"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"404":{"$ref":"#/components/responses/RecoveryVerdictNotServedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"Per-asset recovery verdicts, paged","tags":["Recovery Verdict"]}},"/gateway/shared-services/v1/resilience-program":{"delete":{"description":"Clears the tenant's program so the board returns to \"define your program\". In one transaction it deactivates the active program version (older versions are kept for history and the timeseries), and deletes the live spine and node assignments.\nAll three are cleared together because the board reads all three: the snapshot reads the program, while business exposure groups the estate by the live spine/assignments. Clearing only the program would zero the score but leave exposure unchanged.\nAfter that it deletes the managed policies the plan created, across the tenant's `plan_id` lineage; any it could not delete are listed in `policies_failed`. Governance overrides are not cleared: they are audited and have their own delete endpoint.\nWrites a `resilience_program.reset` governance event to the audit trail, with the authenticated caller as the actor.\nSafe to call when nothing is committed. Requires X-User-Role admin.\n","operationId":"resetResilienceProgram","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramResetResponse"}}},"description":"What was cleared, plus the now-empty snapshot"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"403":{"$ref":"#/components/responses/ResilienceProgramForbiddenError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"Reset the Resilience Program back to its empty state","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/commit":{"post":{"description":"Deactivates the current active program version and inserts the next version (max + 1) as active, in one transaction. Each item in `policies` is created or updated as a managed policy before the program row is written. AWS items are paused_until with a future timestamp; Azure and IBM cluster items create enabled and must pause in YAML via a future `disabled.until`. Create stamps `created_via_plan_id` from this `plan_id` for AWS and cluster policies; update applies only when the existing policy already has `created_via_plan_id` set (any plan: the UI mints a new `plan_id` every sign-off). A same-name policy with no provenance is 409. Policy writes and the program row are not a single transaction. The snapshot is computed immediately so the trend gets a point at commit time. The commit queues a recovery verdict re-evaluation; it does not wait for it, so a snapshot that carries the verdict serves the last completed evaluation and `verdict_evaluated_at` can predate `committed_at`. Writes a `resilience_program.committed` governance event to the audit trail, with the authenticated caller as the actor (the client-sent `signed_off_by` is kept as event metadata only, ). Requires X-User-Role admin.\n","operationId":"commitResilienceProgram","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramCommitRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramCommitResponse"}}},"description":"The committed program version, its fresh snapshot, and the created or updated policies"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"403":{"$ref":"#/components/responses/ResilienceProgramForbiddenError"},"409":{"$ref":"#/components/responses/ResilienceProgramConflictError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"Commit a new Resilience Program version","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/estate":{"get":{"description":"The estate the snapshot pass classifies: per asset its identity, raw {k, v} tags, the resolved resilience class, which precedence arm decided it (override | manual | tag | rule | default), and whether an effective policy membership covers it. Reuses the snapshot's classification, so its numbers foot with the board by construction. Elastio built-in exclusion tags (`elastio:exclude`, `elastio:resource`, `elastio:nobackup`, `awsbackup-restore-test`, also spelled with `.` or `_` instead of `:`) classify as excluded with class_source=tag unless the value is exactly \"false\" (case-sensitive); key-only (empty) values count as excluded, and `elastio:action=scan` does not override them. With no committed program every asset serves standard/default (or its governance override / exclusion tag). This is the Edit-plan wizard's live inventory feed. Same RBAC stance as the snapshot: a tenant-scoped read, any role. With the recovery verdict served, each row also carries `recovery`, its last evaluated verdict; null when the live class is `excluded` or the asset has not been evaluated yet.\n","operationId":"getResilienceProgramEstate","parameters":[{"description":"1-based page number (default 1).","in":"query","name":"page","schema":{"minimum":1,"type":"integer"}},{"description":"Page size, default and cap 500.","in":"query","name":"page_size","schema":{"minimum":1,"type":"integer"}},{"description":"Which population to enumerate. `all` (default) is the whole classified estate, including the `excluded` bucket, which is what the Edit-plan wizard's resolver needs. `promised` narrows the page to the population the board headline counts, so `total` then equals the snapshot's `totals.promised` and a consumer that ENUMERATES the estate agrees with the aggregate.\n","in":"query","name":"scope","schema":{"enum":["all","promised"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramEstate"}}},"description":"One page of the classified estate plus the unpaged total"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"The classified estate, one asset per row","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/estate/exposure":{"get":{"description":"Per-node exposure for the LIVE Business-exposure (by-name) view. Groups the same classified estate GET /estate already serves.\nTag mode (default) uses the tenant's configured spine (GET /spine) and returns per node {asset_count, proven, drift, at_risk, exceptions, excluded}. totals is the disjoint partition (default_node + every depth-1 node) and foots to the snapshot hero: proven + drift + at_risk + exceptions = totals.promised, and assets = promised + excluded. Parent nodes include descendants, so a client must not sum every row.\nA tag-mode level may be the reserved `__account_group__` sentinel. At that level each asset's cloud owner is resolved to the NAME of the Account Group containing it (`key` is `__account_group__`, `value` and the path segment are the group name; `name` honours `node_names` renames). An owner in no group lands in a real `Ungrouped` node at that level; an asset with no owner falls to the Default bucket, as with `__account__`. An owner in several groups is counted in the first group by name (case-insensitive) then UUID - the same disjointness rule as `grouping=account_group` - so the partition still foots. Nodes keyed `__account_group__` take `class` from the matching live `node_assignments` row (path = the group name), falling back to `default_class` when that class is omitted or null. They are also the one tag-mode case that carries the owner seam: `account_ids`, `subscription_ids` and `ibm_scopes` are the group's RBAC MEMBERS (server-authoritative, including members with no live assets yet; Ungrouped carries the owners observed), and `regions` are the regions observed on the node's assets, so a per-group managed policy can be scoped through `account_region_selectors` without the client re-deriving membership. When the level is configured but Account Groups are unreadable in this cell, every owned asset resolves to Ungrouped and the read still serves.\nAccount mode is selected when the committed program's `plan_mode` is `account`, or when `grouping=account` is passed (the query overrides the committed mode; `grouping=tags` forces the spine rollup). Account-mode nodes are one row per live account-bearing node assignment (has AWS account_region_selectors, Azure subscription_regions, or IBM ibm_scopes). Structural assignments with no owners are omitted. `name` is the slash-joined path; `path` is the full path; `key` is always `account`; `value` is the last segment; `class` is the authored assignment class (falling back to default_class). `account_ids` unions AWS account ids and Azure subscription ids (UI seam); `subscription_ids` and `ibm_scopes` are additive. Counts are by owner membership. Totals are default_node (unmatched owners) plus every account-bearing node: a disjoint partition, not the tag-mode depth-1 cut. The spine in this mode is `{keys: [], levels: [], root_name}` so tag keys are not returned. `grouping=account` is 503 when the live node-assignments table has not been migrated in this cell. `grouping=account_group` is selected only when the query is passed (never from committed plan_mode). Nodes are one row per tenant Account Group (`GET /api/v1/accountGroups`): `name` is the group name; `key` is `account_group`; `value` and `path[0]` are the group UUID. Counts are by owner membership (`provider_type` + account id; account-level, not account+region). An account in multiple groups is counted in the first group by name (case-insensitive) then UUID so the partition stays disjoint. Assets in no group land in `default_node` (`name` Ungrouped). Totals are Ungrouped plus every group node. `grouping=account_group` is 503 when `rbac.account_groups` is not present in the users database in this cell.\nThis is the preferred contract over joining the 200-capped snapshot breakdown asset_ids back to /estate.asset_id. Unlike snapshot.classify_estate (which follows the version-frozen spine), tag-mode always uses the live configured spine so a hierarchy edit is visible before the next program commit. Same RBAC as /estate: tenant-scoped read, any role. Served with no committed program (pseudo-program of standard/default), matching GET /estate.\nRecovery verdict: with a committed program and the verdict served (as on the snapshot), every node and default_node also carry proven_count, unproven_count, at_risk_count, proven_with_exceptions_count and critical_unproven_count, totals carries the first four over the same partition, and nodes sort by critical_unproven_count instead of critical_at_risk. Per node, asset_count = proven_count + unproven_count + excluded. Without a committed program the verdict keys are never present.\n","operationId":"getResilienceProgramEstateExposure","parameters":[{"description":"Override the committed `plan_mode` grouping. `account` buckets by live node-assignments; `tags` uses the configured spine; `account_group` buckets by tenant Account Groups. Omit to follow the committed program (`account` only when `plan_mode` is `account`; otherwise tags). `custom` is not a valid grouping override. `account_group` is never the default.\n","in":"query","name":"grouping","schema":{"enum":["tags","account","account_group"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramEstateExposure"}}},"description":"The live per-node exposure rollup"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"Account-mode grouping was requested (explicitly or via committed plan_mode=account) but the node-assignments schema has not been migrated into this cell yet; or grouping=account_group was requested but `rbac.account_groups` is not present in the users database in this cell.\n"}},"summary":"Live Business-exposure rollup by spine, account, or account group","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/node-assignments":{"get":{"description":"The live leaf bindings the Board authors on the Mapped Inventory tree. Each item is keyed by `path` (the same ordered tag-value path as classify_estate.nodes[].path); `path: []` is the Default bucket. Owner columns match v3 policy scope (AWS account_region_selectors, Azure subscription_regions, IBM scopes). `rpo` is the same {target_seconds, severity} object as policy r_rpo, or null. `class` is the optional authored Resilience class of the node (critical | important | standard); omitted stores NULL. This is the editor scratchpad; the signed-off copy is frozen onto the program version at commit. Tenant-scoped read, any role.\n","operationId":"getResilienceProgramNodeAssignments","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignments"}}},"description":"The live assignments, possibly empty"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"The node-assignments schema has not been migrated into this cell yet"}},"summary":"Live per-leaf owner-scope and RPO on the program tree","tags":["Resilience Program"]},"put":{"description":"Replace the tenant's live assignments wholesale. Re-binding one leaf and clearing another are the same write. An empty `assignments` array clears every binding. Each path must be empty (Default bucket) or length equal to the live spine depth (a lowest-level node). A row must bind at least one owner pair or an rpo; blank items are omitted. PUT /spine deletes these live rows in the same transaction. Admin only, like the spine write.\n","operationId":"putResilienceProgramNodeAssignments","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignmentsUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignments"}}},"description":"The stored live assignments"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"The node-assignments schema has not been migrated into this cell yet"}},"summary":"Replace the live per-leaf owner-scope and RPO bindings","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/overrides":{"get":{"description":"The audited per-asset class pins. Distinct from the commit body's `manual_overrides` map: an override carries a reason, an author, a timestamp, an optional expiry and a lifecycle, and it takes effect without committing a new program version. Default status is `active`. Reads follow the board's RBAC (any role).\n","operationId":"listResilienceProgramOverrides","parameters":[{"description":"`active` (default), `removed`, or `all`.","in":"query","name":"status","schema":{"enum":["active","removed","all"],"type":"string"}},{"description":"Filter by the pinned class, or `all`.","in":"query","name":"class","schema":{"enum":["critical","important","standard","excluded","all"],"type":"string"}},{"description":"Filter by record kind: `class` pins, `relax` commitment relaxations, or `all` (default). On a deployment without the relaxation migration `relax` matches nothing.\n","in":"query","name":"kind","schema":{"enum":["class","relax","all"],"type":"string"}},{"description":"1-based page number (default 1).","in":"query","name":"page","schema":{"minimum":1,"type":"integer"}},{"description":"Page size, default 50, capped at 200.","in":"query","name":"page_size","schema":{"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverrideList"}}},"description":"One page of overrides plus the unpaged total"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"List governance overrides","tags":["Resilience Program"]},"post":{"description":"Records a governance override. `engine_class_at_set` is frozen from the classification the rules would produce with no override in play, so the record stays answerable later. At most one active override per asset: a second create is 409. Requires X-User-Role admin; the actor comes from X-User-Email and is stored as `set_by`.\n","operationId":"createResilienceProgramOverride","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverrideCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverride"}}},"description":"The created override"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"403":{"$ref":"#/components/responses/ResilienceProgramForbiddenError"},"404":{"$ref":"#/components/responses/ResilienceProgramNotFoundError"},"409":{"$ref":"#/components/responses/ResilienceProgramConflictError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"Pin one asset to a resilience class","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/overrides/{override_id}":{"delete":{"description":"A soft delete: the row stays with `status: removed` and its history intact, so the decision remains auditable. Removing an already-removed override is idempotent. Requires X-User-Role admin.\n","operationId":"deleteResilienceProgramOverride","responses":{"200":{"content":{"application/json":{"schema":{"properties":{"override_id":{"type":"string"},"status":{"enum":["removed"],"type":"string"}},"type":"object"}}},"description":"The override id and its new status"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"403":{"$ref":"#/components/responses/ResilienceProgramForbiddenError"},"404":{"$ref":"#/components/responses/ResilienceProgramNotFoundError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"Retire a governance override","tags":["Resilience Program"]},"get":{"operationId":"getResilienceProgramOverride","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverride"}}},"description":"The override"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"404":{"$ref":"#/components/responses/ResilienceProgramNotFoundError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"Read one governance override","tags":["Resilience Program"]},"parameters":[{"in":"path","name":"override_id","required":true,"schema":{"format":"uuid","type":"string"}}],"patch":{"description":"Absent fields are left alone; an explicit null for `expires_at` clears the expiry. Each changed dimension appends its own history event. Send the version you read as `If-Match` to make the write conditional (412 when it moved underneath you). Requires X-User-Role admin.\n","operationId":"updateResilienceProgramOverride","parameters":[{"description":"The `version` you read, bare or quoted. Omit for an unconditional write.","in":"header","name":"If-Match","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverridePatchRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverride"}}},"description":"The updated override"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"403":{"$ref":"#/components/responses/ResilienceProgramForbiddenError"},"404":{"$ref":"#/components/responses/ResilienceProgramNotFoundError"},"412":{"$ref":"#/components/responses/ResilienceProgramStaleVersionError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"Amend a governance override","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/overrides/{override_id}/history":{"get":{"description":"The override's own event log, oldest first: created, class_changed, reason_changed, expiry_changed, removed; each with the full before and after states. This is narrower than the tenant audit log, which also receives every one of these mutations.\n","operationId":"getResilienceProgramOverrideHistory","parameters":[{"in":"path","name":"override_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverrideHistory"}}},"description":"The timeline"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"404":{"$ref":"#/components/responses/ResilienceProgramNotFoundError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"One override's timeline","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/overrides/batch-delete":{"post":{"description":"Soft-deletes a set of overrides in one transaction: found rows are locked, active ones move to `status: removed` with a history event, and the write commits once. Already-removed ids are idempotent successes. Unknown or malformed ids are reported in `failed` and do not roll back the found set. A storage error rolls the whole batch back. Requires X-User-Role admin. Cap is 200 ids.\n","operationId":"batchDeleteResilienceProgramOverrides","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverrideBatchDeleteRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverrideBatchDeleteResponse"}}},"description":"The per-id split. `removed` includes already-removed ids; `failed` is unknown or malformed ids. Both arrays are always present, never null.\n"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"403":{"$ref":"#/components/responses/ResilienceProgramForbiddenError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"Retire many governance overrides","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/overrides/summary":{"get":{"description":"Backs the board's overrides pill. `stale_asset_count` counts active overrides whose engine class now equals the pinned class: the rules caught up, so the override is a no-op and can be retired. `expiring_in_30d` counts active overrides whose expiry falls inside the next 30 days (an already-lapsed expiry is not \"expiring\": it is counted by `expired_total` / `expired_by_kind`).\n`active_total`, `by_override_class` and `by_kind` are RECORD counts and foot against `GET /overrides`; the expired counts are the subset the classifier no longer applies. Subtract them to show what is in force, and the number agrees with the snapshot's excluded/committed figures.\n","operationId":"getResilienceProgramOverrideSummary","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramOverrideSummary"}}},"description":"The counts"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"$ref":"#/components/responses/ResilienceProgramFamilyNotReadyError"}},"summary":"Governance-override counts","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/snapshot":{"get":{"description":"Returns the current state of the tenant's active program version: headline totals, per-class metrics (provable + drift + at_risk + exceptions = promised), the drift / at-risk decompositions, the committed spine, and classify_estate (the per-spine-node rollup the Business-exposure table renders). at_risk honors each class's durability floors: a no_airgap_copy (or immutable / cross-region peer) is a program gap only when that class requires it. When no program has been committed, `program` is null, classify_estate is omitted, and every count is zero: the expected first-run state, not an error.\nRecovery verdict: for a tenant with the `recovery-verdict` switch on and a completed evaluation no older than four evaluation intervals, a committed snapshot also carries `verdict_model`, `verdict_evaluated_at`, the RecoveryVerdictCounts fields on `totals` and each `by_class` entry, the three verdict breakdowns, and the verdict counts on every classify_estate node. The counts are read from the last evaluation, grouped by each asset's live class; an excluded asset is never counted, and a promised asset with no evaluated verdict yet counts as unproven with no reason. Otherwise none of these keys is present and the response is unchanged. The empty (no program) snapshot never carries them.\nSide effect: upserts today's per-class promised / provable / drift / at_risk trend point. The verdict evaluation also writes the trend, verdict counts included, on each pass for a tenant with a committed program and the verdict switched on.\n","operationId":"getResilienceProgramSnapshot","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramSnapshot"}}},"description":"The snapshot"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"Current Resilience Program snapshot","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/spine":{"get":{"description":"The SPINE: the ordered list of tag keys that shapes the Mapped Inventory tree. The estate is grouped by keys[0], then each of those buckets by keys[1], and so on, so the array's ORDER is the hierarchy. One spine per tenant. Levels repeat the keys decorated with live coverage, which is what lets the editor say how many assets a level actually reaches before the plan is signed off. A tenant that has never configured one serves `configured: false` and NO keys - it is never given a default hierarchy. Tenant-scoped read, any role.\n","operationId":"getResilienceProgramSpine","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramSpine"}}},"description":"The configured hierarchy, or the unconfigured state"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"The tenant's Mapped Inventory hierarchy","tags":["Resilience Program"]},"put":{"description":"Replace the hierarchy wholesale. Reordering a level, adding one and removing one are all the same write - a different ordered `keys` array - so there is one write path and no half-applied state. Every key must be one GET /tag-keys reports; an undiscovered key is refused with `UNKNOWN_TAG_KEY` naming the offenders. The reserved `__account__` and `__account_group__` sentinels are accepted as levels and may be ordered anywhere among real tags; a spine that names `__account_group__` while Account Groups are not readable in this cell is refused with 503 `ACCOUNT_GROUPS_UNAVAILABLE` rather than `UNKNOWN_TAG_KEY`, because nothing is wrong with the request. An empty array is legal and means \"no hierarchy\": the tree is Root plus the Default bucket. Live node-assignments are deleted in the same transaction, because their paths are only meaningful against the current keys. Admin only, like the commit - re-shaping the hierarchy re-shapes every group the program reports on.\n","operationId":"putResilienceProgramSpine","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramSpineUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramSpine"}}},"description":"The stored hierarchy, re-read with live coverage"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"`SPINE_UNAVAILABLE`: the spine schema has not been migrated into this cell yet. `ACCOUNT_GROUPS_UNAVAILABLE`: a level names `__account_group__` but `rbac.account_groups` is not readable in this cell.\n"}},"summary":"Replace the tenant's Mapped Inventory hierarchy","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/spine/recommend":{"get":{"description":"A PROPOSAL for a tenant that has not configured a hierarchy yet, never an applied default. Nothing is stored: the customer reviews the seed and commits it through PUT /spine, which is where the propose/commit boundary sits. The ranking is pure over the tag census and therefore DETERMINISTIC, so the same estate always yields the same proposal. Candidates are the discovered keys that are neither identifier-shaped nor single-valued, ordered by coverage descending, then by distinct values ascending, then by key ascending; at most three levels are proposed. There is deliberately no bu > app > env fallback: an estate carrying none of those keys is served an empty proposal rather than a hierarchy it cannot satisfy, which is the bug the spine exists to end. Every key passed over is reported in `rejected` with its reason, so the customer sees the reasoning and not just the answer. Tenant-scoped read, any role.\n","operationId":"getResilienceProgramSpineRecommendation","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramSpineRecommendation"}}},"description":"The proposed hierarchy, plus every key it passed over"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"A proposed hierarchy, derived from the estate's own tags","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/tag-keys":{"get":{"description":"Every tag key present on the tenant's estate, most-covering first, with how many assets carry it, how many distinct values it has, and a short sample of those values, plus one reserved `__account__` entry so Account/Subscription can be a hierarchy level mixed with real tags. `__account__` is never a discovered tag: its values are cloud owner ids (AWS account, Azure subscription, IBM scope), identifier_like is always false, and a tenant with no owners still gets the entry with distinct_values 0.\nA second reserved entry, `__account_group__`, lets the tenant's Account Groups (`GET /rbac/api/v1/accountGroups`) be a hierarchy level too, nestable with tags and `__account__`. Its values are Account Group NAMES; `distinct_values` is the number of groups (populated or not); `asset_count` is the live assets whose owner belongs to some group; `sample_values` lists group names most-covering first; identifier_like is always false. It is served whenever `rbac.account_groups` is readable in this cell, including with distinct_values 0, and OMITTED while it is not, because PUT /spine could not honour it. A discovered tag literally named `__account__` or `__account_group__` is dropped so each sentinel is the only entry with its key.\nThis is the CLOSED VOCABULARY a spine level may be set to: the editor offers exactly this list, and PUT /spine rejects any key that is not in it. Tenant-scoped read, any role.\n","operationId":"getResilienceProgramTagKeys","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramTagKeys"}}},"description":"The discovered tag-key vocabulary"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"The tag keys discovered on the estate","tags":["Resilience Program"]}},"/gateway/shared-services/v1/resilience-program/timeseries":{"get":{"description":"Returns the per-class trend for the requested inclusive date range, plus every program version transition. Always exactly three series (critical / important / standard); a class with no rows has an empty points array. granularity=hour is accepted but capped to day rows (the trend store is per-day); range.granularity echoes what was served. A day's point is written by the snapshot read (legacy counts) and by the recovery verdict evaluation (legacy and verdict counts), whichever runs; a day nobody opened the board has a point only when the verdict evaluation ran. With the recovery verdict served every point carries `verdict_model` and the four verdict counts, null on rows written before the model.\n","operationId":"getResilienceProgramTimeseries","parameters":[{"description":"Inclusive start date, YYYY-MM-DD.","in":"query","name":"from","required":true,"schema":{"type":"string"}},{"description":"Inclusive end date, YYYY-MM-DD.","in":"query","name":"to","required":true,"schema":{"type":"string"}},{"description":"Requested granularity; v1 always serves day rows.","in":"query","name":"granularity","schema":{"enum":["day","hour"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramTimeseries"}}},"description":"The trend"},"400":{"$ref":"#/components/responses/ResilienceProgramBadRequestError"},"401":{"$ref":"#/components/responses/ResilienceProgramUnauthorizedError"},"500":{"$ref":"#/components/responses/ResilienceProgramInternalError"}},"summary":"Resilience Program per-class trend","tags":["Resilience Program"]}},"/gateway/shared-services/v1/schedules":{"get":{"operationId":"listSchedules","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSchedulesResponse"}}},"description":"Schedules list"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"List tenant schedules","tags":["Policy Schedules"]},"post":{"description":"Admin only. Creates a new schedule for the tenant.","operationId":"createSchedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScheduleRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}},"description":"Created schedule"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"$ref":"#/components/responses/ConflictError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Create schedule (Admin only)","tags":["Policy Schedules"]}},"/gateway/shared-services/v1/schedules/{id}":{"delete":{"description":"Admin only. Returns 409 (`SCHEDULE_IN_USE`) if any policy still references this schedule. Update or migrate those policies first.","operationId":"deleteSchedule","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"$ref":"#/components/responses/ConflictError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Delete schedule (Admin only)","tags":["Policy Schedules"]},"get":{"operationId":"getSchedule","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}},"description":"Schedule"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Get schedule by id","tags":["Policy Schedules"]},"parameters":[{"$ref":"#/components/parameters/ScheduleID"}],"patch":{"description":"Admin only. Partial update: fields omitted from the request body are preserved. Updating `frequency` immediately changes the next cadence for every policy that references this schedule.","operationId":"updateSchedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScheduleRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleResponse"}}},"description":"Updated schedule"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"$ref":"#/components/responses/ConflictError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Update schedule (Admin only)","tags":["Policy Schedules"]}},"/gateway/shared-services/v1/tenant-settings":{"get":{"description":"Returns settings for the tenant from Authority header. Creates default row if missing.","operationId":"getTenantSettings","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantSettingsResponse"}}},"description":"Current tenant settings"},"401":{"$ref":"#/components/responses/TenantSettingsUnauthorizedError"},"403":{"$ref":"#/components/responses/TenantSettingsForbiddenError"},"500":{"$ref":"#/components/responses/TenantSettingsInternalError"}},"summary":"Get tenant settings (get-or-create)","tags":["Tenant Settings"]},"patch":{"description":"Only fields present in the JSON body are updated; omitted keys keep existing values.\n","operationId":"patchTenantSettings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchTenantSettingsBody"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantSettingsResponse"}}},"description":"Updated tenant settings"},"400":{"$ref":"#/components/responses/TenantSettingsBadRequestError"},"401":{"$ref":"#/components/responses/TenantSettingsUnauthorizedError"},"403":{"$ref":"#/components/responses/TenantSettingsForbiddenError"},"500":{"$ref":"#/components/responses/TenantSettingsInternalError"}},"summary":"Partially update tenant settings","tags":["Tenant Settings"]}},"/gateway/shared-services/v1/threats/{threat_id}/suppress":{"post":{"operationId":"suppressThreat","parameters":[{"in":"path","name":"threat_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressThreatRequestBody"}}},"required":true},"responses":{"204":{"description":"Threat suppressed."},"400":{"$ref":"#/components/responses/ThreatsBadRequestError"},"401":{"$ref":"#/components/responses/ThreatsUnauthorizedError"},"403":{"$ref":"#/components/responses/ThreatsForbiddenError"},"500":{"$ref":"#/components/responses/ThreatsInternalError"}},"summary":"Suppress a finding","tags":["Threats"]}},"/gateway/shared-services/v1/threats/{threat_id}/suppression":{"delete":{"operationId":"removeThreatSuppression","parameters":[{"in":"path","name":"threat_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"description":"Suppression removed."},"400":{"$ref":"#/components/responses/ThreatsBadRequestError"},"401":{"$ref":"#/components/responses/ThreatsUnauthorizedError"},"403":{"$ref":"#/components/responses/ThreatsForbiddenError"},"500":{"$ref":"#/components/responses/ThreatsInternalError"}},"summary":"Remove a finding suppression","tags":["Threats"]}},"/gateway/shared-services/v1/vaults":{"get":{"description":"Returns the vaults available to your tenant. Optionally narrow the results by AWS account and/or region.","operationId":"listVaults","parameters":[{"description":"Only include vaults in this AWS account. Repeat the parameter to match several accounts.","explode":true,"in":"query","name":"aws_account_id","schema":{"items":{"type":"string"},"type":"array"},"style":"form"},{"description":"Only include vaults in this AWS Region. Repeat the parameter to match several regions.","explode":true,"in":"query","name":"aws_region","schema":{"items":{"type":"string"},"type":"array"},"style":"form"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListVaultsResponse"}}},"description":"Vaults matching your filters, with a total count."},"400":{"$ref":"#/components/responses/VaultBadRequestError"},"401":{"$ref":"#/components/responses/VaultUnauthorizedError"},"404":{"$ref":"#/components/responses/VaultNotFoundError"},"500":{"$ref":"#/components/responses/VaultInternalError"}},"summary":"List vaults","tags":["Vault"]},"post":{"description":"Starts provisioning a new vault. The response includes a job identifier you can use to track progress. The request body carries the Cloud Connector, vault name, encryption key, optional network placement, whether this vault should be the default for the connector, and safety lock.","operationId":"createVault","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVaultRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVaultJobResponse"}}},"description":"Creation has started; the body contains a job identifier."},"400":{"$ref":"#/components/responses/VaultBadRequestError"},"401":{"$ref":"#/components/responses/VaultUnauthorizedError"},"403":{"$ref":"#/components/responses/VaultForbiddenError"},"404":{"$ref":"#/components/responses/VaultNotFoundError"},"409":{"$ref":"#/components/responses/VaultConflictError"},"412":{"$ref":"#/components/responses/VaultPreconditionFailedError"},"500":{"$ref":"#/components/responses/VaultInternalError"}},"summary":"Create a vault","tags":["Vault"]}},"/gateway/shared-services/v1/vaults/{vault_id}":{"patch":{"description":"Changes vault details such as description, safety lock, or where the vault runs (VPC and subnets). If you change network placement, the response may include a job identifier while that change is applied.","operationId":"updateVault","parameters":[{"description":"Identifier of the vault to update.","in":"path","name":"vault_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVaultRequestBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVaultJobResponse"}}},"description":"Update applied or accepted; the body may include a job identifier when networking changes."},"400":{"$ref":"#/components/responses/VaultBadRequestError"},"401":{"$ref":"#/components/responses/VaultUnauthorizedError"},"403":{"$ref":"#/components/responses/VaultForbiddenError"},"404":{"$ref":"#/components/responses/VaultNotFoundError"},"409":{"$ref":"#/components/responses/VaultConflictError"},"412":{"$ref":"#/components/responses/VaultPreconditionFailedError"},"500":{"$ref":"#/components/responses/VaultInternalError"}},"summary":"Update a vault","tags":["Vault"]}},"/gateway/shared-services/v1/vaults/destroy":{"post":{"description":"Starts removal of a vault from a Cloud Connector. This action is intended for vaults you no longer need; confirm the connector and vault name before calling.","operationId":"destroyVault","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DestroyVaultRequestBody"}}},"required":true},"responses":{"204":{"description":"Removal request accepted; there is no response body."},"400":{"$ref":"#/components/responses/VaultBadRequestError"},"401":{"$ref":"#/components/responses/VaultUnauthorizedError"},"403":{"$ref":"#/components/responses/VaultForbiddenError"},"404":{"$ref":"#/components/responses/VaultNotFoundError"},"412":{"$ref":"#/components/responses/VaultPreconditionFailedError"},"500":{"$ref":"#/components/responses/VaultInternalError"}},"summary":"Remove a vault","tags":["Vault"]}},"/gateway/shared-services/v2/assets/{id}/policies":{"get":{"description":"The asset→policies reverse lookup, served from the precomputed edge model. Returns the policy names whose active membership includes this catalog asset. Optional `kind` filters by `policy_asset_memberships.policy_kind` (`scheduled` or `event`); omit to return both. 503 when membership storage is not enabled.","operationId":"getAssetPolicies","parameters":[{"description":"Catalog asset UUID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Filter by policy kind. Omit to include both scheduled and event policies.","in":"query","name":"kind","schema":{"enum":["scheduled","event"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetPoliciesResponse"}}},"description":"Policies covering the asset"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Invalid kind query parameter"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Missing or invalid tenant context"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Membership storage not enabled"}},"summary":"List the policies whose membership covers an asset","tags":["Policy Membership"]}},"/gateway/shared-services/v2/azure/subscription-regions":{"get":{"description":"Distinct catalog pairs that currently hold a live Azure VM, disk, blob container, or file share. Live predicates match ingestion's live-assets CTE. Viewer-readable; scoped callers are filtered to their Azure subscriptions. Empty inventory is 200 with an empty array, not 404.","operationId":"listAzureSubscriptionRegions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRegionsResponse"}}},"description":"Distinct (subscription, region) pairs, sorted"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Missing or invalid tenant context"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Internal error"}},"summary":"Live Azure (subscription, region) pairs","tags":["Policy Membership"]}},"/gateway/shared-services/v2/policies":{"get":{"description":"Lists the tenant's policies across AWS, Azure, and IBM from one tenant-scoped read of the authoritative `policies` table. An optional `platform` query parameter narrows the result to a single platform; an unsupported value returns 400. Viewer-readable.","operationId":"listPoliciesV2","parameters":[{"description":"Optional platform filter. When omitted, policies for all platforms are listed.","in":"query","name":"platform","schema":{"enum":["AWS","Azure","IBM","GCP"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPoliciesV2Response"}}},"description":"Policies list"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"List tenant policies v2","tags":["Policies"]},"post":{"description":"Admin only. Platform-aware create. `platform` is required and must be one of AWS, Azure, or IBM. AWS persists and dispatches via the existing v1 path and must not carry `cluster_name`/`cluster_options`. Azure and IBM persist a cluster policy authoritatively; they accept only `platform`, `name`, `description`, `cluster_name`, `subscription_ids` (Azure), and `cluster_options`: any other field present is rejected with 400.\n\nAn Azure policy is scoped by `subscription_ids` (the typed scope): the server resolves each subscription to the scan cluster that serves it and, for every affected cluster, composes ONE document from every Azure policy targeting that cluster (each entry's selectors AND-ed with `subscription_uuid: [...]`) and publishes it with one SetPolicies. Many Azure policies may therefore target one cluster and one subscription. The legacy shape (`cluster_name`, no `subscription_ids`) is still accepted; such a policy joins the composed document of its cluster unscoped. `cluster_name` and `subscription_ids` are mutually exclusive. IBM keeps the single-cluster model: `cluster_name` is required and at most one IBM policy may target a cluster.\n\nOn AWS, `selectors` are capped at 300 KiB serialized; over that the request is rejected with 400 `POLICY_TOO_LARGE`. A larger policy cannot be delivered to the Cloud Connectors and would stop every policy in the tenant from syncing. Only enumerated (`assets`) selectors can reach this size; `is_type` and `has_tags` are constant-size however many assets they match.","operationId":"createPolicyV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicyV2Request"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyV2Response"}}},"description":"Created policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyYAMLValidationErrorResponse"}}},"description":"Bad request. `code` is `VALIDATION_ERROR` for a malformed request; for an Azure/IBM policy whose `cluster_options.policy_yaml` fails strict validation, `code` is `POLICY_YAML_INVALID` and the body carries the structured `issues` array (nothing is persisted or published). For an Azure policy, `SUBSCRIPTION_IDS_INVALID` when `subscription_ids` is empty or carries a non-UUID, and `SUBSCRIPTION_UNRESOLVED` when no scan cluster serves one or more of the named subscriptions (the message lists them; nothing is persisted or published): that body also carries `issues`, one `SUBSCRIPTION_UNRESOLVED` issue per unresolvable element at `/subscription_ids/N` (N indexing `subscription_ids` as sent, exactly as `:validate` reports it)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossPlatformNameConflictError"}}},"description":"Conflict. `code` is `NAME_EXISTS_ON_OTHER_PLATFORM` when the name is already owned by a policy on another platform (then `platform` names it); `CLUSTER_TARGET_EXISTS` (IBM only: Azure allows many policies per cluster) when a differently-named IBM policy already targets the requested cluster; `CLUSTER_AMBIGUOUS` when a target cluster resolves to more than one deliverable connector; `UNIQUE_CONSTRAINT_CONFLICT` for any other unrecognized uniqueness violation; and `CONFLICT` only for a genuine duplicate name on the same platform."},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitOutcomeUnknownErrorResponse"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_AFTER_PERSIST` when the policy was saved but the publish to the Cloud Connector failed (delete it and retry); `COMPOSED_POLICY_INVALID` when the document composed for an Azure cluster failed validation (a server-side composition fault; nothing was published to that cluster); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the policy was saved but the effective document could not be built from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS create transaction's commit outcome could not be resolved: nothing is claimed persisted (a retry can 409 if the attempt actually committed), and the body carries `policy_id`, the create's minted canonical id (the key for the conditional-update recovery flow, `expected_policy_id` on the v3 update)."}},"summary":"Create policy v2 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v2/policies/{name}":{"delete":{"description":"Admin only. Deletes a policy by name across AWS, Azure, and IBM; the name resolves via one lookup of the authoritative `policies` table and the stored platform selects the behavior. AWS runs the existing AWS delete semantics with no publish. Azure and IBM resolve the cluster, publish one SetPolicies clear, then remove the authoritative `policies` row. A non-AWS delete whose cluster does not resolve to exactly one deliverable Cloud Connector returns 409 and leaves the row intact. A cluster that is no longer registered for the tenant has nothing to clear, so it is skipped and the row is removed.","operationId":"deletePolicyV2","responses":{"204":{"description":"Policy deleted"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `CLUSTER_UNRESOLVED` when the non-AWS target cluster is still registered but does not resolve to exactly one deliverable connector (retry once the connector is active). The row is left intact either way."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; or `COMMIT_OUTCOME_UNKNOWN` when an AWS delete transaction's commit outcome could not be resolved; nothing is claimed destroyed and nothing was compensated (a retry converges: it can 404 if the first attempt actually committed)."}},"summary":"Delete policy by name v2 (Admin only)","tags":["Policies"]},"get":{"description":"Reads a single policy by name across AWS, Azure, and IBM via one exact-name lookup of the authoritative `policies` table, whose primary key holds at most one owner per name. The response reflects the resolved `platform`. Viewer-readable.","operationId":"getPolicyV2","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyV2Response"}}},"description":"Policy"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Get policy by name v2","tags":["Policies"]},"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"put":{"description":"Admin only. Platform-aware update. `platform` is required and immutable: updating a name owned under a different platform returns 409. For Azure, `subscription_ids` may change freely (a legacy `cluster_name` policy may also move onto the typed scope): every cluster the policy targeted before or after is recomposed and republished. For IBM, `cluster_name` is immutable; only `cluster_options` and `description` may change.\n\nOn AWS, `selectors` are capped at 300 KiB serialized; over that the request is rejected with 400 `POLICY_TOO_LARGE`. A larger policy cannot be delivered to the Cloud Connectors and would stop every policy in the tenant from syncing. Only enumerated (`assets`) selectors can reach this size; `is_type` and `has_tags` are constant-size however many assets they match.","operationId":"updatePolicyV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePolicyV2Request"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyV2Response"}}},"description":"Updated policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyYAMLValidationErrorResponse"}}},"description":"Bad request. `code` is `VALIDATION_ERROR` for a malformed request; for an Azure/IBM policy whose `cluster_options.policy_yaml` fails strict validation, `code` is `POLICY_YAML_INVALID` and the body carries the structured `issues` array (nothing is persisted or published). For an Azure policy, `SUBSCRIPTION_IDS_INVALID` when `subscription_ids` is empty or carries a non-UUID, and `SUBSCRIPTION_UNRESOLVED` when no scan cluster serves one or more of the named subscriptions (the message lists them; nothing is persisted or published): that body also carries `issues`, one `SUBSCRIPTION_UNRESOLVED` issue per unresolvable element at `/subscription_ids/N` (N indexing `subscription_ids` as sent, exactly as `:validate` reports it)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossPlatformNameConflictError"}}},"description":"Conflict. `code` is `NAME_EXISTS_ON_OTHER_PLATFORM` when the name is owned by a policy on another platform (then `platform` names it); `CLUSTER_NAME_IMMUTABLE` (IBM only) when the request changes the immutable `cluster_name`; `CLUSTER_AMBIGUOUS` when a target cluster resolves to more than one deliverable connector."},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_RETRY` when the change was saved but the publish to the Cloud Connector failed (retry the operation (never delete); `COMPOSED_POLICY_INVALID` when the document composed for an Azure cluster failed validation (a server-side composition fault; nothing was published to that cluster); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the change was saved but the effective document could not be built from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS update transaction's commit outcome could not be resolved) nothing is claimed persisted either way and no compensation or ingestion restoration ran (a retry converges the database state)."}},"summary":"Update policy v2 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v2/policies/{name}/membership":{"get":{"description":"Resolves the policy via one exact-name lookup of the authoritative `policies` table (any platform), loads candidate assets from the catalog (covering pre-filters limit the scan to the policy's account/region scope), and evaluates the policy's selectors against each candidate. Returns the catalog asset ids that match.","operationId":"getPolicyMembership","parameters":[{"$ref":"#/components/parameters/MembershipPolicyName"},{"description":"`computed` (default) evaluates the policy's selectors live against current inventory. `stored` reads the precomputed membership from the last engine pass; returns 503 when that storage is not enabled.","in":"query","name":"source","schema":{"default":"computed","enum":["computed","stored"],"type":"string"}},{"$ref":"#/components/parameters/MembershipPageLimit"},{"$ref":"#/components/parameters/MembershipPageOffset"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipResponse"}}},"description":"Computed membership"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Invalid policy name or pagination parameters"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Missing or invalid tenant context"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Policy not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Internal error (including matcher failures)"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"source=stored requested but membership storage is not enabled"}},"summary":"Compute the assets currently selected by a stored policy","tags":["Policy Membership"]}},"/gateway/shared-services/v2/policies/{name}/pause":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Platform-aware pause across AWS, Azure, and IBM. Resolves the policy via one lookup of the authoritative `policies` table; the resolved platform controls dispatch. AWS reuses the v1 pause (authoritative `policies` status write + SetPlanStatus dispatch). Azure and IBM record the same `status` / `paused_until` on the cluster policy row and publish one SetPolicies request whose derived effective `policy_yaml` disables every `scan_policies` entry; the stored `policy_yaml` is never mutated. The body is required: a present `paused_until` sets `status = paused_until`, an empty body (`{}`) sets `status = disabled`, and a missing/empty body is 400.","operationId":"pausePolicyV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseRequest"}}},"required":true},"responses":{"204":{"description":"Policy paused"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `CLUSTER_UNRESOLVED` when the resolved Azure/IBM cluster is not currently deliverable (no status change is published: retry once the connector is active)."},"412":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Precondition failed (`code` `PRECONDITION_FAILED`). The stored canonical `policy_yaml` is missing/empty or malformed (a `scan_policies` entry is not a mapping, or `disabled` is neither a boolean nor `{ until: <timestamp> }`), so the effective document cannot be derived. `status` is unchanged and nothing is published; repair the policy via a v2 update, then retry."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_RETRY` when the status was saved but the publish to the Cloud Connector failed (retry the operation (never delete); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the status was saved but the effective document could not be built from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS status transaction's commit outcome could not be resolved) nothing is claimed persisted either way (a retry converges)."}},"summary":"Pause policy v2 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v2/policies/{name}/resume":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Platform-aware resume across AWS, Azure, and IBM. Resolves the policy via one lookup of the authoritative `policies` table; the resolved platform controls dispatch. AWS reuses the v1 resume (authoritative `policies` status write + SetPlanStatus dispatch). Azure and IBM set `status = enabled` on the cluster policy row and re-publish the canonical `policy_yaml` byte-identically, so a `scan_policies` entry the user deliberately set to `disabled` survives a pause→resume round-trip unchanged. Takes no body.","operationId":"resumePolicyV2","responses":{"204":{"description":"Policy resumed"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `CLUSTER_UNRESOLVED` when the resolved Azure/IBM cluster is not currently deliverable (no status change is published: retry once the connector is active)."},"412":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Precondition failed (`code` `PRECONDITION_FAILED`). Resume runs the same derivability validation as pause; if the stored canonical `policy_yaml` is missing/empty or malformed (a `scan_policies` entry is not a mapping, or `disabled` is neither a boolean nor `{ until: <timestamp> }`), `status` is unchanged and nothing is published; repair the policy via a v2 update, then retry."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_RETRY` when the status was saved but the publish to the Cloud Connector failed (retry the operation (never delete); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the status was saved as `enabled` but the canonical document could not be re-validated from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS status transaction's commit outcome could not be resolved) nothing is claimed persisted either way (a retry converges)."}},"summary":"Resume policy v2 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v2/policies/{name}/subscription-regions":{"get":{"description":"Resolves the named policy, then returns distinct pairs from its active `policy_asset_memberships` edges (the same stored membership the engine writes). Azure only. Unknown name is 404; AWS/IBM is 400. A policy with no edges yet is 200 with an empty array.","operationId":"getPolicySubscriptionRegions","parameters":[{"$ref":"#/components/parameters/MembershipPolicyName"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRegionsResponse"}}},"description":"Distinct (subscription, region) pairs, sorted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Policy is not Azure, or the name is invalid"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Missing or invalid tenant context"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Policy not found"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Internal error"}},"summary":"Azure (subscription, region) pairs a stored policy covers","tags":["Policy Membership"]}},"/gateway/shared-services/v2/policies/scope-preview":{"post":{"description":"Evaluates an unsaved policy definition against the tenant's current inventory without persisting anything. AWS drafts supply `selectors` and `account_region_selectors` (the same JSON shapes accepted by the v2 policies API); Azure/IBM drafts supply the cluster `policy_yaml` document.","operationId":"previewPolicyScope","parameters":[{"$ref":"#/components/parameters/MembershipPageLimit"},{"$ref":"#/components/parameters/MembershipPageOffset"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScopePreviewRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipResponse"}}},"description":"Computed membership for the draft definition"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Invalid body, platform, or pagination parameters"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Missing or invalid tenant context"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipErrorResponse"}}},"description":"Internal error (including matcher failures)"}},"summary":"Compute the assets a draft policy definition would select","tags":["Policy Membership"]}},"/gateway/shared-services/v2/policies:validate":{"post":{"description":"Admin only. Side-effect-free preflight of a v2 non-AWS create: runs the exact `policy_yaml` validation create/update run (YAML safety + the Cloud Connector policy JSON Schema + product rules) plus the same DB-backed reference checks (Azure subscription → cluster resolution, cluster resolution, the cross-platform name-ownership probe, and (IBM only) cluster-target uniqueness), and returns every finding as a structured issue without persisting or publishing anything. A processed document always returns 200; `valid: false` with issues is a successful validation of an invalid document; 400 is reserved for a malformed envelope (undecodable JSON, an over-limit body, a missing/unsupported `platform` including `AWS`, or an empty required field). `platform` is accepted case-insensitively and canonicalized to `Azure`/`IBM`. The document-validation issues are byte-identical to those create/update return for the same document.","operationId":"validatePolicyYAMLV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePolicyYAMLRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePolicyYAMLResponse"}}},"description":"Validation completed. `valid` is true with an empty `issues` array when the document and all references are acceptable; otherwise `valid` is false and `issues` lists every problem found in one pass: document issues (`YAML_*`, `SCHEMA_VIOLATION`, `POLICY_*`) and preflight reference issues (`NAME_INVALID`, `DESCRIPTION_INVALID`, `SUBSCRIPTION_UNRESOLVED` (one per subscription, at `/subscription_ids/N`), `CLUSTER_NOT_FOUND`, `CLUSTER_AMBIGUOUS`, `CLUSTER_TARGET_EXISTS` (IBM only), `NAME_CONFLICT`, `NAME_EXISTS_ON_OTHER_PLATFORM`), sorted and capped (a final `ISSUES_TRUNCATED` when more than 100 are found)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Malformed envelope (`code` `VALIDATION_ERROR`): undecodable JSON, a body over the 5 MiB limit, a missing/unsupported `platform` (including `AWS`, which carries no `policy_yaml`), an empty `platform`, `name`, or `policy_yaml`, a missing target (`cluster_name` or `subscription_ids`), both targets at once, or a malformed `subscription_ids` (`SUBSCRIPTION_IDS_INVALID`)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error (`code` `INTERNAL_ERROR`). A database/transport error during the reference-resolution stage (as opposed to a negative answer) means validation could not complete, so the request fails rather than returning a 200 with partial issues."}},"summary":"Validate a v2 Azure/IBM policy_yaml (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/ai-provider-credentials":{"get":{"description":"Returns every credential on the tenant, oldest first. A tenant with none gets an empty array, not 404. The credential itself is never included. Admin-only.","operationId":"listAIProviderCredentials","parameters":[{"$ref":"#/components/parameters/AdminRole"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderCredentialListResponse"}}},"description":"The tenant's credentials"},"401":{"$ref":"#/components/responses/AIProviderUnauthorizedError"},"403":{"$ref":"#/components/responses/AIProviderForbiddenError"},"500":{"$ref":"#/components/responses/AIProviderInternalError"}},"summary":"List this tenant's AI provider credentials","tags":["AI Provider Credentials"]},"post":{"description":"Encrypts `credential` and stores it. The object fields depend on `provider`. The response is metadata only. Admin-only.","operationId":"createAIProviderCredential","parameters":[{"$ref":"#/components/parameters/AdminRole"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAIProviderCredentialBody"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderCredential"}}},"description":"The stored credential's metadata"},"400":{"$ref":"#/components/responses/AIProviderBadRequestError"},"401":{"$ref":"#/components/responses/AIProviderUnauthorizedError"},"403":{"$ref":"#/components/responses/AIProviderForbiddenError"},"409":{"$ref":"#/components/responses/AIProviderConflictError"},"500":{"$ref":"#/components/responses/AIProviderInternalError"}},"summary":"Store an AI provider credential","tags":["AI Provider Credentials"]}},"/gateway/shared-services/v3/ai-provider-credentials/{id}":{"delete":{"description":"Hard-deletes the credential. A missing id, or an id that belongs to another tenant, is 404. Admin-only.","operationId":"deleteAIProviderCredential","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/AIProviderBadRequestError"},"401":{"$ref":"#/components/responses/AIProviderUnauthorizedError"},"403":{"$ref":"#/components/responses/AIProviderForbiddenError"},"404":{"$ref":"#/components/responses/AIProviderNotFoundError"},"500":{"$ref":"#/components/responses/AIProviderInternalError"}},"summary":"Delete an AI provider credential","tags":["AI Provider Credentials"]},"get":{"description":"Returns metadata for one credential on this tenant. A missing id, or an id that belongs to another tenant, is 404. The credential itself is never included. Admin-only.","operationId":"getAIProviderCredential","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderCredential"}}},"description":"The credential's metadata"},"400":{"$ref":"#/components/responses/AIProviderBadRequestError"},"401":{"$ref":"#/components/responses/AIProviderUnauthorizedError"},"403":{"$ref":"#/components/responses/AIProviderForbiddenError"},"404":{"$ref":"#/components/responses/AIProviderNotFoundError"},"500":{"$ref":"#/components/responses/AIProviderInternalError"}},"summary":"Get one AI provider credential","tags":["AI Provider Credentials"]},"parameters":[{"$ref":"#/components/parameters/CredentialID"},{"$ref":"#/components/parameters/AdminRole"}],"patch":{"description":"Changes the name, replaces the credential, or both. An omitted `credential` leaves the stored ciphertext untouched. A `credential` object uses the fields for the row's existing provider. Provider cannot be changed. The response is metadata only. Admin-only.","operationId":"updateAIProviderCredential","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAIProviderCredentialBody"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderCredential"}}},"description":"The updated credential's metadata"},"400":{"$ref":"#/components/responses/AIProviderBadRequestError"},"401":{"$ref":"#/components/responses/AIProviderUnauthorizedError"},"403":{"$ref":"#/components/responses/AIProviderForbiddenError"},"404":{"$ref":"#/components/responses/AIProviderNotFoundError"},"500":{"$ref":"#/components/responses/AIProviderInternalError"}},"summary":"Update an AI provider credential","tags":["AI Provider Credentials"]}},"/gateway/shared-services/v3/database-monitoring/databases":{"get":{"description":"One row per database, which is one Database Connector: what the admin added, what the Database Connector registered, and what its last heartbeat said.\n","operationId":"listMonitoredDatabases","parameters":[{"in":"query","name":"status","schema":{"$ref":"#/components/schemas/DatabaseMonitoringStatus"}},{"$ref":"#/components/parameters/DatabaseMonitoringPageSize"},{"$ref":"#/components/parameters/DatabaseMonitoringPageToken"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringDatabaseList"}}},"description":"One page of databases"},"401":{"$ref":"#/components/responses/DatabaseMonitoringUnauthorized"}},"summary":"List the tenant's monitored databases","tags":["Database Monitoring"]},"post":{"description":"Creates a pending row under the given name and mints a personal access token, in the calling admin's name and granted only what the Database Connector routes need, for the Database Connector to report with. The reply carries the SQL to run on the database and a Terraform block with the token in it. The token is shown once. The row stays pending until a Database Connector registers under that name.\n","operationId":"addMonitoredDatabase","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringCreated"}}},"description":"The pending database and its setup"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"}},"summary":"Add a database and get its setup (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}":{"delete":{"description":"Detections, windows, limits and slot observations go with it, and the token issued with it (api_key_id) is revoked. The revoke is best effort and runs as the caller: users-service revokes only the caller's own tokens, so when another admin added the database the token stays under their personal access tokens for them to revoke. A revoke that fails does not fail the delete.\n","operationId":"deleteMonitoredDatabase","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"responses":{"204":{"description":"Removed"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Remove a database and everything recorded under it (admin)","tags":["Database Monitoring"]},"get":{"operationId":"getMonitoredDatabase","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringDatabase"}}},"description":"The database"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Get one database","tags":["Database Monitoring"]},"patch":{"description":"New settings replace the stored ones wholesale and reach the running Database Connector on its next heartbeat reply; settings.revision advances only when they differ from what is stored. The Database Connector reports what it applied in its following heartbeat, as settings_applied. A new agent_size changes the Terraform the setup renders (task_cpu, task_memory) and nothing that is running: Elastio cannot resize the customer's task. The customer re-applies the Terraform; until then resources.matches_size is false. Turning a database off does not stop the Database Connector: the Database Connector hears it on its next heartbeat, closes its stream, and keeps heartbeating, so turning it back on needs no redeploy. The slot is not dropped; the customer must, or it retains write-ahead log until the disk fills.\n","operationId":"updateMonitoredDatabase","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringUpdateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringDatabase"}}},"description":"The database as stored"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Rename a database, turn its Database Connector off and on, change its size, or change its settings (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/ed":{"get":{"description":"Requires encryption detection (ED) scans to be enabled for your tenant. Credentials and row contents never reach this API.","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDJobsResponse"}}},"description":"Success"},"400":{"description":"Invalid scope, catalog, limits, lease or report"},"403":{"description":"Role or database key refused"},"404":{"description":"Tenant database missing or feature disabled"},"409":{"description":"Another job is active"}},"summary":"Get discovered tables and the latest 50 encryption detection (ED) jobs","tags":["Database Monitoring"]},"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"type":"string"}}]},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/ed/discover":{"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"type":"string"}}],"post":{"description":"Requires encryption detection (ED) scans to be enabled for your tenant. Credentials and row contents never reach this API.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDJob"}}},"description":"Success"},"400":{"description":"Invalid scope, catalog, limits, lease or report"},"403":{"description":"Role or database key refused"},"404":{"description":"Tenant database missing or feature disabled"},"409":{"description":"Another job is active"}},"summary":"Queue table discovery (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/ed/scans":{"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"type":"string"}}],"post":{"description":"Requires encryption detection (ED) scans to be enabled for your tenant. Credentials and row contents never reach this API.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDJob"}}},"description":"Success"},"400":{"description":"Invalid scope, catalog, limits, lease or report"},"403":{"description":"Role or database key refused"},"404":{"description":"Tenant database missing or feature disabled"},"409":{"description":"Another job is active"}},"summary":"Queue a paced, read-only encryption detection (ED) scan of discovered tables (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/ed/scans/{job_id}/cancel":{"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"type":"string"}},{"in":"path","name":"job_id","required":true,"schema":{"type":"string"}}],"post":{"description":"Requires encryption detection (ED) scans to be enabled for your tenant. Credentials and row contents never reach this API.","responses":{"204":{"description":"Success"},"400":{"description":"Invalid scope, catalog, limits, lease or report"},"403":{"description":"Role or database key refused"},"404":{"description":"Tenant database missing or feature disabled"},"409":{"description":"Another job is active"}},"summary":"Cancel a queued or running encryption detection (ED) scan (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/ed/schedules":{"post":{"description":"At every fire the tables are discovered again and the scope resolved against the fresh catalog, then the scan is queued. A fire that meets another active job on the database waits for the next tick; one the Database Connector cannot take (off, disconnected, unable) is skipped and says so in last_error. \"Once\" is POST /databases/{database_id}/ed/scans, not a schedule. Requires encryption detection (ED) scans and schedules to be enabled for your tenant; returns 404 otherwise.\n","operationId":"createEDSchedule","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDScheduleCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDSchedule"}}},"description":"The schedule"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Repeat an encryption detection (ED) scan daily or weekly (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/key":{"post":{"description":"Mints a new personal access token for the database's Database Connector, as adding the database does, records it as api_key_id, and revokes the one it replaces. The reply is the same as adding the database: the database and its setup, with the new token in the Terraform block. The token is shown once. Nothing the database has recorded is touched. The running Database Connector stops reporting once its old token is revoked, until it is redeployed with the new one. The revoke is best effort and runs as the caller: users-service revokes only the caller's own tokens, so when another admin minted the old token it stays valid, under their personal access tokens, for them to revoke.\n","operationId":"rotateMonitoredDatabaseKey","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringCreated"}}},"description":"The database and its setup, with the new token"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Replace the Database Connector's key and get the setup with the new one (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/limits":{"get":{"operationId":"listDatabaseMonitoringLimits","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringLimitList"}}},"description":"Declared ceilings, per relation"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"List the row ceilings declared for a database","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/limits/{relation}":{"delete":{"operationId":"deleteDatabaseMonitoringLimit","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"},{"$ref":"#/components/parameters/DatabaseMonitoringRelation"}],"responses":{"204":{"description":"Withdrawn"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Withdraw the row ceilings for one relation (admin)","tags":["Database Monitoring"]},"put":{"description":"Ceilings are rows per window. The Database Connector reads them before every window it judges, so a change applies to the next window. At least one ceiling is required; null is undeclared, which is not the same as zero. A breached ceiling is a finding whatever the table's size.\n","operationId":"putDatabaseMonitoringLimit","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"},{"$ref":"#/components/parameters/DatabaseMonitoringRelation"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringPutLimitRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringLimit"}}},"description":"The ceilings as stored"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Declare the row ceilings for one relation (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/metrics":{"get":{"description":"Heartbeats, the replication slot's held write-ahead log, the stream, windows judged by verdict, rows changed per relation, table sizes, coverage gaps, detections and Database Connector restarts, from `since` until now. The server buckets every series; a reader never receives raw rows. The range is at most 30 days (an older `since` is clamped) and at least an hour (a later one is widened), and is divided into at most 121 buckets of a round width (1m, 5m, 15m, 30m, 1h, 3h, 6h, 12h or 1d). Every list is capped. Heartbeat history is kept 30 days; windows judged benign or routine are kept 7 days, so older buckets count only windows that carried a finding.\n","operationId":"getDatabaseMonitoringMetrics","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"},{"description":"Start of the range, RFC 3339. Defaults to 24 hours ago.","in":"query","name":"since","schema":{"format":"date-time","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringMetrics"}}},"description":"The database's history over the range"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"One database's history, bucketed for charts","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/retention":{"get":{"description":"As the Database Connector observed it. Never acted on. `latest` is null until the slot has been looked at once.\n","operationId":"getDatabaseMonitoringRetention","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringRetention"}}},"description":"The latest observation and a recent series, newest first"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"How much write-ahead log the customer's server holds for the slot","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/server":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInventory"}}},"description":"Success"},"400":{"description":"Invalid selection, catalog or pagination"},"403":{"description":"Admin role or parent deployment key required"},"404":{"description":"Tenant database missing or feature disabled"}},"summary":"Discoverable databases on the same deployed PostgreSQL server","tags":["Database Monitoring"]},"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"type":"string"}}],"patch":{"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerSelection"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInventory"}}},"description":"Success"},"400":{"description":"Invalid selection, catalog or pagination"},"403":{"description":"Admin role or parent deployment key required"},"404":{"description":"Tenant database missing or feature disabled"}},"summary":"Select additional databases for scans and monitoring where permissions allow (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/server/discover":{"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"type":"string"}}],"post":{"responses":{"204":{"description":"Success"},"400":{"description":"Invalid selection, catalog or pagination"},"403":{"description":"Admin role or parent deployment key required"},"404":{"description":"Tenant database missing or feature disabled"}},"summary":"Request a refresh of server database access checks (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/setup":{"get":{"description":"The same setup as the reply to adding the database, without the token: a token is shown once, when the database is added or its key rotated. The Terraform block carries a placeholder where it was.\n","operationId":"getDatabaseMonitoringSetup","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringSetup"}}},"description":"Setup SQL, prerequisites, teardown SQL, the Database Connector's server URL and a Terraform block"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"What the customer runs on the database and deploys beside it","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/update":{"get":{"operationId":"getDatabaseAgentUpdate","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentUpdateState"}}},"description":"Current update state"}},"summary":"Read deployment updater availability and progress","tags":["Database Monitoring"]},"parameters":[{"in":"path","name":"database_id","required":true,"schema":{"format":"uuid","type":"string"}}],"patch":{"operationId":"requestDatabaseAgentUpdate","requestBody":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"auto_upgrade":{"type":"boolean"},"manual":{"type":"boolean"}},"type":"object"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentUpdateState"}}},"description":"Current update state"}},"summary":"Admin latest-only update or automatic upgrade preference","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/databases/{database_id}/windows":{"get":{"description":"One database's judged windows whose last commit is at or after `since`, newest first, each with its worst verdict (benign when no detector reported anything), its row counts and its busiest relation. `since` defaults to an hour ago and reaches back at most 24 hours (an older one is clamped). Windows judged benign or routine are kept 7 days. Polled; there is no push.\n","operationId":"listDatabaseMonitoringWindows","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringDatabaseID"},{"description":"RFC 3339. Defaults to 60 minutes ago; at most 24 hours ago.","in":"query","name":"since","schema":{"format":"date-time","type":"string"}},{"in":"query","name":"limit","schema":{"default":200,"maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringWindowList"}}},"description":"The windows, newest first"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"The live stream of judged windows","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/detections":{"get":{"description":"Without `include=all` only what needs attention is returned: verdict `finding`, verdict `observation_with_gap`, every coverage gap, and every oversized transaction (undecidable, but rare, a blind spot, and ended by giving the Database Connector more memory). `include=all` adds windows that were explained, fell below the threshold, or could not be decided. An undecided window is never reported as clean; it is left out of the default list because on an ordinary database one arrives about every minute, and is counted per database as `undecided_24h` instead. A `verdict` filter overrides the default. A window in which nothing was destroyed is not stored as a detection.\n","operationId":"listDatabaseMonitoringDetections","parameters":[{"in":"query","name":"database_id","schema":{"format":"uuid","type":"string"}},{"in":"query","name":"detector","schema":{"$ref":"#/components/schemas/DatabaseMonitoringDetector"}},{"in":"query","name":"verdict","schema":{"$ref":"#/components/schemas/DatabaseMonitoringVerdict"}},{"in":"query","name":"severity","schema":{"$ref":"#/components/schemas/DatabaseMonitoringSeverity"}},{"description":"Detected at or after, RFC 3339","in":"query","name":"from","schema":{"format":"date-time","type":"string"}},{"description":"Detected at or before, RFC 3339","in":"query","name":"to","schema":{"format":"date-time","type":"string"}},{"in":"query","name":"include","schema":{"enum":["all"],"type":"string"}},{"$ref":"#/components/parameters/DatabaseMonitoringPageSize"},{"$ref":"#/components/parameters/DatabaseMonitoringPageToken"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringDetectionList"}}},"description":"One page of detections"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"}},"summary":"List detections, newest first","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/detections/{detection_id}":{"get":{"description":"`finding` is the Database Connector's output exactly as it was sent, including every benign pattern that was checked and did not match. `window` is null for a coverage gap.\n","operationId":"getDatabaseMonitoringDetection","parameters":[{"in":"path","name":"detection_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringDetection"}}},"description":"The detection"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Get one detection with the Database Connector's finding","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/ed/scans":{"get":{"description":"Returns the requested page size (default 25, maximum 100), ordered newest first with keyset pagination. Completed includes failed and cancelled. Excludes catalog discovery jobs. Stalled claimed jobs become failed after two minutes without updates. Tenant-scoped; no scan-form selection is required.","parameters":[{"in":"query","name":"state","required":true,"schema":{"enum":["running","completed"],"type":"string"}},{"in":"query","name":"next_page_token","schema":{"maxLength":512,"type":"string"}},{"in":"query","name":"page_size","schema":{"default":25,"maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDHistoryResponse"}}},"description":"Success"},"400":{"description":"Invalid selection, catalog or pagination"},"403":{"description":"Admin role or parent deployment key required"},"404":{"description":"Tenant database missing or feature disabled"}},"summary":"List running and completed encryption detection (ED) scans across the tenant","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/ed/schedules":{"get":{"description":"Requires encryption detection (ED) scans and schedules to be enabled for your tenant; returns 404 otherwise.","operationId":"listEDSchedules","parameters":[{"in":"query","name":"database_id","schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDScheduleList"}}},"description":"The schedules"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"A tenant's repeating encryption detection (ED) scans","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/ed/schedules/{schedule_id}":{"delete":{"operationId":"deleteEDSchedule","responses":{"204":{"description":"Removed. A job it already queued runs on."},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Remove a schedule (admin)","tags":["Database Monitoring"]},"parameters":[{"in":"path","name":"schedule_id","required":true,"schema":{"format":"uuid","type":"string"}}],"patch":{"description":"A new frequency, or turning the schedule back on, moves next_fire_at to the cadence's next instant after now. Turning it off abandons a fire in progress; a job already queued runs on.\n","operationId":"updateEDSchedule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDScheduleUpdateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EDSchedule"}}},"description":"The schedule"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Change or pause a schedule (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/incidents":{"get":{"description":"Detections grouped into episodes. A non-routine detection of a window (a finding, an observation with a gap, or an oversized transaction) joins the database's latest unresolved incident when its window's first commit is within 30 minutes of that incident's last window's start, and otherwise opens a new one. Requires database monitoring incidents to be enabled for your tenant; otherwise the list is empty.\n","operationId":"listDatabaseMonitoringIncidents","parameters":[{"in":"query","name":"database_id","schema":{"format":"uuid","type":"string"}},{"in":"query","name":"status","schema":{"enum":["open","resolved"],"type":"string"}},{"description":"Incidents whose last window started at or after this, RFC 3339","in":"query","name":"from","schema":{"format":"date-time","type":"string"}},{"description":"Incidents whose first window started at or before this, RFC 3339","in":"query","name":"to","schema":{"format":"date-time","type":"string"}},{"$ref":"#/components/parameters/DatabaseMonitoringPageSize"},{"$ref":"#/components/parameters/DatabaseMonitoringPageToken"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringIncidentList"}}},"description":"One page of incidents"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"}},"summary":"A tenant's incidents, the most recently active first","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/incidents/{incident_id}":{"get":{"description":"Requires database monitoring incidents to be enabled for your tenant; returns 404 otherwise.","operationId":"getDatabaseMonitoringIncident","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringIncidentID"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringIncidentDetail"}}},"description":"The incident"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"One incident, with its detections, relations, commits and windows","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/database-monitoring/incidents/{incident_id}/resolve":{"post":{"description":"Marks the incident resolved, by whom, with an optional note. Its detections are left as recorded. A later detection opens a new incident. Resolving a resolved incident changes nothing. Requires database monitoring incidents to be enabled for your tenant; returns 404 otherwise.\n","operationId":"resolveDatabaseMonitoringIncident","parameters":[{"$ref":"#/components/parameters/DatabaseMonitoringIncidentID"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringResolveIncidentRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringIncident"}}},"description":"The incident, resolved"},"400":{"$ref":"#/components/responses/DatabaseMonitoringBadRequest"},"403":{"$ref":"#/components/responses/DatabaseMonitoringForbidden"},"404":{"$ref":"#/components/responses/DatabaseMonitoringNotFound"}},"summary":"Resolve an incident (admin)","tags":["Database Monitoring"]}},"/gateway/shared-services/v3/event-policies":{"get":{"description":"Lists the tenant's event-based policies. Each carries its trigger `source`, `source_config`, the `iscan` signature set, embedded `violations`, and the ingestion-hydrated `alert_ids`. Viewer-readable.","operationId":"listEventPolicies","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListEventPoliciesResponse"}}},"description":"Event policies list"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert synchronization unavailable (fail-closed alert hydration)."}},"summary":"List event-based policies","tags":["Policies"]},"post":{"description":"Creates an event policy that fires on an external event (a GuardDuty / Wiz finding), triggering a scan whose completion drives alerts / violations. Validates `source` (closed taxonomy), `source_config` severities, the `iscan` signature floor (malware or ransomware), and `alert_ids` before any write; binds `alert_ids` in ingestion, rolling the just-created policy back on a write-blocking bind failure. Admin-only.","operationId":"createEventPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPolicyCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPolicyResponse"}}},"description":"Created event policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `VALIDATION_ERROR` for a malformed request or an invalid `source`/`source_config`/`iscan`/`status`; `INVALID_VIOLATION_CODE`, `INVALID_SEVERITY_OVERRIDE`, or `DUPLICATE_VIOLATION_CODE` for the `violations` list; `INVALID_ALERT_IDS` for a malformed, duplicate, or unrecognized alert id (the just-created policy is rolled back); or `ALERT_REQUIRED` when alert synchronization is enabled and the request would create an ENABLED event policy with no `alert_ids` (at least one alert must be attached; nothing is created)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Name already exists; or the tenant's alerts V2->V3 migration is freezing binding writes (ALERT_MIGRATION_IN_PROGRESS: retry after it settles)."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert synchronization unavailable (fail-closed alert bind)."}},"summary":"Create an event-based policy","tags":["Policies"]}},"/gateway/shared-services/v3/event-policies/{name}":{"delete":{"description":"Admin only. Permanently deletes the event policy. As of this writes a terminal tombstone (an audit record that survives the removed row, with an optional recorded `reason`) before removing the authoritative row and best-effort clearing its ingestion alert bindings (wire-compatible 204).","operationId":"deleteEventPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeleteReasonRequest"}}},"description":"Optional reason recorded on the tombstone."},"responses":{"204":{"description":"Deleted (a terminal tombstone was recorded)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `INVALID_REASON` when the optional `reason` exceeds 1024 runes, or `BAD_REQUEST` when the request body is malformed."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Snapshot capture failed closed. `code` is `SNAPSHOT_UNAVAILABLE` when the policy's alert bindings could not be read from ingestion (any failure class): the delete is aborted and the policy is untouched."}},"summary":"Delete an event-based policy (Admin only)","tags":["Policies"]},"get":{"description":"Returns one event policy with its ingestion-hydrated `alert_ids`. Viewer-readable.","operationId":"getEventPolicy","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPolicyResponse"}}},"description":"Event policy"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert synchronization unavailable (fail-closed alert hydration)."}},"summary":"Get an event-based policy","tags":["Policies"]},"parameters":[{"description":"The event policy name.","in":"path","name":"name","required":true,"schema":{"type":"string"}}],"put":{"description":"Full-replaces the event policy definition. `alert_ids` uses preserve-on-omit (present replaces; omitted preserves); the binding is reconciled with ingestion before the row is mutated. When alert synchronization is enabled, an update may not leave an ENABLED event policy with zero bound alerts (400 `ALERT_REQUIRED`). Admin-only.","operationId":"updateEventPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPolicyUpdateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventPolicyResponse"}}},"description":"Updated event policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `VALIDATION_ERROR` for a malformed request or an invalid `source`/`source_config`/`iscan`/`status`; `INVALID_VIOLATION_CODE`, `INVALID_SEVERITY_OVERRIDE`, or `DUPLICATE_VIOLATION_CODE` for the `violations` list; `INVALID_ALERT_IDS` for a malformed, duplicate, or unrecognized alert id (the existing policy is left unchanged); or `ALERT_REQUIRED` when alert synchronization is enabled and the update would leave an ENABLED event policy with no bound alerts (a present `[]`, or an omitted `alert_ids` when no bindings exist)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"The tenant's alerts V2->V3 migration is freezing binding writes (ALERT_MIGRATION_IN_PROGRESS: retry after it settles)."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert synchronization unavailable (fail-closed alert bind)."}},"summary":"Update an event-based policy","tags":["Policies"]}},"/gateway/shared-services/v3/event-policies/{name}/soft-delete":{"parameters":[{"description":"The event policy name.","in":"path","name":"name","required":true,"schema":{"type":"string"}}],"post":{"description":"Admin only. Reversibly deletes an event policy: snapshots its prior state (including fail-closed-hydrated `alert_ids`), records an active deletion keyed by its canonical id, and removes the authoritative row; recoverable from the unified deleted-policies list (`GET /shared-services/v3/policies/deleted`). An optional `reason` is recorded.","operationId":"softDeleteEventPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeleteReasonRequest"}}},"description":"Optional reason recorded on the deletion record."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeletionResponse"}}},"description":"The active deletion record (the UI's undo affordance keys on its `id`)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `INVALID_REASON` when the optional `reason` exceeds 1024 runes, or `BAD_REQUEST` when the request body is malformed."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `ALREADY_DELETED` when an active deletion already exists for this event name (restore or permanently delete it first). The event namespace is independent of the scheduled one: a scheduled deletion of the same name does not block."},"500":{"$ref":"#/components/responses/InternalError"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Snapshot capture failed closed. `code` is `SNAPSHOT_UNAVAILABLE` when the policy's alert bindings could not be read from ingestion (any failure class) or the canonical id is unresolvable: nothing is written and the policy is untouched."}},"summary":"Soft-delete an event-based policy by name (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/hunt-rules":{"get":{"description":"Lists the tenant's live (non-deleted) hunt rules, with the policies each is attached to in `attached_policies`. Viewer-readable.","operationId":"listHuntRules","parameters":[{"description":"Comma-separated severity filter (any-of).","in":"query","name":"severity","schema":{"type":"string"}},{"description":"Comma-separated status filter (any-of).","in":"query","name":"status","schema":{"type":"string"}},{"description":"Comma-separated source filter (any-of).","in":"query","name":"source","schema":{"type":"string"}},{"description":"Comma-separated primitive filter (any-of).","in":"query","name":"primitive","schema":{"type":"string"}},{"description":"Comma-separated tag filter (any-of).","in":"query","name":"tag","schema":{"type":"string"}},{"description":"Only rules attached to this policy.","in":"query","name":"policy_id","schema":{"type":"string"}},{"description":"Case-insensitive name substring.","in":"query","name":"q","schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListHuntRulesResponse"}}},"description":"Hunt rules list"},"401":{"$ref":"#/components/responses/UnauthorizedError"}},"summary":"List hunt rules","tags":["Hunt Rules"]},"post":{"description":"Creates a hunt rule. `severity` is required; `status` defaults to `active`, `source` to `CUSTOM`. `bodies` carries the per-primitive rule code keyed by primitive kind (structural=SQL, content=YARA, pattern=regex). Library `yara_match('yara/...')` paths must match `yara_refs` (and unused refs are rejected); `rule.yar` needs no ref. Admin-only.","operationId":"createHuntRule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleResponse"}}},"description":"Created hunt rule"},"400":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"$ref":"#/components/schemas/VerificationFailedError"}]}}},"description":"Validation error, or `VERIFICATION_FAILED` when a library `yara_match('yara/...')` path is not in `yara_refs`, an attached ref is unused in SQL, or a `yara_refs` pin cannot be resolved. `rule.yar` (inline content) does not need a ref."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"A live hunt rule with this name already exists."}},"summary":"Create a hunt rule","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/hunt-rules/{id}":{"delete":{"description":"Soft delete: stamps `deleted_at`, hides the rule from every read, and frees the name for reuse. Blocked with 409 `DELETE_BLOCKED` while the rule is attached to any policy; `blocking_policies` lists them. Admin-only.","operationId":"deleteHuntRule","responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleDeleteBlockedError"}}},"description":"Rule is attached to one or more policies (DELETE_BLOCKED)."}},"summary":"Soft-delete a hunt rule","tags":["Hunt Rules"]},"get":{"description":"Returns one live hunt rule with its policy bindings. Viewer-readable.","operationId":"getHuntRule","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleResponse"}}},"description":"Hunt rule"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Get a hunt rule","tags":["Hunt Rules"]},"parameters":[{"description":"The hunt rule id (UUID).","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"patch":{"description":"PATCH semantics: an omitted field is preserved; a present field (including `[]`/`{}`) replaces. The merged result is re-validated. `name` is not a PATCH field (it is set at create and is the hunt identity); sending it is 400 `BAD_REQUEST`. Clone the rule to use a different name. Setting `status` to `tuning` or `inactive` is rejected 409 `STATUS_CHANGE_BLOCKED` while the rule is attached to any policy (`blocking_policies` lists them: detach first). Admin-only.","operationId":"updateHuntRule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleUpdateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleResponse"}}},"description":"Updated hunt rule"},"400":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"$ref":"#/components/schemas/VerificationFailedError"}]}}},"description":"Validation error (`BAD_REQUEST` and hunt-specific codes) or `VERIFICATION_FAILED` when a library `yara_match('yara/...')` path is not in `yara_refs`, an attached ref is unused in SQL, or a `yara_refs` pin cannot be resolved."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleDeleteBlockedError"}}},"description":"Conflict. `code` is `STATUS_CHANGE_BLOCKED` when the PATCH would set status off `active` while the rule is attached to policies (`blocking_policies` lists them)."}},"summary":"Update a hunt rule","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/hunt-rules/{id}/audit-log":{"get":{"description":"Append-only operator actions, newest first. Viewer-readable.","operationId":"getHuntRuleAuditLog","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRuleAuditResponse"}}},"description":"Audit entries"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"List a hunt rule's audit entries","tags":["Hunt Rules"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Comma-separated audit-action filter.","in":"query","name":"action","schema":{"type":"string"}}]},"/gateway/shared-services/v3/hunt-rules/{id}/policies":{"parameters":[{"description":"The hunt rule id (UUID).","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"post":{"description":"Persists one rule→policy binding (`policy_name` is a caller-provided display snapshot: bindings are loose references). The rule must be status `active`; `tuning` or `inactive` is rejected 400 `HUNT_RULE_NOT_ACTIVE` (those are not egested and would never run). Admin-only.","operationId":"attachHuntRulePolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleAttachPolicyRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleResponse"}}},"description":"The hunt rule with its refreshed binding set."},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"The rule is already attached to this policy (ALREADY_ATTACHED)."}},"summary":"Attach a hunt rule to a policy","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/hunt-rules/{id}/policies/{policyId}":{"delete":{"description":"Removes one rule→policy binding. Admin-only.","operationId":"detachHuntRulePolicy","responses":{"204":{"description":"Detached"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Detach a hunt rule from a policy","tags":["Hunt Rules"]},"parameters":[{"description":"The hunt rule id (UUID).","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"The bound policy id.","in":"path","name":"policyId","required":true,"schema":{"type":"string"}}]},"/gateway/shared-services/v3/hunt-rules/{id}/revert":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"post":{"description":"Creates a NEW version copying the target snapshot's content (bodies / primitives / prompt) so history stays linear. Admin-only.","operationId":"revertHuntRule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevertRuleRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HuntRuleResponse"}}},"description":"The rule at its new (reverted-content) version."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Revert a hunt rule to an earlier version","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/hunt-rules/{id}/signatures/{signatureId}/toggle":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Stable per-rule signature identifier (the YARA rule identifier).","in":"path","name":"signatureId","required":true,"schema":{"type":"string"}}],"post":{"description":"Tuning is operational state, not content: no version bump; the enabled flag survives content re-parses. Admin-only.","operationId":"toggleHuntRuleSignature","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleRuleSignatureRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleRuleSignatureResponse"}}},"description":"The updated signature."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Enable / disable a single signature","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/hunt-rules/{id}/versions":{"get":{"description":"Immutable content snapshots, newest first. Viewer-readable.","operationId":"listHuntRuleVersions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRuleVersionsResponse"}}},"description":"Version snapshots"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"List a hunt rule's version snapshots","tags":["Hunt Rules"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}]},"/gateway/shared-services/v3/hunt-rules:batch-delete":{"post":{"description":"Soft-deletes a set of hunt rules with per-rule block-if-attached. The response body is always the per-id results envelope; the status code carries the aggregate: 200 nothing blocked, 207 mixed outcome, 409 every requested id blocked (nothing deleted is only true for the blocked ids; unblocked ids in the same request are deleted). Admin-only.","operationId":"batchDeleteHuntRules","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDeleteHuntRulesRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDeleteHuntRulesResponse"}}},"description":"All requested ids deleted (or not found)."},"207":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDeleteHuntRulesResponse"}}},"description":"Mixed outcome: some deleted, some blocked."},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchDeleteHuntRulesResponse"}}},"description":"Every requested id is blocked by policy attachments."}},"summary":"Batch soft-delete hunt rules","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/licenses":{"get":{"description":"Returns every live license on the tenant, oldest first, with `status` computed on the server clock (one clock and one \"expiring soon\" window for every consumer). A tenant with no licenses gets an empty array, not 404. Admin-only (`X-User-Role: admin`), like every action on this surface.","operationId":"listTenantLicenses","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantLicenseListResponse"}}},"description":"The tenant's licenses"},"401":{"$ref":"#/components/responses/LicensesUnauthorizedError"},"403":{"$ref":"#/components/responses/LicensesForbiddenError"},"500":{"$ref":"#/components/responses/LicensesInternalError"}},"summary":"List this tenant's licenses","tags":["Licenses"]},"post":{"description":"Verifies the pasted key and stores it. Whitespace anywhere in the key (a line-wrapped paste) is ignored. Checks run in the reference verifier's order: envelope, header, `kid` against this deployment's key registry, PS256 signature over the literal `envelope.header.payload` bytes, payload schema version, product, expiry. A key that is already live on the tenant (same bytes) answers 409 rather than a duplicate row. Admin-only (`X-User-Role: admin`).","operationId":"addTenantLicense","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddTenantLicenseBody"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantLicense"}}},"description":"The stored license"},"400":{"$ref":"#/components/responses/LicensesBadRequestError"},"401":{"$ref":"#/components/responses/LicensesUnauthorizedError"},"403":{"$ref":"#/components/responses/LicensesForbiddenError"},"409":{"$ref":"#/components/responses/LicensesConflictError"},"500":{"$ref":"#/components/responses/LicensesInternalError"}},"summary":"Add a license key to this tenant","tags":["Licenses"]}},"/gateway/shared-services/v3/licenses/{id}":{"delete":{"description":"Removes one license. The row is kept for the audit trail but leaves every read, and the same key can be added again afterwards. A second DELETE of the same id, an id on another tenant, or a malformed id all answer 404. Admin-only (`X-User-Role: admin`).","operationId":"removeTenantLicense","parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"204":{"description":"Removed"},"401":{"$ref":"#/components/responses/LicensesUnauthorizedError"},"403":{"$ref":"#/components/responses/LicensesForbiddenError"},"404":{"$ref":"#/components/responses/LicensesNotFoundError"},"500":{"$ref":"#/components/responses/LicensesInternalError"}},"summary":"Remove a license from this tenant","tags":["Licenses"]}},"/gateway/shared-services/v3/policies":{"get":{"description":"Lists the tenant's policies across AWS, Azure, and IBM, identically to the v2 list (the same single tenant-scoped read of the authoritative `policies` table and optional `platform` filter), and additionally carries each policy's `violations` selection. Viewer-readable.","operationId":"listPoliciesV3","parameters":[{"description":"Optional platform filter. When omitted, policies for all platforms are listed.","in":"query","name":"platform","schema":{"enum":["AWS","Azure","IBM","GCP"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPoliciesV3Response"}}},"description":"Policies list"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert read hydration failed closed. `code` is `ALERT_SYNC_UNAVAILABLE` when fetching the alert bindings from ingestion failed for a config-class reason (auth/permission or M2M token mint). Because one M2M credential backs every call, an auth failure is global, so the WHOLE list fails closed rather than masking an M2M misconfiguration by degrading every policy's `alert_ids` to `[]`. Transient/availability read failures do NOT surface here: each policy's `alert_ids` degrades to `[]` and the list is still returned."}},"summary":"List tenant policies v3","tags":["Policies"]},"post":{"description":"Admin only. A strict superset of the v2 create: same platform-aware behavior (AWS persists/dispatches via the v1 path; Azure/IBM persist a cluster policy and publish one SetPolicies request), plus an optional `violations` list accepted on all platforms. Each violation code is validated against the catalog dictionary before anything persists; the selection is stored on the policy and echoed on the response.\n\nOn AWS, `selectors` are capped at 300 KiB serialized; over that the request is rejected with 400 `POLICY_TOO_LARGE`. A larger policy cannot be delivered to the Cloud Connectors and would stop every policy in the tenant from syncing. Only enumerated (`assets`) selectors can reach this size; `is_type` and `has_tags` are constant-size however many assets they match.","operationId":"createPolicyV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePolicyV3Request"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyV3Response"}}},"description":"Created policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyYAMLValidationErrorResponse"}}},"description":"Bad request. `code` is `VALIDATION_ERROR` for a malformed request; for an Azure/IBM policy whose `cluster_options.policy_yaml` fails strict validation, `code` is `POLICY_YAML_INVALID` and the body carries the structured `issues` array. For the `violations` list, `code` is `INVALID_VIOLATION_CODE` (a code absent from the catalog dictionary), `INVALID_SEVERITY_OVERRIDE` (a `severity_override` outside `critical`/`high`/`medium`/`low`/`info`), or `DUPLICATE_VIOLATION_CODE` (the same code listed twice). For the `r_rpo` target, `code` is `INVALID_RRPO_TARGET` (a non-positive `target_seconds`), `INVALID_RRPO_SEVERITY` (a `severity` outside `critical`/`high`/`medium`/`low`), or `RESERVED_VIOLATION_CODE` (the `r_rpo_exceeded` code listed in `violations`: it is configured via `r_rpo`). For the `alert_ids` set, `code` is `INVALID_ALERT_IDS` (an entry that is not a well-formed, non-nil UUID, a duplicate, or an alert id ingestion does not recognize (the just-created policy is rolled back so none remains)) or `ALERT_REQUIRED` when alert synchronization is enabled and the request would create an ENABLED policy with no `alert_ids` (at least one alert must be attached; nothing is created). For the `hunt_rule_ids` set, `code` is `INVALID_HUNT_RULE_IDS` (an entry that is not a well-formed, non-nil UUID, a duplicate, or a hunt-rule id that does not exist) or `HUNT_RULE_NOT_ACTIVE` when an id refers to a live rule whose status is not `active` (`tuning` or `inactive` rules are not egested and would never run). `CONNECTOR_VERSION_TOO_LOW` when the request turns on a scan capability (hunt, pursuit, data classification, or encryption detection) that a Cloud Connector the policy targets is too old to run; the message names each connector and the version it needs. Enforced only when Cloud Connector version checks are enabled for your tenant. Nothing is persisted or published on any 400."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossPlatformNameConflictError"}}},"description":"Conflict. `code` is `NAME_EXISTS_ON_OTHER_PLATFORM` when the name is already owned by a policy on another platform (then `platform` names it); `CLUSTER_TARGET_EXISTS` (IBM only: Azure allows many policies per cluster) when a differently-named IBM policy already targets the requested cluster; `CLUSTER_AMBIGUOUS` when a target cluster resolves to more than one deliverable connector; `UNIQUE_CONSTRAINT_CONFLICT` for any other unrecognized uniqueness violation; `POLICY_NOT_ENABLED` if ingestion reports a FailedPrecondition on the alert bind; `ALERT_MIGRATION_IN_PROGRESS` when the tenant's alerts V2->V3 migration is freezing binding writes (retry after it settles); and `CONFLICT` only for a genuine duplicate name on the same platform."},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommitOutcomeUnknownErrorResponse"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_AFTER_PERSIST` when the policy was saved but the publish to the Cloud Connector failed (delete it and retry); `COMPOSED_POLICY_INVALID` when the document composed for an Azure cluster failed validation (a server-side composition fault; nothing was published to that cluster); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the policy was saved but the effective document could not be built from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when the create transaction's commit outcome could not be resolved; nothing is claimed persisted (a retry can 409 if the attempt actually committed), and the body carries `policy_id`, the create's minted canonical id: the key for the conditional-update recovery flow (`expected_policy_id` on the v3 update)."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Ingestion sync failed closed. `code` is `ALERT_SYNC_UNAVAILABLE` when the alert binding OR the violation-override projection could not be synchronized to ingestion for a config-class reason (auth/permission, M2M token mint, or the just-created policy not visible to ingestion). The write fails closed and the just-created policy is rolled back, rather than silently succeeding with the alerts or overrides unsynced. Transient/availability sync failures do NOT surface here: the policy write proceeds best-effort."}},"summary":"Create policy v3 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/{name}":{"delete":{"description":"Admin only. Permanently deletes a policy by name across AWS, Azure, and IBM; the name resolves via one lookup of the authoritative `policies` table. As of this writes a terminal tombstone (an audit record that survives the removed row, with an optional recorded `reason`) before neutralizing the runtime: the row is still gone (wire-compatible 204), but the deletion is now audited. Azure/IBM resolve the cluster and publish one SetPolicies clear as before; a cluster that is no longer registered for the tenant is skipped.","operationId":"deletePolicyV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeleteReasonRequest"}}},"description":"Optional reason recorded on the tombstone."},"responses":{"204":{"description":"Policy deleted (a terminal tombstone was recorded)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `INVALID_REASON` when the optional `reason` exceeds 1024 runes, or `BAD_REQUEST` when the request body is malformed (undecodable JSON, unknown fields, or trailing content)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `CLUSTER_UNRESOLVED` when the non-AWS target cluster is still registered but does not resolve to exactly one deliverable connector (retry once the connector is active). The row is left intact either way."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; or `COMMIT_OUTCOME_UNKNOWN` when the AWS destruction transaction's commit outcome could not be resolved: the terminal tombstone is RETAINED beside the possibly-live policy (never compensated on an unresolved outcome) and the state settles on retry via the residue probes."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Snapshot capture failed closed. `code` is `SNAPSHOT_UNAVAILABLE` when the policy's alert bindings could not be read from ingestion (any failure class): the delete is aborted and the policy is untouched rather than destroying its bindings without recording them. An AWS policy whose canonical id is unresolvable degrades instead (a tombstone with a null `last_known_id`), except when an active deletion record already exists for the name, which also fails 502."}},"summary":"Delete policy by name v3 (Admin only)","tags":["Policies"]},"get":{"description":"Reads a single policy by name across AWS, Azure, and IBM, identically to the v2 get (the same single exact-name lookup of the authoritative `policies` table), and additionally carries the policy's `violations` selection. Viewer-readable.","operationId":"getPolicyV3","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyV3Response"}}},"description":"Policy"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"$ref":"#/components/responses/InternalError"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert read hydration failed closed. `code` is `ALERT_SYNC_UNAVAILABLE` when fetching the policy's alert bindings from ingestion failed for a config-class reason (auth/permission or M2M token mint). The read fails closed rather than masking an M2M misconfiguration by degrading `alert_ids` to `[]`. Transient/availability read failures do NOT surface here: `alert_ids` degrades to `[]` and the policy is still returned."}},"summary":"Get policy by name v3","tags":["Policies"]},"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"put":{"description":"Admin only. A strict superset of the v2 update: same platform-aware, platform-immutable behavior, plus the `violations` list. A v3 update fully replaces the stored selection: an omitted or empty `violations` clears it to `[]` (unlike a v2 update, which never touches it). Each supplied code is validated against the catalog dictionary before anything persists.\n\nOn AWS, `selectors` are capped at 300 KiB serialized; over that the request is rejected with 400 `POLICY_TOO_LARGE`. A larger policy cannot be delivered to the Cloud Connectors and would stop every policy in the tenant from syncing. Only enumerated (`assets`) selectors can reach this size; `is_type` and `has_tags` are constant-size however many assets they match.","operationId":"updatePolicyV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePolicyV3Request"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyV3Response"}}},"description":"Updated policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyYAMLValidationErrorResponse"}}},"description":"Bad request. `code` is `VALIDATION_ERROR` for a malformed request; for an Azure/IBM policy whose `cluster_options.policy_yaml` fails strict validation, `code` is `POLICY_YAML_INVALID` and the body carries the structured `issues` array. For the `violations` list, `code` is `INVALID_VIOLATION_CODE`, `INVALID_SEVERITY_OVERRIDE`, or `DUPLICATE_VIOLATION_CODE`. For the `r_rpo` target, `code` is `INVALID_RRPO_TARGET`, `INVALID_RRPO_SEVERITY`, or `RESERVED_VIOLATION_CODE` (`r_rpo_exceeded` listed in `violations`). For the `alert_ids` set, `code` is `INVALID_ALERT_IDS` (an entry that is not a well-formed, non-nil UUID, a duplicate, or an alert id ingestion does not recognize (the existing policy is left unchanged)) or `ALERT_REQUIRED` when alert synchronization is enabled and the update would leave an ENABLED policy with no bound alerts (a present `[]`, or an omitted `alert_ids` when no bindings exist). For the `hunt_rule_ids` set, `code` is `INVALID_HUNT_RULE_IDS` (an entry that is not a well-formed, non-nil UUID, a duplicate, or a hunt-rule id that does not exist) or `HUNT_RULE_NOT_ACTIVE` when an id refers to a live rule whose status is not `active`. `CONNECTOR_VERSION_TOO_LOW` when the update turns on a scan capability the stored policy did not have on, and a Cloud Connector the policy targets is too old to run it (a capability that was already on is never refused). Enforced only when Cloud Connector version checks are enabled for your tenant. Nothing is persisted or published on any 400."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrossPlatformNameConflictError"}}},"description":"Conflict. `code` is `NAME_EXISTS_ON_OTHER_PLATFORM` when the name is owned by a policy on another platform (then `platform` names it); `CLUSTER_NAME_IMMUTABLE` (IBM only) when the request changes the immutable `cluster_name`; `CLUSTER_AMBIGUOUS` when a target cluster resolves to more than one deliverable connector; `POLICY_NOT_ENABLED` if ingestion reports a FailedPrecondition on the alert bind; `ALERT_MIGRATION_IN_PROGRESS` when the tenant's alerts V2->V3 migration is freezing binding writes and reads (retry after it settles); or `EXPECTED_POLICY_ID_MISMATCH` when the name is still owned but not by the request's `expected_policy_id`: it was replaced by a different-id policy (on any platform), or its canonical id is unresolvable; the policy and any same-name replacement are left untouched (a name that is truly gone is a 404, not this conflict). The policy is left unchanged."},"412":{"$ref":"#/components/responses/PreconditionFailedError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_RETRY` when the change was saved but the publish to the Cloud Connector failed (retry the operation (never delete); `COMPOSED_POLICY_INVALID` when the document composed for an Azure cluster failed validation (a server-side composition fault; nothing was published to that cluster); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the change was saved but the effective document could not be built from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS update transaction's commit outcome could not be resolved) nothing is claimed persisted either way and no compensation or ingestion restoration ran (a retry converges the database state)."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Ingestion sync failed closed. `code` is `ALERT_SYNC_UNAVAILABLE` when the alert binding OR the violation-override projection could not be synchronized to ingestion for a config-class reason (auth/permission, M2M token mint, or the policy not visible to ingestion). Both reconciles happen before the policy is mutated, so the policy is left unchanged rather than silently diverging from ingestion. Transient/availability sync failures do NOT surface here: the policy write proceeds best-effort."}},"summary":"Update policy v3 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/{name}/pause":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Exact v2 reproduction (no violations dimension): platform-aware pause across AWS, Azure, and IBM. The body is required: a present `paused_until` sets `status = paused_until`, an empty body (`{}`) sets `status = disabled`, and a missing/empty body is 400. Delegates to the v2 pause service method.","operationId":"pausePolicyV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseRequest"}}},"required":true},"responses":{"204":{"description":"Policy paused"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `CLUSTER_UNRESOLVED` when the resolved Azure/IBM cluster is not currently deliverable (no status change is published: retry once the connector is active)."},"412":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Precondition failed (`code` `PRECONDITION_FAILED`). The stored canonical `policy_yaml` is missing/empty or malformed, so the effective document cannot be derived. `status` is unchanged and nothing is published; repair the policy via a v3 update, then retry."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_RETRY` when the status was saved but the publish to the Cloud Connector failed (retry the operation (never delete); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the status was saved but the effective document could not be built from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS status transaction's commit outcome could not be resolved) nothing is claimed persisted either way (a retry converges)."}},"summary":"Pause policy v3 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/{name}/resume":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Exact v2 reproduction (no violations dimension): platform-aware resume across AWS, Azure, and IBM. Azure/IBM set `status = enabled` and re-publish the canonical `policy_yaml` byte-identically. Takes no body. Delegates to the v2 resume service method.","operationId":"resumePolicyV3","responses":{"204":{"description":"Policy resumed"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `CLUSTER_UNRESOLVED` when the resolved Azure/IBM cluster is not currently deliverable (no status change is published: retry once the connector is active)."},"412":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Precondition failed (`code` `PRECONDITION_FAILED`). Resume runs the same derivability validation as pause; if the stored canonical `policy_yaml` is missing/empty or malformed, `status` is unchanged and nothing is published: repair the policy via a v3 update, then retry."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; `PUBLISH_FAILED_RETRY` when the status was saved but the publish to the Cloud Connector failed (retry the operation (never delete); `EFFECTIVE_POLICY_DERIVATION_FAILED_AFTER_PERSIST` when the status was saved as `enabled` but the canonical document could not be re-validated from the persisted row (repair the policy and retry); or `COMMIT_OUTCOME_UNKNOWN` when an AWS status transaction's commit outcome could not be resolved) nothing is claimed persisted either way (a retry converges)."}},"summary":"Resume policy v3 (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/{name}/run":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Dispatches an immediate run of an already-saved policy and returns the parent job id. Takes no body and writes nothing: the schedule, selectors, and status are untouched, so a run cannot alter the policy.\n\nThis is NOT the retired execute-now surface. `execute_immediately` on create/update stays rejected and `POST /shared-services/v1/policies/{name}/execute` stays a 410 tombstone: both were removed because an execution inferred from a write reported success for work that never happened. An explicitly requested run of an existing policy has no such ambiguity, and dispatch failures here are surfaced rather than swallowed.\n\nAWS only: Azure/IBM policies are delivered as cluster YAML and have no per-connector execute job. One child job is dispatched per active Cloud Connector, rolling up under the returned parent.","operationId":"runPolicyNowV3","responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunPolicyResponse"}}},"description":"Run dispatched. `job_id` is the parent job the per-connector children roll up under; poll it for progress."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `POLICY_RUN_NOT_SUPPORTED` when the policy is not an AWS policy, or `NO_ACTIVE_CONNECTORS` when the tenant has no active Cloud Connectors to run it on: nothing is dispatched in either case, rather than returning a parent job no worker would adopt."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Run policy on demand (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/{name}/soft-delete":{"parameters":[{"$ref":"#/components/parameters/PolicyName"}],"post":{"description":"Admin only. Reversibly deletes a scheduled policy: snapshots its prior state (including fail-closed-hydrated `alert_ids`), records an active deletion keyed by its canonical id, and neutralizes the runtime; the policy leaves the live list but can be restored from the deleted-policies recovery list. An optional `reason` is recorded.","operationId":"softDeletePolicyV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeleteReasonRequest"}}},"description":"Optional reason recorded on the deletion record."},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeletionResponse"}}},"description":"The active deletion record (the UI's undo affordance keys on its `id`)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `INVALID_REASON` when the optional `reason` exceeds 1024 runes, or `BAD_REQUEST` when the request body is malformed."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `ALREADY_DELETED` when an active deletion already exists for this scheduled name (restore or permanently delete it first); `CLUSTER_UNRESOLVED` when a non-AWS target cluster is still registered but does not resolve to exactly one deliverable connector."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; or `COMMIT_OUTCOME_UNKNOWN` when the AWS destruction transaction's commit outcome could not be resolved: the deletion record and its snapshot are RETAINED (never compensated on an unresolved outcome) and the state settles on retry via the residue probes."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Snapshot capture failed closed. `code` is `SNAPSHOT_UNAVAILABLE` when the policy's alert bindings could not be read from ingestion (any failure class) or the canonical id is unresolvable: nothing is written and the policy is untouched."}},"summary":"Soft-delete a scheduled policy by name (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/deleted":{"get":{"description":"Lists the tenant's active policy deletions of BOTH kinds (scheduled and event), ordered by `deleted_at` descending: the deleted-policies recovery list. Viewer-readable. No pagination or filters.","operationId":"listDeletedPoliciesV3","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListPolicyDeletionsResponse"}}},"description":"Active deletions of both kinds."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"List active policy deletions","tags":["Policies"]}},"/gateway/shared-services/v3/policies/deleted/{id}":{"delete":{"description":"Admin only. Terminalizes an active soft-deletion record as hard-deleted: the deleted-policies page's permanent delete. Completes a crashed soft-delete's neutralization if one is still pending, then settles the record. Serves both kinds (the record's `kind` dispatches). An optional `reason` is recorded.","operationId":"terminalizeDeletedPolicyV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeleteReasonRequest"}}},"description":"Optional reason recorded on the record."},"responses":{"204":{"description":"The record was settled as hard-deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request. `code` is `INVALID_REASON` when the optional `reason` exceeds 1024 runes, or `BAD_REQUEST` when the request body is malformed or the `{id}` path segment is not a well-formed UUID."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"No deletion record with this id (`code` `DELETION_NOT_FOUND`)."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"The record is already settled (restored or hard-deleted): `code` is `DELETION_NOT_ACTIVE`. A restored record cannot later be hard-deleted, and vice versa (the lifecycle CHECK holds)."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `INTERNAL_ERROR`; or `COMMIT_OUTCOME_UNKNOWN` when the residue-repair neutralize's commit outcome could not be resolved: the record stays active (never settled on an unknown outcome); retry."}},"summary":"Permanently delete a soft-deleted policy (Admin only)","tags":["Policies"]},"get":{"description":"Returns one deletion record in any state (soft-deleted, restored, or hard-deleted) with its full audit columns and the verbatim `prior_snapshot`. Serves both kinds (the record's `kind` dispatches). Viewer-readable.","operationId":"getDeletedPolicyV3","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeletionResponse"}}},"description":"The deletion record."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request: the `{id}` path segment is not a well-formed UUID (`code` `BAD_REQUEST`)."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"No deletion record with this id (`code` `DELETION_NOT_FOUND`)."},"500":{"$ref":"#/components/responses/InternalError"}},"summary":"Read one policy deletion / tombstone","tags":["Policies"]},"parameters":[{"$ref":"#/components/parameters/DeletionID"}]},"/gateway/shared-services/v3/policies/deleted/{id}/restore":{"parameters":[{"$ref":"#/components/parameters/DeletionID"}],"post":{"description":"Admin only. Re-creates the policy from its snapshot with its ORIGINAL id and prior config (via the record's `kind`), re-syncs its alert bindings, re-pushes the ingestion violation-override projection, and clears the active deletion. Id-stable, so all cross-system wiring (alert bindings, `X-Policy-Ids` scopes, asset memberships, hunt-rule bindings) re-attaches. Serves both kinds.","operationId":"restoreDeletedPolicyV3","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyDeletionResponse"}}},"description":"The updated deletion record (now with `restored_at`/`restored_by` set). The response-only `bound_alert_ids` reports what actually re-bound."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyYAMLValidationErrorResponse"}}},"description":"The snapshot fails create-time re-validation (drift/corruption): `code` is `VALIDATION_ERROR` (invalid name/selectors/frequency, or the event-kind validators), or `POLICY_YAML_INVALID` with the structured `issues` array for an invalid non-AWS `policy_yaml`; also `BAD_REQUEST` when the `{id}` path segment is not a well-formed UUID. Nothing is recreated."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"No deletion record with this id (`code` `DELETION_NOT_FOUND`)."},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict. `code` is `DELETION_NOT_ACTIVE` when the record is already settled; `NAME_IN_USE` when the name is live again within the record's kind (a different-id occupant, an unresolvable-id occupant, or a concurrent create/restore hitting the recreate backstop); or `ALERT_MIGRATION_IN_PROGRESS` when the tenant's alerts V2->V3 migration is freezing binding writes: like the config-class 502, the recreate is rolled back and the deletion record stays active, retryable after the migration settles."},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error. `code` is `SNAPSHOT_VERSION_UNSUPPORTED` when the persisted snapshot envelope version is not 1 (defensive), or `INTERNAL_ERROR`: including a true infrastructure failure of the AWS recreate transaction (the authoritative `policies` insert), which is rolled back, leaving the deletion record active (retryable)."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Alert re-bind failed closed. `code` is `ALERT_SYNC_UNAVAILABLE` when the re-bind failed for a config-class reason (auth/permission or M2M token mint): the recreate is rolled back and the deletion record stays active, retryable after the fix. If that rollback itself fails or its commit outcome is unresolvable, the record still stays active but a live policy may linger until the next restore attempt re-drives it (server-logged; the binding error remains the response). Other re-bind failure classes keep the restore and degrade the bound set."}},"summary":"Restore a soft-deleted policy (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/policies/pursuit-playbooks":{"get":{"description":"Returns the static catalog of built-in pursuit playbook names available on Cloud Connector images. The names are baked into the CC Docker image at build time; this endpoint lets clients discover valid `built_in` values for pursuit scan options without needing a live CC.","operationId":"listPursuitPlaybooks","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BuiltInPursuitPlaybooksResponse"}}},"description":"Built-in pursuit playbooks"}},"summary":"List built-in pursuit playbooks","tags":["Policies"]}},"/gateway/shared-services/v3/policies:validate":{"post":{"description":"Admin only. Exact v2 reproduction (no violations dimension): side-effect-free preflight of a non-AWS create. Runs the same `policy_yaml` validation and DB-backed reference checks as v2 and returns every finding as a structured issue without persisting or publishing anything. A processed document always returns 200; 400 is reserved for a malformed envelope. Delegates to the v2 validate service method.","operationId":"validatePolicyYAMLV3","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePolicyYAMLRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatePolicyYAMLResponse"}}},"description":"Validation completed. `valid` is true with an empty `issues` array when the document and all references are acceptable; otherwise `valid` is false and `issues` lists every problem found in one pass, sorted and capped (a final `ISSUES_TRUNCATED` when more than 100 are found)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Malformed envelope (`code` `VALIDATION_ERROR`): undecodable JSON, a body over the 5 MiB limit, a missing/unsupported `platform` (including `AWS`, which carries no `policy_yaml`), or an empty `platform`, `name`, `cluster_name`, or `policy_yaml`."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Server error (`code` `INTERNAL_ERROR`). A database/transport error during the reference-resolution stage means validation could not complete, so the request fails rather than returning a 200 with partial issues."}},"summary":"Validate a v3 Azure/IBM policy_yaml (Admin only)","tags":["Policies"]}},"/gateway/shared-services/v3/system-events/catalog":{"get":{"description":"Returns every system event kind, including kinds that are not emitted yet (`available: false`). Unavailable kinds are served rather than hidden so a client can render the full shape of the capability and grey out what is not live; hiding them would make a partly-landed rollout look like a smaller product instead of an in-progress one. The response is ordered by display group, then by event kind. Viewer-readable.","operationId":"listSystemEventCatalog","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemEventCatalogResponse"}}},"description":"The full catalog"},"401":{"$ref":"#/components/responses/SystemEventsUnauthorizedError"},"500":{"$ref":"#/components/responses/SystemEventsInternalError"}},"summary":"List the operational event vocabulary","tags":["System Events"]}},"/gateway/shared-services/v3/system-events/subscriptions":{"get":{"deprecated":true,"description":"Per-event subscriptions were replaced by System Policies. An alert attaches to a System Policy, which selects the system events.","operationId":"listSystemEventSubscriptions","responses":{"410":{"$ref":"#/components/responses/SystemEventsSubscriptionsRetired"}},"summary":"Retired, use System Policies","tags":["System Events"]},"put":{"deprecated":true,"description":"Per-event subscriptions were replaced by System Policies. An alert attaches to a System Policy, which selects the system events.","operationId":"replaceSystemEventSubscriptions","responses":{"410":{"$ref":"#/components/responses/SystemEventsSubscriptionsRetired"}},"summary":"Retired, use System Policies","tags":["System Events"]}},"/gateway/shared-services/v3/system-policies":{"get":{"description":"Returns every system policy of the tenant, seeded first. Never creates one: a tenant not yet cut over to System Policies gets an empty list. Viewer-readable.","operationId":"listSystemPolicies","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyList"}}},"description":"The tenant's system policies"},"401":{"$ref":"#/components/responses/SystemPolicyUnauthorized"},"500":{"$ref":"#/components/responses/SystemPolicyInternalError"}},"summary":"List the tenant's system policies","tags":["System Policies"]}},"/gateway/shared-services/v3/system-policies/{id}":{"delete":{"description":"Seeded policies cannot be deleted (409 SEEDED_POLICY). Admin only.","operationId":"deleteSystemPolicy","responses":{"204":{"description":"Deleted"},"404":{"$ref":"#/components/responses/SystemPolicyNotFound"},"409":{"$ref":"#/components/responses/SystemPolicyConflict"},"502":{"$ref":"#/components/responses/SystemPolicyAlertSyncUnavailable"}},"summary":"Delete a system policy","tags":["System Policies"]},"get":{"operationId":"getSystemPolicy","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicy"}}},"description":"The policy"},"404":{"$ref":"#/components/responses/SystemPolicyNotFound"}},"summary":"Get a system policy","tags":["System Policies"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"put":{"description":"Absent fields keep their stored value. `alert_ids`, when present, replaces the attached alerts and needs at least one. `event_severities`, when present, replaces the stored overrides (`[]` clears them); when absent they are kept, except that a policy that does not set `all_event_kinds` drops the overrides for kinds its edited `event_kinds` no longer covers. The Unprotected Assets policy takes no event kinds, scope or severity overrides. Admin only.","operationId":"updateSystemPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyUpdate"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicy"}}},"description":"The updated policy"},"400":{"$ref":"#/components/responses/SystemPolicyBadRequest"},"404":{"$ref":"#/components/responses/SystemPolicyNotFound"},"409":{"$ref":"#/components/responses/SystemPolicyConflict"},"502":{"$ref":"#/components/responses/SystemPolicyAlertSyncUnavailable"}},"summary":"Update a system policy","tags":["System Policies"]}},"/gateway/shared-services/v3/yara-rules":{"get":{"description":"Lists the tenant's live YARA rules. Viewer-readable.","operationId":"listYaraRules","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListYaraRulesResponse"}}},"description":"YARA rules list"},"401":{"$ref":"#/components/responses/UnauthorizedError"}},"summary":"List YARA rules","tags":["Hunt Rules"]},"post":{"description":"Parser-v0 extracts one signature per `rule X {}` block; zero blocks → 400 NO_RULES_FOUND (nothing saved). Name defaults to the first rule identifier. Version 1 is snapshotted and RULE_IMPORT audited. Admin-only. Multipart upload and git-sync are later phases.","operationId":"createYaraRule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRuleCreateRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRuleResponse"}}},"description":"Imported YARA rule (with signatures)."},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"A live YARA rule with this name already exists."}},"summary":"Import a YARA rule (pasted body)","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rules/{id}":{"delete":{"description":"Stamps deleted_at and frees the name; version/audit history survives. Blocked with 409 `DELETE_BLOCKED` while a live hunt `yara_refs` this file (`blocking_hunt_rules` lists them). Admin-only.","operationId":"deleteYaraRule","responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRefDeleteBlockedError"}}},"description":"A live hunt pins this file (DELETE_BLOCKED)."}},"summary":"Soft-delete a YARA rule","tags":["Hunt Rules"]},"get":{"description":"Returns one live YARA rule including its body. Viewer-readable.","operationId":"getYaraRule","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRuleResponse"}}},"description":"YARA rule"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Get a YARA rule","tags":["Hunt Rules"]},"parameters":[{"description":"The YARA rule id (UUID).","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"patch":{"description":"PATCH semantics: omitted preserves, present replaces. A body change re-parses signatures (tuning preserved by signature id) and bumps the version; metadata-only patches update in place. Admin-only.","operationId":"updateYaraRule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRuleUpdateRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRuleResponse"}}},"description":"Updated YARA rule."},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Rename collides with an existing live YARA rule name."}},"summary":"Update a YARA rule","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rules/{id}/audit-log":{"get":{"description":"Append-only operator actions, newest first. Viewer-readable.","operationId":"getYaraRuleAuditLog","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRuleAuditResponse"}}},"description":"Audit entries"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"List a YARA rule's audit entries","tags":["Hunt Rules"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"description":"Comma-separated audit-action filter.","in":"query","name":"action","schema":{"type":"string"}}]},"/gateway/shared-services/v3/yara-rules/{id}/revert":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"post":{"description":"Creates a NEW version copying the target snapshot's body. Admin-only.","operationId":"revertYaraRule","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevertRuleRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRuleResponse"}}},"description":"The rule at its new (reverted-content) version."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Revert a YARA rule to an earlier version","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rules/{id}/signatures/{signatureId}/toggle":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"in":"path","name":"signatureId","required":true,"schema":{"type":"string"}}],"post":{"description":"No version bump; tuning survives content re-parses. Admin-only.","operationId":"toggleYaraRuleSignature","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleRuleSignatureRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleRuleSignatureResponse"}}},"description":"The updated signature."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Enable / disable a single YARA signature","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rules/{id}/versions":{"get":{"description":"Immutable content snapshots, newest first. Viewer-readable.","operationId":"listYaraRuleVersions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRuleVersionsResponse"}}},"description":"Version snapshots"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"List a YARA rule's version snapshots","tags":["Hunt Rules"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}]},"/gateway/shared-services/v3/yara-rulesets":{"get":{"description":"Lists the tenant's live YARA rulesets (packs). List stays lean (no `files`). Viewer-readable.","operationId":"listYaraRulesets","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListYaraRulesetsResponse"}}},"description":"YARA rulesets list"},"401":{"$ref":"#/components/responses/UnauthorizedError"}},"summary":"List YARA rulesets","tags":["Hunt Rules"]},"post":{"description":"Accepts `multipart/form-data` (repeated `files` parts: `.yar` / `.yara` or one `.zip` / `.tar.gz`) or JSON `{ name, files: [{ name, content }] }`. Non-YARA members are ignored. Zero parseable `rule` blocks → 400 `NO_RULES_FOUND`. Parser-v0 only; `RULESET_COMPILE_FAILED` and `DUPLICATE_IDENTIFIER` are reserved for a later libyara compile pass and are not produced yet. Admin-only.","operationId":"createYaraRuleset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRulesetCreateRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/YaraRulesetMultipartRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRulesetResponse"}}},"description":"Imported YARA ruleset"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"`NO_RULES_FOUND` (nothing saved). `PAYLOAD_TOO_LARGE` when the unpacked pack exceeds 20MiB or 1024 YARA files. `RULESET_COMPILE_FAILED` and `DUPLICATE_IDENTIFIER` are reserved and not emitted yet."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"A live ruleset with this name or path already exists."}},"summary":"Import a YARA ruleset","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rulesets/{id}":{"delete":{"description":"Stamps deleted_at and frees the name; version/audit history survives. Blocked with 409 `DELETE_BLOCKED` while a live hunt `yara_refs` this ruleset (`blocking_hunt_rules` lists them). Admin-only.","operationId":"deleteYaraRuleset","responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRefDeleteBlockedError"}}},"description":"A live hunt pins this ruleset (DELETE_BLOCKED)."}},"summary":"Soft-delete a YARA ruleset","tags":["Hunt Rules"]},"get":{"description":"Detail includes `files` metadata (`name`, `size`, `signature_count`) without bodies. Viewer-readable.","operationId":"getYaraRuleset","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRulesetResponse"}}},"description":"YARA ruleset"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Get a YARA ruleset","tags":["Hunt Rules"]},"parameters":[{"description":"The YARA ruleset id (UUID).","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"patch":{"description":"PATCH: omitted preserves. `path` and `kind` are immutable (sending them is 400 `BAD_REQUEST`). A present `files` array replaces the pack (including `[]`, which is 400 `NO_RULES_FOUND`). A files change re-parses signatures and bumps the version. `RULESET_COMPILE_FAILED` / `DUPLICATE_IDENTIFIER` are reserved. Admin-only.","operationId":"updateYaraRuleset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRulesetUpdateRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/YaraRulesetMultipartRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRulesetResponse"}}},"description":"Updated YARA ruleset"},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Rename collides with an existing live ruleset name or path."}},"summary":"Update a YARA ruleset","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rulesets/{id}/audit-log":{"get":{"description":"Newest first. Viewer-readable.","operationId":"getYaraRulesetAuditLog","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRuleAuditResponse"}}},"description":"Audit entries"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Get a YARA ruleset's audit log","tags":["Hunt Rules"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"in":"query","name":"action","schema":{"type":"string"}}]},"/gateway/shared-services/v3/yara-rulesets/{id}/revert":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"post":{"description":"Copies the target snapshot onto the live row as a NEW version (history stays linear). Admin-only.","operationId":"revertYaraRuleset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevertRuleRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/YaraRulesetResponse"}}},"description":"The ruleset after revert (new current version)."},"400":{"$ref":"#/components/responses/BadRequestError"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Revert a YARA ruleset to a prior version","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rulesets/{id}/signatures/{signatureID}/toggle":{"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},{"in":"path","name":"signatureID","required":true,"schema":{"type":"string"}}],"post":{"description":"No version bump; tuning survives content re-parses. Admin-only.","operationId":"toggleYaraRulesetSignature","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleRuleSignatureRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToggleRuleSignatureResponse"}}},"description":"The updated signature."},"401":{"$ref":"#/components/responses/UnauthorizedError"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"Enable / disable a single ruleset signature","tags":["Hunt Rules"]}},"/gateway/shared-services/v3/yara-rulesets/{id}/versions":{"get":{"description":"Immutable content snapshots, newest first. Viewer-readable. Snapshots keep `files[].body`.","operationId":"listYaraRulesetVersions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListRuleVersionsResponse"}}},"description":"Version snapshots"},"401":{"$ref":"#/components/responses/UnauthorizedError"},"404":{"$ref":"#/components/responses/NotFoundError"}},"summary":"List a YARA ruleset's version snapshots","tags":["Hunt Rules"]},"parameters":[{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}]},"/gateway/reporting/v1/reports":{"get":{"tags":["Reports"],"summary":"List reports","description":"Returns a paginated list of reports for the tenant. `pageSize` is\nsilently capped at 100; values above 100 are reduced to 100 in the\nresponse.\n","operationId":"listReports","parameters":[{"name":"page","in":"query","required":false,"description":"1-based page number. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Page size. Defaults to `20`. Values above `100` are accepted but\nsilently capped to `100` in the response: the returned\n`pageSize` field reflects the effective value, not the\nrequested one.\n","schema":{"type":"integer","minimum":1,"default":20}},{"name":"platform","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Platform"}},{"name":"template","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Template"}},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ReportStatus"}},{"name":"createdFrom","in":"query","required":false,"description":"Inclusive lower bound on `createdAt`, RFC 3339.","schema":{"type":"string","format":"date-time"}},{"name":"createdTo","in":"query","required":false,"description":"Inclusive upper bound on `createdAt`, RFC 3339. Must not be earlier than `createdFrom`.","schema":{"type":"string","format":"date-time"}},{"name":"search","in":"query","required":false,"description":"Case-insensitive substring matched against report title and\ndescription (OR). A trimmed query whose length falls outside\n[2, 200] returns 400. Whitespace-only or absent values mean\n\"no search filter\".\n","schema":{"type":"string","minLength":2,"maxLength":200}}],"responses":{"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"401":{"description":"Invalid gateway signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"403":{"description":"Admin or API scope required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"404":{"description":"Flag disabled or resource unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"429":{"description":"Capacity or request budget exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"500":{"description":"Execution failed","content":{"200":{"description":"Paginated list of reports.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportListResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"},"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}}}},"post":{"tags":["Reports"],"summary":"Create a report","description":"Enqueues a new report job and returns its initial metadata. Admin\nonly: requires `X-User-Role: admin`.\n\nThe request body must be a single JSON object no larger than\n64 KB. `failed-scans` is not available for the `onprem` platform.\n","operationId":"createReport","parameters":[{"$ref":"#/components/parameters/XUserRoleAdmin"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReportRequest"}}}},"responses":{"202":{"description":"Report accepted and enqueued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReportResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v1/reports/{id}":{"get":{"tags":["Reports"],"summary":"Get a report","description":"Returns the full report payload. The report must be in `ready`\nstatus; in-flight or failed reports respond `409 REPORT_NOT_READY`.\n","operationId":"getReport","parameters":[{"$ref":"#/components/parameters/ReportId"}],"responses":{"200":{"description":"Report payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportDetail"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/NotReady"},"500":{"$ref":"#/components/responses/InternalError1"}}},"delete":{"tags":["Reports"],"summary":"Delete a report","description":"Soft-deletes the report. Admin only: requires `X-User-Role: admin`.\n","operationId":"deleteReport","parameters":[{"$ref":"#/components/parameters/ReportId"},{"$ref":"#/components/parameters/XUserRoleAdmin"}],"responses":{"204":{"description":"Report soft-deleted; no body."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v1/reports/{id}/status":{"get":{"tags":["Reports"],"summary":"Get report status","description":"Returns the report's current status without the full payload.\nSuitable for polling in-flight jobs. Failed reports return `200`\nwith the failure detail in the body's `error` field; the HTTP\nstatus remains `200`.\n","operationId":"getReportStatus","parameters":[{"$ref":"#/components/parameters/ReportId"}],"responses":{"200":{"description":"Report status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportStatusResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v2/reports":{"get":{"tags":["Reports"],"summary":"List v2 reports","description":"Returns a paginated list of the tenant's v2 (tenant-wide) reports.\nScoped to the v2 family: `platform` accepts only `all` and `template`\nonly the v2 slugs; v1 reports never appear. `pageSize` is capped at\n100 as in v1.\n","operationId":"listReportsV2","parameters":[{"name":"page","in":"query","required":false,"description":"1-based page number. Defaults to `1`.","schema":{"type":"integer","minimum":1,"default":1}},{"name":"pageSize","in":"query","required":false,"description":"Page size. Defaults to `20`; values above `100` are silently capped to `100`.","schema":{"type":"integer","minimum":1,"default":20}},{"name":"platform","in":"query","required":false,"schema":{"$ref":"#/components/schemas/V2Platform"}},{"name":"template","in":"query","required":false,"schema":{"$ref":"#/components/schemas/V2Template"}},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ReportStatus"}},{"name":"createdFrom","in":"query","required":false,"description":"Inclusive lower bound on `createdAt`, RFC 3339.","schema":{"type":"string","format":"date-time"}},{"name":"createdTo","in":"query","required":false,"description":"Inclusive upper bound on `createdAt`, RFC 3339. Must not be earlier than `createdFrom`.","schema":{"type":"string","format":"date-time"}},{"name":"search","in":"query","required":false,"description":"Case-insensitive substring matched against report title and\ndescription (OR). A trimmed query whose length falls outside\n[2, 200] returns 400.\n","schema":{"type":"string","minLength":2,"maxLength":200}}],"responses":{"200":{"description":"Paginated list of v2 reports.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportListResponseV2"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError1"}}},"post":{"tags":["Reports"],"summary":"Create a v2 report","description":"Enqueues a new tenant-wide report job and returns its initial\nmetadata. Admin only: requires `X-User-Role: admin`.\n\n`platform` must be `all`. `template` must be an enabled v2 slug;\na slug that is registered but not enabled for this deployment is\nrejected. `filters` is validated against the template's filter\nspec: unknown keys, or values not allowed for the template, are\nrejected with `400`.\n","operationId":"createReportV2","parameters":[{"$ref":"#/components/parameters/XUserRoleAdmin"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReportRequestV2"}}}},"responses":{"202":{"description":"Report accepted and enqueued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateReportResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v2/reports/{id}":{"get":{"tags":["Reports"],"summary":"Get a v2 report","description":"Returns the full v2 report payload. The report must be in `ready`\nstatus; in-flight or failed reports respond `409 REPORT_NOT_READY`.\nA v1 id is not visible here and responds `404`.\n","operationId":"getReportV2","parameters":[{"$ref":"#/components/parameters/ReportId"}],"responses":{"200":{"description":"Report payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportDetailV2"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/NotReady"},"500":{"$ref":"#/components/responses/InternalError1"}}},"delete":{"tags":["Reports"],"summary":"Delete a v2 report","description":"Soft-deletes the v2 report. Admin only: requires `X-User-Role: admin`.\nA v1 id is not visible here and responds `404`.\n","operationId":"deleteReportV2","parameters":[{"$ref":"#/components/parameters/ReportId"},{"$ref":"#/components/parameters/XUserRoleAdmin"}],"responses":{"204":{"description":"Report soft-deleted; no body."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v2/reports/{id}/status":{"get":{"tags":["Reports"],"summary":"Get v2 report status","description":"Returns the v2 report's current status without the full payload.\nFailed reports return `200` with the failure detail in `error`.\nA v1 id is not visible here and responds `404`.\n","operationId":"getReportStatusV2","parameters":[{"$ref":"#/components/parameters/ReportId"}],"responses":{"200":{"description":"Report status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportStatusResponse"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v2/schedules":{"get":{"tags":["Report Schedules"],"summary":"List report schedules","description":"Returns every live schedule for the tenant as `{items, total}`: no pagination; the per-tenant cap bounds the list. Ordered by\n`created_at` descending, `id` descending as the tiebreak.\n","operationId":"listSchedules1","responses":{"200":{"description":"The tenant's live schedules.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError1"}}},"post":{"tags":["Report Schedules"],"summary":"Create a report schedule","description":"Creates a scheduled report. Admin only. `name` and `template` are\nrequired; every omitted optional defaults (`period: last_7_days`,\n`cadence: daily`, `format: csv`, `filters: {}`, `delivery: {}`,\n`enabled: true`, and `cadence_config` contextually per the\neffective cadence; `{}` for `hourly`, `{\"time_utc\":\"08:00\"}` for\n`daily`; `weekly` and `monthly` have no sane default and reject an\nomitted config with `400`).\n\n`template` passes the same gate as `POST /reporting/v2/reports`\nand `filters` validates against the template's filter spec. The\nserver owns `id`, `created_at`, `created_by`, `last_run_at`,\n`next_run_at`, and `sync_status`; sending them (or any unknown\nkey, or an explicit `null` for an optional key) is a `400`.\n","operationId":"createSchedule1","parameters":[{"$ref":"#/components/parameters/XUserRoleAdmin"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScheduleRequest1"}}}},"responses":{"201":{"description":"Schedule created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleWire"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/ScheduleCapExceeded"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v2/schedules/{id}":{"get":{"tags":["Report Schedules"],"summary":"Get a report schedule","operationId":"getSchedule1","parameters":[{"$ref":"#/components/parameters/ScheduleId"}],"responses":{"200":{"description":"The schedule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleWire"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/ScheduleNotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}},"patch":{"tags":["Report Schedules"],"summary":"Update a report schedule","description":"Partial merge over the create-request keys; the merged document is\nrevalidated through the full create path. A PATCH that changes\n`cadence` and omits `cadence_config` receives the new cadence's\ncontextual default (`400` for `weekly`/`monthly`, same as create).\nAny mutation resets `sync_status` to `pending`. Admin only.\n","operationId":"updateSchedule1","parameters":[{"$ref":"#/components/parameters/ScheduleId"},{"$ref":"#/components/parameters/XUserRoleAdmin"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScheduleRequest1"}}}},"responses":{"200":{"description":"The updated schedule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleWire"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/ScheduleNotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}},"delete":{"tags":["Report Schedules"],"summary":"Delete a report schedule","description":"Deletes the schedule and returns `204` immediately; the id\nvanishes from list, GET, and PATCH at once. Admin only.\n","operationId":"deleteSchedule1","parameters":[{"$ref":"#/components/parameters/ScheduleId"},{"$ref":"#/components/parameters/XUserRoleAdmin"}],"responses":{"204":{"description":"Schedule deleted."},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/ScheduleNotFound"},"500":{"$ref":"#/components/responses/InternalError1"}}}},"/gateway/reporting/v1/eql/datasets":{"get":{"tags":["EQL"],"operationId":"listEQLDatasets","summary":"Discover EQL datasets and capabilities","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLCatalog"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}}}},"/gateway/reporting/v1/eql/draft":{"post":{"tags":["EQL"],"operationId":"draftEQLReport","summary":"Draft EQL from a natural-language report request","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. Sends intent and public catalog definitions to Azure OpenAI, not customer rows. Returns compiled EQL or a clarification; never executes, saves or schedules. Use the selected past UTC period, at most 90 days. Maximum prompt 4000 bytes. Two active EQL requests per process, one per tenant, ten attempts per tenant per minute; AI additionally capped at 30/minute and 1000/day per process. No automatic retries.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLDraft"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"422":{"description":"Generated EQL did not pass validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"},"502":{"description":"Provider unavailable or invalid output","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"503":{"description":"AI not configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLDraftRequest"}}}}}},"/gateway/reporting/v1/eql/query":{"post":{"tags":["EQL"],"operationId":"previewEQLReport","summary":"Preview a bounded EQL report","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLResult"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLRequest"}}}}}},"/gateway/reporting/v1/eql/reports":{"post":{"tags":["EQL"],"operationId":"createEQLReport","summary":"Generate and save an EQL report","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLReport"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLRequest"}}}}},"get":{"tags":["EQL"],"operationId":"listEQLReports","summary":"List saved EQL reports","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLReportPage"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":10000,"default":1}}]}},"/gateway/reporting/v1/eql/reports/{id}":{"get":{"tags":["EQL"],"operationId":"getEQLReport","summary":"Get a saved EQL report and its query","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLReport"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/gateway/reporting/v1/eql/reports/{id}/pdf":{"get":{"tags":["EQL"],"operationId":"downloadEQLReportPDF","summary":"Download a completed EQL PDF","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"409":{"description":"Report not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/gateway/reporting/v1/eql/schedules":{"get":{"tags":["EQL"],"operationId":"listEQLSchedules","summary":"List EQL report schedules","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. Requires schedules capability and authenticated scheduler provisioned.","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLScheduleList"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}}},"post":{"tags":["EQL"],"operationId":"createEQLSchedule","summary":"Schedule an EQL report","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. Requires schedules capability. Stores query for revalidation on each fire; format json or pdf, template eql. Saved reports only; email/webhook delivery is not supported.","responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLSchedule"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLScheduleRequest"}}}}}},"/gateway/reporting/v1/eql/schedules/{id}":{"get":{"tags":["EQL"],"operationId":"getEQLSchedule","summary":"Get an EQL report schedule","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLSchedule"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"patch":{"tags":["EQL"],"operationId":"updateEQLSchedule","summary":"Update or pause an EQL schedule","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLSchedule"}}}},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLSchedulePatch"}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]},"delete":{"tags":["EQL"],"operationId":"deleteEQLSchedule","summary":"Delete an EQL report schedule","description":"Requires a signed gateway tenant-admin session or universal API scope and the tenant eql-reporting flag. Available only when the dedicated EQL reader is configured. All queries are validated and executed with bounded resource limits. ","responses":{"204":{"description":"Success"},"400":{"$ref":"#/components/responses/EQL400"},"401":{"$ref":"#/components/responses/EQL401"},"403":{"$ref":"#/components/responses/EQL403"},"404":{"$ref":"#/components/responses/EQL404"},"429":{"$ref":"#/components/responses/EQL429"},"500":{"$ref":"#/components/responses/EQL500"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}}},"components":{"schemas":{"StatusResponse":{"type":"object","properties":{"status":{"type":"string","example":"ok"}},"required":["status"]},"User":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"last_logged_in":{"type":"string","format":"date-time","nullable":true},"status":{"type":"string","enum":["active","disabled","invited"]},"role":{"type":"string","enum":["admin","viewer"]},"user_groups":{"type":"array","items":{"type":"string","description":"User‑friendly name of the group"}},"account_groups":{"type":"array","items":{"type":"string","description":"User‑friendly name of the account group"}}},"required":["id","email","status","role"]},"UserDetail":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["admin","viewer"]},"user_groups_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"userGroups":{"type":"array","items":{"type":"string","format":"uuid"}},"accountGroups":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["id"]},"DisableUsersRequest":{"type":"array","items":{"type":"string","format":"uuid"}},"UserIdArray":{"type":"array","items":{"type":"string","format":"uuid"}},"ResendInviteRequest":{"type":"object","properties":{"email_address":{"type":"string","format":"email"}},"required":["email_address"]},"UserGroup":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"role":{"type":"string","enum":["admin","viewer"]},"user_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"users":{"type":"array","items":{"$ref":"#/components/schemas/UserDetail"}},"account_groups_names":{"type":"array","items":{"type":"string"}}},"required":["id","name","role"]},"UserGroupCreate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"role":{"type":"string","enum":["admin","viewer"]},"users_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"User IDs to associate with the group (snake_case format)"},"userIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"User IDs to associate with the group (camelCase format, alternative to users_ids)"},"users_emails":{"type":"array","items":{"type":"string","format":"email"}},"account_groups_ids":{"type":"array","items":{"type":"string","format":"uuid"}}},"required":["name","role"]},"UserGroupUpdate":{"allOf":[{"$ref":"#/components/schemas/UserGroupCreate"},{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"]}]},"AccountGroup":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/AccountAssociationDetail"}}},"required":["id","name","accounts"]},"AccountGroupCreate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/AccountAssociationDetail"}}},"required":["name","accounts"]},"AccountAssociationDetail":{"type":"object","properties":{"account_id":{"type":"string"},"provider_type":{"type":"string","enum":["aws","ova","azure","ibm","gcp"]}},"required":["account_id","provider_type"]},"AccountGroupUpdate":{"allOf":[{"$ref":"#/components/schemas/AccountGroupCreate"},{"type":"object","properties":{"id":{"type":"string","format":"uuid"}},"required":["id"]}]},"Role":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","name","created_at","updated_at"]},"RoleCreate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}},"required":["name"]},"RoleUpdate":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}}},"AssignRoleRequest":{"type":"object","properties":{"role_id":{"type":"string","format":"uuid"}},"required":["role_id"]},"AuditLog":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"log":{"type":"string","description":"Human-readable log message describing the action"},"category":{"type":"string","description":"Category of the log entry (e.g., \"rbac\")"},"generated_by":{"type":"string","description":"User who performed the action"},"created_at":{"type":"string","format":"date-time","description":"Timestamp when the log entry was created"}},"required":["id","log","category","generated_by","created_at"]},"AuditLogPagination":{"type":"object","properties":{"next_page_token":{"type":"string","nullable":true,"description":"Token for the next page of results"},"prev_page_token":{"type":"string","nullable":true,"description":"Token for the previous page of results"},"total_count":{"type":"integer","description":"Total number of audit logs matching the query"}}},"AuditLogResponse":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}},"pagination":{"$ref":"#/components/schemas/AuditLogPagination"}},"required":["data","pagination"]},"AuditLogFilters":{"type":"object","properties":{"categories":{"type":"array","items":{"type":"string"},"description":"Available categories for filtering"},"generated_by":{"type":"array","items":{"type":"string"},"description":"Available users for filtering"}},"required":["categories","generated_by"]},"Account":{"type":"object","properties":{"account_id":{"type":"string","description":"AWS account ID (12 digits)","example":"123456789012"},"region":{"type":"string","description":"AWS region for the account (Cloud Connector or asset account)","example":"us-east-1"},"type":{"type":"string","description":"Type of account - \"cloud_connector\" for Cloud Connectors or \"protected_account\" for protected/asset accounts","enum":["cloud_connector","protected_account"],"example":"cloud_connector"}},"required":["account_id","region","type"]},"AccountsResponse":{"type":"object","properties":{"accounts":{"type":"array","description":"List of active AWS accounts for the tenant","items":{"$ref":"#/components/schemas/Account"}}},"required":["accounts"]},"EnableRequest":{"type":"object","properties":{"integration":{"type":"string","description":"Integration type to enable","enum":["guardduty"],"example":"guardduty"},"account_id":{"type":"string","description":"AWS account ID (12 digits)","example":"123456789012"},"region":{"type":"string","description":"AWS region where the customer's hub is deployed","example":"us-east-1"}},"required":["integration","account_id","region"]},"EnableResponse":{"type":"object","properties":{"event_bus_name":{"type":"string","description":"Name of the created EventBridge event bus","example":"elastio-acme-corp-123456789012"},"rule_name":{"type":"string","description":"Name of the EventBridge rule","example":"elastio-acme-corp-123456789012-guardduty"},"eventbridge_rule_name":{"type":"string","description":"Same as rule_name (for backward compatibility)","example":"elastio-acme-corp-123456789012-guardduty"},"status":{"type":"string","description":"Integration status","enum":["enabled"],"example":"enabled"},"message":{"type":"string","description":"Human-readable status message","example":"ok"}},"required":["event_bus_name","rule_name","eventbridge_rule_name","status","message"]},"DisableRequest":{"type":"object","properties":{"integration":{"type":"string","description":"Integration type to disable","enum":["guardduty"],"example":"guardduty"},"account_id":{"type":"string","description":"AWS account ID (12 digits)","example":"123456789012"},"region":{"type":"string","description":"AWS region where the customer's hub is deployed","example":"us-east-1"}},"required":["integration","account_id","region"]},"DisableResponse":{"type":"object","properties":{"event_bus_name":{"type":"string","description":"Name of the deleted EventBridge event bus","example":"elastio-acme-corp-123456789012"},"rule_name":{"type":"string","description":"Name of the deleted EventBridge rule","example":"elastio-acme-corp-123456789012-guardduty"},"status":{"type":"string","description":"Integration status","enum":["deleted"],"example":"deleted"},"message":{"type":"string","description":"Human-readable status message","example":"Integration deleted successfully"}},"required":["event_bus_name","rule_name","status","message"]},"LinkedAccountsRequest":{"type":"object","properties":{"account_ids":{"type":"array","description":"List of AWS account IDs to add or remove","items":{"type":"string","pattern":"^[0-9]{12}$"},"example":["222222222222","333333333333"]}},"required":["account_ids"]},"LinkedAccountsResponse":{"type":"object","properties":{"hub_account_id":{"type":"string","description":"AWS account ID of the hub","example":"111111111111"},"linked_account_ids":{"type":"array","description":"Current list of linked account IDs after the operation","items":{"type":"string"},"example":["222222222222","333333333333"]},"added":{"type":"array","description":"Account IDs that were added (only present on add operation)","items":{"type":"string"},"example":["333333333333"]},"already_linked":{"type":"array","description":"Account IDs that were already linked (only present on add operation)","items":{"type":"string"},"example":["222222222222"]},"removed":{"type":"array","description":"Account IDs that were removed (only present on remove operation)","items":{"type":"string"},"example":["222222222222"]},"not_found":{"type":"array","description":"Account IDs that were not found in linked accounts (only present on remove operation)","items":{"type":"string"},"example":["999999999999"]},"failed":{"type":"array","description":"Account IDs that failed validation (only present on add operation with partial success)","items":{"type":"string"},"example":["444444444444"]},"validation_errors":{"type":"array","description":"Validation error messages for failed accounts (only present on add operation with partial success)","items":{"type":"string"},"example":["account 444444444444 not found in tenant's AWS accounts"]},"message":{"type":"string","description":"Human-readable status message","example":"Accounts linked successfully"}},"required":["hub_account_id","linked_account_ids","message"]},"ErrorResponse":{"type":"object","description":"The error envelope returned by the Elastio API gateway.","properties":{"status":{"type":"integer","minimum":400,"maximum":599,"example":404},"error":{"type":"string","example":"Not Found"},"message":{"type":"string","example":"Asset 6c1f... was not found"},"cached":{"type":"boolean","example":false}},"required":["status","error","message"]},"StatusAccount":{"type":"object","properties":{"account_id":{"type":"string","description":"AWS account ID of the hub (12 digits)","example":"123456789012"},"region":{"type":"string","description":"AWS region where the customer's hub is deployed","example":"us-east-1"},"event_bus_name":{"type":"string","description":"Name of the EventBridge event bus (same name for both Elastio and hub)","example":"gd-123456789012-uat-development"},"elastio_event_bus_arn":{"type":"string","description":"ARN of Elastio's EventBridge event bus (where events are forwarded to)","example":"arn:aws:events:eu-central-1:937593779230:event-bus/gd-123456789012-uat-development"},"hub_event_bus_arn":{"type":"string","description":"ARN of the customer's hub EventBridge event bus (where spokes send events)","example":"arn:aws:events:us-east-1:123456789012:event-bus/gd-123456789012-uat-development"},"eventbridge_rule_name":{"type":"string","description":"Name of the EventBridge rule","example":"gd-123456789012-uat-development"},"linked_account_ids":{"type":"array","description":"List of spoke account IDs that forward events through this hub","items":{"type":"string"},"example":["222222222222","333333333333"]},"last_event_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp (RFC3339) of the most recent GuardDuty finding ingested through this hub, folded across the hub account and every currently linked spoke. `null` means no finding has been ingested yet (or the activity rollup could not be read).","example":"2026-09-01T11:10:02Z"},"events_last_24h":{"type":"integer","format":"int64","nullable":true,"minimum":0,"description":"Number of GuardDuty findings ingested through this hub in the last 24 hours, folded across the hub account and every currently linked spoke. `0` is an honest \"no findings in the window\"; `null` means the rollup is unavailable, so a client should hide the metric rather than render a zero. Counts findings the ingestion pipeline accepted and stored: GuardDuty features other than `S3MalwareProtection` and `EbsVolumeScan` are dropped upstream and never counted here.","example":3},"scans_scheduled_last_24h":{"type":"integer","format":"int64","nullable":true,"minimum":0,"description":"How many of those findings produced a scan job, over the same window and the same fold. Ingesting a finding is only half the work: when the Cloud Connector cannot be scheduled against, the finding is still stored and no scan ever runs. A value below `events_last_24h` is that failure, made visible. `null` means the rollup is unavailable, so a client should hide the metric rather than render a zero.","example":3}},"required":["account_id","region","event_bus_name","elastio_event_bus_arn","hub_event_bus_arn","eventbridge_rule_name"]},"StatusResponse1":{"type":"object","properties":{"status":{"type":"string","description":"Overall integration status for the tenant","enum":["enabled","disabled"],"example":"enabled"},"accounts":{"type":"array","description":"List of accounts with enabled integrations (only present when status is 'enabled')","items":{"$ref":"#/components/schemas/StatusAccount"}}},"required":["status"]},"RuleMode":{"type":"object","description":"Rule mode determines whether notifications are sent or suppressed. Compatible with Rust notifications-service RuleMode enum.","properties":{"kind_tag":{"type":"string","description":"Mode type discriminator","enum":["notify","suppress"],"example":"notify"},"reason":{"type":"string","description":"Reason for suppression (required when kind_tag is 'suppress')","example":"Maintenance window"},"until":{"type":"string","format":"date-time","description":"RFC3339 timestamp when suppression expires (required when kind_tag is 'suppress')","example":"2026-02-01T00:00:00Z"}},"required":["kind_tag"]},"RuleCriteria":{"type":"object","description":"Criteria for matching events. Compatible with Rust RuleCriteriaAttrs.","properties":{"asset_ids":{"type":"array","nullable":true,"description":"List of specific asset UUIDs to match (null for all assets)","items":{"type":"string","format":"uuid"},"example":null},"aws_account_id_regions":{"type":"array","description":"AWS account and region pairs to match","items":{"$ref":"#/components/schemas/AwsAccountIdRegion"},"example":[{"account_id":"123456789012","region":"us-east-1"},{"account_id":"123456789012","region":"us-west-2"}]},"ova_account_id_providers":{"type":"array","nullable":true,"description":"OVA account and backup provider pairs to match","items":{"$ref":"#/components/schemas/OvaAccountIdProvider"},"example":null},"azure_subscription_id_resource_groups":{"type":"array","nullable":true,"description":"Azure subscription and resource group pairs to match","items":{"$ref":"#/components/schemas/AzureSubscriptionIdResourceGroup"},"example":null},"ibm_scopes":{"type":"array","nullable":true,"description":"IBM scope values to match","items":{"$ref":"#/components/schemas/IbmScope"},"example":null},"tags":{"$ref":"#/components/schemas/TagsCriterion"},"dc_findings":{"$ref":"#/components/schemas/DCFindingsCriterion"},"event_kinds":{"$ref":"#/components/schemas/EventKindCriterion"},"severities":{"type":"array","description":"Severity routing. The alert fires only for events whose severity is in this list (OR). critical, high, medium and low are real findings; info is the absence of findings (e.g. a clean scan), opt-in for an audit trail, and never folds into low. Omitted means unrestricted (every existing alert). On update, an omitted key keeps the stored selection, null clears it, and a list replaces it; an empty list is rejected. Responses always carry an explicit list (all five when unrestricted). A system event that reaches the alert through a System Policy takes that policy's severity override for its kind first; an alert on several covering policies matches when any of them yields a selected severity. Otherwise the event's severity is its label \"severity\" (hunt, Pursuit; a Pursuit low is a clean result and routes as info), else \"violation_severity\" (violations), else high for a detection kind (threat, anomaly, data classification: raised only when something was found), else the system event catalog's severity_default. Events with no severity (job health, audit) pass any selection. Applies to system and policy alerts; one policy can route its findings by severity through several alerts.","minItems":1,"items":{"$ref":"#/components/schemas/AlertSeverity"},"example":["critical","high"]}},"required":["event_kinds"]},"AlertSeverity":{"type":"string","enum":["critical","high","medium","low","info"],"description":"Alert routing severity. critical, high, medium, low are real findings that need remediation; info is the absence of findings (a clean run)."},"DCFindingsCriterion":{"type":"object","description":"Filters data-classification findings events by sensitive-data category. Only applies when event_kinds includes elastio:asset:data-classification:findings:detected.","properties":{"kind_tag":{"type":"string","description":"all_categories matches any finding category; exact_categories requires at least one overlap with the event finding_categories label (OR match).","enum":["all_categories","exact_categories"],"example":"exact_categories"},"categories":{"type":"array","description":"Required when kind_tag is exact_categories. At least one listed category must appear on the event.","items":{"type":"string"},"example":["PII","HIPAA","PCI DSS"]}}},"AwsAccountIdRegion":{"type":"object","description":"AWS account and region pair","properties":{"account_id":{"type":"string","description":"AWS account ID (12 digits)","example":"123456789012"},"region":{"type":"string","description":"AWS region","example":"us-east-1"}},"required":["account_id","region"]},"OvaAccountIdProvider":{"type":"object","description":"OVA account and backup provider pair","properties":{"account_id":{"type":"string","format":"uuid","description":"OVA account UUID"},"backup_provider":{"type":"string","description":"Backup provider type","enum":["veeam","commvault","rubrik","cohesity","veritas"],"example":"veeam"}},"required":["account_id","backup_provider"]},"AzureSubscriptionIdResourceGroup":{"type":"object","description":"Azure subscription and optional resource group pair","properties":{"subscription_id":{"type":"string","description":"Azure subscription ID","example":"12345678-1234-1234-1234-123456789abc"},"resource_group":{"type":"string","description":"Azure resource group name (optional, omit to match any resource group in the subscription)","example":"my-resource-group"}},"required":["subscription_id"]},"IbmScope":{"type":"object","description":"IBM scope criterion","properties":{"scope":{"type":"string","description":"IBM scope identifier","example":"crn:v1:bluemix:public:cloud-object-storage:global:a/abc123:def456::"}},"required":["scope"]},"TagsCriterion":{"type":"object","nullable":true,"description":"Tag matching criteria","properties":{"tags":{"type":"array","description":"List of tags to match","items":{"$ref":"#/components/schemas/Tag"}},"operator":{"$ref":"#/components/schemas/TagOperator"}},"required":["tags","operator"]},"TagOperator":{"type":"object","description":"Tag matching operator","properties":{"kind_tag":{"type":"string","description":"Logical operator for combining tag matches","enum":["and","or"],"example":"and"}},"required":["kind_tag"]},"Tag":{"type":"object","description":"A tag criterion","properties":{"key":{"type":"string","description":"Tag key to match","example":"Environment"},"value":{"type":"string","nullable":true,"description":"Tag value to match (null matches any value)","example":"Production"}},"required":["key"]},"EventKindCriterion":{"type":"object","description":"Event kinds to match. Compatible with Rust EventKindCriterion enum.","properties":{"kind_tag":{"type":"string","description":"Event kind criterion type","enum":["all_events","exact_events"],"example":"exact_events"},"event_kinds":{"type":"array","description":"List of event kinds to match (required when kind_tag is 'exact_events')","items":{"type":"string"},"example":["elastio:asset:threat:detected","elastio:asset:iscan:succeeded"]}},"required":["kind_tag"]},"NotificationChannels":{"type":"object","description":"Notification delivery channels. Compatible with Rust NotificationChannelsAttrs.","properties":{"webhooks":{"type":"array","description":"Webhook channels to notify","items":{"$ref":"#/components/schemas/WebhookChannel"},"example":[{"webhook_id":"550e8400-e29b-41d4-a716-446655440000"}]},"splunk":{"type":"array","description":"Splunk HEC channels to notify","items":{"$ref":"#/components/schemas/SplunkChannel"},"example":[{"splunk_config_id":"770e8400-e29b-41d4-a716-446655440000"}]},"tenant_members":{"type":"array","description":"Tenant member email channels (by customer ID)","items":{"$ref":"#/components/schemas/TenantMemberChannel"},"example":[{"customer_id":"660e8400-e29b-41d4-a716-446655440000"}]},"emails":{"type":"array","description":"Direct email channels","items":{"$ref":"#/components/schemas/EmailChannel"},"example":[{"email":"security@company.com"}]},"slack":{"type":"array","nullable":true,"description":"Slack integration channels to notify, one entry per Slack integration (ids from /integration/v1/slack). Send an empty array or null to turn Slack off. The legacy boolean form is not accepted on create or update: `true` is rejected with 400 (it used to be accepted and silently dropped), and `false` is treated the same as null (Slack off). Alerts stored with the legacy boolean read back with no Slack channels.","items":{"$ref":"#/components/schemas/SlackIntegrationChannel"},"example":[{"slack_id":"880e8400-e29b-41d4-a716-446655440000"}]},"tenant_admins":{"type":"boolean","description":"Email the tenant's admins. The recipient list is resolved at delivery time, so it follows admin changes without editing the alert. Omitted (false) when not set.","example":false}}},"SlackIntegrationChannel":{"type":"object","description":"Slack notification channel, referencing a tenant Slack integration","properties":{"slack_id":{"type":"string","format":"uuid","description":"Id of the tenant's Slack integration to post to (from /integration/v1/slack)"}},"required":["slack_id"]},"WebhookChannel":{"type":"object","description":"Webhook notification channel","properties":{"webhook_id":{"type":"string","format":"uuid","description":"UUID of the webhook to invoke"}},"required":["webhook_id"]},"SplunkChannel":{"type":"object","description":"Splunk HEC notification channel","properties":{"splunk_config_id":{"type":"string","format":"uuid","description":"UUID of the Splunk HEC config to send events to"}},"required":["splunk_config_id"]},"TenantMemberChannel":{"type":"object","description":"Tenant member email channel","properties":{"customer_id":{"type":"string","format":"uuid","description":"UUID of the tenant member (customer)"}},"required":["customer_id"]},"EmailChannel":{"type":"object","description":"Direct email notification channel","properties":{"email":{"type":"string","format":"email","description":"Email address to notify"}},"required":["email"]},"CreateAlertRequest":{"type":"object","description":"Request to create a new alert. Format is compatible with Rust notifications-service.","properties":{"name":{"type":"string","description":"Alert name (must be unique per tenant)","minLength":1,"maxLength":255,"example":"Critical Scan Failures"},"description":{"type":"string","description":"Human-readable description","maxLength":1000,"example":"Notify when critical scan failures occur"},"mode":{"$ref":"#/components/schemas/RuleMode"},"status":{"type":"string","description":"Alert status","enum":["enabled","disabled"],"example":"enabled"},"criteria":{"$ref":"#/components/schemas/RuleCriteria"},"channels":{"$ref":"#/components/schemas/NotificationChannels"}},"required":["name","mode","status","criteria","channels"]},"UpdateAlertRequest":{"type":"object","description":"Request to update an existing alert (all fields optional for partial updates)","properties":{"name":{"type":"string","description":"Alert name (must be unique per tenant)","minLength":1,"maxLength":255,"example":"Updated Alert Name"},"description":{"type":"string","description":"Human-readable description","maxLength":1000,"example":"Updated description"},"mode":{"$ref":"#/components/schemas/RuleMode"},"status":{"type":"string","description":"Alert status","enum":["enabled","disabled"],"example":"enabled"},"criteria":{"$ref":"#/components/schemas/RuleCriteria"},"channels":{"$ref":"#/components/schemas/NotificationChannels"}}},"AlertResponse":{"type":"object","description":"Alert configuration details. Format is compatible with Rust notifications-service.","properties":{"id":{"type":"string","format":"uuid","description":"Alert unique identifier","example":"123e4567-e89b-12d3-a456-426614174000"},"tenant_name":{"type":"string","description":"Tenant identifier","example":"acme-corp.elastio.us"},"name":{"type":"string","description":"Alert name","example":"Critical Scan Failures"},"description":{"type":"string","description":"Alert description","example":"Notify when critical scan failures occur"},"mode":{"$ref":"#/components/schemas/RuleMode"},"status":{"type":"string","description":"Alert status (database value)","enum":["enabled","disabled"],"example":"enabled"},"criteria":{"$ref":"#/components/schemas/RuleCriteria"},"channels":{"$ref":"#/components/schemas/NotificationChannels"},"created_at":{"type":"string","format":"date-time","description":"Alert creation timestamp","example":"2026-01-23T10:30:00Z"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp","example":"2026-01-23T12:45:00Z"}},"required":["id","tenant_name","name","mode","status","criteria","channels","created_at","updated_at"]},"ListAlertsResponse":{"type":"object","description":"Paginated list of alerts","properties":{"alerts":{"type":"array","description":"Array of alert configurations","items":{"$ref":"#/components/schemas/AlertResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["alerts","pagination"]},"V2EventKindCriterion":{"type":"object","description":"Controls which events trigger this alert.\n\n**no_events**: Criteria path is off. On a `policy` alert, threats,\nanomalies, violations, data-classification findings, custom-hunt\nfindings, and Pursuit findings fire through recovery-policy bindings\n(`policy_ids` optional until bound). On a `system` alert this is an\ninert draft until kinds are added. Omit the `event_kinds` array.\nWithout bindings, a policy alert will not match events.\n\n**all_events**: Notify on every event kind in the tenant. Omit the `event_kinds` array.\n\n**exact_events**: Notify only on the event kinds you list in `event_kinds` (for example,\nscan or backup events). Do not list `elastio:asset:threat:detected`,\n`elastio:asset:anomaly:detected`, `elastio:asset:violation:detected`,\n`elastio:asset:data-classification:findings:detected`,\n`elastio:asset:custom-hunt:findings:detected`, or\n`elastio:asset:pursuit:findings:detected`; those are scoped to recovery\npolicies. Use **no_events** with `policy_ids` for threat, anomaly,\nviolation, data-classification, custom-hunt, and Pursuit findings\nnotifications.\n","properties":{"kind_tag":{"type":"string","enum":["no_events","all_events","exact_events"]},"event_kinds":{"type":"array","description":"Required when `kind_tag` is `exact_events`. Omit when `kind_tag` is `no_events` or `all_events`. Cannot include threat, anomaly, violation, data-classification, custom-hunt, or Pursuit findings detected kinds: use `no_events` with `policy_ids` for those.","items":{"type":"string"}}},"required":["kind_tag"]},"V2RuleCriteria":{"type":"object","description":"v2 alert matching criteria. On create, omit this object to persist `no_events`. Policy creates must be `no_events` (or omit) and must not send asset/account/tag/DC scope fields. System creates may set those scope fields, including on a `no_events` draft. On update, omitted scope keys are preserved; a present key (`[]`, `null`, or values) replaces or clears it. Policy updates reject non-empty scope and drop leftover scope keys when criteria is saved.","properties":{"event_kinds":{"$ref":"#/components/schemas/V2EventKindCriterion"},"asset_ids":{"type":"array","description":"System-only. Specific asset IDs to match.","items":{"type":"string"}},"aws_account_id_regions":{"type":"array","description":"System-only. AWS account and region pairs to match.","items":{"$ref":"#/components/schemas/AwsAccountIdRegion"}},"ova_account_id_providers":{"type":"array","description":"System-only. OVA account and backup provider pairs to match.","items":{"$ref":"#/components/schemas/OvaAccountIdProvider"}},"azure_subscription_id_resource_groups":{"type":"array","description":"System-only. Azure subscription and resource group pairs to match.","items":{"$ref":"#/components/schemas/AzureSubscriptionIdResourceGroup"}},"ibm_scopes":{"type":"array","description":"System-only. IBM scope values to match.","items":{"$ref":"#/components/schemas/IbmScope"}},"tags":{"$ref":"#/components/schemas/TagsCriterion"},"dc_findings":{"$ref":"#/components/schemas/DCFindingsCriterion"},"severities":{"type":"array","description":"Severity routing. The alert fires only for events whose severity is in this list (OR). critical, high, medium and low are real findings; info is the absence of findings (e.g. a clean scan), opt-in for an audit trail, and never folds into low. Omitted means unrestricted (every existing alert). On update, an omitted key keeps the stored selection, null clears it, and a list replaces it; an empty list is rejected. Responses always carry an explicit list (all five when unrestricted). A system event that reaches the alert through a System Policy takes that policy's severity override for its kind first; an alert on several covering policies matches when any of them yields a selected severity. Otherwise the event's severity is its label \"severity\" (hunt, Pursuit; a Pursuit low is a clean result and routes as info), else \"violation_severity\" (violations), else high for a detection kind (threat, anomaly, data classification: raised only when something was found), else the system event catalog's severity_default. Events with no severity (job health, audit) pass any selection. Applies to system and policy alerts; one policy can route its findings by severity through several alerts.","minItems":1,"items":{"$ref":"#/components/schemas/AlertSeverity"},"example":["critical","high"]}},"required":["event_kinds"]},"CreateAlertV2Request":{"type":"object","description":"Request to create a policy-aware alert (v2 integration API). `matching_semantics` is required. `criteria` is optional: omit it to persist `no_events`. Policy creates must omit criteria or send `no_events`; `policy_ids` is optional and forbidden on system alerts.","properties":{"name":{"type":"string","minLength":1},"description":{"type":"string"},"mode":{"$ref":"#/components/schemas/RuleMode"},"status":{"type":"string","enum":["enabled","disabled"]},"matching_semantics":{"type":"string","enum":["system","policy"],"description":"Required matching-semantics class. `system` matches by criteria (optionally a `no_events` draft until kinds are added later). `policy` matches by recovery-policy bindings; create criteria must be omitted or `no_events`, and `policy_ids` is optional. Persisted on create (including before cutover) and cannot be changed via update."},"policy_ids":{"type":"array","description":"Optional scheduled or event policy UUIDs to bind (each policy must exist for the tenant). Allowed only when `matching_semantics` is `policy`; sending `policy_ids` with `system` returns 400.","items":{"type":"string","format":"uuid"}},"criteria":{"$ref":"#/components/schemas/V2RuleCriteria"},"channels":{"$ref":"#/components/schemas/NotificationChannels"}},"required":["name","mode","status","channels","matching_semantics"]},"UpdateAlertV2Request":{"type":"object","description":"Partial update for a v2 alert. Omit a field to leave it unchanged.\n`matching_semantics` is not accepted and is rejected if present.\nThe stored alert must already have matching_semantics (`system` or\n`policy`); unlabeled v1 leftovers return 400: update those via v1\nuntil cutover. GET and list still return unlabeled rows.\nFor policy_ids, omit the field to leave bindings unchanged; send an empty\narray to remove all policy bindings; send a non-empty array to replace\nall bindings with the given policy UUIDs. Scope keys on criteria\n(aws_account_id_regions, tags, etc.) use presence-map merge on system\nalerts: omitted keeps the stored value; present (`[]`, `null`, or values)\nreplaces or clears. Policy alerts reject non-empty scope; a criteria\nsave drops leftover hybrid scope keys. Name-only updates do not strip.\n","properties":{"name":{"type":"string"},"description":{"type":"string"},"mode":{"$ref":"#/components/schemas/RuleMode"},"status":{"type":"string","enum":["enabled","disabled"]},"criteria":{"$ref":"#/components/schemas/V2RuleCriteria"},"channels":{"$ref":"#/components/schemas/NotificationChannels"},"policy_ids":{"type":"array","description":"Policy binding semantics on update: omitted; leave existing bindings unchanged;\nempty array; remove all bindings; non-empty; replace all bindings with the\nlisted policy UUIDs (each must exist for the tenant).\n","items":{"type":"string","format":"uuid"}}}},"AlertV2Response":{"type":"object","description":"v2 alert including policy bindings","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"mode":{"$ref":"#/components/schemas/RuleMode"},"status":{"type":"string","enum":["enabled","disabled"]},"criteria":{"$ref":"#/components/schemas/V2RuleCriteria"},"channels":{"$ref":"#/components/schemas/NotificationChannels"},"policy_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"matching_semantics":{"type":"string","enum":["system","policy"],"readOnly":true,"description":"Stored matching-semantics class. Always present on v2 responses: unlabeled leftovers are not returned by v2 list or GET. Set by the client on v2 create (and by cutover backfill for leftover NULL v1 rows). Read-only on responses; update cannot change it."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","tenant_name","name","mode","status","criteria","channels","policy_ids","matching_semantics","created_at","updated_at"]},"ListAlertsV2Response":{"type":"object","properties":{"alerts":{"type":"array","items":{"$ref":"#/components/schemas/AlertV2Response"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["alerts","pagination"]},"AlertActivityChannelItem":{"type":"object","properties":{"kind":{"type":"string","description":"Channel kind (webhook, slack, splunk, email)"},"delivery_id":{"type":"string","format":"uuid"},"channel_name":{"type":"string"},"status":{"type":"string"},"message":{"type":"string","description":"Optional detail from the delivery row (e.g. latest webhook delivery event reason, or channel invocation error_message). Often empty for successful deliveries."},"created_at":{"type":"string","format":"date-time"}},"required":["kind","delivery_id","status","created_at"]},"AlertActivityItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"alert_event_matches row id"},"alert_id":{"type":"string","format":"uuid"},"event_id":{"type":"string","format":"uuid"},"event_kind":{"type":"string"},"event_description":{"type":"string"},"event_time":{"type":"string","format":"date-time"},"event_labels":{"type":"object","additionalProperties":{"type":"string"},"description":"Labels from the matched event. Omitted when the stored event has no labels."},"severity":{"allOf":[{"$ref":"#/components/schemas/AlertSeverity"}],"nullable":true,"description":"The severity the matched event was routed at, resolved the way the matcher resolves it: for an event routed through a System Policy, that policy's override for its kind (when several bound policies cover it, the most severe one the alert selects), else the event's label, else the system event catalog's severity_default. Resolved at read time, so it reflects current overrides. null when the event has none."},"channels":{"type":"array","items":{"$ref":"#/components/schemas/AlertActivityChannelItem"}}},"required":["id","alert_id","event_id","event_kind","event_description","event_time","channels"]},"AlertActivityResponse":{"type":"object","properties":{"activity":{"type":"array","items":{"$ref":"#/components/schemas/AlertActivityItem"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["activity","pagination"]},"AlertActivityOption":{"type":"object","properties":{"value":{"type":"string","description":"Machine value sent back as a query param."},"label":{"type":"string","description":"Human-readable label for UI display."}},"required":["value","label"]},"AlertActivityOptionsResponse":{"type":"object","properties":{"periods":{"type":"array","description":"Supported period choices (e.g. 1d, 7d, 30d) with display labels.","items":{"$ref":"#/components/schemas/AlertActivityOption"}},"event_kinds":{"type":"array","description":"Distinct event kinds observed for this alert in the last 30 days.","items":{"$ref":"#/components/schemas/AlertActivityOption"}}},"required":["periods","event_kinds"]},"PaginationInfo":{"type":"object","description":"Cursor-based pagination information","properties":{"next_page_token":{"type":"string","nullable":true,"description":"Token for fetching the next page of results","example":"eyJzb3J0Ijp7ImZpZWxkIjoiY3JlYXRlZF9hdCIsImRpcmVjdGlvbiI6ImRlc2MifX0="},"prev_page_token":{"type":"string","nullable":true,"description":"Token for fetching the previous page of results","example":null},"total_count":{"type":"integer","description":"Total number of items matching the query","example":42}},"required":["total_count"]},"ChannelsResponse":{"type":"object","description":"Grouped notification channels","properties":{"webhooks":{"type":"array","description":"List of webhook channels","items":{"$ref":"#/components/schemas/ChannelResponse"}},"splunk":{"type":"array","description":"List of Splunk HEC channels","items":{"$ref":"#/components/schemas/ChannelResponse"}}},"required":["webhooks","splunk"]},"ChannelResponse":{"type":"object","description":"A notification channel","properties":{"id":{"type":"string","format":"uuid","description":"Channel unique identifier","example":"550e8400-e29b-41d4-a716-446655440000"},"name":{"type":"string","description":"Channel name","example":"Production Webhook"},"type":{"type":"string","description":"Channel type","example":"webhook"},"direction":{"type":"string","enum":["incoming","outgoing"],"description":"Whether events flow into Elastio (incoming) or out of Elastio (outgoing). Currently only Wiz is incoming; all other channel types are outgoing.","example":"outgoing"},"description":{"type":"string","nullable":true,"description":"Channel description","example":"Main production webhook"},"created_at":{"type":"string","format":"date-time","description":"Creation timestamp","example":"2026-01-23T10:30:00Z"},"last_triggered":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of the most recent delivery/event for this channel","example":"2026-01-24T08:15:00Z"},"used_by_count":{"type":"integer","description":"Number of alert rules currently referencing this channel","example":3},"last_delivery_status":{"type":"object","allOf":[{"$ref":"#/components/schemas/LastDeliveryStatus"}],"nullable":true,"description":"Most recent delivery status details for this channel"}},"required":["id","name","type","direction","created_at"]},"LastDeliveryStatus":{"type":"object","description":"Most recent delivery attempt/result metadata for a channel","properties":{"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the latest delivery attempt/event","example":"2026-01-24T08:15:00Z"},"success":{"type":"boolean","deprecated":true,"description":"Deprecated legacy boolean. Use `status` instead.","example":true},"status":{"type":"string","description":"Canonical delivery status string (for example delivered, failed, scheduled, received)","example":"delivered"}},"required":["timestamp","success","status"]},"WizChannel":{"type":"object","description":"A Wiz incoming channel (auto-created on first event from a Wiz source)","properties":{"id":{"type":"string","format":"uuid","example":"550e8400-e29b-41d4-a716-446655440000"},"tenant_name":{"type":"string","example":"acme"},"name":{"type":"string","example":"Wiz Integration 1"},"description":{"type":"string","nullable":true,"example":"Production Wiz organisation"},"wiz_source_id":{"type":"string","description":"Wiz subscription/organisation ID extracted from the payload","example":"sub-abc123"},"status":{"type":"string","enum":["active","inactive"],"example":"active"},"created_at":{"type":"string","format":"date-time","example":"2026-02-19T10:00:00Z"},"updated_at":{"type":"string","format":"date-time","example":"2026-02-19T10:00:00Z"},"last_scan_asset_name":{"type":"string","nullable":true,"description":"Asset name for the most recent Wiz event that triggered a scan (for example, S3 bucket name)","example":"gd-test-malware-01"},"last_scan_asset_id":{"type":"string","nullable":true,"description":"Asset identifier for the most recent Wiz event that triggered a scan (for example, S3 bucket ARN)","example":"arn:aws:s3:::gd-test-malware-01"},"total_received_last_7_days":{"type":"integer","description":"Total Wiz events received for this integration in the last 7 days","example":5},"scannable_received_last_7_days":{"type":"integer","nullable":true,"description":"Wiz events in the last 7 days that name an asset Elastio scans (AWS S3 bucket,\nEC2 instance, EBS volume). Null when the statistics could not be computed.\n","example":2},"scans_scheduled_last_7_days":{"type":"integer","nullable":true,"description":"Wiz events in the last 7 days that scheduled a scan job. Below\nscannable_received_last_7_days means scans are not being scheduled.\nNull when the statistics could not be computed.\n","example":2},"last_received_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of the most recent Wiz event received for this integration","example":"2026-02-25T18:42:00Z"}},"required":["id","tenant_name","name","wiz_source_id","status","created_at","updated_at"]},"UpdateWizRequest":{"type":"object","description":"Fields to update on a Wiz channel; all fields are optional","properties":{"name":{"type":"string","example":"Prod Wiz Org"},"description":{"type":"string","example":"Main production Wiz organisation"},"status":{"type":"string","enum":["active","inactive"],"example":"inactive"}}},"EmailResponse":{"type":"object","description":"Available email address for a tenant user","properties":{"customer_id":{"type":"string","format":"uuid","description":"User ID (UUID) from the users database","example":"550e8400-e29b-41d4-a716-446655440000"},"email":{"type":"string","format":"email","description":"User email address (required, always present)","example":"john.doe@company.com"},"name":{"type":"string","nullable":true,"description":"User display name (from users.display_name)","example":"John Doe"}},"required":["customer_id","email"]},"EventKindCatalogEntry":{"type":"object","description":"Catalog entry for a selectable alert event kind","properties":{"event_kind":{"type":"string","description":"Event kind identifier","example":"elastio:asset:threat:detected"},"description":{"type":"string","description":"Human-readable description","example":"Threat detected in asset"},"category":{"type":"string","description":"Event category","enum":["security","operational","identity","recovery"],"example":"security"}},"required":["event_kind","description","category"]},"MultiPlatformAccountsResponse":{"type":"object","description":"Accounts grouped by platform","properties":{"aws":{"$ref":"#/components/schemas/AWSAccountsResponse"},"azure":{"$ref":"#/components/schemas/AzureAccountsResponse"},"ova":{"$ref":"#/components/schemas/OVAAccountsResponse"}},"required":["aws","azure","ova"]},"AWSAccountsResponse":{"type":"object","description":"AWS accounts with regions","properties":{"accounts":{"type":"array","description":"List of AWS accounts with their regions","items":{"$ref":"#/components/schemas/AccountWithRegions"}}},"required":["accounts"]},"AccountWithRegions":{"type":"object","description":"Account with available regions","properties":{"account_id":{"type":"string","description":"AWS account ID (12 digits)","example":"123456789012"},"account_name":{"type":"string","nullable":true,"description":"Account name (if available)"},"regions":{"type":"array","description":"List of regions for this account","items":{"type":"string"},"example":["us-east-1","us-west-2"]}},"required":["account_id","regions"]},"AzureAccountsResponse":{"type":"object","description":"Azure subscriptions","properties":{"subscriptions":{"type":"array","description":"List of Azure subscriptions","items":{"$ref":"#/components/schemas/AzureSubscription"}}},"required":["subscriptions"]},"AzureSubscription":{"type":"object","description":"Azure subscription","properties":{"subscription_id":{"type":"string","format":"uuid","description":"Azure subscription ID","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"Subscription name","example":"Production Subscription"},"azure_tenant_id":{"type":"string","nullable":true,"description":"Azure tenant ID","example":"tenant-12345"}},"required":["subscription_id","name"]},"OVAAccountsResponse":{"type":"object","description":"OVA accounts","properties":{"accounts":{"type":"array","description":"List of OVA accounts","items":{"$ref":"#/components/schemas/OVAAccount"}}},"required":["accounts"]},"OVAAccount":{"type":"object","description":"OVA account","properties":{"id":{"type":"string","format":"uuid","description":"OVA account ID","example":"123e4567-e89b-12d3-a456-426614174000"},"name":{"type":"string","description":"Account name","example":"Production OVA"},"custom_name":{"type":"string","nullable":true,"description":"Custom name for the account","example":"My Custom Name"},"backup_providers":{"type":"array","description":"List of backup providers for this OVA account","items":{"type":"string","enum":["veeam","commvault","rubrik","cohesity","veritas"]},"example":["veeam","commvault"]}},"required":["id","name","backup_providers"]},"WebhookAuthentication":{"type":"object","description":"Authentication configuration for webhook endpoint","properties":{"type":{"type":"string","enum":["none","basic_auth","bearer_token","api_key","custom_headers"],"description":"Authentication type","example":"basic_auth"},"username":{"type":"string","description":"Username for basic_auth","example":"product@test.com"},"password":{"type":"string","description":"Password for basic_auth (write-only, never returned)","format":"password","example":"******"},"token":{"type":"string","description":"Token for bearer_token (write-only, never returned)","format":"password","example":"sk_live_abc123..."},"key":{"type":"string","description":"API key name for api_key","example":"X-API-Key"},"value":{"type":"string","description":"API key value for api_key (write-only, never returned)","format":"password","example":"abc123..."},"custom_headers":{"type":"object","description":"Custom headers for custom_headers type","additionalProperties":{"type":"string"},"example":{"X-Custom-Auth":"value123"}}},"required":["type"]},"CreateWebhookRequest":{"type":"object","description":"Request to create a new webhook","properties":{"name":{"type":"string","description":"Webhook name (must be unique per tenant)","minLength":1,"maxLength":255,"example":"Production Webhook"},"description":{"type":"string","description":"Human-readable description","maxLength":1000,"example":"System Default"},"endpoint":{"type":"string","format":"uri","description":"Webhook URL endpoint","example":"https://api.example.com/webhook"},"authentication":{"$ref":"#/components/schemas/WebhookAuthentication"}},"required":["name","endpoint"]},"UpdateWebhookRequest":{"type":"object","description":"Request to update an existing webhook (partial updates supported)","properties":{"name":{"type":"string","description":"Webhook name (must be unique per tenant)","minLength":1,"maxLength":255,"example":"Updated Webhook Name"},"description":{"type":"string","description":"Human-readable description","maxLength":1000,"example":"Updated description"},"endpoint":{"type":"string","format":"uri","description":"Webhook URL endpoint","example":"https://api.example.com/webhook/v2"},"status":{"type":"string","enum":["active","inactive"],"description":"Webhook status","example":"active"},"authentication":{"$ref":"#/components/schemas/WebhookAuthentication"}}},"WebhookResponse":{"type":"object","description":"Webhook configuration details","properties":{"id":{"type":"string","format":"uuid","description":"Webhook unique identifier","example":"660e8400-e29b-41d4-a716-446655440000"},"name":{"type":"string","description":"Webhook name","example":"Production Webhook"},"description":{"type":"string","description":"Webhook description","example":"System Default"},"endpoint":{"type":"string","format":"uri","description":"Webhook URL endpoint","example":"https://api.example.com/webhook"},"status":{"type":"string","enum":["active","inactive"],"description":"Webhook status","example":"active"},"authentication":{"type":"object","description":"Authentication info (without sensitive fields)","properties":{"type":{"type":"string","enum":["none","basic_auth","bearer_token","api_key","custom_headers"],"example":"basic_auth"},"username":{"type":"string","description":"Username (only for basic_auth)","example":"product@test.com"},"key":{"type":"string","description":"API key name (only for api_key)","example":"X-API-Key"}}},"used_in_alert_rules":{"type":"integer","description":"Number of alert rules using this webhook","example":3},"success_rate":{"type":"number","format":"float","description":"Delivery success rate percentage","example":98.5},"last_triggered_at":{"type":"string","format":"date-time","description":"Last time webhook was triggered","example":"2026-01-19T10:28:00Z"},"created_at":{"type":"string","format":"date-time","description":"Webhook creation timestamp","example":"2026-01-19T10:30:00Z"},"updated_at":{"type":"string","format":"date-time","description":"Last update timestamp","example":"2026-01-19T10:30:00Z"}},"required":["id","name","endpoint","status","created_at"]},"ListWebhooksResponse":{"type":"object","description":"Paginated list of webhooks","properties":{"webhooks":{"type":"array","description":"Array of webhook configurations (empty array if no webhooks)","items":{"$ref":"#/components/schemas/WebhookResponse"},"default":[]},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["webhooks","pagination"]},"WebhookStatisticsResponse":{"type":"object","description":"Webhook delivery statistics","properties":{"data":{"type":"object","properties":{"total_webhooks":{"type":"integer","description":"Total number of webhooks","example":3},"active_webhooks":{"type":"integer","description":"Number of active webhooks","example":2},"inactive_webhooks":{"type":"integer","description":"Number of inactive webhooks","example":1},"total_deliveries":{"type":"integer","description":"Total delivery attempts","example":4},"successful_deliveries":{"type":"integer","description":"Successful deliveries","example":2},"failed_deliveries":{"type":"integer","description":"Failed deliveries","example":1},"period_days":{"type":"integer","description":"Number of days in the reporting period","example":7}},"required":["total_webhooks","active_webhooks","inactive_webhooks","total_deliveries","successful_deliveries","failed_deliveries","period_days"]}},"required":["data"]},"SplunkStatisticsResponse":{"type":"object","description":"Splunk delivery statistics (tenant-level aggregate)","properties":{"status":{"type":"integer","description":"HTTP status code","example":200},"data":{"type":"object","properties":{"total_splunk_configs":{"type":"integer","description":"Total number of Splunk configs","example":3},"active_splunk_configs":{"type":"integer","description":"Number of active Splunk configs","example":2},"inactive_splunk_configs":{"type":"integer","description":"Number of inactive Splunk configs","example":1},"total_deliveries":{"type":"integer","description":"Total delivery attempts","example":4},"successful_deliveries":{"type":"integer","description":"Successful deliveries","example":2},"failed_deliveries":{"type":"integer","description":"Failed deliveries","example":1},"period_days":{"type":"integer","description":"Number of days in the reporting period","example":7}},"required":["total_splunk_configs","active_splunk_configs","inactive_splunk_configs","total_deliveries","successful_deliveries","failed_deliveries","period_days"]},"message":{"type":"string","example":"success"}},"required":["status","data","message"]},"SlackStatisticsResponse":{"type":"object","description":"Slack delivery statistics (tenant-level aggregate)","properties":{"status":{"type":"integer","description":"HTTP status code","example":200},"data":{"type":"object","properties":{"total_slack_configs":{"type":"integer","description":"Total number of Slack integrations","example":2},"active_slack_configs":{"type":"integer","description":"Number of active Slack integrations","example":1},"inactive_slack_configs":{"type":"integer","description":"Number of inactive Slack integrations","example":1},"total_deliveries":{"type":"integer","description":"Total delivery attempts","example":10},"successful_deliveries":{"type":"integer","description":"Successful deliveries","example":8},"failed_deliveries":{"type":"integer","description":"Failed deliveries","example":1},"period_days":{"type":"integer","description":"Number of days in the reporting period","example":7}},"required":["total_slack_configs","active_slack_configs","inactive_slack_configs","total_deliveries","successful_deliveries","failed_deliveries","period_days"]},"message":{"type":"string","example":"success"}},"required":["status","data","message"]},"SlackInvocationResponse":{"type":"object","description":"A single Slack invocation/delivery attempt","properties":{"id":{"type":"string","format":"uuid"},"slack_id":{"type":"string","format":"uuid"},"slack_name":{"type":"string"},"event_type":{"type":"string"},"status":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"]},"http_status_code":{"type":"integer","nullable":true},"response_time_ms":{"type":"integer","nullable":true},"request_payload":{"type":"object"},"response_body":{"type":"string","nullable":true},"error_message":{"type":"string","nullable":true},"retry_count":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ListSlackInvocationsResponse":{"type":"object","description":"Paginated list of Slack invocations","properties":{"invocations":{"type":"array","items":{"$ref":"#/components/schemas/SlackInvocationResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["invocations","pagination"]},"SlackInvocationFilterOptionsResponse":{"type":"object","description":"Filter options for the Slack invocations list (integration name and status dropdowns)","properties":{"slack_names":{"type":"array","description":"Slack integration names usable in the name filter on GET.../invocations","items":{"type":"string"},"example":["Production","Staging","Test"]},"statuses":{"type":"array","description":"Valid values for the status filter on GET.../invocations","items":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"]},"example":["scheduled","in_progress","delivered","failed","retryable"]}},"required":["slack_names","statuses"]},"SlackErrorResponse":{"type":"object","description":"Error body emitted by every /integration/v1/slack endpoint. Note this is NOT the flat `ErrorResponse` used elsewhere in this document: the Slack handler nests the code and message under `error` (see SlackHandler.respondError).","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Machine-readable error code","example":"feature_not_available"},"message":{"type":"string","description":"Human-readable error message","example":"New alerts feature is not enabled for this tenant"}},"required":["code","message"]}},"required":["error"]},"SlackIntegration":{"type":"object","description":"A Slack workspace connection. Tokens are always masked on read (`xoxb-********` / `xoxp-********`); the real values never leave the service. Optional properties are omitted entirely when unset rather than sent as null.","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"name":{"type":"string","description":"Unique per tenant. OAuth-created rows are named \"Slack - <workspace>\".","example":"Security alerts"},"workspace_id":{"type":"string","example":"T0ADALJ19J7"},"workspace_name":{"type":"string","example":"test-slack-integration"},"status":{"type":"string","enum":["active","inactive"]},"auth_method":{"type":"string","description":"How the integration was authenticated","enum":["oauth","token"]},"bot_token":{"type":"string","description":"Masked. Present only when a bot token is stored.","example":"xoxb-********"},"user_access_token":{"type":"string","description":"Masked. Present only when a user token is stored.","example":"xoxp-********"},"description":{"type":"string"},"channel_id":{"type":"string","description":"Channel set at create time. Takes priority over the default channel mapping when delivery resolves a target.","example":"C0ADDKEPP8V"},"channel_name":{"type":"string","example":"all-test-slack-integration"},"slack_user_id":{"type":"string"},"slack_user_name":{"type":"string"},"granted_scopes":{"type":"string","description":"Comma-separated user scopes granted during OAuth","example":"chat:write,channels:read,groups:read,im:read"},"newly_created":{"type":"boolean","description":"True while an OAuth-created integration still needs its setup finished"},"installed_at":{"type":"string","format":"date-time"},"token_revoked_at":{"type":"string","format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","tenant_name","name","workspace_id","workspace_name","status","auth_method","newly_created","created_at","updated_at"]},"SlackIntegrationDetailResponse":{"description":"A single integration, plus the cheap oauth_available flag the detail read adds on top of the stored row (SlackHandler.GetSlackIntegration).","allOf":[{"$ref":"#/components/schemas/SlackIntegration"},{"type":"object","properties":{"oauth_available":{"type":"boolean","description":"Whether this cell has the OAuth prerequisites. See GET /integration/v1/slack/status for a live answer."}},"required":["oauth_available"]}]},"ListSlackIntegrationsResponse":{"type":"object","description":"All Slack integrations for the tenant, plus whether this cell can run an OAuth install","properties":{"integrations":{"type":"array","items":{"$ref":"#/components/schemas/SlackIntegration"}},"oauth_available":{"type":"boolean","description":"Cheap check (no network call) for whether the OAuth prerequisites exist. Use GET /integration/v1/slack/status for a live answer."}},"required":["integrations","oauth_available"]},"CreateSlackIntegrationRequest":{"type":"object","description":"Registers a workspace from a bot token obtained out of band. The normal path is the OAuth install, which creates the integration server-side from the callback.","properties":{"name":{"type":"string","description":"Unique per tenant"},"description":{"type":"string"},"workspace_id":{"type":"string"},"workspace_name":{"type":"string"},"bot_token":{"type":"string","description":"Must start with \"xoxb-\"","example":"xoxb-your-bot-token"},"channel_id":{"type":"string"},"channel_name":{"type":"string"},"newly_created":{"type":"boolean"}},"required":["name","workspace_id","workspace_name","bot_token"]},"UpdateSlackIntegrationRequest":{"type":"object","description":"Partial update. Only these three fields are writable: the workspace, tokens and channel_id are set by the install and cannot be changed here.","properties":{"name":{"type":"string"},"description":{"type":"string"},"newly_created":{"type":"boolean"}}},"SlackOAuthAuthorizeResponse":{"type":"object","description":"The Slack consent URL to send the browser to, and the signed state it carries","properties":{"authorize_url":{"type":"string","format":"uri","example":"https://slack.com/oauth/v2/authorize?client_id=...&state=..."},"state":{"type":"string","description":"Base64 JSON carrying tenant_name, ingestion_url, expired_at and a state_token. Valid for 10 minutes and validated against Redis on callback."}},"required":["authorize_url","state"]},"SlackServiceStatusResponse":{"type":"object","description":"Whether this cell can run the OAuth install. CRUD and the delivery test work regardless; only the install needs Slack app credentials and Redis (which holds the OAuth state).","properties":{"oauth_available":{"type":"boolean","description":"oauth_configured AND redis_available"},"oauth_configured":{"type":"boolean","description":"SLACK_CLIENT_ID / SLACK_CLIENT_SECRET are set"},"redis_available":{"type":"boolean","description":"Result of a live Redis ping"},"crud_available":{"type":"boolean"},"test_available":{"type":"boolean"},"oauth_unavailable_reasons":{"type":"array","description":"Present only when oauth_available is false","items":{"type":"string"},"example":["Slack OAuth credentials not configured (SLACK_CLIENT_ID, SLACK_CLIENT_SECRET)"]}},"required":["oauth_available","oauth_configured","redis_available","crud_available","test_available"]},"SlackChannel":{"type":"object","description":"A conversation the installed bot can see, from Slack's conversations.list","properties":{"id":{"type":"string","example":"C0ADDKEPP8V"},"name":{"type":"string","example":"all-test-slack-integration"},"type":{"type":"string","description":"Derived from Slack's is_group / is_private / is_im flags","enum":["channel","group","im"]},"is_member":{"type":"boolean","description":"Slack's own flag; whether the bot user is a member of the conversation"},"is_private":{"type":"boolean"},"num_members":{"type":"integer"},"purpose":{"type":"string"},"can_post":{"type":"boolean","description":"Whether chat.postMessage with the bot token will reach this channel: true when the bot is a member, or when the channel is public and the token carries chat:write.public (read from the X-OAuth-Scopes header Slack echoes on conversations.list). Private channels and DMs always require membership. A workspace installed before chat:write.public was requested reports false for public channels it was not invited to, until it is re-installed.","example":false}},"required":["id","name","type","is_member","is_private","num_members","purpose","can_post"]},"ListSlackChannelsResponse":{"type":"object","description":"Channels visible to the integration's bot token. Paged from Slack (conversations.list, public and private, archived excluded) at 1000 per page, capped at 5 pages (5000 channels).","properties":{"channels":{"type":"array","items":{"$ref":"#/components/schemas/SlackChannel"}}},"required":["channels"]},"TestSlackRequest":{"type":"object","description":"Posts a test message. The bot token is resolved server-side from the integration: with integration_id from that row, without it from the tenant's FIRST integration. Prefer POST /integration/v1/slack/{id}/test, which is unambiguous.","properties":{"channel_id":{"type":"string","example":"C0ADDKEPP8V"},"integration_id":{"type":"string","format":"uuid","description":"Which integration's token to post with"}},"required":["channel_id"]},"TestSlackByIdRequest":{"type":"object","description":"Optional body. With no channel_id, the integration's own channel_id is used.","properties":{"channel_id":{"type":"string","example":"C0ADDKEPP8V"}}},"TestSlackResponse":{"type":"object","description":"Outcome of the test post to Slack's chat.postMessage","properties":{"success":{"type":"boolean"},"status_code":{"type":"integer","example":200},"latency_ms":{"type":"integer","example":246},"error_message":{"type":"string","description":"Present only when success is false"}},"required":["success","status_code","latency_ms"]},"SlackChannelMapping":{"type":"object","description":"A channel this integration may deliver to. Exactly one may be the default, which is what delivery falls back to when the integration has no channel_id of its own.","properties":{"id":{"type":"string","format":"uuid"},"slack_integration_id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"channel_id":{"type":"string","example":"C0ADDKEPP8V"},"channel_name":{"type":"string","example":"all-test-slack-integration"},"is_default":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","slack_integration_id","tenant_name","channel_id","is_default","created_at","updated_at"]},"ListSlackChannelMappingsResponse":{"type":"object","description":"Channel mappings for one integration, default first","properties":{"channel_mappings":{"type":"array","items":{"$ref":"#/components/schemas/SlackChannelMapping"}}},"required":["channel_mappings"]},"CreateSlackChannelMappingRequest":{"type":"object","description":"A live mapping is unique per (integration, channel): creating one for a channel that already has a live mapping returns 500. Delete the existing mapping first.","properties":{"channel_id":{"type":"string","example":"C0ADDKEPP8V"},"channel_name":{"type":"string","example":"all-test-slack-integration"},"is_default":{"type":"boolean","default":false}},"required":["channel_id"]},"SplunkInvocationResponse":{"type":"object","description":"A single Splunk HEC invocation/delivery attempt","properties":{"id":{"type":"string","format":"uuid","description":"Invocation unique identifier"},"splunk_id":{"type":"string","format":"uuid","description":"Splunk config ID"},"splunk_name":{"type":"string","description":"Splunk config name"},"event_type":{"type":"string","description":"Event type sent to Splunk"},"status":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"],"description":"Delivery status"},"http_status_code":{"type":"integer","nullable":true,"description":"HTTP response status code from Splunk HEC"},"response_time_ms":{"type":"integer","nullable":true,"description":"Response time in milliseconds"},"request_payload":{"type":"object","description":"Payload sent to Splunk HEC"},"response_body":{"type":"string","nullable":true},"error_message":{"type":"string","nullable":true},"retry_count":{"type":"integer","description":"Number of retry attempts"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"ListSplunkInvocationsResponse":{"type":"object","description":"Paginated list of Splunk invocations","properties":{"invocations":{"type":"array","items":{"$ref":"#/components/schemas/SplunkInvocationResponse"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["invocations","pagination"]},"SplunkInvocationFilterOptionsResponse":{"type":"object","description":"Filter options for the Splunk invocations list (config name and status dropdowns)","properties":{"splunk_names":{"type":"array","description":"Splunk config names usable in the name filter on GET.../invocations","items":{"type":"string"},"example":["Production HEC","Staging","Test"]},"statuses":{"type":"array","description":"Valid values for the status filter on GET.../invocations","items":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"]},"example":["scheduled","in_progress","delivered","failed","retryable"]}},"required":["splunk_names","statuses"]},"WebhookInvocation":{"type":"object","description":"Webhook invocation/delivery record","properties":{"id":{"type":"string","description":"Invocation unique identifier","example":"inv_123"},"webhook_id":{"type":"string","format":"uuid","description":"Webhook ID that was invoked","example":"660e8400-e29b-41d4-a716-446655440000"},"webhook_name":{"type":"string","description":"Webhook name","example":"Production Webhook"},"event_type":{"type":"string","description":"Event type that triggered the webhook","example":"user.created"},"created_at":{"type":"string","format":"date-time","description":"Invocation timestamp","example":"2026-01-19T10:28:00Z"},"response_time_ms":{"type":"integer","description":"Response time in milliseconds","example":245},"http_status_code":{"type":"integer","description":"HTTP response status code","example":200},"status":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"],"description":"Delivery status","example":"delivered"},"request_payload":{"type":"object","description":"Request payload sent to webhook","example":{"event":"user.created","data":{"id":"usr_123456","email":"john@example.com"}}},"response_body":{"type":"object","description":"Response body from webhook endpoint","example":{"success":true,"message":"User created successfully"}}},"required":["id","webhook_name","event_type","created_at","status"]},"ListInvocationsResponse":{"type":"object","description":"List of webhook invocations with pagination","properties":{"invocations":{"type":"array","description":"Array of webhook invocations","items":{"$ref":"#/components/schemas/WebhookInvocation"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["invocations","pagination"]},"WebhookDelivery":{"type":"object","description":"Webhook delivery record (from ingestion_webhook_deliveries + events)","properties":{"id":{"type":"string","format":"uuid","description":"Delivery unique identifier"},"webhook_id":{"type":"string","format":"uuid","description":"Webhook ID"},"webhook_name":{"type":"string","description":"Webhook name"},"event_type":{"type":"string","description":"Event type that triggered the delivery"},"status":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"],"description":"Delivery status"},"event":{"type":"object","description":"Event payload sent to the webhook"},"reason":{"type":"string","description":"Error or status reason (e.g. when failed)","nullable":true},"created_at":{"type":"string","format":"date-time","description":"Delivery creation time"},"updated_at":{"type":"string","format":"date-time","description":"Last update time"}},"required":["id","webhook_id","webhook_name","event_type","status","created_at","updated_at"]},"ListDeliveriesResponse":{"type":"object","description":"List of webhook deliveries with pagination","properties":{"deliveries":{"type":"array","description":"Array of webhook deliveries","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"pagination":{"$ref":"#/components/schemas/PaginationInfo"}},"required":["deliveries","pagination"]},"WebhookDeliveryFilterOptionsResponse":{"type":"object","description":"Filter options for the webhook deliveries list (webhook name and status dropdowns)","properties":{"webhook_names":{"type":"array","description":"Webhook names usable in the name filter on GET.../deliveries","items":{"type":"string"},"example":["Production Webhook","Staging","Test"]},"statuses":{"type":"array","description":"Valid values for the status filter on GET.../deliveries","items":{"type":"string","enum":["scheduled","in_progress","delivered","failed","retryable"]},"example":["scheduled","in_progress","delivered","failed","retryable"]}},"required":["webhook_names","statuses"]},"ThreatHuntEc2Backup":{"type":"object","description":"Scan AWS Backup recovery points of an EC2 instance","properties":{"instance_id":{"type":"string","description":"EC2 instance ID","pattern":"^i-[a-f0-9]{8,17}$","example":"i-1234567890abcdef0"}},"required":["instance_id"]},"ThreatHuntEc2Drs":{"type":"object","description":"Scan AWS DRS recovery snapshots of an EC2 instance","properties":{"instance_id":{"type":"string","description":"EC2 instance ID","pattern":"^i-[a-f0-9]{8,17}$","example":"i-1234567890abcdef0"}},"required":["instance_id"]},"ThreatHuntEbs":{"type":"object","description":"Scan EBS snapshots of a volume","properties":{"volume_id":{"type":"string","description":"EBS volume ID","pattern":"^vol-[a-f0-9]{8,17}$","example":"vol-1234567890abcdef0"}},"required":["volume_id"]},"ThreatHuntEbsBackup":{"type":"object","description":"Scan AWS Backup recovery points of an EBS volume","properties":{"volume_id":{"type":"string","description":"EBS volume ID","pattern":"^vol-[a-f0-9]{8,17}$","example":"vol-1234567890abcdef0"}},"required":["volume_id"]},"ThreatHuntCloudConnector":{"type":"object","description":"Cloud Connector to use for running the job (AWS account and region).","required":["aws_account_id","aws_region"],"properties":{"aws_account_id":{"type":"string","description":"AWS account ID of the Cloud Connector (12-digit)","pattern":"^[0-9]{12}$","example":"123456789012"},"aws_region":{"type":"string","description":"AWS region of the Cloud Connector","pattern":"^[a-z]{2}-[a-z]+-\\d+$","example":"us-east-1"}}},"ThreatHuntAssetKind":{"type":"object","description":"Specifies the type of asset to scan. Exactly one of the properties must be provided.","properties":{"ec2_backup":{"$ref":"#/components/schemas/ThreatHuntEc2Backup"},"ec2_drs":{"$ref":"#/components/schemas/ThreatHuntEc2Drs"},"ebs":{"$ref":"#/components/schemas/ThreatHuntEbs"},"ebs_backup":{"$ref":"#/components/schemas/ThreatHuntEbsBackup"}}},"ThreatHuntRequest":{"type":"object","description":"Request to start a hunt operation","properties":{"tenant_name":{"type":"string","description":"Tenant identifier","maxLength":255,"pattern":"^[a-zA-Z0-9]([a-zA-Z0-9.-]*[a-zA-Z0-9])?$","example":"acme-corp"},"cloud_connector":{"$ref":"#/components/schemas/ThreatHuntCloudConnector"},"asset_kind":{"$ref":"#/components/schemas/ThreatHuntAssetKind"},"asset_account_id":{"type":"string","description":"AWS account ID where the asset resides (optional, defaults to cloud_connector.aws_account_id)","pattern":"^[0-9]{12}$","example":"123456789012"},"aws_backup_vault":{"type":"string","description":"AWS Backup vault name (defaults to \"Default\")","example":"Default"},"scan_type":{"type":"string","description":"Elastio iscan scan type (kebab-case enum). Matching is case-insensitive so legacy clients may still send \"Full\". Defaults to \"full\" when omitted.","enum":["none","malware","ransomware","encryption-detection","ransomware-malware","ransomware-encryption-detection","malware-encryption-detection","full"],"default":"full","example":"full"},"oldest_timestamp":{"type":"string","format":"date-time","description":"Limits the scan to backups newer than this timestamp. If not specified, runs in threat-hunt mode (scans all backups until finding a clean one).","example":"2024-01-01T00:00:00Z"},"reverse_incremental":{"type":"boolean","description":"Changes incremental scan lookup behavior to look for oldest scan results newer than the scanned resource instead of most recent older results.","default":false},"max_parallel_scan_jobs":{"type":"integer","description":"Maximum number of parallel scan jobs (1-50)","minimum":1,"maximum":50,"default":10,"example":10},"vault":{"type":"string","description":"Elastio vault to use for the scan","example":"my-vault"}},"required":["tenant_name","cloud_connector","asset_kind"]},"ThreatHuntResponse":{"type":"object","description":"Response from initiating a hunt","properties":{"success":{"type":"boolean","description":"Whether the job was submitted successfully","example":true},"message":{"type":"string","description":"Human-readable status message","example":"Threat-hunt job submitted successfully"},"job_id":{"type":"string","description":"Job ID for tracking (single job)","example":"01234567-89ab-cdef-0123-456789abcdef"},"aws_backup_vault":{"type":"string","description":"AWS Backup vault name (optional; only for ec2_backup/ebs_backup)","example":"Default"},"error":{"type":"string","description":"Error details (only present on failure)"},"timestamp":{"type":"string","format":"date-time","description":"Response timestamp in RFC3339 format","example":"2024-01-15T10:30:00Z"}},"required":["success","message","timestamp"]},"CreateVirusTotalRequest":{"type":"object","description":"Request body for creating a VirusTotal integration (one per tenant/user)","properties":{"api_key":{"type":"string","description":"VirusTotal API key (stored encrypted). Required for file report lookups."}},"required":["api_key"]},"UpdateVirusTotalRequest":{"type":"object","description":"Request body for updating the VirusTotal API key","properties":{"api_key":{"type":"string","description":"New VirusTotal API key (stored encrypted)"}},"required":["api_key"]},"VirusTotalResponse":{"type":"object","description":"VirusTotal integration metadata (api_key never returned)","properties":{"id":{"type":"string","format":"uuid","description":"Integration ID"},"tenant_name":{"type":"string","description":"Tenant name"},"user_id":{"type":"string","format":"uuid","description":"User ID"},"created_at":{"type":"string","format":"date-time","description":"Creation time (RFC3339)"},"updated_at":{"type":"string","format":"date-time","description":"Last update time (RFC3339)"}},"required":["id","tenant_name","user_id","created_at","updated_at"]},"PostureOverview":{"type":"object","properties":{"total_resources":{"type":"integer","description":"Total number of discovered posture resources, including unscored resources the checkers could not evaluate."},"compliant":{"type":"integer","description":"Number of resources meeting all posture rules"},"non_compliant":{"type":"integer","description":"Number of resources failing one or more rules"},"unscored":{"type":"integer","description":"Resources the checkers could not evaluate: typically a denied AWS call. Included in total_resources (they were discovered) but excluded from score, which is compliant/(compliant+non_compliant). Counting them in the denominator alone would read them as failures; counting them as compliant would read them as passes."},"score":{"type":"number","format":"double","description":"Compliance score (0–100), calculated as compliant/(compliant+non_compliant)."},"posture_score":{"type":"number","format":"double","minimum":0,"maximum":100,"description":"RPO compliance score (0–100). Computed as the share of assessed resources with no open violation in the `RPO/RTO` rule category. `0` when there are no resources."},"hunt_score":{"type":"number","format":"double","minimum":0,"maximum":100,"description":"Immutability / integrity score (0–100). Computed as `sum(compliant) / sum(total) * 100` over the `Immutability` and `Platform & Integrity` rule categories: i.e. a weighted average across the two categories' rows; a resource that appears in both categories contributes once per category to the numerator and denominator. `0` when there are no resources."},"recovery_confidence_percent":{"type":"number","format":"double","minimum":0,"maximum":100,"description":"Share of assets meeting their RPO target (0–100). Currently computed identically to `posture_score`; the FE consumes both fields under separate names so they can diverge later without a schema break."},"trend":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/PostureScorePoint"},"description":"Score trend over the last 30 days (null if no snapshots exist)"},"by_service":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/ServiceStat"},"description":"Per-resource-type breakdown (s3_bucket, ebs_volume, rds_instance, etc.)"},"by_severity":{"type":"object","additionalProperties":{"type":"integer"},"description":"Open violation counts keyed by severity (critical, high, medium, low)"},"by_category":{"type":"object","additionalProperties":{"type":"integer"},"description":"Open violation counts keyed by category (Immutability, Cryptographic, RPO/RTO, Identity, Platform & Integrity, Access Control). Lets the FE render a \"Top gap categories\" widget without an extra `/findings` round-trip."},"regions":{"type":"array","items":{"$ref":"#/components/schemas/RegionStat"},"description":"Per-region asset and gap counts ordered alphabetically by region. Empty tenants return `[]` (never `null`)."},"last_sync":{"type":"object","nullable":true,"description":"Latest sync status (null if no sync has run)","allOf":[{"$ref":"#/components/schemas/PostureSyncStatus"}]}}},"PostureScorePoint":{"type":"object","properties":{"score":{"type":"number","format":"double"},"recovery_confidence_percent":{"type":"number","format":"double","minimum":0,"maximum":100},"captured_at":{"type":"string","format":"date-time"}}},"ServiceStat":{"type":"object","properties":{"total":{"type":"integer"},"compliant":{"type":"integer"},"non_compliant":{"type":"integer"},"unscored":{"type":"integer","description":"Resources of this type that could not be evaluated."}}},"RegionStat":{"type":"object","required":["region","assets","gaps","confidence_score"],"properties":{"region":{"type":"string","example":"us-east-1","description":"AWS region identifier."},"assets":{"type":"integer","description":"Total assets in this region."},"gaps":{"type":"integer","description":"Non-compliant assets in this region (resources with at least one open violation)."},"confidence_score":{"type":"number","format":"double","minimum":0,"maximum":100,"description":"Per-region confidence score (0–100), computed as `(assets - gaps) / assets * 100`. `0` when the region has no assets."}}},"PostureResource":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"sync_id":{"type":"string","format":"uuid"},"resource_type":{"type":"string","enum":["aurora_cluster","aws_config_recorder","backup_job","backup_plan","backup_vault","cloudtrail_trail","cloudwatch_alarm","cloudwatch_log_group","dynamodb_table","ebs_snapshot","ebs_volume","ec2_instance","ecr_repository","ecs_task_definition","efs_filesystem","guardduty_detector","iam_user","kms_key","lambda_function","rds_instance","rds_snapshot","s3_bucket","secret","security_group","security_hub_account","sns_topic","sqs_queue","ssm_session_manager","vpc_flow_logs"]},"resource_id":{"type":"string","description":"Cloud-native identifier (bucket name, vol-xxx, instance ID, etc.)"},"resource_name":{"type":"string"},"cloud_provider":{"type":"string","enum":["aws"]},"aws_account_id":{"type":"string"},"region":{"type":"string"},"status":{"type":"string","enum":["compliant","non_compliant","error","unknown"]},"details":{"type":"object","description":"Service-specific posture details (encryption, versioning, snapshots, etc.)"},"last_scan_at":{"type":"string","format":"date-time","nullable":true,"description":"All timestamps are returned in UTC."},"last_backup_at":{"type":"string","format":"date-time","nullable":true,"description":"All timestamps are returned in UTC."},"created_at":{"type":"string","format":"date-time","description":"All timestamps are returned in UTC."},"updated_at":{"type":"string","format":"date-time","description":"All timestamps are returned in UTC."},"open_findings_count":{"type":"integer","description":"Number of open findings against this resource."},"open_finding_titles":{"type":"array","description":"Top 5 open finding titles for this resource (severity-ordered).","items":{"type":"string"}},"compliance_impact":{"type":"array","description":"Frameworks/controls impacted by this resource's open findings, deduplicated. Empty if there are no open findings.","items":{"$ref":"#/components/schemas/ComplianceMapping"}}},"required":["id","tenant_name","resource_type","resource_id","resource_name","cloud_provider","aws_account_id","region","status"]},"PostureResourceListResponse":{"type":"object","properties":{"resources":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/PostureResource"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"PostureViolation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenant_name":{"type":"string"},"resource_id":{"type":"string","format":"uuid"},"rule_id":{"type":"string","format":"uuid"},"sync_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["open","resolved","suppressed"]},"details":{"type":"object"},"resolved_at":{"type":"string","format":"date-time","nullable":true,"description":"All timestamps are returned in UTC (RFC3339 with `Z` suffix)."},"created_at":{"type":"string","format":"date-time","description":"All timestamps are returned in UTC (RFC3339 with `Z` suffix)."},"updated_at":{"type":"string","format":"date-time","description":"All timestamps are returned in UTC (RFC3339 with `Z` suffix)."},"rule_code":{"type":"string","description":"Rule identifier (e.g. S3_VERSIONING, EBS_ENCRYPTION)"},"rule_title":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","description":"Gap category: Immutability, Cryptographic, RPO/RTO, Identity, Platform & Integrity, Access Control"},"resource_name":{"type":"string"},"resource_type":{"type":"string"},"source":{"type":"string","enum":["posture","hunt","data_classification","cloudtrail"],"description":"Origin of the finding. Posture endpoints always return `posture`; the field is reserved so the FE can switch on a single field once findings from other sources land in the same response."},"compliance":{"type":"array","description":"Frameworks/controls this finding violates. Empty array when the rule has no compliance mappings configured.","items":{"$ref":"#/components/schemas/ComplianceMapping"}}}},"ComplianceMapping":{"type":"object","required":["framework","control"],"description":"Pair of (framework, control) describing a compliance obligation violated by a finding or impacted by a resource. `control` is a human-readable string composed as `<control_id>: <control_title>`.","properties":{"framework":{"type":"string","description":"Compliance framework name.","example":"SOC2"},"control":{"type":"string","description":"Framework control reference combining ID and title.","example":"CC6.1: Logical Access Controls"},"control_id":{"type":"string","description":"Raw control identifier (e.g. CC6.1, A.10.1.1, PR.DS-1)."},"control_title":{"type":"string","description":"Human-readable control title."}}},"PostureViolationListResponse":{"type":"object","properties":{"findings":{"type":"array","nullable":true,"items":{"$ref":"#/components/schemas/PostureViolation"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"ComplianceScore":{"type":"object","properties":{"framework":{"type":"string","description":"Compliance framework name. Known values include ISO27001, NIST, SOC2, NYDFS, and DORA. Additional frameworks may be added dynamically.","example":"ISO27001"},"score":{"type":"number","format":"double","description":"Framework compliance score (0–100)"},"status":{"type":"string","enum":["Healthy","At Risk","Failing","Unscored"],"description":"Healthy >= 90, At Risk >= 50, Failing < 50, computed over Passed and Failed controls only. Unscored means no control in the framework could be evaluated: reporting Failing (0%) would assert a compliance failure we have not established."},"unscored_controls":{"type":"integer","description":"Controls whose backing checks could not be evaluated. Excluded from score's denominator, so this is how a caller sees that a high score was computed over fewer controls than the framework contains."},"controls":{"type":"array","items":{"$ref":"#/components/schemas/ControlStatus"}}}},"ControlStatus":{"type":"object","properties":{"control_id":{"type":"string","description":"Framework control reference (e.g. A.10.1.1, PR.DS-1)"},"control_title":{"type":"string"},"status":{"type":"string","enum":["Passed","Failed","Unscored"],"description":"Unscored means the checks backing this control could not be evaluated: typically a denied AWS call. It is deliberately not Passed: zero violations because nothing was checked is not compliance, and treating it as a pass lets an under-permissioned connector earn a framework score it has not demonstrated. When several rules map to one control, Failed outranks Unscored, which outranks Passed."},"assets":{"type":"array","items":{"type":"string"},"description":"Resource names that fail this control"}}},"InternalPolicy":{"type":"object","required":["id","name","description","status","coverage"],"properties":{"id":{"type":"string","example":"POL-001","description":"Stable internal policy identifier."},"name":{"type":"string","example":"RPO Compliance (24h)"},"description":{"type":"string","description":"Human-readable policy description."},"status":{"type":"string","enum":["Passed","Warning","Failed"],"description":"Policy verdict. `Passed` when coverage is 100%, including the special case where the tenant has no resources of any type covered by the policy (reported as `100%`). `Failed` when raw coverage is below 80% or any open critical-severity violation exists in the backing categories. `Warning` otherwise."},"coverage":{"type":"string","example":"78%","description":"Coverage as a percentage string with the % sign."}}},"ComplianceResponse":{"type":"object","properties":{"frameworks":{"type":"array","items":{"$ref":"#/components/schemas/ComplianceScore"}},"policies":{"type":"array","items":{"$ref":"#/components/schemas/InternalPolicy"},"description":"Internal Elastio posture policies that summarise the tenant's coverage across RPO, immutability, encryption, access-control, and platform & forensic integrity rule categories. Empty tenants return `[]` (never `null`)."},"total":{"type":"integer","description":"Total number of frameworks (pre-pagination)."},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"LineageNode":{"type":"object","properties":{"id":{"type":"string","description":"Cloud-native resource identifier"},"label":{"type":"string","description":"Resource type"},"sublabel":{"type":"string","description":"Resource name"},"type":{"type":"string","enum":["asset","volume","snapshot","backup"],"description":"Hierarchy level. `volume` covers EBS/RDS instances; `snapshot` covers EBS/RDS snapshots; `backup` covers backup vaults; all other resource types fall back to `asset`."},"status":{"type":"string","enum":["Clean","Vulnerable","Unscored"],"description":"Unscored means the checker could not determine whether the resource is clean or vulnerable."},"accountId":{"type":"string"},"region":{"type":"string"},"findingCount":{"type":"integer"},"children":{"type":"array","items":{"type":"string"}}}},"AccountBoundary":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string"}}},"LineageResponse":{"type":"object","properties":{"nodes":{"type":"array","items":{"$ref":"#/components/schemas/LineageNode"}},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/AccountBoundary"}},"total":{"type":"integer","description":"Total number of nodes (pre-pagination)."},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"PostureResourceCounts":{"type":"object","required":["total","affected"],"properties":{"total":{"type":"integer","description":"Total resources owned by the tenant."},"affected":{"type":"integer","description":"Subset of `total` with at least one open violation. Always ≤ total; both values come from the same SQL row."},"unscored":{"type":"integer","description":"Subset of total the checkers could not evaluate. total remains the full inventory so it matches the resource list; callers deriving \"compliant\" must subtract both affected and unscored."}}},"PostureSyncStatus":{"type":"object","required":["id","status","trigger_type"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","in_progress","completed","failed"]},"trigger_type":{"type":"string","enum":["manual","scheduled"]},"started_at":{"type":"string","format":"date-time","nullable":true,"description":"All timestamps are returned in UTC."},"completed_at":{"type":"string","format":"date-time","nullable":true,"description":"All timestamps are returned in UTC."},"error_message":{"type":"string"},"accounts_scanned":{"type":"integer"},"regions_scanned":{"type":"integer"},"resources_found":{"type":"integer"},"findings_found":{"type":"integer"},"expected_accounts":{"type":"integer","description":"Total accounts expected for this sync, set by the scanner at sync start. Used to compute progress_percent."},"expected_regions":{"type":"integer","description":"Total account+region targets expected for this sync."},"progress_percent":{"type":"integer","minimum":0,"maximum":100,"description":"Sync progress as a percentage (0-100), computed as regions_scanned/expected_regions. Reaches 100 only when the sync completed AND covered every account and region it expected: see coverage_complete. A completed sync that missed a target reports its real ratio, so a half-scanned estate is no longer indistinguishable from a fully scanned one. Returns 0 when the expected totals are unset (legacy syncs, or before the scanner records totals); the FE should fall back to an indeterminate spinner in that case."},"coverage_complete":{"type":"boolean","description":"Whether the sync reached every account and region it set out to. A sync can finish without error and still miss an entire account (an assume-role that was refused, credentials absent for that account, a region that errored out); every resource in an unreached account is then invisible, and invisible is indistinguishable from absent in coverage, compliance and score. False whenever the expected totals are unknown or the sync has not completed, because coverage is not knowable in those states."},"missed_accounts":{"type":"integer","minimum":0,"description":"expected_accounts minus accounts_scanned, floored at zero, so a caller can report what was missed rather than only that something was."},"missed_regions":{"type":"integer","minimum":0,"description":"expected_regions minus regions_scanned, floored at zero."},"duration_seconds":{"type":"integer","format":"int64","description":"Elapsed time in seconds. While a sync is still running this is the time since started_at; once completed it is the gap between started_at and completed_at."}}},"PostureSyncTriggerResponse":{"type":"object","properties":{"message":{"type":"string"},"sync_id":{"type":"string","format":"uuid"},"status":{"type":"string"}}},"PostureSyncListResponse":{"type":"object","properties":{"syncs":{"type":"array","items":{"$ref":"#/components/schemas/PostureSyncStatus"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}},"PostureAWSCredentialsRequest":{"type":"object","required":["access_key_id","secret_access_key","default_region"],"description":"Per-tenant static AWS credentials used to pull posture data from a customer AWS account when role-based assume isn't usable (temporary credentials, SSO, or external accounts not in the cross-account trust). Secret material is encrypted at rest with AWS KMS.\n\nPrefer POST /ingestion/v1/posture/credentials/role. This path stores long-lived secrets at rest; the role path stores nothing that is useful to an attacker who reads the table.","properties":{"access_key_id":{"type":"string","description":"AWS access key ID (e.g., \"AKIA...\").","example":"AKIAIOSFODNN7EXAMPLE"},"secret_access_key":{"type":"string","format":"password","description":"AWS secret access key. Encrypted with KMS before storage; never returned by GET."},"session_token":{"type":"string","format":"password","description":"Optional AWS session token for temporary credentials / SSO. Encrypted with KMS before storage."},"default_region":{"type":"string","description":"Default AWS region to use when scanning posture data.","example":"us-east-1"}}},"PostureAWSRoleCredentialsRequest":{"type":"object","required":["role_arn","default_region"],"description":"Role-based posture credentials: the preferred way to connect a tenant's AWS account. Nothing stored by this path is useful to an attacker who reads the table: the role ARN is not secret, and the external ID only means anything to the principal the customer's trust policy already names.\n\nThe role is assumed before anything is persisted, so a trust policy that was never applied fails at connect time rather than silently producing no posture data at the next scan.","properties":{"role_arn":{"type":"string","description":"IAM role to assume in the customer account, of the form arn:<partition>:iam::<account-id>:role/<name>.","example":"arn:aws:iam::123456789012:role/ElastioPosture"},"external_id":{"type":"string","format":"password","description":"Optional but strongly recommended sts:ExternalId. Without it, anyone who learns the role ARN can attempt to use our principal as a confused deputy. Encrypted with KMS before storage; never returned."},"default_region":{"type":"string","description":"Default AWS region to use when scanning posture data.","example":"us-east-1"},"aws_account_id":{"type":"string","description":"Empty resolves from the assumed session; \"*\" is explicit consent for cross-account use and skips verification; an exact id must match the account the assumed session resolves to."}}},"PostureAWSCredentialsResponse":{"type":"object","required":["access_key_id","default_region","auth_mode","has_session_token","created_at","updated_at"],"description":"Non-secret metadata about the stored posture credentials. The secret access key and session token are intentionally omitted to prevent leakage in logs, replays, or screenshots.","properties":{"access_key_id":{"type":"string","description":"Empty on a role-based row."},"default_region":{"type":"string"},"auth_mode":{"type":"string","description":"Which mechanism this tenant is connected by. Present so a role row is not mistaken for a misconfigured static row with a blank access_key_id.","enum":["role","static_keys"]},"role_arn":{"type":"string","description":"Set only when auth_mode is \"role\"."},"has_external_id":{"type":"boolean","description":"True if an external ID is on file. The value is never returned."},"has_session_token":{"type":"boolean","description":"True if a session token was supplied alongside the access key."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"PostureAWSCredentialsUpsertResponse":{"type":"object","required":["message","access_key_id","default_region","has_session_token"],"properties":{"message":{"type":"string"},"access_key_id":{"type":"string"},"default_region":{"type":"string"},"has_session_token":{"type":"boolean"}}},"PostureConnectionStatusResponse":{"type":"object","required":["connected"],"description":"Whether the stored tenant credentials successfully authenticate against AWS. Validated by calling `sts:GetCallerIdentity` with the decrypted credentials. The response intentionally never returns the secret access key or session token.","properties":{"connected":{"type":"boolean"},"auth_mode":{"type":"string","description":"Which mechanism the stored row uses.","enum":["role","static_keys"]},"role_arn":{"type":"string","description":"Set only when auth_mode is \"role\"."},"account_id":{"type":"string","description":"AWS account ID returned by STS (only when connected)."},"user_arn":{"type":"string","description":"Caller ARN returned by STS (only when connected)."},"default_region":{"type":"string"},"access_key_id":{"type":"string"},"error":{"type":"string","description":"Human-readable failure reason when `connected` is false. When no credentials are configured, this is set to \"no posture credentials configured\" and the endpoint still returns HTTP 200 so the FE can render a single tile."}}},"PostureRule":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"code":{"type":"string","description":"Rule identifier (e.g. S3_VERSIONING)","example":"S3_VERSIONING"},"title":{"type":"string"},"description":{"type":"string"},"severity":{"type":"string","enum":["critical","high","medium","low","info"]},"category":{"type":"string","description":"Gap category: Immutability, Cryptographic, RPO/RTO, Identity, Platform & Integrity, Access Control"},"resource_type":{"type":"string"},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"}}},"SuppressionRequest":{"type":"object","required":["reason"],"description":"At least one scope field (rule_code, aws_account_id, region, resource_type, resource_id, resource_id_pattern, tag_filters) must be provided.","properties":{"rule_code":{"type":"string"},"aws_account_id":{"type":"string"},"region":{"type":"string"},"resource_type":{"type":"string"},"resource_id":{"type":"string"},"resource_id_pattern":{"type":"string","description":"SQL LIKE pattern matched against resource_id"},"tag_filters":{"type":"object","description":"JSONB tag key/value filters"},"reason":{"type":"string"},"expires_at":{"type":"string","format":"date-time","nullable":true}}},"SuppressionResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"rule_code":{"type":"string"},"aws_account_id":{"type":"string"},"region":{"type":"string"},"resource_type":{"type":"string"},"resource_id":{"type":"string"},"resource_id_pattern":{"type":"string"},"tag_filters":{"type":"object"},"suppressed_by":{"type":"string"},"reason":{"type":"string"},"effective_from":{"type":"string","format":"date-time"},"expires_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"AIProviderCredential":{"description":"Metadata only. The credential is never served.","properties":{"created_at":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"provider":{"enum":["openai","amazon_bedrock","azure_foundry"],"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","provider","name","created_at","updated_at"],"type":"object"},"AIProviderCredentialListResponse":{"properties":{"credentials":{"items":{"$ref":"#/components/schemas/AIProviderCredential"},"type":"array"}},"required":["credentials"],"type":"object"},"AIProviderStandardError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"AccountRegionSelector":{"properties":{"account_id":{"type":"string"},"region":{"type":"string"}},"required":["account_id","region"],"type":"object"},"AddTenantLicenseBody":{"properties":{"key":{"description":"The raw license key string, exactly as issued.","example":"EFcaDgE.eyJhbGciOiJQUzI1NiIs...","type":"string"}},"required":["key"],"type":"object"},"AgentRelease":{"properties":{"build":{"type":"string"},"notes":{"type":"string"},"published_at":{"format":"date-time","type":"string"},"version":{"description":"Published semantic version; empty for historical unnumbered builds.","type":"string"}},"required":["version","build","notes"],"type":"object"},"AgentUpdateState":{"properties":{"auto_upgrade":{"type":"boolean"},"available":{"type":"boolean"},"channel":{"enum":["production","development",""],"type":"string"},"current_release":{"$ref":"#/components/schemas/AgentRelease"},"current_version":{"type":"string"},"deployment":{"type":"string"},"detail":{"type":"string"},"latest_release":{"$ref":"#/components/schemas/AgentRelease"},"progress":{"maximum":100,"minimum":0,"type":"integer"},"release_error":{"type":"string"},"request_id":{"type":"string"},"status":{"enum":["idle","queued","checking","downloading","restarting","verifying","completed","failed"],"type":"string"},"target_version":{"type":"string"}},"required":["available","auto_upgrade","deployment","request_id","status","target_version","current_version","detail","progress"],"type":"object"},"AssetAccount":{"properties":{"alias":{"type":"string"},"aws_account_id":{"type":"string"},"connector_aws_account_id":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"id":{"type":"string"},"region_stacks":{"items":{"$ref":"#/components/schemas/RegionStack"},"type":"array"},"stack_region":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"version":{"type":"string"}},"required":["id","region_stacks","aws_account_id","connector_aws_account_id","alias","description","stack_region","version","created_at","updated_at"],"type":"object"},"AssetAccountLinkingJob":{"properties":{"asset_region_stack_deployment_job":{"$ref":"#/components/schemas/ConnectorJobId"},"region":{"type":"string"}},"required":["region"],"type":"object"},"AssetEvidence":{"properties":{"asset":{"$ref":"#/components/schemas/AssetRef"},"coverage":{"description":"Amendment A2 - the analysis matrix, clean runs included.","items":{"$ref":"#/components/schemas/CoverageRecord"},"type":"array"},"degraded":{"description":"Section paths whose read FAILED, `recovery_verdict` included. Empty means every section resolved.\n","items":{"type":"string"},"type":"array"},"determination":{"$ref":"#/components/schemas/Determination"},"recovery_posture":{"$ref":"#/components/schemas/RecoveryPosture"},"recovery_verdict":{"allOf":[{"$ref":"#/components/schemas/AssetRecoveryVerdict"}],"description":"The recovery verdict shared-services serves for this asset, the same object `GET /shared-services/v1/recovery-verdict/assets` returns as `recovery`, including every applied exception with its waived requirement, approval id, author, approval time, expiry and reason. Null when the verdict is not served for the tenant or the asset has no evaluation; named in `degraded` when the read failed.\n","nullable":true},"tested_backup":{"$ref":"#/components/schemas/TestedBackup"},"threats":{"items":{"$ref":"#/components/schemas/ThreatCategory"},"type":"array"},"violations":{"$ref":"#/components/schemas/Violations"}},"required":["asset","determination","threats","violations","recovery_posture","recovery_verdict","tested_backup","coverage","degraded"],"type":"object"},"AssetPoliciesResponse":{"properties":{"asset_id":{"format":"uuid","type":"string"},"policies":{"items":{"type":"string"},"type":"array"}},"required":["asset_id","policies"],"type":"object"},"AssetRecoveryVerdict":{"properties":{"at_risk":{"type":"boolean"},"at_risk_reasons":{"items":{"$ref":"#/components/schemas/RecoveryAtRiskReason"},"type":"array"},"compromise_started_at":{"format":"date-time","nullable":true,"type":"string"},"effective_target":{"$ref":"#/components/schemas/RecoveryEffectiveTarget"},"evaluated_at":{"format":"date-time","type":"string"},"exceptions":{"description":"The exceptions applied in this evaluation (active and unexpired).","items":{"$ref":"#/components/schemas/RecoveryException"},"type":"array"},"newest_clean_point_at":{"format":"date-time","nullable":true,"type":"string"},"proven_with_exceptions":{"type":"boolean"},"qualifying_point":{"description":"The newest qualifying point; null when unproven.","nullable":true,"properties":{"copies":{"items":{"enum":["immutable","air_gapped","cross_region"],"type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"recovery_point_id":{"type":"string"}},"type":"object"},"unproven_reasons":{"items":{"$ref":"#/components/schemas/RecoveryUnprovenReason"},"type":"array"},"verdict":{"$ref":"#/components/schemas/RecoveryVerdict"}},"required":["verdict","unproven_reasons","at_risk","at_risk_reasons","proven_with_exceptions","exceptions","effective_target","evaluated_at"],"type":"object"},"AssetRef":{"properties":{"health":{"description":"Inventory-level rollup, the one the v2 assets read serves: an EC2 instance or Azure VM rolls up its scanned volumes / disks, any other asset is its own health row, and no row is at_risk. CONTEXT only, outranked by determination.\n","type":"string"},"id":{"type":"string"},"kind":{"type":"string"},"name":{"type":"string"},"platform":{"type":"string"}},"required":["id","name","kind","platform","health"],"type":"object"},"AwsAccountUpgradePlanResponse":{"properties":{"account_id":{"type":"string"},"latest_version":{"description":"Newest version enabled for the tenant, whatever the account template allows","type":"string"},"pinned_version":{"description":"Highest version Elastio holds the tenant at; empty when not pinned","type":"string"},"regions":{"items":{"$ref":"#/components/schemas/UpgradePlanRegion"},"type":"array"},"target_version":{"description":"Newest version enabled for the tenant that the account template allows; empty when none","type":"string"},"vault_target_version":{"description":"Version the Elastio vaults of an upgraded region move to","type":"string"}},"required":["account_id","target_version","latest_version","vault_target_version","pinned_version","regions"],"type":"object"},"AwsVaultCreateBody":{"properties":{"red_stack_id":{"type":"string"},"safety_lock":{"type":"boolean"},"set_default":{"type":"boolean"},"subnet_ids":{"items":{"type":"string"},"type":"array"},"vault_kms_key":{"type":"string"},"vault_name":{"type":"string"},"vpc_id":{"description":"Optional. Leave empty to use the default Elastio-managed network. If you set a VPC, you must also provide at least one subnet in `subnet_ids`.","type":"string"}},"required":["red_stack_id","vault_name","vault_kms_key","set_default","subnet_ids","safety_lock"],"type":"object"},"AwsVaultDestroyBody":{"properties":{"red_stack_id":{"type":"string"},"vault_name":{"type":"string"}},"required":["red_stack_id","vault_name"],"type":"object"},"AzureAssetCounts":{"description":"Picker only. Live asset counts for the (subscription, region) pair, per matchable kind: the same live predicates the pair listing uses. Absent on the per-policy variant.","properties":{"azure_blob_container":{"type":"integer"},"azure_disk":{"type":"integer"},"azure_storage_file_share":{"type":"integer"},"azure_vm":{"type":"integer"}},"required":["azure_vm","azure_disk","azure_blob_container","azure_storage_file_share"],"type":"object"},"AzureSubscriptionRegion":{"properties":{"asset_counts":{"$ref":"#/components/schemas/AzureAssetCounts"},"azure_tenant_id":{"description":"Picker only. The Azure AD tenant the subscription belongs to. Absent when unknown and on the per-policy variant.","type":"string"},"region":{"type":"string"},"subscription_id":{"type":"string"},"subscription_name":{"type":"string"},"subscription_state":{"description":"Picker only. The subscription's state as recorded by inventory: enabled, warned, past_due, disabled, or deleted. Absent on the per-policy variant.","type":"string"}},"required":["subscription_id","subscription_name","region"],"type":"object"},"BatchDeleteHuntRulesRequest":{"properties":{"ignore_blocked":{"description":"Client intent flag; unblocked ids are always deleted regardless.","type":"boolean"},"rule_ids":{"items":{"format":"uuid","type":"string"},"type":"array"}},"required":["rule_ids"],"type":"object"},"BatchDeleteHuntRulesResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/BatchDeleteResult"},"type":"array"}},"required":["results"],"type":"object"},"BatchDeleteResult":{"properties":{"blocking_policies":{"items":{"$ref":"#/components/schemas/HuntRulePolicyRef"},"type":"array"},"rule_id":{"type":"string"},"status":{"enum":["DELETED","BLOCKED","NOT_FOUND"],"type":"string"}},"required":["rule_id","status"],"type":"object"},"BreakdownEntry":{"properties":{"count":{"format":"int64","type":"integer"},"key":{"type":"string"},"label":{"type":"string"}},"required":["key","label","count"],"type":"object"},"BuiltInPursuitPlaybook":{"additionalProperties":false,"properties":{"description":{"description":"Human-readable description of the playbook.","type":"string"},"name":{"description":"Machine-readable playbook name (e.g. `persistence`).","type":"string"}},"required":["name","description"],"type":"object"},"BuiltInPursuitPlaybooksResponse":{"additionalProperties":false,"properties":{"playbooks":{"description":"All built-in pursuit playbooks available on Cloud Connector images.","items":{"$ref":"#/components/schemas/BuiltInPursuitPlaybook"},"type":"array"}},"required":["playbooks"],"type":"object"},"CCLSeverityOverride":{"additionalProperties":false,"properties":{"ccl_type":{"type":"string"},"severity":{"enum":["critical","high","medium","low"],"type":"string"}},"required":["ccl_type","severity"],"type":"object"},"ClusterOptions":{"description":"Cluster policy options for Azure/IBM platforms. Extra keys are ignored by this service.","properties":{"policy_yaml":{"description":"Multicloud scan-policy document (YAML). On create and update it is strictly validated by this service in three layers and an invalid document is rejected with 400 `POLICY_YAML_INVALID` and a structured `issues` array (nothing is persisted or published): YAML safety (single document, no anchors/aliases/merge keys, no duplicate or non-scalar keys, size/depth/entry limits), the Cloud Connector policy JSON Schema, and product rules deliberately stricter than the Cloud Connector's own parser (unknown-key, platform-mismatch, empty-selector, identifier- format, and derivability checks). Submit a draft to `POST /shared-services/v2/policies:validate` to preflight it without creating anything.","type":"string"}},"required":["policy_yaml"],"type":"object"},"CommitOutcomeUnknownErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"properties":{"policy_id":{"description":"The create attempt's minted canonical id (create only).","format":"uuid","type":"string"}},"type":"object"}],"description":"500 body for a write whose transaction commit outcome could not be resolved (`code` `COMMIT_OUTCOME_UNKNOWN`, D2). Extends the standard error envelope with an optional `policy_id`, set only on the create sentinel (any AWS create facet (v1/v2/v3): the create attempt's minted canonical id) the key for the `expected_policy_id` conditional-update recovery flow on the v3 update."},"ConnectorAccountInstallFlowItem":{"properties":{"autoinstall_in_aws_regions":{"items":{"type":"string"},"type":"array"},"aws_account_id":{"description":"12-digit AWS account ID","type":"string"},"created_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"state":{"enum":["waiting_for_account_level_stack","connector_installs_scheduled","unknown"],"type":"string"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"vpc_permissions_enabled":{"type":"boolean"}},"required":["id","tenant_name","aws_account_id","autoinstall_in_aws_regions","vpc_permissions_enabled","state"],"type":"object"},"ConnectorJobId":{"properties":{"cc_job_id":{"format":"byte","type":"string"},"human_readable_cc_job_id":{"type":"string"},"job_id":{"type":"string"}},"required":["job_id","cc_job_id","human_readable_cc_job_id"],"type":"object"},"CorruptedColumn":{"properties":{"column":{"type":"string"},"relation":{"type":"string"},"sampled":{"type":"boolean"},"values":{"description":"Confirmed damaged column values in the sampled writes, not distinct rows.","type":"integer"}},"required":["relation","column","values","sampled"],"type":"object"},"CoverageRecord":{"properties":{"at":{"nullable":true,"type":"string"},"finding_id":{"nullable":true,"type":"string"},"freshness":{"allOf":[{"$ref":"#/components/schemas/Freshness"}],"nullable":true},"method":{"type":"string"},"note":{"description":"Explains a non-ran status in the reader's language; rendered verbatim.","nullable":true,"type":"string"},"score":{"allOf":[{"$ref":"#/components/schemas/Score"}],"nullable":true},"status":{"description":"inconclusive is excluded from the ran/expected denominator, not counted as a skip.","enum":["ran","not_run","inconclusive","errored"],"type":"string"},"subject":{"$ref":"#/components/schemas/Subject"},"verdict":{"description":"Meaningful only when status is \"ran\".","enum":["clean","finding","remediated","suspicious","unknown"],"type":"string"}},"required":["subject","method","status","verdict","score","at","freshness","finding_id","note"],"type":"object"},"CreateAIProviderCredentialBody":{"properties":{"credential":{"$ref":"#/components/schemas/CredentialPayload"},"name":{"maxLength":255,"type":"string"},"provider":{"enum":["openai","amazon_bedrock","azure_foundry"],"type":"string"}},"required":["provider","name","credential"],"type":"object"},"CreatePolicyRequest":{"description":"Provide either `frequency` (inline) or `schedule_id` (reference to a standalone schedule), never both. Setting both is rejected with 400.","properties":{"account_region_selectors":{"items":{"$ref":"#/components/schemas/AccountRegionSelector"},"type":"array"},"data_classification_scan_options":{"$ref":"#/components/schemas/DataClassificationScanOptions"},"description":{"description":"Human-readable description for the policy","type":"string"},"execute_immediately":{"deprecated":true,"description":"Removed. Sending true on an AWS create or update is rejected with 400 POLICY_EXECUTE_REMOVED before any side effect; absent or false is accepted and has no effect.","type":"boolean"},"frequency":{"$ref":"#/components/schemas/Frequency"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanRequest"},"mode":{"allOf":[{"$ref":"#/components/schemas/Mode"}],"example":{"ec2_or_ebs":{"keep_last_clean_copy":true,"keep_latest_infected_copy":false},"efs":{},"kind_tag":"scan_only","s3":{"threat_hunt":true}}},"name":{"type":"string"},"paused_until":{"format":"date-time","nullable":true,"type":"string"},"platform":{"default":"AWS","description":"Target platform","enum":["AWS"],"type":"string"},"protect_new_immediately":{"enum":["disabled","enabled"],"type":"string"},"pursuit_scan_options":{"$ref":"#/components/schemas/PursuitScanOptions"},"schedule_id":{"description":"Reference to a row in the schedules API. Mutually exclusive with `frequency`.","format":"uuid","nullable":true,"type":"string"},"selectors":{"example":[{"criteria":[{"asset_type":"s3","kind_tag":"is_type"}]}],"items":{"$ref":"#/components/schemas/Selector"},"minItems":1,"type":"array"},"skip_ebs_backup":{"type":"boolean"},"snapshot_import":{"enum":["skip","latest","all"],"type":"string"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"tags":{"additionalProperties":{"nullable":true,"type":"string"},"type":"object"},"vaults":{"items":{"$ref":"#/components/schemas/RequestedVault"},"type":"array"}},"required":["name","selectors","mode"],"type":"object"},"CreatePolicyV2Request":{"description":"Body for POST /shared-services/v2/policies. `platform` is required. For AWS this behaves like the v1 create: the v1 policy fields apply and `cluster_name`/`cluster_options` must be omitted. For Azure/IBM only `platform`, `name`, `description`, `cluster_name`, `subscription_ids` (Azure only), and `cluster_options` are accepted (any other field present → 400) and `cluster_options.policy_yaml` is required. The v1 fields below carry the same shape as CreatePolicyRequest.","properties":{"account_region_selectors":{"items":{"$ref":"#/components/schemas/AccountRegionSelector"},"type":"array"},"cluster_name":{"description":"Legacy single-cluster target. Required for IBM. For Azure it is the legacy shape, mutually exclusive with `subscription_ids`. Must be omitted for AWS.","nullable":true,"type":"string"},"cluster_options":{"allOf":[{"$ref":"#/components/schemas/ClusterOptions"}],"description":"Cluster policy options for Azure/IBM (carries `policy_yaml`). Must be omitted for AWS.","nullable":true},"data_classification_scan_options":{"$ref":"#/components/schemas/DataClassificationScanOptions"},"description":{"description":"Human-readable description for the policy","type":"string"},"execute_immediately":{"deprecated":true,"description":"Removed. For AWS policies, sending true is rejected with 400 POLICY_EXECUTE_REMOVED before any side effect; absent or false is accepted and has no effect. For Azure and IBM policies the field must be omitted entirely - presence, even false, is rejected by the non-AWS field allowlist.","type":"boolean"},"frequency":{"$ref":"#/components/schemas/Frequency"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanRequest"},"mode":{"allOf":[{"$ref":"#/components/schemas/Mode"}],"example":{"ec2_or_ebs":{"keep_last_clean_copy":true,"keep_latest_infected_copy":false},"efs":{},"kind_tag":"scan_only","s3":{"threat_hunt":true}}},"name":{"type":"string"},"paused_until":{"format":"date-time","nullable":true,"type":"string"},"platform":{"description":"Target platform. Required on v2. AWS uses the v1 policy fields; Azure and IBM use `cluster_name` and `cluster_options`.","enum":["AWS","Azure","IBM","GCP"],"type":"string"},"protect_new_immediately":{"enum":["disabled","enabled"],"type":"string"},"pursuit_scan_options":{"$ref":"#/components/schemas/PursuitScanOptions"},"schedule_id":{"description":"Reference to a row in the schedules API. Mutually exclusive with `frequency`.","format":"uuid","nullable":true,"type":"string"},"selectors":{"items":{"$ref":"#/components/schemas/Selector"},"minItems":1,"type":"array"},"skip_ebs_backup":{"type":"boolean"},"snapshot_import":{"enum":["skip","latest","all"],"type":"string"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"subscription_ids":{"description":"Azure only; the typed scope: the subscriptions the policy covers (UUIDs, deduplicated server-side). The server resolves each to the scan cluster that serves it; an unresolvable subscription is a 400 `SUBSCRIPTION_UNRESOLVED`. Mutually exclusive with `cluster_name`.","items":{"format":"uuid","type":"string"},"minItems":1,"nullable":true,"type":"array"},"tags":{"additionalProperties":{"nullable":true,"type":"string"},"type":"object"},"vaults":{"items":{"$ref":"#/components/schemas/RequestedVault"},"type":"array"}},"required":["name","platform"],"type":"object"},"CreatePolicyV3Request":{"allOf":[{"$ref":"#/components/schemas/CreatePolicyV2Request"},{"properties":{"alert_ids":{"description":"Alert UUIDs to bind to the policy on create. Each id must be a well-formed, non-nil UUID with no duplicates, validated before anything persists (400 `INVALID_ALERT_IDS`). When alert synchronization is enabled, a create that produces an ENABLED policy must carry at least one id: omitting it (or sending `[]`) is rejected 400 `ALERT_REQUIRED`; disabled/paused creates may omit it (they bind no alerts). Accepted on all platforms (AWS/Azure/IBM).","items":{"format":"uuid","type":"string"},"type":"array"},"ccl_severity_overrides":{"description":"Explicit CCL severity overrides. A type omitted here keeps the catalog default. Omitted or empty persists and reads back as `[]`. When the policy selects a non-empty `ccl_types` list (AWS `data_classification_scan_options`, or Azure `options.data_classification` in the cluster YAML), every override type must be in that list. An empty `ccl_types` still scans every type.","items":{"$ref":"#/components/schemas/CCLSeverityOverride"},"type":"array"},"created_via_plan_id":{"description":"Optional provenance (the \"Managed\" facet): the Resilience Program plan this policy is materialized from. Stamped once at create and immutable (there is no counterpart on update). Omitting it (or sending null/blank) creates an unmanaged policy. Accepted for AWS and cluster (Azure/IBM) policies.","nullable":true,"type":"string"},"hunt_rule_ids":{"description":"Hunt-rule UUIDs to bind to the policy on create. Each id must be a well-formed, non-nil UUID with no duplicates, and must refer to a live hunt rule with status `active`, validated before anything persists (400 `INVALID_HUNT_RULE_IDS` for a malformed, duplicate, or unknown id; 400 `HUNT_RULE_NOT_ACTIVE` for a `tuning` or `inactive` rule: those are not egested and would never run). When present, `iscan.hunt` is derived automatically (non-empty set = true, empty = false). Omitting the field binds no hunt rules. AWS scheduled policies only.","items":{"format":"uuid","type":"string"},"type":"array"},"r_rpo":{"allOf":[{"$ref":"#/components/schemas/RRPOTarget"}],"description":"Optional per-policy Recovery RPO target. Omitting it (or sending null) persists no R-RPO. Validated before anything persists: a non-positive `target_seconds` is rejected 400 `INVALID_RRPO_TARGET` and an out-of-enum `severity` 400 `INVALID_RRPO_SEVERITY`.","nullable":true},"violations":{"description":"Optional per-policy violation selection. Each code is validated against the catalog dictionary; an omitted or empty list persists and reads back as `[]`. A repeated code is rejected 400 `DUPLICATE_VIOLATION_CODE`.","items":{"$ref":"#/components/schemas/RequestedViolation"},"type":"array"}},"type":"object"}],"description":"Body for POST /shared-services/v3/policies. A strict superset of CreatePolicyV2Request, adding the optional `violations` list (accepted on all platforms) and the optional `r_rpo` target. Every v2 field applies unchanged."},"CreateScheduleRequest":{"properties":{"description":{"description":"Optional human-readable description. Omit the field to leave an existing description unchanged on PATCH; explicit JSON null is treated the same as omission.","type":"string"},"frequency":{"$ref":"#/components/schemas/Frequency"},"name":{"description":"Per-tenant unique schedule name (1-255 chars)","type":"string"}},"required":["name","frequency"],"type":"object"},"CreateVaultJobResponse":{"properties":{"job_id":{"type":"string"}},"required":["job_id"],"type":"object"},"CreateVaultRequestBody":{"properties":{"aws_vault_create":{"$ref":"#/components/schemas/AwsVaultCreateBody"}},"required":["aws_vault_create"],"type":"object"},"CredentialPayload":{"description":"Write-only. openai requires api_key. amazon_bedrock requires region. azure_foundry requires base_url and api_key. Fields for another provider are rejected. The server seals the provider plaintext; this object is not stored as-is.","properties":{"api_key":{"description":"OpenAI or Azure Foundry API key. Never returned.","maxLength":4096,"type":"string"},"base_url":{"description":"Azure Foundry endpoint. Must be an https URL.","format":"uri","maxLength":2048,"type":"string"},"region":{"description":"Amazon Bedrock region, for example us-east-1.","maxLength":2048,"type":"string"}},"type":"object"},"CrossPlatformNameConflictError":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"properties":{"platform":{"description":"The platform that already owns the requested name (e.g. `AWS`).","type":"string"}},"type":"object"}],"description":"409 conflict body for the v2 write endpoints. Extends the standard error envelope with an optional `platform`, set only when `code` is `NAME_EXISTS_ON_OTHER_PLATFORM`."},"DataClassificationCustomCclLocation":{"additionalProperties":false,"properties":{"container":{"type":"string"},"prefix":{"type":"string"}},"required":["container","prefix"],"type":"object"},"DataClassificationScanOptions":{"additionalProperties":false,"description":"Optional DC scan configuration. It may be stored even when `iscan.data_classification` is false, but it only affects execution when the boolean is enabled.","properties":{"archives":{"type":"boolean"},"ccl_names":{"items":{"type":"string"},"type":"array"},"ccl_regions":{"items":{"type":"string"},"type":"array"},"ccl_types":{"items":{"type":"string"},"type":"array"},"custom_ccls":{"$ref":"#/components/schemas/DataClassificationCustomCclLocation"},"self_extracted_archives":{"type":"boolean"}},"type":"object"},"DatabaseMonitoringAPIKey":{"description":"The Database Connector key this database accepts: the one\npersonal access token a Database Connector reporting for this database is accepted\nwith. Another database's key, or a tenant's all-scopes key, is refused.\nNever the token itself, which is shown once, in the setup.\n","properties":{"created_at":{"description":"When the current key was minted","format":"date-time","nullable":true,"type":"string"},"enforced":{"description":"True when every Database Connector request that does not prove it carries this key is refused. While false, a request carrying another key the gateway identified is still refused, but one whose key could not be identified is accepted.","type":"boolean"},"id":{"description":"The token's id. Empty when no key was issued here.","type":"string"},"last_rejected_at":{"format":"date-time","nullable":true,"type":"string"},"last_used_at":{"description":"The last Database Connector request identified as made with this key, to within a minute","format":"date-time","nullable":true,"type":"string"},"name":{"description":"The token's name, as personal access tokens lists it. Null when unknown, for a key minted before names were recorded that could not be looked up.","nullable":true,"type":"string"},"rejected_attempts_24h":{"description":"Database Connector requests for this database refused in the last 24 hours because they did not carry this key, counted to within a minute","type":"integer"},"rotated_at":{"description":"When the key last replaced another. Null when never rotated.","format":"date-time","nullable":true,"type":"string"}},"required":["id","name","created_at","rotated_at","last_used_at","rejected_attempts_24h","last_rejected_at","enforced"],"type":"object"},"DatabaseMonitoringAgentSettings":{"description":"What an admin set for this database's Database Connector, sent to it on its own register and heartbeat replies. A setting that is absent is the value the Database Connector was deployed with. The deployment is the ceiling: content analysis can be turned off here but never on.\n","properties":{"content_analysis":{"description":"false turns content analysis off; true leaves it as deployed. A Database Connector deployed without the encryption detector refuses true.","type":"boolean"},"review_minutes":{"description":"How long after a finding later activity may still explain it. Deployed 60.","maximum":1440,"minimum":30,"type":"integer"},"revision":{"description":"Advances with every change an admin saves. 0 is never set.","format":"int64","minimum":0,"type":"integer"},"size_sample_seconds":{"description":"How often table sizes and the slot are sampled. Deployed 60.","maximum":3600,"minimum":30,"type":"integer"},"window_idle_seconds":{"description":"A window closes once the database has committed nothing for this long. Deployed 60.","maximum":3600,"minimum":10,"type":"integer"},"window_max_span_seconds":{"description":"A window closes after this long even on a database that is never quiet. Not below the idle period in force. Deployed 900.","maximum":3600,"minimum":60,"type":"integer"}},"required":["revision"],"type":"object"},"DatabaseMonitoringAgentSize":{"description":"The Database Connector's Fargate task size, rendered into the setup's Terraform as task_cpu and task_memory. small is 256 CPU units and 512 MiB, medium 512 and 1024, large 1024 and 2048, xlarge 2048 and 4096.\n","enum":["small","medium","large","xlarge"],"type":"string"},"DatabaseMonitoringAppliedSettings":{"description":"The settings the Database Connector reported running with, as it sent them.","properties":{"content_analysis":{"description":"Whether rewritten values are being sampled for the encryption detector now","type":"boolean"},"content_analysis_available":{"description":"Whether the Database Connector was deployed with the encryption detector, the only way to have it","type":"boolean"},"refused":{"description":"Values the Database Connector did not apply, each with why. The deployed value is in force for each.","items":{"properties":{"reason":{"description":"One sentence for the UI","type":"string"},"setting":{"description":"The setting's name, as in settings","type":"string"}},"required":["setting","reason"],"type":"object"},"type":"array"},"review_minutes":{"type":"integer"},"revision":{"description":"The revision these came from. 0 before the Database Connector received any.","format":"int64","type":"integer"},"size_sample_seconds":{"type":"integer"},"window_idle_seconds":{"type":"integer"},"window_max_span_seconds":{"type":"integer"}},"required":["revision","window_idle_seconds","window_max_span_seconds","review_minutes","size_sample_seconds","content_analysis","content_analysis_available"],"type":"object"},"DatabaseMonitoringCheck":{"description":"One benign pattern that was checked. Returned whether or not it matched: a check that appears only when it fires makes a missing finding indistinguishable from one that was never looked for.\n","properties":{"applied":{"type":"boolean"},"detail":{"type":"string"},"name":{"type":"string"},"raises":{"type":"boolean"},"reason":{"description":"Why the check could not be applied","type":"string"},"suppresses":{"type":"boolean"}},"required":["name","applied","suppresses"],"type":"object"},"DatabaseMonitoringCommit":{"properties":{"commit":{"$ref":"#/components/schemas/DatabaseMonitoringPosition"},"commit_time":{"description":"RFC 3339 with fractional seconds","type":"string"},"destructive":{"description":"In the evidence of a finding in its window","type":"boolean"},"relations":{"items":{"properties":{"deleted":{"format":"int64","type":"integer"},"inserted":{"format":"int64","type":"integer"},"relation":{"type":"string"},"truncated":{"type":"boolean"},"updated":{"format":"int64","type":"integer"}},"required":["relation","inserted","updated","deleted"],"type":"object"},"type":"array"},"transaction_ref":{"description":"The PostgreSQL transaction id, decimal","type":"string"}},"required":["transaction_ref","commit","commit_time","destructive","relations"],"type":"object"},"DatabaseMonitoringCreateRequest":{"properties":{"name":{"description":"What the UI shows. The Database Connector registers under it, which is how it lands on this row.","maxLength":128,"minLength":1,"type":"string"}},"required":["name"],"type":"object"},"DatabaseMonitoringCreated":{"properties":{"database":{"$ref":"#/components/schemas/DatabaseMonitoringDatabase"},"setup":{"$ref":"#/components/schemas/DatabaseMonitoringSetup"}},"required":["database","setup"],"type":"object"},"DatabaseMonitoringDatabase":{"properties":{"agent_size":{"$ref":"#/components/schemas/DatabaseMonitoringAgentSize"},"agent_version":{"type":"string"},"api_key":{"$ref":"#/components/schemas/DatabaseMonitoringAPIKey"},"api_key_id":{"description":"The personal access token issued with the setup, so an admin can find and revoke it. Empty when none was minted here. The same value as api_key.id, kept for older clients.","type":"string"},"created_at":{"format":"date-time","type":"string"},"database":{"type":"string"},"db_user":{"type":"string"},"detections_24h":{"description":"Standing findings in the last 24 hours","type":"integer"},"disabled":{"description":"The admin's switch. The Database Connector heartbeats without streaming while it is set.","type":"boolean"},"host":{"description":"Empty while pending; from here to agent_version, what the Database Connector registered","type":"string"},"id":{"format":"uuid","type":"string"},"lag_seconds":{"description":"stream.lag_seconds from the latest heartbeat. Null when the Database Connector did not say.","nullable":true,"type":"number"},"last_accepted_at":{"description":"When a transaction last entered the Database Connector's ledger","format":"date-time","nullable":true,"type":"string"},"last_heartbeat_at":{"format":"date-time","nullable":true,"type":"string"},"lineage":{"type":"string"},"name":{"description":"What the admin called it, or what the Database Connector registered as","type":"string"},"observed_ratio_24h":{"description":"Connected heartbeats over the heartbeats expected in the last 24 hours, counted from the oldest held, at most 1. Null when there were none.\n","nullable":true,"type":"number"},"open_gap":{"description":"While true, silence from this database is not evidence that nothing happened","type":"boolean"},"open_incident_id":{"description":"The database's most recently active unresolved incident. Null when none, or when incidents are off for the tenant.","format":"uuid","nullable":true,"type":"string"},"port":{"type":"integer"},"publication":{"type":"string"},"registered_at":{"description":"When a Database Connector last announced itself","format":"date-time","nullable":true,"type":"string"},"resources":{"$ref":"#/components/schemas/DatabaseMonitoringResources"},"server_version":{"type":"string"},"settings":{"$ref":"#/components/schemas/DatabaseMonitoringAgentSettings"},"settings_applied":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringAppliedSettings"}],"description":"The settings the Database Connector last reported running with. Null until a Database Connector that reports them heartbeats: not yet connected, or older than 0.1.9. The Database Connector has the settings once settings_applied.revision equals settings.revision.\n","nullable":true},"settings_applied_at":{"description":"When the Database Connector last reported the settings it runs with","format":"date-time","nullable":true,"type":"string"},"slot":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringSlot"}],"description":"Null until the Database Connector has assessed the slot once","nullable":true},"slot_name":{"type":"string"},"slot_state":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringSlotState"}],"description":"Null until the Database Connector has heartbeated once","nullable":true},"status":{"$ref":"#/components/schemas/DatabaseMonitoringStatus"},"status_detail":{"type":"string"},"stream":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringStreamState"}],"description":"Null until the Database Connector has heartbeated once","nullable":true},"strip_24h":{"description":"The last 24 hours in 96 cells of 15 minutes, oldest first, each the worst state seen in it","items":{"$ref":"#/components/schemas/DatabaseMonitoringStripCell"},"type":"array"},"system_identifier":{"type":"string"},"tables":{"description":"How many relations the latest table-size sample holds (the metrics' relations_total). Null before the first sample.","nullable":true,"type":"integer"},"transactions_24h":{"description":"Transactions in those windows","format":"int64","type":"integer"},"undecided_24h":{"description":"Windows in the last 24 hours that no detector could decide. An oversized transaction is one of them; detections_24h does not count it, and resources.oversized_7d counts it on its own.\n","type":"integer"},"windows_24h":{"description":"Windows judged in the last 24 hours","format":"int64","type":"integer"}},"required":["id","name","host","port","database","db_user","slot_name","publication","server_version","system_identifier","lineage","agent_version","api_key_id","api_key","disabled","status","status_detail","stream","slot_state","slot","open_gap","detections_24h","undecided_24h","windows_24h","transactions_24h","agent_size","resources","settings","settings_applied","settings_applied_at","created_at","registered_at","last_heartbeat_at","last_accepted_at"],"type":"object"},"DatabaseMonitoringDatabaseList":{"properties":{"databases":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringDatabase"},"type":"array"},"pagination":{"$ref":"#/components/schemas/DatabaseMonitoringPagination"}},"required":["databases","pagination"],"type":"object"},"DatabaseMonitoringDatabaseRef":{"properties":{"database":{"type":"string"},"id":{"format":"uuid","type":"string"},"name":{"type":"string"}},"required":["id","name","database"],"type":"object"},"DatabaseMonitoringDetection":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringDetectionSummary"},{"properties":{"finding":{"$ref":"#/components/schemas/DatabaseMonitoringFinding"},"oversized":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringOversized"}],"description":"Set for quell.oversized_transaction only","nullable":true},"window":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringWindow"}],"nullable":true}},"required":["window","finding"],"type":"object"}]},"DatabaseMonitoringDetectionList":{"properties":{"detections":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringDetectionSummary"},"type":"array"},"pagination":{"$ref":"#/components/schemas/DatabaseMonitoringPagination"}},"required":["detections","pagination"],"type":"object"},"DatabaseMonitoringDetectionSummary":{"properties":{"corrupted_columns":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringEncryptedColumnRef"},"type":"array"},"database":{"$ref":"#/components/schemas/DatabaseMonitoringDatabaseRef"},"detected_at":{"format":"date-time","type":"string"},"detector":{"$ref":"#/components/schemas/DatabaseMonitoringDetector"},"encrypted_columns":{"description":"The columns whose rewritten values content analysis found encrypted, read out of the finding's encrypted_columns. Empty when the finding carries none. Row counts and whether a sample was analyzed stay on the finding.\n","items":{"$ref":"#/components/schemas/DatabaseMonitoringEncryptedColumnRef"},"type":"array"},"explanation":{"type":"string"},"first_destructive_at":{"description":"Where destruction was first seen, not where it began. No onset estimate is made.","format":"date-time","nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"incident_id":{"description":"The incident the detection was grouped into. Absent while it is in none: routine, a coverage gap, recorded before grouping was switched on, or grouping is off for the tenant.\n","format":"uuid","type":"string"},"last_destructive_at":{"format":"date-time","nullable":true,"type":"string"},"relations":{"items":{"type":"string"},"type":"array"},"resolution":{"description":"Set together with resolved_at. A detection is never deleted or rewritten: what was reported, and why it no longer stands, both stay on the record.\n","enum":["","explained_by_later_activity","coverage_restored"],"type":"string"},"resolution_detail":{"type":"string"},"resolved_at":{"format":"date-time","nullable":true,"type":"string"},"rows_affected":{"description":"Rows deleted plus rows rewritten in place. A copy carries no structured count.","format":"int64","type":"integer"},"severity":{"$ref":"#/components/schemas/DatabaseMonitoringSeverity"},"verdict":{"$ref":"#/components/schemas/DatabaseMonitoringVerdict"}},"required":["id","database","detector","verdict","severity","rows_affected","relations","explanation","first_destructive_at","last_destructive_at","detected_at","resolved_at","resolution","resolution_detail","encrypted_columns"],"type":"object"},"DatabaseMonitoringDetector":{"description":"quell.oversized_transaction is an observation, verdict undecidable and severity none: a transaction was too large for the Database Connector's memory, so the window's counts are known but its row-level checks were skipped.\n","enum":["quell.bulk_deletion","quell.bulk_overwrite","quell.bulk_copy","quell.corruption","quell.coverage_gap","quell.oversized_transaction"],"type":"string"},"DatabaseMonitoringEncryptedColumnRef":{"properties":{"column":{"type":"string"},"relation":{"type":"string"},"values":{"description":"Confirmed damaged values, which may include multiple columns or writes of one row.","minimum":0,"type":"integer"}},"required":["relation","column"],"type":"object"},"DatabaseMonitoringError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"DatabaseMonitoringFinding":{"additionalProperties":true,"description":"The Database Connector's output, verbatim, as it serializes it. Arrays may be null. A field a newer Database Connector adds is stored and served as sent.\n","properties":{"benign_patterns_checked":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringCheck"},"nullable":true,"type":"array"},"corrupted_columns":{"items":{"$ref":"#/components/schemas/CorruptedColumn"},"type":"array"},"coverage":{"nullable":true,"properties":{"last_accepted":{"description":"The last position the Database Connector durably holds, never the server's","type":"string"},"lineage":{"type":"string"},"observed_at":{"type":"string"},"reason":{"enum":["lost","missing"],"type":"string"},"server_confirmed":{"type":"string"},"slot":{"type":"string"}},"type":"object"},"deciding_limits":{"items":{"type":"string"},"nullable":true,"type":"array"},"detector":{"$ref":"#/components/schemas/DatabaseMonitoringDetector"},"encrypted_columns":{"items":{"additionalProperties":true,"properties":{"column":{"type":"string"},"first_commit":{"$ref":"#/components/schemas/DatabaseMonitoringPoint"},"last_commit":{"$ref":"#/components/schemas/DatabaseMonitoringPoint"},"relation":{"type":"string"},"rows":{"type":"integer"},"sampled":{"type":"boolean"}},"type":"object"},"nullable":true,"type":"array"},"explanation":{"type":"string"},"feature_version":{"type":"string"},"finding_id":{"description":"A hash of the finding's content, and the key a detection is stored under","type":"string"},"gaps":{"items":{"properties":{"reason":{"type":"string"},"relation":{"type":"string"},"unexplained_rows":{"format":"int64","type":"integer"}},"required":["relation","unexplained_rows","reason"],"type":"object"},"nullable":true,"type":"array"},"observed":{"nullable":true,"properties":{"destructive_transactions":{"type":"integer"},"evidence_ids":{"items":{"type":"string"},"nullable":true,"type":"array"},"evidence_ids_truncated":{"type":"boolean"},"first_destructive":{"$ref":"#/components/schemas/DatabaseMonitoringPoint"},"last_commit_before":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringPoint"}],"description":"The last commit observed immediately before first_destructive, in commit order: the recovery point. A fact, not an onset estimate. Absent when nothing preceded it, and from Database Connectors older than 0.1.13. Only commit_position is set when the Database Connector's ledger no longer held the transaction.\n"},"last_destructive":{"$ref":"#/components/schemas/DatabaseMonitoringPoint"},"transactions_after_last_commit_before":{"description":"The window's transactions committed after last_commit_before, the destructive ones included","type":"integer"}},"type":"object"},"overwritten":{"items":{"additionalProperties":true,"type":"object"},"nullable":true,"type":"array"},"proportion":{"type":"number"},"proportion_coverage":{"type":"number"},"proportion_known":{"type":"boolean"},"relations":{"items":{"type":"string"},"nullable":true,"type":"array"},"relations_touched":{"items":{"type":"string"},"nullable":true,"type":"array"},"relations_truncated":{"type":"integer"},"rows_deleted":{"type":"integer"},"ruleset_version":{"type":"string"},"severity":{"$ref":"#/components/schemas/DatabaseMonitoringSeverity"},"source_id":{"type":"string"},"tables":{"items":{"additionalProperties":true,"type":"object"},"nullable":true,"type":"array"},"verdict":{"$ref":"#/components/schemas/DatabaseMonitoringVerdict"},"window_closed_by":{"type":"string"}},"required":["finding_id","ruleset_version","feature_version","detector","source_id","verdict","severity","explanation"],"type":"object"},"DatabaseMonitoringIncident":{"properties":{"closed_at":{"description":"When nothing had joined it for 30 minutes, which froze commits_after and tables_after. A later detection within 30 minutes of its last window reopens it.","format":"date-time","nullable":true,"type":"string"},"commits_after":{"description":"Transactions committed after the recovery point until the incident closed. Null until it closes, and when it cannot be known (a Database Connector older than 0.1.13 sent no commits, or the windows after it are past their 7-day retention).\n","format":"int64","nullable":true,"type":"integer"},"corrupted":{"type":"boolean"},"coverage_since":{"description":"The start of continuous observation covering the incident; the last coverage gap that closed before it, else when the database was first observed","format":"date-time","nullable":true,"type":"string"},"damaged_values":{"description":"Column values corruption was confirmed in, not distinct rows","format":"int64","type":"integer"},"database":{"$ref":"#/components/schemas/DatabaseMonitoringDatabaseRef"},"destructive_transactions":{"description":"Per window, the most any of its detections observed; summed","format":"int64","type":"integer"},"detection_count":{"type":"integer"},"detectors":{"items":{"type":"string"},"type":"array"},"encrypted":{"type":"boolean"},"first_destructive_at":{"description":"The earliest observed destructive commit, else the first member window's first commit","format":"date-time","nullable":true,"type":"string"},"first_window_start":{"format":"date-time","type":"string"},"gaps_overlapping":{"description":"Coverage gaps open at any time during the incident","type":"integer"},"id":{"format":"uuid","type":"string"},"last_destructive_at":{"format":"date-time","nullable":true,"type":"string"},"last_window_start":{"format":"date-time","type":"string"},"opened_at":{"format":"date-time","type":"string"},"recovery_point":{"$ref":"#/components/schemas/DatabaseMonitoringRecoveryPoint"},"resolution_note":{"type":"string"},"resolved_at":{"format":"date-time","nullable":true,"type":"string"},"resolved_by":{"nullable":true,"type":"string"},"rows_affected":{"format":"int64","type":"integer"},"rows_encrypted":{"description":"Per finding and relation, the most rows any encrypted column was found in; summed","format":"int64","type":"integer"},"status":{"description":"Open until an admin resolves it, closed or not","enum":["open","resolved"],"type":"string"},"tables":{"type":"integer"},"tables_after":{"description":"Distinct relations those transactions changed. Null until the incident closes.","nullable":true,"type":"integer"}},"required":["id","database","status","opened_at","first_window_start","last_window_start","closed_at","resolved_at","resolved_by","detectors","encrypted","corrupted","detection_count","rows_affected","rows_encrypted","damaged_values","tables","destructive_transactions","first_destructive_at","last_destructive_at","commits_after","tables_after","coverage_since","gaps_overlapping"],"type":"object"},"DatabaseMonitoringIncidentDetail":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringIncident"},{"properties":{"commits":{"description":"The member windows' commits, in commit order. Empty when the Database Connector sent none (older than 0.1.13).","items":{"$ref":"#/components/schemas/DatabaseMonitoringCommit"},"type":"array"},"detections":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringDetectionSummary"},"type":"array"},"relations":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringIncidentRelation"},"type":"array"},"windows":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringIncidentWindow"},"type":"array"}},"required":["detections","relations","commits","windows"],"type":"object"}]},"DatabaseMonitoringIncidentList":{"properties":{"incidents":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringIncident"},"type":"array"},"next_page_token":{"description":"Absent on the last page","type":"string"}},"required":["incidents"],"type":"object"},"DatabaseMonitoringIncidentRelation":{"properties":{"corrupted":{"type":"boolean"},"detectors":{"items":{"type":"string"},"type":"array"},"encrypted":{"type":"boolean"},"relation":{"type":"string"},"rows":{"description":"Rows deleted plus rows rewritten in place","format":"int64","type":"integer"},"share":{"description":"rows over table_size, at most 1. Absent when the size is unknown.","type":"number"},"table_size":{"format":"int64","type":"integer"},"transaction_ref":{"description":"The first destructive transaction that touched it, when known","type":"string"}},"required":["relation","rows","detectors","encrypted","corrupted"],"type":"object"},"DatabaseMonitoringIncidentWindow":{"properties":{"closed_by":{"type":"string"},"detection_ids":{"items":{"format":"uuid","type":"string"},"type":"array"},"first_commit_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"last_commit_at":{"format":"date-time","type":"string"}},"required":["id","first_commit_at","last_commit_at","closed_by","detection_ids"],"type":"object"},"DatabaseMonitoringLimit":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringPutLimitRequest"},{"properties":{"relation":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"updated_by":{"type":"string"}},"required":["relation","updated_at","updated_by"],"type":"object"}]},"DatabaseMonitoringLimitList":{"properties":{"limits":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringLimit"},"type":"array"}},"required":["limits"],"type":"object"},"DatabaseMonitoringMetrics":{"properties":{"bucket_seconds":{"type":"integer"},"buckets":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringMetricsBucket"},"maxItems":121,"type":"array"},"coverage_gaps":{"items":{"properties":{"closed_at":{"format":"date-time","nullable":true,"type":"string"},"explanation":{"type":"string"},"id":{"format":"uuid","type":"string"},"opened_at":{"format":"date-time","type":"string"},"resolution_detail":{"type":"string"}},"required":["id","opened_at","closed_at","explanation","resolution_detail"],"type":"object"},"maxItems":50,"type":"array"},"database_id":{"format":"uuid","type":"string"},"detections":{"items":{"properties":{"detected_at":{"format":"date-time","type":"string"},"detector":{"type":"string"},"id":{"format":"uuid","type":"string"},"last_commit_at":{"format":"date-time","nullable":true,"type":"string"},"relations":{"items":{"type":"string"},"type":"array"},"resolution":{"description":"Why the detection stopped standing, set together with resolved_at. The verdict is kept as reported.\n","enum":["","explained_by_later_activity","coverage_restored"],"type":"string"},"resolved_at":{"format":"date-time","nullable":true,"type":"string"},"rows_affected":{"format":"int64","type":"integer"},"seconds_to_detect":{"nullable":true,"type":"number"},"severity":{"type":"string"},"verdict":{"type":"string"}},"required":["id","detector","verdict","severity","rows_affected","relations","detected_at","resolved_at","resolution","last_commit_at","seconds_to_detect"],"type":"object"},"maxItems":100,"type":"array"},"detections_total":{"type":"integer"},"heartbeat_interval_seconds":{"type":"integer"},"history":{"properties":{"routine_retention_days":{"description":"How long windows without a finding are kept.","type":"integer"},"sample_retention_days":{"type":"integer"},"samples_since":{"description":"The oldest heartbeat sample held. Null when there is none.","format":"date-time","nullable":true,"type":"string"}},"required":["samples_since","sample_retention_days","routine_retention_days"],"type":"object"},"relations":{"items":{"properties":{"deleted":{"format":"int64","type":"integer"},"inserted":{"format":"int64","type":"integer"},"relation":{"type":"string"},"truncations":{"format":"int64","type":"integer"},"updated":{"format":"int64","type":"integer"}},"required":["relation","inserted","updated","deleted","truncations"],"type":"object"},"maxItems":20,"type":"array"},"relations_total":{"type":"integer"},"restarts":{"items":{"properties":{"agent_version":{"type":"string"},"at":{"format":"date-time","type":"string"}},"required":["at","agent_version"],"type":"object"},"maxItems":50,"type":"array"},"server_capped":{"description":"Whether max_slot_wal_keep_size is set on the server, from the latest slot observation. The cap's value is not reported.\n","nullable":true,"type":"boolean"},"since":{"description":"The range's start after clamping.","format":"date-time","type":"string"},"summary":{"properties":{"connected_heartbeats":{"format":"int64","type":"integer"},"findings":{"type":"integer"},"heartbeats_expected":{"format":"int64","type":"integer"},"heartbeats_received":{"format":"int64","type":"integer"},"max_seconds_to_detect":{"nullable":true,"type":"number"},"median_seconds_to_detect":{"nullable":true,"type":"number"},"restarts":{"type":"integer"},"slot_held_bytes_latest":{"description":"What the slot holds now: the latest slot observation, the same one the database's slot.held_bytes reports. Null until the slot has been observed.\n","format":"int64","nullable":true,"type":"integer"},"slot_held_bytes_max":{"description":"The peak for the range: the most write-ahead log the slot held at any heartbeat in it. Not the current value.\n","format":"int64","nullable":true,"type":"integer"},"slot_observed_at":{"description":"When slot_held_bytes_latest was observed.","format":"date-time","nullable":true,"type":"string"},"transactions":{"format":"int64","type":"integer"},"unconfirmed_heartbeats":{"description":"Heartbeats in the range that reported no confirmed position. See the bucket's unconfirmed_heartbeats.\n","format":"int64","type":"integer"},"windows":{"format":"int64","type":"integer"}},"required":["heartbeats_received","heartbeats_expected","connected_heartbeats","unconfirmed_heartbeats","restarts","windows","transactions","findings","slot_held_bytes_max","slot_held_bytes_latest","slot_observed_at","median_seconds_to_detect","max_seconds_to_detect"],"type":"object"},"table_sizes":{"properties":{"points":{"items":{"properties":{"sizes":{"additionalProperties":{"format":"int64","type":"integer"},"type":"object"},"start":{"format":"date-time","type":"string"},"taken_at":{"format":"date-time","type":"string"}},"required":["start","taken_at","sizes"],"type":"object"},"maxItems":121,"type":"array"},"relations":{"items":{"properties":{"latest_rows":{"format":"int64","type":"integer"},"relation":{"type":"string"}},"required":["relation","latest_rows"],"type":"object"},"maxItems":8,"type":"array"},"relations_total":{"type":"integer"}},"required":["relations","relations_total","points"],"type":"object"},"until":{"format":"date-time","type":"string"}},"required":["database_id","since","until","bucket_seconds","heartbeat_interval_seconds","history","server_capped","summary","buckets","relations","relations_total","table_sizes","coverage_gaps","detections","detections_total","restarts"],"type":"object"},"DatabaseMonitoringMetricsBucket":{"properties":{"ack_lag_bytes_max":{"description":"How far the Database Connector's accepted position ran ahead of what it acknowledged, never more than the slot held at the same heartbeat. Measured only from heartbeats that reported a confirmed position; null when none in the bucket did. A Database Connector that has acknowledged nothing has no lag, not a lag the size of the slot: that state is unconfirmed_heartbeats equal to heartbeats.\n","format":"int64","nullable":true,"type":"integer"},"busiest_relation":{"description":"The relation with the most rows changed in the bucket. Absent when none changed.","type":"string"},"bytes_judged":{"format":"int64","type":"integer"},"connected_heartbeats":{"format":"int64","type":"integer"},"expected_heartbeats":{"description":"Zero before the oldest sample held, which is no record, not an outage.","format":"int64","type":"integer"},"heartbeats":{"format":"int64","type":"integer"},"memory_limit_bytes":{"description":"The latest memory limit the Database Connector reported in the bucket","format":"int64","nullable":true,"type":"integer"},"memory_peak_bytes_max":{"description":"The most memory the Database Connector reported using in the bucket","format":"int64","nullable":true,"type":"integer"},"rows_deleted":{"format":"int64","type":"integer"},"rows_inserted":{"format":"int64","type":"integer"},"rows_updated":{"format":"int64","type":"integer"},"slot_held_bytes_max":{"description":"The most write-ahead log the slot held at any heartbeat in the bucket. For drawing the line, never the current value.\n","format":"int64","nullable":true,"type":"integer"},"slot_missing":{"type":"boolean"},"start":{"format":"date-time","type":"string"},"transactions":{"format":"int64","type":"integer"},"unconfirmed_heartbeats":{"description":"Heartbeats in the bucket that reported no confirmed position, and so contributed nothing to ack_lag_bytes_max. Equal to heartbeats, the bucket has no ack lag at all; less, the lag is from the others only.\n","format":"int64","type":"integer"},"wal_read_bytes":{"description":"How far the stream position advanced in the bucket, summed over consecutive samples of one registration and lineage. Null where no pair could be measured: the first sample, and the first after a missed minute or a Database Connector restart, carry a position of unknown age.\n","format":"int64","nullable":true,"type":"integer"},"windows":{"description":"Windows by the most serious verdict any detector reached; benign is none.","properties":{"below_threshold":{"format":"int64","type":"integer"},"benign":{"format":"int64","type":"integer"},"finding":{"format":"int64","type":"integer"},"observation_with_gap":{"format":"int64","type":"integer"},"suppressed":{"format":"int64","type":"integer"},"undecidable":{"format":"int64","type":"integer"}},"required":["finding","observation_with_gap","undecidable","suppressed","below_threshold","benign"],"type":"object"}},"required":["start","heartbeats","expected_heartbeats","connected_heartbeats","slot_held_bytes_max","slot_missing","ack_lag_bytes_max","unconfirmed_heartbeats","wal_read_bytes","memory_limit_bytes","memory_peak_bytes_max","windows","transactions","bytes_judged","rows_inserted","rows_updated","rows_deleted"],"type":"object"},"DatabaseMonitoringOversized":{"description":"What an oversized-transaction finding says, read out of the finding by the server. Every figure is null when the Database Connector did not report it.\n","properties":{"budget_bytes":{"description":"The in-memory budget the transaction exceeded","format":"int64","nullable":true,"type":"integer"},"bytes_seen":{"format":"int64","nullable":true,"type":"integer"},"memory_limit_bytes":{"description":"The Database Connector's memory limit when it met the transaction","format":"int64","nullable":true,"type":"integer"},"recommended_agent_size":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringAgentSize"}],"description":"The smallest size with at least recommended_task_memory_mib; xlarge when none has","nullable":true},"recommended_task_memory_mib":{"format":"int64","nullable":true,"type":"integer"},"rows_by_relation":{"description":"Rows the transaction carried, per relation, largest first","items":{"properties":{"relation":{"type":"string"},"rows":{"format":"int64","type":"integer"}},"required":["relation","rows"],"type":"object"},"type":"array"}},"required":["rows_by_relation","bytes_seen","memory_limit_bytes","budget_bytes","recommended_task_memory_mib","recommended_agent_size"],"type":"object"},"DatabaseMonitoringPagination":{"properties":{"next_page_token":{"description":"Empty on the last page","type":"string"},"page_size":{"format":"int64","type":"integer"},"total":{"format":"int64","type":"integer"}},"required":["total","page_size","next_page_token"],"type":"object"},"DatabaseMonitoringPoint":{"properties":{"commit_position":{"type":"string"},"commit_time":{"type":"string"},"transaction_ref":{"type":"string"}},"type":"object"},"DatabaseMonitoringPosition":{"description":"A place in the replication stream, as the Database Connector reports it","properties":{"ordinal":{"format":"int64","type":"integer"},"raw":{"description":"As the server prints it, e.g. \"0/1A2B3C4D\"","type":"string"}},"required":["raw","ordinal"],"type":"object"},"DatabaseMonitoringPutLimitRequest":{"properties":{"max_rows_copied":{"minimum":0,"nullable":true,"type":"integer"},"max_rows_deleted":{"minimum":0,"nullable":true,"type":"integer"},"max_rows_rewritten":{"minimum":0,"nullable":true,"type":"integer"}},"type":"object"},"DatabaseMonitoringRecoveryPoint":{"description":"Where to restore to. transaction_ref, commit_position and commit_time are the last commit observed before the incident's first destructive one, which is a fact, not an onset estimate; they are absent when the Database Connector did not report it (older than 0.1.13, or nothing preceded it), and only before is set. before is the first destructive commit, or, for a detection that observed none, the window's first commit time.\n","properties":{"before":{"$ref":"#/components/schemas/DatabaseMonitoringPoint"},"commit_position":{"description":"As PostgreSQL prints it, e.g. \"33/17FE2C08\"","type":"string"},"commit_time":{"description":"RFC 3339 with fractional seconds","type":"string"},"transaction_ref":{"type":"string"}},"required":["before"],"type":"object"},"DatabaseMonitoringResolveIncidentRequest":{"additionalProperties":false,"properties":{"note":{"maxLength":2000,"type":"string"}},"type":"object"},"DatabaseMonitoringResources":{"description":"The Database Connector's size as configured here beside what the running Database Connector reports, and whether it recently met a transaction too large for it.\n","properties":{"agent_size":{"$ref":"#/components/schemas/DatabaseMonitoringAgentSize"},"last_oversized_at":{"format":"date-time","nullable":true,"type":"string"},"matches_size":{"description":"Whether the running Database Connector is at the configured size. Null until a limit is reported. False after the size is changed until the customer re-applies the Terraform.\n","nullable":true,"type":"boolean"},"memory_limit_bytes":{"description":"The memory limit the Database Connector last reported. Null until a Database Connector that reports it heartbeats.","format":"int64","nullable":true,"type":"integer"},"memory_peak_bytes":{"description":"The most memory the Database Connector last reported using since it started","format":"int64","nullable":true,"type":"integer"},"oversized_7d":{"description":"Oversized transactions detected in the last 7 days","type":"integer"},"recommended_agent_size":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringAgentSize"}],"description":"The smallest size with the memory the newest oversized transaction of the last 7 days asked for; xlarge when none has. Null when there was none, or it did not say.\n","nullable":true},"reported_at":{"description":"When the Database Connector last reported its memory","format":"date-time","nullable":true,"type":"string"},"reported_size":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringAgentSize"}],"description":"The size whose memory the reported limit is, within 10%. Null when it is none of them.","nullable":true},"task_cpu":{"description":"The configured size's Fargate CPU units","type":"integer"},"task_memory_mib":{"description":"The configured size's memory","type":"integer"}},"required":["agent_size","task_cpu","task_memory_mib","memory_limit_bytes","memory_peak_bytes","reported_at","reported_size","matches_size","oversized_7d","last_oversized_at","recommended_agent_size"],"type":"object"},"DatabaseMonitoringRetention":{"properties":{"latest":{"allOf":[{"$ref":"#/components/schemas/DatabaseMonitoringSlot"}],"nullable":true},"series":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringSlot"},"type":"array"}},"required":["latest","series"],"type":"object"},"DatabaseMonitoringSettingsUpdate":{"additionalProperties":false,"description":"The Database Connector's settings, replacing the stored ones wholesale: a setting left out or null is the value the Database Connector was deployed with, and {} resets them all. A value out of bounds is refused with 400, and so is a longest window in force shorter than the idle period in force, each being the value given here or else the deployed one (window_idle_seconds 60, window_max_span_seconds 900): the error names window_max_span_seconds when it is given, else window_idle_seconds. Any other field is refused.\n","properties":{"content_analysis":{"nullable":true,"type":"boolean"},"review_minutes":{"maximum":1440,"minimum":30,"nullable":true,"type":"integer"},"size_sample_seconds":{"maximum":3600,"minimum":30,"nullable":true,"type":"integer"},"window_idle_seconds":{"maximum":3600,"minimum":10,"nullable":true,"type":"integer"},"window_max_span_seconds":{"maximum":3600,"minimum":60,"nullable":true,"type":"integer"}},"type":"object"},"DatabaseMonitoringSetup":{"properties":{"api_key_id":{"description":"The key the Terraform block is for, the only one this database accepts. Empty when none was issued here.","type":"string"},"api_key_name":{"description":"That key's name. Null when unknown.","nullable":true,"type":"string"},"prerequisites":{"items":{"type":"string"},"type":"array"},"server_url":{"description":"The base URL the Database Connector reports to, on this tenant's host","type":"string"},"sql":{"description":"Run on the database as a superuser; creates the login, the publication and the slot","type":"string"},"teardown":{"type":"string"},"terraform":{"description":"A module block for the Elastio Database Connector Terraform module (terraform.cloudsmith.io/public/elastio-database-monitoring-agent/aws), preceded by the one-time.terraformrc credentials entry for that registry, with the token in it when freshly minted and task_cpu and task_memory for the database's agent_size","type":"string"}},"required":["sql","prerequisites","teardown","server_url","terraform","api_key_id","api_key_name"],"type":"object"},"DatabaseMonitoringSeverity":{"enum":["high","medium","none"],"type":"string"},"DatabaseMonitoringSlot":{"description":"The Database Connector's assessment of what the slot is costing the database","properties":{"active":{"type":"boolean"},"because":{"type":"string"},"exists":{"type":"boolean"},"held_bytes":{"format":"int64","type":"integer"},"level":{"description":"healthy, unguarded, over_budget, at_risk, lost or missing","type":"string"},"observed_at":{"format":"date-time","type":"string"},"server_capped":{"description":"Whether max_slot_wal_keep_size is set. Null when the server would not say, which is a different answer from false.\n","nullable":true,"type":"boolean"},"wal_status":{"type":"string"}},"required":["level","exists","active","wal_status","held_bytes","server_capped","because","observed_at"],"type":"object"},"DatabaseMonitoringSlotState":{"description":"The slot as the Database Connector last saw it, from its heartbeat","properties":{"active":{"type":"boolean"},"exists":{"type":"boolean"},"held_bytes":{"format":"int64","type":"integer"},"status":{"description":"wal_status as the server reports it","type":"string"}},"required":["exists","active","held_bytes"],"type":"object"},"DatabaseMonitoringStatus":{"description":"The state of the Database Connector. pending: added, no Database Connector has registered yet. registered: a Database Connector announced itself and has not heartbeated yet. connecting, streaming, degraded, unreachable: the Database Connector's own word, from its last heartbeat, except that while a coverage gap is open (open_gap) registered, connecting, streaming and unreachable all read degraded. disabled: turned off by an admin. silent: four heartbeat intervals without a heartbeat, two minutes at the default interval.\n","enum":["pending","registered","connecting","streaming","degraded","unreachable","disabled","silent"],"type":"string"},"DatabaseMonitoringStreamState":{"description":"The stream as the Database Connector sees it, from its last heartbeat","properties":{"confirmed":{"$ref":"#/components/schemas/DatabaseMonitoringPosition"},"connected":{"type":"boolean"},"lag_seconds":{"description":"Seconds between the primary's clock in its latest keepalive or data message and when the Database Connector processed it: roughly how far behind the primary the Database Connector is. Absent when unknown, and from Database Connectors older than 0.1.13.\n","type":"number"},"last_data_at":{"format":"date-time","type":"string"},"last_heard_at":{"format":"date-time","type":"string"},"position":{"$ref":"#/components/schemas/DatabaseMonitoringPosition"}},"required":["connected"],"type":"object"},"DatabaseMonitoringStreamWindow":{"properties":{"busiest_relation":{"description":"The relation with the most rows changed. Absent when none changed.","type":"string"},"bytes":{"format":"int64","type":"integer"},"closed_by":{"type":"string"},"detection_ids":{"items":{"format":"uuid","type":"string"},"type":"array"},"first_commit_at":{"format":"date-time","type":"string"},"id":{"description":"The window's id, as the Database Connector was told it","type":"string"},"judged_at":{"format":"date-time","type":"string"},"last_commit_at":{"format":"date-time","type":"string"},"rows_deleted":{"format":"int64","type":"integer"},"rows_inserted":{"format":"int64","type":"integer"},"rows_updated":{"format":"int64","type":"integer"},"transactions":{"format":"int64","type":"integer"},"verdict":{"description":"The most serious verdict any detector reached on the window; benign when none reported anything","enum":["finding","observation_with_gap","undecidable","suppressed","below_threshold","benign"],"type":"string"}},"required":["id","first_commit_at","last_commit_at","judged_at","closed_by","transactions","bytes","rows_inserted","rows_updated","rows_deleted","verdict","detection_ids"],"type":"object"},"DatabaseMonitoringStripCell":{"properties":{"at":{"description":"The cell's start; cells are 15 minutes","format":"date-time","type":"string"},"state":{"description":"The worst seen in the cell, in this order from best to worst: quiet (no window), clean (nothing worse than explained), below (below the threshold), undecided, finding (a finding or rows that vanished with a gap), gap (a coverage gap, or every heartbeat disconnected).\n","enum":["quiet","clean","below","undecided","finding","gap"],"type":"string"}},"required":["at","state"],"type":"object"},"DatabaseMonitoringUpdateRequest":{"additionalProperties":false,"description":"At least one of the four. Any other field is refused.","properties":{"agent_size":{"$ref":"#/components/schemas/DatabaseMonitoringAgentSize"},"disabled":{"type":"boolean"},"name":{"maxLength":128,"minLength":1,"type":"string"},"settings":{"$ref":"#/components/schemas/DatabaseMonitoringSettingsUpdate"}},"type":"object"},"DatabaseMonitoringVerdict":{"enum":["finding","suppressed","below_threshold","no_destruction","observation_with_gap","undecidable"],"type":"string"},"DatabaseMonitoringWindow":{"properties":{"bytes":{"description":"Canonical bytes of the evidence judged","format":"int64","type":"integer"},"closed_by":{"description":"Why the window ended, for example \"idle 1m0s\" or \"max_span\"","type":"string"},"first_commit_at":{"format":"date-time","type":"string"},"last_commit_at":{"format":"date-time","type":"string"},"relations":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringWindowRelation"},"type":"array"},"transactions":{"type":"integer"}},"required":["closed_by","first_commit_at","last_commit_at","transactions","bytes","relations"],"type":"object"},"DatabaseMonitoringWindowList":{"properties":{"windows":{"items":{"$ref":"#/components/schemas/DatabaseMonitoringStreamWindow"},"type":"array"}},"required":["windows"],"type":"object"},"DatabaseMonitoringWindowRelation":{"description":"What one window saw of one relation; the numbers behind the verdict","properties":{"deleted":{"format":"int64","type":"integer"},"inserted":{"format":"int64","type":"integer"},"relation":{"type":"string"},"size_before":{"description":"Absent when unknown","format":"int64","type":"integer"},"truncated":{"type":"boolean"},"updated":{"format":"int64","type":"integer"}},"required":["relation","inserted","updated","deleted"],"type":"object"},"DatabaseStatus":{"properties":{"is_updated":{"type":"boolean"},"update_timestamp":{"nullable":true,"type":"string"}},"required":["is_updated","update_timestamp"],"type":"object"},"DeleteAssetRegionStackResponse":{"properties":{"job_id":{"$ref":"#/components/schemas/ConnectorJobId"}},"required":["job_id"],"type":"object"},"DeleteRedstackResponse":{"properties":{"job_id":{"description":"Scheduled deletion job id","format":"uuid","type":"string"}},"required":["job_id"],"type":"object"},"DestroyVaultRequestBody":{"properties":{"aws_vault_destroy":{"$ref":"#/components/schemas/AwsVaultDestroyBody"}},"required":["aws_vault_destroy"],"type":"object"},"Determination":{"properties":{"as_of":{"description":"Determining scan instant; null = never scanned.","nullable":true,"type":"string"},"elapsed_seconds":{"format":"int64","nullable":true,"type":"integer"},"state":{"description":"A scan we could not read is not_scanned, never clean.","enum":["clean","infected","not_scanned"],"type":"string"}},"required":["state","as_of","elapsed_seconds"],"type":"object"},"DiscoverCfnDescription":{"properties":{"arn":{"type":"string"},"region":{"type":"string"}},"required":["region","arn"],"type":"object"},"DiscoverInstalledCfnRequestBody":{"properties":{"aws_account_id":{"description":"12-digit AWS account ID (Cloud Connector account)","type":"string"}},"required":["aws_account_id"],"type":"object"},"DiscoverInstalledCfnResponse":{"properties":{"description":{"$ref":"#/components/schemas/DiscoverCfnDescription"},"is_installed":{"type":"boolean"},"status":{"enum":["not_installed","installed","installing","update_required","updating","unknown"],"type":"string"}},"required":["is_installed","status"],"type":"object"},"EDCertificate":{"nullable":true,"properties":{"canonical_report":{"description":"Base64 encoded exact report bytes hashed by report_sha256 and bound inside the signed payload.","format":"byte","type":"string"},"id":{"type":"string"},"issued_at":{"format":"date-time","type":"string"},"issuer":{"type":"string"},"observed_at":{"format":"date-time","type":"string"},"payload":{"description":"Base64 encoded exact signed JSON bytes; decode before Ed25519 verification.","format":"byte","type":"string"},"public_key":{"type":"string"},"report_sha256":{"type":"string"},"signature":{"type":"string"},"statement":{"type":"string"}},"required":["id","issuer","issued_at","observed_at","report_sha256","signature","public_key","payload","statement","canonical_report"],"type":"object"},"EDHistoryResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/EDJob"},"type":"array"},"next_page_token":{"type":"string"},"total":{"minimum":0,"type":"integer"}},"required":["jobs","next_page_token","total"],"type":"object"},"EDJob":{"nullable":true,"properties":{"bytes_scanned":{"format":"int64","type":"integer"},"certificate":{"$ref":"#/components/schemas/EDCertificate"},"created_at":{"format":"date-time","type":"string"},"database_id":{"type":"string"},"database_name":{"type":"string"},"detection_id":{"description":"The detection the job was started to confirm. Absent when none.","format":"uuid","type":"string"},"error":{"nullable":true,"type":"string"},"id":{"type":"string"},"incident_id":{"description":"The incident the job was started to confirm. Absent when none.","format":"uuid","type":"string"},"kind":{"enum":["discover","scan"],"type":"string"},"progress_percent":{"nullable":true,"type":"number"},"remaining_seconds":{"nullable":true,"type":"integer"},"report":{"$ref":"#/components/schemas/EDReport"},"rows_scanned":{"format":"int64","type":"integer"},"scan_type":{"default":"encryption","description":"Each scan checks one condition. Legacy jobs default to encryption.","enum":["encryption","corruption"],"type":"string"},"scope":{"$ref":"#/components/schemas/EDScope"},"status":{"enum":["queued","checking_access","scanning","reporting","completed","failed","cancelled"],"type":"string"},"tables":{"items":{"$ref":"#/components/schemas/EDTable"},"type":"array"},"tables_completed":{"format":"int64","type":"integer"},"tables_total":{"format":"int64","type":"integer"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","kind","database_id","database_name","scope","status","created_at","updated_at","tables","tables_completed","tables_total","rows_scanned","bytes_scanned","progress_percent","remaining_seconds","error","report","certificate"],"type":"object"},"EDJobsResponse":{"properties":{"available":{"type":"boolean"},"catalog":{"$ref":"#/components/schemas/EDJob"},"certificates_available":{"type":"boolean"},"jobs":{"items":{"$ref":"#/components/schemas/EDJob"},"type":"array"},"scan_version":{"description":"Database Connector protocol version. Version 2 supports corruption and higher intensity.","type":"integer"}},"required":["available","certificates_available","catalog","jobs"],"type":"object"},"EDReport":{"nullable":true,"properties":{"completed_at":{"format":"date-time","type":"string"},"consistency":{"enum":["snapshot","per_table"],"type":"string"},"coverage":{"enum":["complete","partial"],"type":"string"},"detector_version":{"type":"string"},"outcome":{"enum":["clean","detected","inconclusive"],"type":"string"},"scan_type":{"default":"encryption","description":"Each scan checks one condition. Legacy jobs default to encryption.","enum":["encryption","corruption"],"type":"string"},"snapshot_at":{"format":"date-time","nullable":true,"type":"string"},"started_at":{"format":"date-time","type":"string"},"tables":{"items":{"$ref":"#/components/schemas/EDTableResult"},"type":"array"}},"required":["outcome","coverage","consistency","snapshot_at","started_at","completed_at","detector_version","tables"],"type":"object"},"EDRequest":{"properties":{"batch_rows":{"default":64,"maximum":256,"minimum":16,"type":"integer"},"catalog_id":{"format":"uuid","type":"string"},"detection_id":{"description":"The detection of this database the job is started to confirm. Optional.","format":"uuid","type":"string"},"incident_id":{"description":"The incident of this database the job is started to confirm. Optional.","format":"uuid","type":"string"},"max_seconds":{"default":900,"maximum":3600,"minimum":30,"type":"integer"},"pause_ms":{"default":500,"maximum":5000,"minimum":0,"type":"integer"},"scan_type":{"default":"encryption","description":"Each scan checks one condition. Legacy jobs default to encryption.","enum":["encryption","corruption"],"type":"string"},"table_ids":{"items":{"type":"string"},"maxItems":5000,"type":"array"}},"type":"object"},"EDSchedule":{"properties":{"created_at":{"format":"date-time","type":"string"},"created_by":{"type":"string"},"database_id":{"format":"uuid","type":"string"},"enabled":{"type":"boolean"},"frequency":{"$ref":"#/components/schemas/EDScheduleFrequency"},"id":{"format":"uuid","type":"string"},"last_error":{"description":"Why the last fire queued no scan. Absent when it did.","type":"string"},"last_fired_at":{"format":"date-time","type":"string"},"last_job_id":{"description":"The last scan a fire queued","format":"uuid","type":"string"},"next_fire_at":{"format":"date-time","type":"string"},"profile":{"$ref":"#/components/schemas/EDScheduleProfile"},"scan_type":{"enum":["encryption","corruption"],"type":"string"},"scope":{"$ref":"#/components/schemas/EDScheduleScope"}},"required":["id","database_id","scan_type","scope","profile","frequency","next_fire_at","enabled","created_at","created_by"],"type":"object"},"EDScheduleCreateRequest":{"additionalProperties":false,"properties":{"frequency":{"$ref":"#/components/schemas/EDScheduleFrequency"},"profile":{"$ref":"#/components/schemas/EDScheduleProfile"},"scan_type":{"default":"encryption","enum":["encryption","corruption"],"type":"string"},"scope":{"$ref":"#/components/schemas/EDScheduleScope"}},"required":["scope","profile","frequency"],"type":"object"},"EDScheduleFrequency":{"additionalProperties":true,"description":"Frequency, daily or weekly only. daily carries monday..sunday booleans and time; weekly carries day (Sunday.. Saturday) and time. time is {time: \"HH:MM:SS\", timezone: IANA name}.\n","properties":{"kind_tag":{"enum":["daily","weekly"],"type":"string"}},"required":["kind_tag"],"type":"object"},"EDScheduleList":{"properties":{"schedules":{"items":{"$ref":"#/components/schemas/EDSchedule"},"type":"array"}},"required":["schedules"],"type":"object"},"EDScheduleProfile":{"description":"The pacing profile: rows per fetch and pause, 16/2000 ms, 64/500, 128/200, 256/50, 256/0, and faster (64/100) for Database Connectors before protocol version 2.\n","enum":["extra_gentle","low_impact","balanced","aggressive","ultra_aggressive","faster"],"type":"string"},"EDScheduleScope":{"properties":{"pattern":{"description":"Table filter: commas form a union; a term with * or ? matches the whole schema.table; any other term is a case-insensitive substring. Resolved against a fresh catalog at every fire.\n","maxLength":1024,"type":"string"},"tables":{"description":"Tables scanned as well, by exact schema.table","items":{"type":"string"},"maxItems":5000,"type":"array"}},"required":["pattern"],"type":"object"},"EDScheduleUpdateRequest":{"additionalProperties":false,"properties":{"enabled":{"type":"boolean"},"frequency":{"$ref":"#/components/schemas/EDScheduleFrequency"},"profile":{"$ref":"#/components/schemas/EDScheduleProfile"},"scope":{"$ref":"#/components/schemas/EDScheduleScope"}},"type":"object"},"EDScope":{"properties":{"kind":{"enum":["tables"],"type":"string"},"table_ids":{"items":{"type":"string"},"type":"array"}},"required":["kind","table_ids"],"type":"object"},"EDTable":{"properties":{"bytes":{"format":"int64","type":"integer"},"id":{"type":"string"},"name":{"type":"string"},"readable":{"type":"boolean"},"rows":{"format":"int64","nullable":true,"type":"integer"},"schema":{"type":"string"}},"required":["id","schema","name","rows","bytes","readable"],"type":"object"},"EDTableResult":{"properties":{"bytes_scanned":{"format":"int64","type":"integer"},"detail":{"type":"string"},"name":{"type":"string"},"outcome":{"enum":["clean","detected","inconclusive","skipped"],"type":"string"},"rows_scanned":{"format":"int64","type":"integer"},"schema":{"type":"string"}},"required":["schema","name","rows_scanned","bytes_scanned","outcome","detail"],"type":"object"},"EfsAssociation":{"properties":{"covered":{"type":"boolean"},"source":{"type":"string"}},"required":["covered","source"],"type":"object"},"ElastioPDFDocument":{"additionalProperties":false,"properties":{"sections":{"items":{"additionalProperties":false,"properties":{"heading":{"maxLength":4096,"type":"string"},"paragraphs":{"items":{"maxLength":4096,"type":"string"},"maxItems":1000,"type":"array"},"table":{"additionalProperties":false,"properties":{"columns":{"items":{"maxLength":128,"minLength":1,"type":"string"},"maxItems":32,"minItems":1,"type":"array"},"rows":{"items":{"items":{"maxLength":4096,"type":"string"},"maxItems":32,"type":"array"},"maxItems":10000,"type":"array"}},"required":["columns","rows"],"type":"object"}},"type":"object"},"maxItems":32,"minItems":1,"type":"array"},"subtitle":{"maxLength":1000,"type":"string"},"title":{"maxLength":500,"minLength":1,"type":"string"}},"required":["title","sections"],"type":"object"},"ErrorResponse1":{"properties":{"code":{"type":"string"},"details":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"EventPolicyCreateRequest":{"properties":{"alert_ids":{"description":"Alert UUIDs to bind on create (validated; bound in ingestion). When alert synchronization is enabled, a create that produces an ENABLED event policy must carry at least one id (else 400 `ALERT_REQUIRED`); disabled/paused creates may omit it.","items":{"format":"uuid","type":"string"},"type":"array"},"description":{"type":"string"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanRequest"},"name":{"type":"string"},"paused_until":{"format":"date-time","type":"string"},"platform":{"description":"Defaults to AWS when omitted. MVP sources are AWS.","enum":["AWS","Azure","IBM","GCP"],"type":"string"},"selectors":{"description":"Scope selectors fed to the membership engine.","items":{"type":"object"},"type":"array"},"source":{"description":"Dotted canonical trigger source.","enum":["aws.guardduty.finding_raised","wiz.finding_raised"],"type":"string"},"source_config":{"$ref":"#/components/schemas/EventSourceConfig"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"violations":{"items":{"$ref":"#/components/schemas/RequestedViolation"},"type":"array"}},"required":["name","source"],"type":"object"},"EventPolicyResponse":{"properties":{"alert_ids":{"description":"The bound alert set, hydrated from ingestion ([] never null).","items":{"format":"uuid","type":"string"},"type":"array"},"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"id":{"format":"uuid","type":"string"},"integrity_check":{"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanOptions"},"name":{"type":"string"},"paused_until":{"format":"date-time","nullable":true,"type":"string"},"platform":{"type":"string"},"selectors":{"items":{"type":"object"},"type":"array"},"source":{"type":"string"},"source_config":{"$ref":"#/components/schemas/EventSourceConfig"},"status":{"type":"string"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"violations":{"items":{"$ref":"#/components/schemas/PolicyViolation"},"type":"array"}},"required":["id","tenant_name","name","status","source","source_config","selectors","violations","alert_ids"],"type":"object"},"EventPolicyUpdateRequest":{"description":"Full-replaces the definition. alert_ids uses preserve-on-omit (present replaces; omitted preserves). When alert synchronization is enabled, an update may not leave an ENABLED event policy with zero bound alerts: a present `[]`, or an omit when no bindings exist, is rejected 400 `ALERT_REQUIRED`.","properties":{"alert_ids":{"items":{"format":"uuid","type":"string"},"type":"array"},"description":{"type":"string"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanRequest"},"paused_until":{"format":"date-time","type":"string"},"platform":{"enum":["AWS","Azure","IBM","GCP"],"type":"string"},"selectors":{"items":{"type":"object"},"type":"array"},"source":{"enum":["aws.guardduty.finding_raised","wiz.finding_raised"],"type":"string"},"source_config":{"$ref":"#/components/schemas/EventSourceConfig"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"violations":{"items":{"$ref":"#/components/schemas/RequestedViolation"},"type":"array"}},"required":["source"],"type":"object"},"EventSourceConfig":{"description":"Per-source trigger config. For alert-only finding sources (aws.guardduty.finding_raised / wiz.finding_raised) it carries the finding severities that trigger a scan.","properties":{"severities":{"description":"Finding severities that trigger a scan (OR-matched).","items":{"enum":["low","medium","high","critical"],"type":"string"},"type":"array"}},"type":"object"},"EvidenceErrorResponse":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"ExcludedTag":{"properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key"],"type":"object"},"Frequency":{"discriminator":{"mapping":{"daily":"#/components/schemas/FrequencyDaily","every_hour":"#/components/schemas/FrequencyEveryHour","every5_minutes":"#/components/schemas/FrequencyEvery5Minutes","every12_hours":"#/components/schemas/FrequencyEvery12Hours","every15_minutes":"#/components/schemas/FrequencyEvery15Minutes","every30_minutes":"#/components/schemas/FrequencyEvery30Minutes","monthly":"#/components/schemas/FrequencyMonthly","weekly":"#/components/schemas/FrequencyWeekly"},"propertyName":"kind_tag"},"oneOf":[{"$ref":"#/components/schemas/FrequencyEvery5Minutes"},{"$ref":"#/components/schemas/FrequencyEvery15Minutes"},{"$ref":"#/components/schemas/FrequencyEvery30Minutes"},{"$ref":"#/components/schemas/FrequencyEveryHour"},{"$ref":"#/components/schemas/FrequencyEvery12Hours"},{"$ref":"#/components/schemas/FrequencyDaily"},{"$ref":"#/components/schemas/FrequencyWeekly"},{"$ref":"#/components/schemas/FrequencyMonthly"}]},"FrequencyDaily":{"properties":{"friday":{"type":"boolean"},"kind_tag":{"enum":["daily"],"type":"string"},"monday":{"type":"boolean"},"saturday":{"type":"boolean"},"sunday":{"type":"boolean"},"thursday":{"type":"boolean"},"time":{"$ref":"#/components/schemas/PlanTime"},"tuesday":{"type":"boolean"},"wednesday":{"type":"boolean"}},"required":["kind_tag","monday","tuesday","wednesday","thursday","friday","saturday","sunday"],"type":"object"},"FrequencyEvery5Minutes":{"properties":{"kind_tag":{"enum":["every5_minutes"],"type":"string"},"window":{"$ref":"#/components/schemas/TimeWindow"}},"required":["kind_tag"],"type":"object"},"FrequencyEvery12Hours":{"properties":{"kind_tag":{"enum":["every12_hours"],"type":"string"},"time":{"$ref":"#/components/schemas/PlanTime"}},"required":["kind_tag"],"type":"object"},"FrequencyEvery15Minutes":{"properties":{"kind_tag":{"enum":["every15_minutes"],"type":"string"},"window":{"$ref":"#/components/schemas/TimeWindow"}},"required":["kind_tag"],"type":"object"},"FrequencyEvery30Minutes":{"properties":{"kind_tag":{"enum":["every30_minutes"],"type":"string"},"window":{"$ref":"#/components/schemas/TimeWindow"}},"required":["kind_tag"],"type":"object"},"FrequencyEveryHour":{"properties":{"kind_tag":{"enum":["every_hour"],"type":"string"},"window":{"$ref":"#/components/schemas/TimeWindow"}},"required":["kind_tag"],"type":"object"},"FrequencyMonthly":{"properties":{"day_of_month":{"type":"integer"},"kind_tag":{"enum":["monthly"],"type":"string"},"time":{"$ref":"#/components/schemas/PlanTime"}},"required":["kind_tag","day_of_month"],"type":"object"},"FrequencyWeekly":{"properties":{"day":{"enum":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"type":"string"},"kind_tag":{"enum":["weekly"],"type":"string"},"time":{"$ref":"#/components/schemas/PlanTime"}},"required":["kind_tag","day"],"type":"object"},"Freshness":{"properties":{"age_seconds":{"format":"int64","nullable":true,"type":"integer"},"db_version":{"nullable":true,"type":"string"}},"required":["db_version","age_seconds"],"type":"object"},"GetCloudFormationLinkResponse":{"properties":{"link":{"format":"uri","type":"string"}},"required":["link"],"type":"object"},"GetConnectorAccountInstallFlowResponse":{"properties":{"flow":{"allOf":[{"$ref":"#/components/schemas/ConnectorAccountInstallFlowItem"}],"description":"The install flow when present; JSON null when there is no install flow for this account.","nullable":true}},"required":["flow"],"type":"object"},"HuntRuleAttachPolicyRequest":{"properties":{"policy_id":{"type":"string"},"policy_name":{"description":"Display snapshot of the policy name (bindings are loose references).","type":"string"}},"required":["policy_id"],"type":"object"},"HuntRuleCreateRequest":{"properties":{"author":{"type":"string"},"bodies":{"additionalProperties":{"type":"string"},"type":"object"},"cloned_from_rule_id":{"format":"uuid","type":"string"},"description":{"type":"string"},"mitre_mapping":{"items":{"type":"string"},"type":"array"},"name":{"description":"Must contain only alphanumeric characters, '-' and '_'.","maxLength":255,"pattern":"^[a-zA-Z0-9_-]+$","type":"string"},"primitives":{"items":{"enum":["structural","content","pattern"],"type":"string"},"type":"array"},"prompt":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"source":{"default":"CUSTOM","enum":["CUSTOM","ELASTIO","IMPORTED"],"type":"string"},"status":{"default":"active","enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"yara_refs":{"description":"Library attachments. Each pin must be used by a library `yara_match('yara/...')` in structural SQL, and each such path must be attached. `rule.yar` does not need a ref.","items":{"$ref":"#/components/schemas/YaraRef"},"type":"array"}},"required":["name","severity"],"type":"object"},"HuntRuleDeleteBlockedError":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"properties":{"blocking_policies":{"items":{"$ref":"#/components/schemas/HuntRulePolicyRef"},"type":"array"}},"type":"object"}],"description":"409 body for a hunt-rule write blocked by live policy bindings: `DELETE_BLOCKED` (delete) or `STATUS_CHANGE_BLOCKED` (PATCH that would deactivate an attached rule). Extends the standard error envelope with the blocking policies so the UI's blocked modal can list them."},"HuntRulePolicyRef":{"description":"One persisted rule→policy binding (loose reference; name is a display snapshot).","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"type":"object"},"HuntRuleResponse":{"description":"A hunt rule. Collections are always present ([]/{} never null); last_match_at stays null and matches_30d stays 0 until detection integration lands.","properties":{"attached_policies":{"items":{"$ref":"#/components/schemas/HuntRulePolicyRef"},"type":"array"},"author":{"type":"string"},"bodies":{"additionalProperties":{"type":"string"},"description":"Per-primitive rule code keyed by primitive kind (structural=SQL, content=YARA, pattern=regex).","type":"object"},"cloned_from_rule_id":{"format":"uuid","nullable":true,"type":"string"},"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"id":{"format":"uuid","type":"string"},"last_match_at":{"format":"date-time","nullable":true,"type":"string"},"matches_30d":{"type":"integer"},"mitre_mapping":{"items":{"type":"string"},"type":"array"},"name":{"type":"string"},"primitives":{"items":{"enum":["structural","content","pattern"],"type":"string"},"type":"array"},"prompt":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"signature_count":{"type":"integer"},"signatures":{"description":"Present on the detail response only; the list stays lean.","items":{"$ref":"#/components/schemas/RuleSignature"},"type":"array"},"source":{"enum":["CUSTOM","ELASTIO","IMPORTED"],"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"version":{"description":"Current content version (1 for rules that predate versioning).","type":"integer"},"version_count":{"description":"Number of stored version snapshots (0 for pre-versioning rules).","type":"integer"},"yara_refs":{"description":"Library YARA attachments (always present, [] never null).","items":{"$ref":"#/components/schemas/YaraRef"},"type":"array"}},"required":["id","tenant_name","name","description","author","source","severity","status","tags","mitre_mapping","primitives","bodies","prompt","matches_30d","attached_policies","yara_refs","version","version_count","signature_count","created_at","updated_at"],"type":"object"},"HuntRuleUpdateRequest":{"description":"PATCH: omitted fields are preserved; present fields (including []/{}) replace. `name` is not accepted (set at create; sending it is 400 BAD_REQUEST). Clone the rule to use a different name.","properties":{"author":{"type":"string"},"bodies":{"additionalProperties":{"type":"string"},"type":"object"},"change_summary":{"description":"Operator note attached to the new version when the PATCH touches content.","type":"string"},"description":{"type":"string"},"mitre_mapping":{"items":{"type":"string"},"type":"array"},"primitives":{"items":{"enum":["structural","content","pattern"],"type":"string"},"type":"array"},"prompt":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"source":{"enum":["CUSTOM","ELASTIO","IMPORTED"],"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"yara_refs":{"description":"Omitted preserves; `[]` clears. Changing refs is a content bump.","items":{"$ref":"#/components/schemas/YaraRef"},"type":"array"}},"type":"object"},"InstallRedstackRequestBody":{"properties":{"account_id":{"description":"12-digit AWS account ID where Cloud Connector should be installed","type":"string"},"regions":{"items":{"$ref":"#/components/schemas/RedStackInstallRegionParams"},"minItems":1,"type":"array"}},"required":["account_id","regions"],"type":"object"},"InstallRedstackResponse":{"properties":{"jobs_ids":{"description":"UUID strings of scheduled installation jobs","items":{"format":"uuid","type":"string"},"type":"array"}},"required":["jobs_ids"],"type":"object"},"IscanOptions":{"properties":{"bk":{"description":"Legacy iscan option name preserved from enum-to-struct migration","type":"string"},"data_classification":{"description":"Enables or disables data classification scans.","type":"boolean"},"encryption_detection":{"type":"boolean"},"hunt":{"type":"boolean"},"malware":{"type":"boolean"},"pursuit":{"description":"Enables or disables pursuit scans.","type":"boolean"},"ransomware":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"type":"object"},"IscanRequest":{"additionalProperties":false,"properties":{"data_classification":{"description":"Enables or disables data classification scans.","type":"boolean"},"encryption_detection":{"type":"boolean"},"hunt":{"type":"boolean"},"malware":{"type":"boolean"},"pursuit":{"description":"Enables or disables pursuit scans.","type":"boolean"},"ransomware":{"type":"boolean"}},"required":["ransomware","malware","encryption_detection","data_classification","hunt","pursuit"],"type":"object"},"IssuePATRequestBody":{"properties":{"all_scopes":{"description":"Universal API access. When true, grants is ignored.","type":"boolean"},"expires_at":{"description":"Optional. Unset means the token never expires.","format":"date-time","type":"string"},"grants":{"description":"Required (non-empty) when all_scopes is false.","items":{"$ref":"#/components/schemas/ScopeGrant"},"type":"array"},"name":{"type":"string"}},"required":["name"],"type":"object"},"IssuePATResponse":{"properties":{"details":{"$ref":"#/components/schemas/TokenDetails"},"token":{"description":"Raw token value, shown only once.","type":"string"}},"required":["token","details"],"type":"object"},"JobResult":{"properties":{"at":{"type":"string"},"result":{"type":"string"}},"required":["result","at"],"type":"object"},"LastCleanRP":{"properties":{"backup_vendor":{"description":"Third-party BACKUP product, never the scan engine.","nullable":true,"type":"string"},"policy_names":{"items":{"type":"string"},"type":"array"},"timestamp":{"type":"string"}},"required":["timestamp","policy_names","backup_vendor"],"type":"object"},"LatestRedStackVersionResponse":{"properties":{"version":{"description":"Newest globally-enabled Cloud Connector version (semver, e.g. \"0.41.68\")","example":"0.41.68","type":"string"}},"required":["version"],"type":"object"},"LedgerCoverage":{"properties":{"clean":{"format":"int64","type":"integer"},"errored":{"format":"int64","type":"integer"},"expected":{"format":"int64","type":"integer"},"findings":{"format":"int64","type":"integer"},"inconclusive":{"format":"int64","type":"integer"},"not_run":{"format":"int64","type":"integer"},"ran":{"format":"int64","type":"integer"}},"required":["expected","ran","findings","clean","not_run","inconclusive","errored"],"type":"object"},"LedgerPopulation":{"properties":{"assets_attempted":{"format":"int64","type":"integer"},"assets_expected":{"format":"int64","type":"integer"},"assets_failed":{"format":"int64","type":"integer"},"assets_retrieved":{"format":"int64","type":"integer"},"cap":{"format":"int64","type":"integer"},"cap_applied":{"type":"boolean"}},"required":["assets_expected","assets_attempted","assets_retrieved","assets_failed","cap_applied","cap"],"type":"object"},"LedgerRecord":{"properties":{"asset":{"$ref":"#/components/schemas/AssetRef"},"at":{"nullable":true,"type":"string"},"finding_id":{"nullable":true,"type":"string"},"freshness":{"allOf":[{"$ref":"#/components/schemas/Freshness"}],"nullable":true},"method":{"type":"string"},"note":{"nullable":true,"type":"string"},"score":{"allOf":[{"$ref":"#/components/schemas/Score"}],"nullable":true},"status":{"enum":["ran","not_run","inconclusive","errored"],"type":"string"},"subject":{"$ref":"#/components/schemas/Subject"},"verdict":{"enum":["clean","finding","remediated","suspicious","unknown"],"type":"string"}},"required":["asset","subject","method","status","verdict","score","at","freshness","finding_id","note"],"type":"object"},"LedgerResponse":{"properties":{"coverage":{"$ref":"#/components/schemas/LedgerCoverage"},"degraded":{"items":{"type":"string"},"type":"array"},"pagination":{"$ref":"#/components/schemas/Pagination"},"population":{"$ref":"#/components/schemas/LedgerPopulation"},"records":{"items":{"$ref":"#/components/schemas/LedgerRecord"},"type":"array"},"scope":{"$ref":"#/components/schemas/LedgerScope"}},"required":["scope","coverage","population","records","degraded","pagination"],"type":"object"},"LedgerScope":{"properties":{"kind":{"type":"string"},"label":{"type":"string"},"params":{"additionalProperties":{"type":"string"},"type":"object"}},"required":["kind","label","params"],"type":"object"},"LicensesStandardError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"LinkAssetAccountRequestBody":{"properties":{"asset_account_id":{"description":"12-digit AWS account id to link as the asset account","type":"string"},"connector_account_id":{"description":"12-digit AWS account id where Cloud Connectors are deployed for this asset","type":"string"}},"required":["asset_account_id","connector_account_id"],"type":"object"},"LinkAssetAccountResponse":{"properties":{"linking_jobs":{"items":{"$ref":"#/components/schemas/AssetAccountLinkingJob"},"type":"array"}},"required":["linking_jobs"],"type":"object"},"ListAssetAccountsResponse":{"properties":{"asset_accounts":{"items":{"$ref":"#/components/schemas/AssetAccount"},"type":"array"}},"required":["asset_accounts"],"type":"object"},"ListAwsVpcsResponse":{"properties":{"vpcs":{"items":{"$ref":"#/components/schemas/Vpc"},"type":"array"}},"required":["vpcs"],"type":"object"},"ListEventPoliciesResponse":{"properties":{"event_policies":{"items":{"$ref":"#/components/schemas/EventPolicyResponse"},"type":"array"},"total_count":{"type":"integer"}},"required":["event_policies","total_count"],"type":"object"},"ListHuntRulesResponse":{"properties":{"hunt_rules":{"items":{"$ref":"#/components/schemas/HuntRuleResponse"},"type":"array"},"total_count":{"type":"integer"}},"required":["hunt_rules","total_count"],"type":"object"},"ListPATsResponse":{"properties":{"tokens_details":{"items":{"$ref":"#/components/schemas/TokenDetails"},"type":"array"},"total":{"format":"int64","type":"integer"}},"required":["tokens_details","total"],"type":"object"},"ListPoliciesResponse":{"properties":{"policies":{"items":{"$ref":"#/components/schemas/PolicyResponse"},"type":"array"},"total_count":{"type":"integer"}},"required":["policies","total_count"],"type":"object"},"ListPoliciesV2Response":{"description":"Response for GET /shared-services/v2/policies. Wraps PolicyV2Response items (not PolicyResponse) so non-AWS `cluster_name` / `cluster_options` are carried in the list.","properties":{"policies":{"items":{"$ref":"#/components/schemas/PolicyV2Response"},"type":"array"},"total_count":{"type":"integer"}},"required":["policies","total_count"],"type":"object"},"ListPoliciesV3Response":{"description":"Response for GET /shared-services/v3/policies. Wraps PolicyV3Response items (PolicyV2Response plus `violations`).","properties":{"policies":{"items":{"$ref":"#/components/schemas/PolicyV3Response"},"type":"array"},"total_count":{"type":"integer"}},"required":["policies","total_count"],"type":"object"},"ListPolicyDeletionsResponse":{"description":"Response for GET /shared-services/v3/policies/deleted: active deletions of BOTH kinds, ordered `deleted_at` descending. No pagination or filters.","properties":{"policies":{"items":{"$ref":"#/components/schemas/PolicyDeletionListItem"},"type":"array"},"total_count":{"type":"integer"}},"required":["policies","total_count"],"type":"object"},"ListRedStackConnectorDetails":{"properties":{"deployment_type":{"enum":["self_managed","elastio_managed"],"type":"string"}},"required":["deployment_type"],"type":"object"},"ListRedStackIntegrityError":{"properties":{"kind":{"enum":["infrastructure","unknown"],"type":"string"},"message":{"type":"string"}},"required":["kind"],"type":"object"},"ListRedStackItem":{"properties":{"account_alias":{"type":"string"},"account_description":{"type":"string"},"aws_account":{"description":"12-digit AWS account ID","type":"string"},"aws_account_cfn_version":{"type":"string"},"aws_region":{"type":"string"},"cfn_upgrade_required":{"type":"boolean"},"created_at":{"format":"date-time","type":"string"},"details":{"$ref":"#/components/schemas/ListRedStackConnectorDetails"},"iam_role":{"type":"string"},"last_error_message":{"type":"string"},"last_integrity_check_errors":{"items":{"$ref":"#/components/schemas/ListRedStackIntegrityError"},"type":"array"},"last_warning_message":{"type":"string"},"multicloud_clusters":{"items":{"$ref":"#/components/schemas/ListRedStackMulticloudCluster"},"type":"array"},"red_stack_id":{"type":"string"},"status":{"enum":["active","inactive","deleted","upgrade_required","unknown"],"type":"string"},"support":{"$ref":"#/components/schemas/ListRedStackSupport"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"version":{"type":"string"}},"required":["red_stack_id","aws_account","aws_region","account_alias","status"],"type":"object"},"ListRedStackMissingCapability":{"properties":{"capability":{"enum":["pursuit","hunt","data_classification","encryption_detection","cross_account_scan","unspecified"],"type":"string"},"required_version":{"description":"Oldest connector version that runs the capability.","type":"string"}},"required":["capability","required_version"],"type":"object"},"ListRedStackMulticloudCluster":{"properties":{"created_at":{"format":"date-time","type":"string"},"enable_azure":{"type":"boolean"},"enable_ibm":{"type":"boolean"},"name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["name","enable_azure","enable_ibm"],"type":"object"},"ListRedStackSupport":{"description":"How far this region stack has drifted from the newest version its account may run, and what its version cannot do. Measured against latest_available_version, the same version the upgrade plan targets.\n","properties":{"latest_available_version":{"description":"Newest version this account may run: enabled for the tenant, within its pin, and allowed by the account-level template.\n","type":"string"},"minimum_supported_version":{"description":"Oldest version Elastio supports for this account.","type":"string"},"minors_behind":{"description":"Minor lines between this version and latest_available_version.","format":"int32","type":"integer"},"missing_capabilities":{"items":{"$ref":"#/components/schemas/ListRedStackMissingCapability"},"type":"array"},"state":{"description":"support_ending means the region sits at the floor: it is supported until the next minor line reaches the account. unknown means there is no version to measure, or nothing to measure it against.\n","enum":["current","update_available","support_ending","unsupported","unknown"],"type":"string"},"tenant_latest_version":{"description":"Newest version enabled for the tenant whatever its account template allows. Above latest_available_version when the template caps the account.\n","type":"string"}},"required":["state","minors_behind"],"type":"object"},"ListRedStacksResponse":{"properties":{"red_stacks":{"items":{"$ref":"#/components/schemas/ListRedStackItem"},"type":"array"},"total":{"description":"Total number of Cloud Connectors matching the query (across all pages)","format":"int64","type":"integer"}},"required":["red_stacks","total"],"type":"object"},"ListRuleAuditResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/RuleAuditEntry"},"type":"array"},"total_count":{"type":"integer"}},"required":["entries","total_count"],"type":"object"},"ListRuleVersionsResponse":{"properties":{"total_count":{"type":"integer"},"versions":{"items":{"$ref":"#/components/schemas/RuleVersion"},"type":"array"}},"required":["versions","total_count"],"type":"object"},"ListScanClusterItem":{"properties":{"cluster_kind":{"enum":["azure","ibm","on_prem","gcp"],"type":"string"},"cluster_name":{"type":"string"},"cluster_type":{"enum":["self_managed","elastio_managed"],"type":"string"},"created_at":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"metadata":{"$ref":"#/components/schemas/ScanClusterMetadata"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","cluster_name","cluster_kind","cluster_type","metadata"],"type":"object"},"ListScanClustersResponse":{"properties":{"scan_clusters":{"items":{"$ref":"#/components/schemas/ListScanClusterItem"},"type":"array"},"total":{"description":"Total number of standalone scan clusters registered for the tenant","format":"int64","type":"integer"}},"required":["scan_clusters","total"],"type":"object"},"ListSchedulesResponse":{"properties":{"schedules":{"items":{"$ref":"#/components/schemas/ScheduleResponse"},"type":"array"},"total_count":{"type":"integer"}},"required":["schedules","total_count"],"type":"object"},"ListSupportedAwsRegionsResponse":{"properties":{"region_names":{"items":{"type":"string"},"type":"array"}},"required":["region_names"],"type":"object"},"ListVaultsResponse":{"description":"Mirrors the vault list service. Each entry includes identifiers, AWS scope, usage counts (assets and recovery points), networking, integrity notes, and optional compute settings.","properties":{"total_count":{"format":"int64","type":"integer"},"vaults":{"items":{"$ref":"#/components/schemas/VaultListItem"},"type":"array"}},"required":["vaults","total_count"],"type":"object"},"ListYaraRulesResponse":{"properties":{"total_count":{"type":"integer"},"yara_rules":{"items":{"$ref":"#/components/schemas/YaraRuleResponse"},"type":"array"}},"required":["yara_rules","total_count"],"type":"object"},"ListYaraRulesetsResponse":{"properties":{"total_count":{"type":"integer"},"yara_rulesets":{"items":{"$ref":"#/components/schemas/YaraRulesetResponse"},"type":"array"}},"required":["yara_rulesets","total_count"],"type":"object"},"MembershipErrorResponse":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error"],"type":"object"},"MembershipResponse":{"properties":{"asset_ids":{"description":"Catalog asset UUIDs in this page, sorted.","items":{"format":"uuid","type":"string"},"type":"array"},"candidate_assets":{"description":"Number of catalog assets evaluated.","type":"integer"},"computed_at":{"format":"date-time","type":"string"},"pagination":{"properties":{"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["limit","offset"],"type":"object"},"platform":{"enum":["AWS","Azure","IBM"],"type":"string"},"policy_name":{"type":"string"},"total_matched":{"description":"Total matches before pagination.","type":"integer"}},"required":["policy_name","platform","candidate_assets","total_matched","asset_ids","computed_at","pagination"],"type":"object"},"Mode":{"description":"AWS plan mode. `backup` has no per-family option bags. `scan_only` carries one or more of `ec2_or_ebs`, `s3`, `efs`, `fsx_ontap`.","discriminator":{"mapping":{"backup":"#/components/schemas/ModeBackup","scan_only":"#/components/schemas/ModeScanOnly"},"propertyName":"kind_tag"},"oneOf":[{"$ref":"#/components/schemas/ModeBackup"},{"$ref":"#/components/schemas/ModeScanOnly"}]},"ModeBackup":{"example":{"kind_tag":"backup"},"properties":{"kind_tag":{"enum":["backup"],"type":"string"}},"required":["kind_tag"],"type":"object"},"ModeScanOnly":{"additionalProperties":false,"description":"Scan-only mode. Include at least one family option bag. Multiple families may be set on the same policy (for example EC2/EBS + S3 + EFS).","example":{"ec2_or_ebs":{"keep_last_clean_copy":true,"keep_latest_infected_copy":false},"efs":{},"kind_tag":"scan_only","s3":{"threat_hunt":true}},"minProperties":2,"properties":{"ec2_or_ebs":{"$ref":"#/components/schemas/ScanOnlyEc2OrEbsOptions"},"efs":{"$ref":"#/components/schemas/ScanOnlyEfsOptions"},"fsx_ontap":{"$ref":"#/components/schemas/ScanOnlyFsxOntapOptions"},"kind_tag":{"enum":["scan_only"],"type":"string"},"s3":{"$ref":"#/components/schemas/ScanOnlyS3Options"}},"required":["kind_tag"],"type":"object"},"Objectives":{"properties":{"backup_age_seconds":{"format":"int64","nullable":true,"type":"integer"},"rpo_target_seconds":{"description":"The R-RPO the served recovery verdict measures this asset against (`recovery_verdict.effective_target.r_rpo_seconds`; the relaxed value while an approved exception relaxes it). Null when the verdict is not served or an exception waives the R-RPO target.\n","format":"int64","nullable":true,"type":"integer"}},"required":["backup_age_seconds","rpo_target_seconds"],"type":"object"},"PATErrorResponse":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"Pagination":{"properties":{"next_page_token":{"type":"string"},"offset":{"format":"int64","type":"integer"},"page_size":{"format":"int64","type":"integer"},"total":{"format":"int64","type":"integer"}},"required":["total","page_size","offset","next_page_token"],"type":"object"},"PatchAwsAccountBody":{"description":"Partial update: include only `account_alias` and/or `description` fields you want to change.\nOmitted properties are left unchanged. At least one property must be sent.\n","properties":{"account_alias":{"maxLength":256,"type":"string"},"description":{"maxLength":4096,"type":"string"}},"type":"object"},"PatchConnectorAccountInstallFlowBody":{"description":"At least one of `enable_vpc_permissions` (set to true) or non-empty `add_aws_regions_to_autoinstall`\nmust be sent. Omitted `enable_vpc_permissions` is treated as false.\n","properties":{"add_aws_regions_to_autoinstall":{"items":{"description":"AWS region name (e.g. us-east-1)","type":"string"},"type":"array"},"enable_vpc_permissions":{"description":"When true, requests VPC permissions on CloudFormation templates for this account. False or omitted does not enable them.\n","type":"boolean"}},"type":"object"},"PatchTenantSettingsBody":{"properties":{"backup_stale_threshold_seconds":{"maximum":7776000,"minimum":1,"type":"integer"},"entropy_detection_notifications":{"enum":["enabled","disabled"],"type":"string"},"excluded_tags":{"items":{"$ref":"#/components/schemas/ExcludedTag"},"type":"array"},"session_absolute_timeout_seconds":{"type":"integer"},"session_idle_timeout_seconds":{"type":"integer"}},"type":"object"},"PauseRequest":{"properties":{"paused_until":{"format":"date-time","nullable":true,"type":"string"}},"type":"object"},"PlanTime":{"properties":{"time":{"description":"Time in HH:MM:SS format (24-hour, zero-padded)","example":"09:00:00","type":"string"},"timezone":{"description":"IANA timezone identifier","example":"Etc/UTC","type":"string"}},"required":["time","timezone"],"type":"object"},"PlanVault":{"properties":{"red_stack_id":{"type":"string"},"vault_name":{"type":"string"}},"required":["red_stack_id","vault_name"],"type":"object"},"PolicyDeleteReasonRequest":{"description":"Optional body shared by the five reason-bearing deletion-lifecycle mutations (both soft-deletes, both live DELETE endpoints, and terminalize: D9). An absent or empty body means no reason.","properties":{"reason":{"description":"Free-text reason recorded on the deletion record (`delete_reason` on a soft-delete, `hard_delete_reason` on a live DELETE or terminalize). Up to 1024 runes; longer is rejected 400 `INVALID_REASON`.","maxLength":1024,"type":"string"}},"type":"object"},"PolicyDeletionListItem":{"description":"One row of the unified deleted-policies list. Carries both scheduled and event kinds; `last_known_name` is the UI recovery table's key.","properties":{"delete_reason":{"description":"The optional reason recorded on the soft-delete; absent when none was given.","nullable":true,"type":"string"},"deleted_at":{"format":"date-time","type":"string"},"deleted_by":{"description":"The acting user id (`X-User-Id`); the `\"unknown\"` sentinel when the header was absent.","type":"string"},"id":{"description":"The deletion record id: the key for restore / terminalize / tombstone read.","format":"uuid","type":"string"},"kind":{"description":"Which policy namespace the deleted policy belonged to.","enum":["scheduled","event"],"type":"string"},"last_known_name":{"description":"The policy's name at deletion time (a scheduled and an event policy may legitimately share a name).","type":"string"},"platform":{"description":"The deleted policy's platform (AWS/Azure/IBM for scheduled; recorded, unconstrained).","type":"string"},"prior_state":{"description":"The policy's lifecycle state at deletion, derived from the snapshot.","enum":["enabled","disabled","paused"],"type":"string"}},"required":["id","kind","last_known_name","platform","prior_state","deleted_at","deleted_by"],"type":"object"},"PolicyDeletionResponse":{"description":"The full deletion record: returned by both soft-deletes, restore, and the tombstone read in any state (soft-deleted, restored, hard-deleted). The settle columns are always present and null until their lifecycle step runs.","properties":{"alert_ids":{"description":"The policy's alert bindings captured in the snapshot ( D3/D4): always the snapshotted set, `[]` when none, never null.","items":{"format":"uuid","type":"string"},"type":"array"},"bound_alert_ids":{"description":"Response-only on RESTORE: the set that actually re-bound in ingestion; present on every restore response, including `[]` when a degraded bind bound nothing. Absent on every persisted read (soft-delete, tombstone), as the bound outcome is not stored.","items":{"format":"uuid","type":"string"},"nullable":true,"type":"array"},"delete_reason":{"description":"The soft-delete reason, if one was recorded.","nullable":true,"type":"string"},"deleted_at":{"format":"date-time","type":"string"},"deleted_by":{"type":"string"},"hard_delete_reason":{"description":"The live-hard-delete or terminalize reason, if one was recorded.","nullable":true,"type":"string"},"hard_deleted_at":{"format":"date-time","nullable":true,"type":"string"},"hard_deleted_by":{"nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"kind":{"enum":["scheduled","event"],"type":"string"},"last_known_id":{"description":"The policy's canonical id, preserved so restore is id-stable. Null only on the degraded live-hard-delete path where the policy's canonical id could not be resolved.","format":"uuid","nullable":true,"type":"string"},"last_known_name":{"type":"string"},"platform":{"type":"string"},"prior_snapshot":{"additionalProperties":true,"description":"The versioned snapshot envelope, passed through verbatim: the marshalled domain policy plus its fail-closed-hydrated `alert_ids`. Viewer-readable (viewers can already read live policy config).","type":"object"},"prior_state":{"description":"Derived from the snapshot at read time.","enum":["enabled","disabled","paused"],"type":"string"},"restored_at":{"format":"date-time","nullable":true,"type":"string"},"restored_by":{"nullable":true,"type":"string"}},"required":["id","kind","last_known_name","last_known_id","platform","prior_state","prior_snapshot","alert_ids","deleted_at","deleted_by","delete_reason","restored_at","restored_by","hard_deleted_at","hard_deleted_by","hard_delete_reason"],"type":"object"},"PolicyResponse":{"properties":{"account_region_selectors":{"items":{"$ref":"#/components/schemas/AccountRegionSelector"},"type":"array"},"created_at":{"type":"string"},"data_classification_scan_options":{"allOf":[{"$ref":"#/components/schemas/DataClassificationScanOptions"}],"description":"Optional DC scan configuration. Stored independently from `iscan.data_classification` and only takes effect when that boolean is enabled.","nullable":true},"description":{"type":"string"},"frequency":{"allOf":[{"$ref":"#/components/schemas/Frequency"}],"description":"Always populated. When the policy references an external schedule (schedule_id non-null), the server hydrates this field from the referenced schedule so callers don't need a second round-trip."},"id":{"description":"Stable surrogate policy id; the canonical identifier carried in the X-Policy-Ids scope header.","format":"uuid","type":"string"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanOptions"},"kind":{"enum":["default","custom"],"type":"string"},"last_run_at":{"description":"Timestamp of the most recent backup run, derived from the policy's backup job history. Null if the policy has never run.","format":"date-time","nullable":true,"type":"string"},"mode":{"$ref":"#/components/schemas/Mode"},"name":{"type":"string"},"paused_until":{"nullable":true,"type":"string"},"platform":{"default":"AWS","enum":["AWS"],"type":"string"},"protect_new_immediately":{"enum":["disabled","enabled"],"type":"string"},"pursuit_scan_options":{"allOf":[{"$ref":"#/components/schemas/PursuitScanOptions"}],"description":"Optional pursuit scan configuration. Stored independently from `iscan.pursuit` and only takes effect when that boolean is enabled.","nullable":true},"schedule_id":{"description":"Set when the policy references a schedule rather than carrying an inline frequency.","format":"uuid","nullable":true,"type":"string"},"selectors":{"items":{"$ref":"#/components/schemas/Selector"},"type":"array"},"skip_ebs_backup":{"type":"boolean"},"snapshot_import":{"enum":["skip","latest","all"],"type":"string"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"tags":{"additionalProperties":{"type":"string"},"type":"object"},"tenant_name":{"type":"string"},"updated_at":{"type":"string"},"vaults":{"items":{"$ref":"#/components/schemas/PlanVault"},"type":"array"}},"required":["id","tenant_name","name","frequency","status","selectors","tags","iscan","kind","vaults","snapshot_import","integrity_check","skip_ebs_backup","account_region_selectors","mode","protect_new_immediately","created_at","updated_at","description","platform"],"type":"object"},"PolicyV2Response":{"description":"Response for the v2 policy endpoints (create, update, get and list). Carries the same fields as PolicyResponse plus the cluster fields. For AWS, `cluster_name` is empty, `subscription_ids`, `cluster_names` and `cluster_options` are null. For Azure/IBM `cluster_options` holds the persisted options and the AWS-only fields (`frequency`, `iscan`, `mode`) are null; an Azure policy scoped by `subscription_ids` carries them plus the server-derived `cluster_name` (the primary scan cluster its subscriptions resolve to, re-derived on every write) and `cluster_names` (every cluster it is delivered to), while a legacy Azure or IBM policy carries the `cluster_name` it was created with, a null `subscription_ids`, and `cluster_names` holding that one cluster. `cluster_names` is null until the pechkin `policies.cluster_names` column exists ( phase 2).","properties":{"account_region_selectors":{"items":{"$ref":"#/components/schemas/AccountRegionSelector"},"type":"array"},"cluster_name":{"description":"The single-cluster target: the cluster a legacy Azure or IBM policy was created with, or (for an Azure policy scoped by `subscription_ids`) the server-derived primary scan cluster (the one serving the most of its subscriptions, ties broken by the lowest name), rewritten on every create and update. Empty for AWS policies, and for scoped Azure rows written before that the backfill has not yet visited.","nullable":true,"type":"string"},"cluster_names":{"description":"Every scan cluster the policy is delivered to, sorted: all clusters a subscription-scoped Azure policy's subscriptions resolve to, or the single `cluster_name` of a legacy Azure / IBM policy. Derived server-side, never accepted on a request. Null for AWS policies and until the pechkin `policies.cluster_names` column exists ( phase 2).","items":{"type":"string"},"nullable":true,"type":"array"},"cluster_options":{"allOf":[{"$ref":"#/components/schemas/ClusterOptions"}],"description":"Cluster policy options for Azure/IBM (carries `policy_yaml`). Null for AWS policies.","nullable":true},"created_at":{"type":"string"},"data_classification_scan_options":{"allOf":[{"$ref":"#/components/schemas/DataClassificationScanOptions"}],"description":"Optional DC scan configuration. Stored independently from `iscan.data_classification` and only takes effect when that boolean is enabled.","nullable":true},"description":{"type":"string"},"frequency":{"allOf":[{"$ref":"#/components/schemas/Frequency"}],"description":"Null for Azure/IBM cluster policies: their cadence lives in cluster_options.policy_yaml, not here. For AWS always populated: when the policy references an external schedule (schedule_id non-null), the server hydrates this field from the referenced schedule so callers don't need a second round-trip.","nullable":true},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"allOf":[{"$ref":"#/components/schemas/IscanOptions"}],"description":"Null for Azure/IBM cluster policies; always set for AWS.","nullable":true},"kind":{"enum":["default","custom"],"type":"string"},"last_run_at":{"description":"Timestamp of the most recent backup run. For AWS policies derived from the backup job history; for Azure/IBM the reconciler-maintained value. Null if the policy has never run.","format":"date-time","nullable":true,"type":"string"},"mode":{"allOf":[{"$ref":"#/components/schemas/Mode"}],"description":"Null for Azure/IBM cluster policies; always set for AWS.","nullable":true},"name":{"type":"string"},"paused_until":{"nullable":true,"type":"string"},"platform":{"enum":["AWS","Azure","IBM","GCP"],"type":"string"},"protect_new_immediately":{"enum":["disabled","enabled"],"type":"string"},"pursuit_scan_options":{"allOf":[{"$ref":"#/components/schemas/PursuitScanOptions"}],"description":"Optional pursuit scan configuration. Stored independently from `iscan.pursuit` and only takes effect when that boolean is enabled.","nullable":true},"schedule_id":{"description":"Set when the policy references a schedule rather than carrying an inline frequency.","format":"uuid","nullable":true,"type":"string"},"selectors":{"items":{"$ref":"#/components/schemas/Selector"},"type":"array"},"skip_ebs_backup":{"type":"boolean"},"snapshot_import":{"enum":["skip","latest","all"],"type":"string"},"status":{"description":"Operational pause state, surfaced for every platform: AWS, and (since v2 pause/resume) Azure/IBM cluster policies. A non-AWS row left without a status (legacy/in-flight) is reported as `enabled`.","enum":["enabled","disabled","paused_until"],"type":"string"},"subscription_ids":{"description":"Azure typed scope (normalized: lowercase, deduplicated, sorted). Null for AWS, IBM, and legacy Azure policies.","items":{"format":"uuid","type":"string"},"nullable":true,"type":"array"},"tags":{"additionalProperties":{"type":"string"},"type":"object"},"tenant_name":{"type":"string"},"updated_at":{"type":"string"},"vaults":{"items":{"$ref":"#/components/schemas/PlanVault"},"type":"array"}},"required":["tenant_name","name","frequency","status","selectors","tags","iscan","kind","vaults","snapshot_import","integrity_check","skip_ebs_backup","account_region_selectors","mode","protect_new_immediately","created_at","updated_at","description","platform","cluster_name","cluster_options"],"type":"object"},"PolicyV3Response":{"allOf":[{"$ref":"#/components/schemas/PolicyV2Response"},{"properties":{"alert_ids":{"description":"Alert UUIDs bound to the policy. Always present; `[]` when the policy has no bound alerts, never null.","items":{"format":"uuid","type":"string"},"type":"array"},"ccl_severity_overrides":{"description":"Persisted CCL severity overrides. Always present; `[]` when the policy keeps every type at the catalog default.","items":{"$ref":"#/components/schemas/CCLSeverityOverride"},"type":"array"},"created_via_plan_id":{"description":"Provenance (the \"Managed\" facet): the Resilience Program plan this policy was created via, as persisted (the read is the source of truth). Omitted/null when created directly, not via a plan. Stamped once at create; immutable thereafter.","nullable":true,"type":"string"},"hunt_rule_ids":{"description":"Hunt-rule UUIDs bound to the policy, hydrated from hunt_rule_policy_bindings. Always present; `[]` when the policy has no bound hunt rules, never null.","items":{"format":"uuid","type":"string"},"type":"array"},"r_rpo":{"allOf":[{"$ref":"#/components/schemas/RRPOTarget"}],"description":"Per-policy Recovery RPO target as persisted (the read is the source of truth). Always present; null when the policy stores no R-RPO.","nullable":true},"violations":{"description":"Per-policy violation selection as persisted (the read is the source of truth). Always present; `[]` when none.","items":{"$ref":"#/components/schemas/PolicyViolation"},"type":"array"}},"required":["violations","r_rpo","alert_ids","hunt_rule_ids","ccl_severity_overrides"],"type":"object"}],"description":"Response for the v3 policy endpoints (create, update, get, list). Embeds PolicyV2Response and adds the `violations` list (always present; `[]` when the policy tracks none, never null) and the `r_rpo` target (always present; null when the policy stores no R-RPO)."},"PolicyViolation":{"description":"One entry in a v3 policy response `violations` list. Echoes what was stored; the effective severity (`severity_override` if present, else the dictionary default) is resolved by the consumer.","properties":{"code":{"type":"string"},"severity_override":{"description":"Present only when the policy overrides the dictionary default severity.","enum":["critical","high","medium","low","info"],"type":"string"}},"required":["code"],"type":"object"},"PolicyYAMLValidationErrorResponse":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"properties":{"issues":{"description":"The structured policy_yaml validation issues, deterministically sorted and capped (a final `ISSUES_TRUNCATED` when more than 100 are found).","items":{"$ref":"#/components/schemas/ValidationIssue"},"type":"array"}},"type":"object"}],"description":"400 body for a v2 create/update rejected by strict `policy_yaml` validation (`code` `POLICY_YAML_INVALID`) or, for an Azure policy, by subscription resolution (`code` `SUBSCRIPTION_UNRESOLVED`, one issue per unresolvable element at `/subscription_ids/N`). Extends the standard error envelope with the structured `issues` array; additive: `issues` is absent for every other 400 (`code` `VALIDATION_ERROR`)."},"PursuitPlaybook":{"description":"A pursuit playbook identified by source. Exactly one of `custom` or `built_in` must be set; providing both or neither is rejected 400 `VALIDATION_ERROR`.","oneOf":[{"additionalProperties":false,"properties":{"custom":{"description":"Name of a custom playbook registered in the scan cluster.","type":"string"}},"required":["custom"],"type":"object"},{"additionalProperties":false,"properties":{"built_in":{"description":"Name of a built-in playbook shipped inside the Elastio image.","type":"string"}},"required":["built_in"],"type":"object"}],"type":"object"},"PursuitScanOptions":{"additionalProperties":false,"description":"Optional pursuit scan configuration. Stored independently from `iscan.pursuit` and only takes effect when that boolean is enabled. When that boolean is enabled, `playbooks` must contain exactly one entry.","properties":{"playbooks":{"description":"Playbooks to run. A scan runs exactly one, so a policy may name at most one. When `iscan.pursuit` is true this array must contain exactly one entry (`[]` is rejected 400 `VALIDATION_ERROR`). Duplicate entries are rejected 400 `VALIDATION_ERROR`.","items":{"$ref":"#/components/schemas/PursuitPlaybook"},"maxItems":1,"type":"array"}},"type":"object"},"RRPOTarget":{"description":"Per-policy Recovery RPO target: the maximum acceptable age of the last proven clean recovery point (`target_seconds`) and the severity raised when an asset's most recent clean copy is older than that target (`severity`). It parameterizes the `r_rpo_exceeded` violation: which is therefore reserved from the `violations` list (400 `RESERVED_VIOLATION_CODE`). Both fields are required when `r_rpo` is present.","properties":{"severity":{"description":"Severity raised when the target is exceeded. The full server-enforced set (the UI may surface a subset); accepted case-insensitively and stored lowercase. A value outside the enum is rejected 400 `INVALID_RRPO_SEVERITY`.","enum":["critical","high","medium","low"],"type":"string"},"target_seconds":{"description":"Maximum acceptable age, in seconds, of the last proven clean recovery point. A positive integer; a non-positive value is rejected 400 `INVALID_RRPO_TARGET`. The server does not cap it (no maximum).","minimum":1,"type":"integer"}},"required":["target_seconds","severity"],"type":"object"},"RecoveryAtRiskReason":{"enum":["no_enabled_policy","plan_not_activated","near_expiry","policy_looser_than_target"],"type":"string"},"RecoveryEffectiveTarget":{"properties":{"r_rpo_seconds":{"type":"integer"},"required_copies":{"items":{"enum":["immutable","air_gapped","cross_region"],"type":"string"},"type":"array"},"source":{"enum":["program_class_floor","program_node","policy","default"],"type":"string"}},"required":["r_rpo_seconds","source","required_copies"],"type":"object"},"RecoveryException":{"properties":{"commitment_key":{"enum":["rrpo_target_seconds","immutable_required","airgap_required","cross_region_required"],"type":"string"},"expires_at":{"format":"date-time","nullable":true,"type":"string"},"override_id":{"format":"uuid","type":"string"},"reason":{"type":"string"},"relaxed_to":{"nullable":true,"type":"string"},"set_at":{"format":"date-time","type":"string"},"set_by":{"type":"string"}},"required":["override_id","commitment_key","reason","set_by","set_at"],"type":"object"},"RecoveryExceptionBreakdownEntry":{"properties":{"asset_count":{"type":"integer"},"asset_ids":{"description":"Capped at 200 ids per entry.","items":{"type":"string"},"type":"array"},"class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"commitment_key":{"enum":["rrpo_target_seconds","immutable_required","airgap_required","cross_region_required"],"type":"string"}},"required":["commitment_key","class","asset_count","asset_ids"],"type":"object"},"RecoveryPoint":{"properties":{"id":{"type":"string"},"is_last_clean":{"type":"boolean"},"status":{"type":"string"},"when":{"type":"string"}},"required":["id","when","status","is_last_clean"],"type":"object"},"RecoveryPosture":{"properties":{"coverage_sources":{"items":{"type":"string"},"nullable":true,"type":"array"},"efs_backup_association":{"allOf":[{"$ref":"#/components/schemas/EfsAssociation"}],"nullable":true},"last_clean_rp":{"allOf":[{"$ref":"#/components/schemas/LastCleanRP"}],"description":"Null = no clean recovery point on record, unless named in degraded.","nullable":true},"objectives":{"$ref":"#/components/schemas/Objectives"},"recovery_points":{"description":"The last 365 days, newest first, at most 200.","items":{"$ref":"#/components/schemas/RecoveryPoint"},"type":"array"}},"required":["last_clean_rp","recovery_points","coverage_sources","efs_backup_association","objectives"],"type":"object"},"RecoveryReasonBreakdownEntry":{"properties":{"asset_count":{"type":"integer"},"asset_ids":{"description":"Capped at 200 ids per entry.","items":{"type":"string"},"type":"array"},"class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"reason":{"description":"A RecoveryUnprovenReason or RecoveryAtRiskReason code.","type":"string"}},"required":["reason","class","asset_count","asset_ids"],"type":"object"},"RecoveryUnprovenReason":{"enum":["no_recovery_point","no_scanned_point","no_clean_point","r_rpo_exceeded","missing_immutable_copy","missing_air_gapped_copy","missing_cross_region_copy","immutable_copy_not_observable","air_gapped_copy_not_observable","cross_region_copy_not_observable"],"type":"string"},"RecoveryVerdict":{"enum":["proven","unproven"],"type":"string"},"RecoveryVerdictAssetPage":{"properties":{"assets":{"items":{"$ref":"#/components/schemas/RecoveryVerdictAssetRow"},"type":"array"},"page":{"type":"integer"},"page_size":{"type":"integer"},"total":{"description":"The unpaged count for the filters.","type":"integer"}},"required":["assets","page","page_size","total"],"type":"object"},"RecoveryVerdictAssetRow":{"description":"One live asset with its live resilience class and its last evaluated verdict.","properties":{"account_id":{"description":"Cloud owner identity: AWS account id, Azure subscription id, or IBM scope. Null when the asset has none.\n","nullable":true,"type":"string"},"asset_id":{"format":"uuid","type":"string"},"class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"kind":{"type":"string"},"name":{"type":"string"},"recovery":{"allOf":[{"$ref":"#/components/schemas/AssetRecoveryVerdict"}],"description":"The asset's last evaluated verdict; null when the asset has not been evaluated yet.","nullable":true},"region":{"nullable":true,"type":"string"}},"required":["asset_id","name","kind","account_id","region","class","recovery"],"type":"object"},"RecoveryVerdictCounts":{"properties":{"at_risk_by_reason":{"additionalProperties":{"type":"integer"},"type":"object"},"at_risk_count":{"description":"Subset of proven_count.","type":"integer"},"proven_count":{"type":"integer"},"proven_with_exceptions_count":{"description":"Subset of proven_count.","type":"integer"},"unproven_by_reason":{"additionalProperties":{"type":"integer"},"description":"Assets per reason. An asset with several reasons counts under each.","type":"object"},"unproven_count":{"type":"integer"}},"required":["proven_count","unproven_count","at_risk_count","proven_with_exceptions_count","unproven_by_reason","at_risk_by_reason"],"type":"object"},"RecoveryVerdictSummary":{"properties":{"by_class":{"additionalProperties":{"allOf":[{"$ref":"#/components/schemas/RecoveryVerdictCounts"},{"properties":{"asset_total":{"type":"integer"}},"type":"object"}]},"description":"Keys critical, important, standard, excluded. Each carries asset_total plus the counts.","type":"object"},"by_target_source":{"description":"Assets per effective-target arm.","properties":{"default":{"type":"integer"},"policy":{"type":"integer"},"program_class_floor":{"type":"integer"},"program_node":{"type":"integer"}},"type":"object"},"counts":{"$ref":"#/components/schemas/RecoveryVerdictCounts"},"estate_total":{"description":"Live assets, live AWS AMI families included, the same population as the `total` of GET /api/v2/assets.\n","type":"integer"},"evaluated_at":{"format":"date-time","type":"string"},"program_committed":{"type":"boolean"},"verdict_model":{"enum":["recovery_verdict_v1"],"type":"string"}},"required":["verdict_model","evaluated_at","program_committed","estate_total","counts","by_class","by_target_source"],"type":"object"},"RedStackInstallRegionParams":{"properties":{"region":{"description":"AWS region name (e.g. us-east-1)","type":"string"},"safety_lock":{"type":"boolean"},"subnet_ids":{"items":{"type":"string"},"type":"array"},"vpc_id":{"description":"Optional. If omitted, Elastio-defined VPC/subnets are used and `subnet_ids` must be empty.\nIf set, `subnet_ids` must list at least one subnet in that VPC.\n","type":"string"}},"required":["region","safety_lock"],"type":"object"},"RegionStack":{"properties":{"aws_region":{"type":"string"},"cloud_connector_id":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"id":{"type":"string"},"status":{"$ref":"#/components/schemas/RegionStackStatus"},"updated_at":{"format":"date-time","type":"string"},"version":{"type":"string"}},"required":["id","aws_region","cloud_connector_id","status","version","created_at","updated_at"],"type":"object"},"RegionStackStatus":{"properties":{"connector_job":{"$ref":"#/components/schemas/ConnectorJobId"},"error_message":{"type":"string"},"type":{"enum":["install_pending","install_failed","linked","deletion_pending","deletion_failed","unknown"],"type":"string"}},"required":["type"],"type":"object"},"RequestedVault":{"properties":{"cc_id":{"type":"string"},"vault_name":{"type":"string"}},"required":["vault_name","cc_id"],"type":"object"},"RequestedViolation":{"description":"One entry in a v3 create/update policy `violations` list: a violation code from the catalog dictionary and an optional per-policy severity override.","properties":{"code":{"description":"Violation code from the catalog dictionary. Matched exactly (lowercase snake_case); a code absent from the dictionary is rejected 400 `INVALID_VIOLATION_CODE`.","type":"string"},"severity_override":{"description":"Optional per-policy severity override. Accepted case-insensitively and stored lowercase; a value outside the enum is rejected 400 `INVALID_SEVERITY_OVERRIDE`. `info` is override-only: it may downgrade a violation below `low` (the base dictionary and `r_rpo.severity` stay four-valued). Omit to use the dictionary default.","enum":["critical","high","medium","low","info"],"type":"string"}},"required":["code"],"type":"object"},"RescanRedstackResponse":{"properties":{"aws_account":{"description":"AWS account the re-scanned region stack belongs to","type":"string"},"aws_region":{"description":"Region of the re-scanned stack","type":"string"},"job_id":{"description":"Scheduled re-scan job id","format":"uuid","type":"string"}},"required":["job_id","aws_account","aws_region"],"type":"object"},"ResilienceProgramBlock":{"description":"The active program version; null when none is committed. Carries the committed plan definition additively so an authoring client can rehydrate the active program instead of guessing.\n","nullable":true,"properties":{"active_version":{"type":"integer"},"committed_at":{"format":"date-time","type":"string"},"default_class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"inventory_source":{"enum":["tags","virtual","custom"],"type":"string"},"manual_overrides":{"additionalProperties":{"type":"string"},"description":"Commit-time per-asset class pins ({asset_id: tier}).","type":"object"},"node_assignments":{"description":"Leaf owner-scope + RPO frozen at commit. JSON null for versions committed before the column existed. Unlike spine, a null is not filled from the live table.\n","items":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignment"},"nullable":true,"type":"array"},"plan_id":{"type":"string"},"plan_mode":{"description":"Committed grouping switch. `tags` is the historical default (spine / tag-key tree). `account` selects the account-node exposure rollup on GET /estate/exposure. `custom` is reserved; exposure treats it as tags unless `grouping` overrides. Versions committed before the column existed are served as `tags`.\n","enum":["tags","account","custom"],"type":"string"},"rules":{"description":"The committed tag rules, in evaluation order.","items":{"properties":{"tag_key":{"type":"string"},"tag_values":{"items":{"type":"string"},"type":"array"},"tier":{"$ref":"#/components/schemas/ResilienceProgramTier"}},"type":"object"},"type":"array"},"signed_off_by":{"additionalProperties":true,"description":"Sign-off metadata stored verbatim at commit time.","nullable":true,"type":"object"},"spine":{"description":"The hierarchy this version was signed off against, frozen at commit (keys + level labels + root_name). JSON null when the version froze none and no live spine is configured. On snapshot read, a null stored spine is filled from the live configured spine so the board can label nodes without a re-commit.\n","nullable":true,"properties":{"keys":{"items":{"type":"string"},"type":"array"},"levels":{"items":{"properties":{"key":{"type":"string"},"label":{"type":"string"}},"type":"object"},"type":"array"},"node_names":{"additionalProperties":{"type":"string"},"type":"object"},"root_name":{"type":"string"}},"type":"object"},"tier_definitions":{"additionalProperties":true,"description":"Class floors this version was signed off against. The UI blob (`critical|important|standard` → `per_asset` / `relational`). Snapshot at-risk scoring reads only the three boolean durability keys (airgap_required, immutable_required, cross_region_required); extra keys are stored and ignored. JSON null (omitted commit field, or column not migrated) uses the default grid: Critical requires those three, Important and Standard do not. Unlike spine, a null is not filled from a live table. The recovery verdict also reads each class's `per_asset.rrpo_target_seconds` as its floor R-RPO (default 3600 / 86400 / 604800 for Critical / Important / Standard).\n","nullable":true,"type":"object"}},"type":"object"},"ResilienceProgramClassMetrics":{"description":"Invariant: provable + drift + at_risk + exceptions = promised. With `verdict_model` on the snapshot it also carries the RecoveryVerdictCounts fields, with proven_count + unproven_count = promised.\n","properties":{"at_risk":{"deprecated":true,"type":"integer"},"at_risk_by_reason":{"additionalProperties":{"type":"integer"},"description":"Recovery verdict. Assets per at-risk reason.","type":"object"},"at_risk_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"drift":{"deprecated":true,"type":"integer"},"exceptions":{"deprecated":true,"type":"integer"},"excluded":{"type":"integer"},"promised":{"type":"integer"},"provable":{"deprecated":true,"type":"integer"},"proven_count":{"description":"Recovery verdict; present only with `verdict_model`.","type":"integer"},"proven_with_exceptions_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"unproven_by_reason":{"additionalProperties":{"type":"integer"},"description":"Recovery verdict. Assets per unproven reason; an asset with several reasons counts under each.\n","type":"object"},"unproven_count":{"description":"Recovery verdict; present only with `verdict_model`. proven_count + unproven_count = promised.\n","type":"integer"}},"type":"object"},"ResilienceProgramClassifyEstate":{"description":"Per-class headline plus the per-spine-node rollup the Plan board's Business-exposure table renders. Present on every committed snapshot; omitted when no program is committed (the board's honest-empty gate). Sourced from the same classification GET /estate already serves. Follows the version-frozen spine, including its reserved `__account__` and `__account_group__` levels: the latter resolves each owner to its Account Group name (Ungrouped when in none), with the same node shape and owner seam GET /estate/exposure documents.\n","properties":{"byClass":{"additionalProperties":{"type":"integer"},"description":"Asset counts per class, including excluded.","type":"object"},"default_node":{"$ref":"#/components/schemas/ResilienceProgramClassifyEstateNode"},"defaultBucketCount":{"description":"Assets whose class came from default_class (not excluded).","type":"integer"},"defaultClass":{"$ref":"#/components/schemas/ResilienceProgramTier"},"excludedBreakdown":{"properties":{"by_override":{"type":"integer"},"by_rule":{"type":"integer"}},"type":"object"},"grouping_model":{"enum":["tags","custom","account","account_group"],"type":"string"},"nodes":{"description":"One row per populated spine path, at every depth. path[i] is the tag value of keys[i]. asset_ids is capped at 200; asset_count is the uncapped total. proven / drift / at_risk / exceptions / excluded are the snapshot buckets (proven is `provable` only); critical_at_risk is critical-class unproven. Parent nodes include descendants; the estate partition is default_node plus the depth-1 nodes. With `verdict_model` every node and default_node also carry the recovery verdict counts and the nodes sort by critical_unproven_count.\n","items":{"$ref":"#/components/schemas/ResilienceProgramClassifyEstateNode"},"type":"array"},"total":{"type":"integer"},"zeroTagCount":{"type":"integer"}},"type":"object"},"ResilienceProgramClassifyEstateNode":{"properties":{"account_ids":{"description":"Account-mode, account-group mode, and tag-mode nodes whose `key` is `__account_group__`. AWS account ids plus Azure subscription ids plus OVA account ids (UI seam so a tags-era client can still render owners). On an `__account_group__` node these are the group's RBAC members (Ungrouped: observed owners). Omitted on every other tag-mode node.\n","items":{"type":"string"},"type":"array"},"asset_count":{"description":"Uncapped size of this node. Equal to proven + drift + at_risk + exceptions + excluded.\n","type":"integer"},"asset_ids":{"items":{"type":"string"},"type":"array"},"at_risk":{"deprecated":true,"type":"integer"},"at_risk_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"critical_at_risk":{"deprecated":true,"type":"integer"},"critical_unproven_count":{"description":"Recovery verdict; critical-class unproven assets. A tag-mode `__account_group__` node with an authored class counts all its unproven assets when that class is critical, and 0 otherwise.\n","type":"integer"},"drift":{"deprecated":true,"type":"integer"},"exceptions":{"deprecated":true,"type":"integer"},"excluded":{"type":"integer"},"ibm_scopes":{"description":"Account-mode, account-group mode, and `__account_group__` tag-mode nodes. Dashless IBM resource-group ids. Omitted on every other tag-mode node.\n","items":{"type":"string"},"type":"array"},"is_default":{"type":"boolean"},"key":{"type":"string"},"name":{"type":"string"},"parent_path":{"type":"string"},"path":{"items":{"type":"string"},"type":"array"},"proven":{"deprecated":true,"type":"integer"},"proven_count":{"description":"Recovery verdict; present only when the verdict is served. asset_count = proven_count + unproven_count + excluded.\n","type":"integer"},"proven_with_exceptions_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"regions":{"description":"Account-mode and `__account_group__` tag-mode nodes. Union of AWS and Azure owner regions; on an `__account_group__` node these are the regions observed on the node's assets. Omitted on every other tag-mode node.\n","items":{"type":"string"},"type":"array"},"subscription_ids":{"description":"Account-mode, account-group mode, and `__account_group__` tag-mode nodes. Azure subscription ids, additive to account_ids. Omitted on every other tag-mode node.\n","items":{"type":"string"},"type":"array"},"unproven_count":{"description":"Recovery verdict; promised assets of the node not proven.","type":"integer"},"value":{"type":"string"}},"type":"object"},"ResilienceProgramCommitRequest":{"properties":{"cmi_snapshot":{"additionalProperties":true,"description":"Opaque client round-trip state; never interpreted.","type":"object"},"default_class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"inventory_source":{"enum":["tags","virtual","custom"],"type":"string"},"manual_overrides":{"additionalProperties":{"$ref":"#/components/schemas/ResilienceProgramTier"},"description":"assetId -> tier; outranks every rule.","type":"object"},"node_assignments":{"description":"Leaf assignments this sign-off is against. Absent or null → the service freezes the tenant's live GET /node-assignments so a client that never sends the field still records it. An explicit body is stored verbatim.\n","items":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignment"},"nullable":true,"type":"array"},"plan_id":{"type":"string"},"plan_mode":{"description":"Grouping switch frozen onto this version. Omit to store `tags` so existing commit bodies stay valid. `account` selects account-node exposure on GET /estate/exposure.\n","enum":["tags","account","custom"],"type":"string"},"policies":{"description":"One v3 policy create body per committed class scope (same shape as POST /shared-services/v3/policies). Each item is created if the name is new, or updated in place if that name is already plan-managed. AWS items must be `status: paused_until` with a `paused_until` timestamp in the future, and scope must include a `has_tags` criterion or a non-empty `account_region_selectors`; `exclude_tags` is still accepted as a filter. Selectors must not use `kind_tag: assets`. An AWS policy with neither include is 400 `POLICY_SCOPE_REQUIRED`. Azure/IBM items are cluster create bodies (`platform`, `name`, `cluster_name` or, for Azure, `subscription_ids`, `cluster_options.policy_yaml`) and must not send AWS `status` / `paused_until` / `selectors` (those keys 400 on cluster create). Cluster create lands enabled; pause is POST /v3/policies/{name}/pause, not a create field. `cluster_name` / `subscription_ids` and `policy_yaml` are enforced by the v3 create and update paths, not this commit pre-check; an Azure subscription no scan cluster serves is 400 `SUBSCRIPTION_UNRESOLVED`. Commit does require every `scan_policies` entry to set `disabled.until` in the future (the YAML equivalent of AWS `paused_until`); `disabled: true` or a past timestamp is 400. Each item must include a non-empty `alert_ids` array of UUIDs (400 `ALERT_REQUIRED` if omitted or empty; 400 `INVALID_ALERT_IDS` if malformed, nil, or duplicate). AWS bindings are accepted while the policy is paused_until; alerts stay silent until enable. On create the service overwrites `created_via_plan_id` with this commit's `plan_id`; update does not restamp provenance.\n","items":{"additionalProperties":true,"type":"object"},"minItems":1,"type":"array"},"rules":{"description":"Tag rules evaluated in array order; empty tag_values matches any value of the key. Reserved spine sentinels (`__account__`, `__account_group__`) are not tags and are 400; set class on node_assignments instead.\n","items":{"properties":{"tag_key":{"type":"string"},"tag_values":{"items":{"type":"string"},"type":"array"},"tier":{"$ref":"#/components/schemas/ResilienceProgramTier"}},"required":["tag_key","tier"],"type":"object"},"type":"array"},"signed_off_by":{"additionalProperties":true,"description":"signed_at defaults to the commit time when omitted.","type":"object"},"spine":{"additionalProperties":true,"description":"The hierarchy this sign-off is against. Absent or null → the service freezes the tenant's live configured spine so a client that never sends the field still records it.\n","type":"object"},"tier_definitions":{"additionalProperties":true,"description":"Class floors this sign-off is against. Absent or null stores NULL; scoring uses the default UI grid. Accepts the full UI object (hunt_types, rrpo_target_seconds, …); only the three boolean durability keys affect at-risk.\n","nullable":true,"type":"object"}},"required":["plan_id","policies"],"type":"object"},"ResilienceProgramCommitResponse":{"properties":{"policies":{"description":"The policies created or updated by this commit, each a v3 policy response (same shape as POST /shared-services/v3/policies). Always an array, never null.\n","items":{"additionalProperties":true,"type":"object"},"type":"array"},"program":{"$ref":"#/components/schemas/ResilienceProgramBlock"},"snapshot":{"$ref":"#/components/schemas/ResilienceProgramSnapshot"}},"type":"object"},"ResilienceProgramError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"type":"object"},"ResilienceProgramEstate":{"properties":{"as_of":{"format":"date-time","type":"string"},"assets":{"items":{"properties":{"account_group":{"description":"Value of the reserved `__account_group__` spine level: the name of the Account Group containing this asset's owner, resolved by the same index `GET /estate/exposure` groups with, including its overlap rule (name case-insensitively, then UUID; first match wins), so a client projecting these rows lands on the same nodes the server computes. `Ungrouped` when the owner is in no group. Null when the asset has no owner at all, mirroring `account_id`. Served on every page, not only when the saved spine carries the level, because the plan editor offers the level before any `PUT /spine`.\n","nullable":true,"type":"string"},"account_id":{"description":"Cloud owner identity used as the reserved `__account__` spine level: AWS account id, Azure subscription id, or IBM scope. Null when the asset has none. Not AWS-only.\n","nullable":true,"type":"string"},"asset_id":{"format":"uuid","type":"string"},"cc_asset_id":{"type":"string"},"class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"class_source":{"description":"Which precedence arm decided the class. `tag` is an Elastio built-in exclusion tag (`elastio:exclude`, `elastio:resource`, `elastio:nobackup`, `awsbackup-restore-test`, also spelled with `.` or `_`) present with any value except exactly \"false\"; `elastio:action=scan` does not override it.\n","enum":["override","manual","tag","rule","default"],"type":"string"},"in_policy":{"description":"An effective policy membership covers the asset.","type":"boolean"},"kind":{"type":"string"},"name":{"type":"string"},"recovery":{"allOf":[{"$ref":"#/components/schemas/AssetRecoveryVerdict"}],"description":"Recovery verdict; the key is present only when the verdict is served. The asset's last evaluated verdict, null when the live class is `excluded` (the Program does not evaluate an asset it excludes) or the asset has not been evaluated yet.\n","nullable":true},"region":{"nullable":true,"type":"string"},"tags":{"description":"The asset's raw tags: the only per-asset class binding. A key-only tag serves v as \"\".\n","items":{"properties":{"k":{"type":"string"},"v":{"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"type":"array"},"page":{"type":"integer"},"page_size":{"type":"integer"},"total":{"description":"The unpaged estate size.","type":"integer"}},"type":"object"},"ResilienceProgramEstateExposure":{"description":"Live Business-exposure rollup. In tag mode, totals is the disjoint spine partition (default_node + every depth-1 node) and foots to the snapshot hero. In account mode, totals is default_node plus every account-bearing node (also disjoint; not the depth-1 cut). In account_group mode, totals is Ungrouped (default_node) plus every Account Group node (disjoint; first-match on overlapping groups).\n","properties":{"as_of":{"format":"date-time","type":"string"},"default_node":{"$ref":"#/components/schemas/ResilienceProgramClassifyEstateNode"},"defaultClass":{"$ref":"#/components/schemas/ResilienceProgramTier"},"grouping_model":{"enum":["tags","custom","account","account_group"],"type":"string"},"nodes":{"description":"Tag mode: one row per populated spine path, at every depth. Account mode: one row per account-bearing live node assignment (including zero-count nodes). path is the full assignment path; name is slash-joined; key is `account`; class is the authored node class. Account-group mode: one row per tenant Account Group (including zero-count groups). name is the group name; key is `account_group`; value and path[0] are the group UUID; class is the max class of assets in the node. asset_ids is capped at 200; asset_count is uncapped.\n","items":{"$ref":"#/components/schemas/ResilienceProgramClassifyEstateNode"},"type":"array"},"spine":{"description":"Tag mode: the tenant's configured spine (GET /spine), not the version-frozen copy. JSON null when none is configured. Account mode and account_group mode: `{keys: [], levels: [], root_name}`; tag keys are not returned; root_name is kept from the live spine.\n","nullable":true,"properties":{"keys":{"items":{"type":"string"},"type":"array"},"levels":{"items":{"properties":{"key":{"type":"string"},"label":{"type":"string"}},"type":"object"},"type":"array"},"root_name":{"type":"string"}},"type":"object"},"totals":{"description":"Tag mode: default_node plus every depth-1 node. Account mode: default_node plus every (disjoint) account-bearing node. Account-group mode: Ungrouped plus every (disjoint) Account Group node. proven + drift + at_risk + exceptions = snapshot totals.promised; assets = promised + excluded. With the recovery verdict served it also carries the four verdict counts over the same partition, with assets = proven_count + unproven_count + excluded.\n","properties":{"assets":{"type":"integer"},"at_risk":{"deprecated":true,"type":"integer"},"at_risk_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"drift":{"deprecated":true,"type":"integer"},"exceptions":{"deprecated":true,"type":"integer"},"excluded":{"type":"integer"},"proven":{"deprecated":true,"type":"integer"},"proven_count":{"description":"Recovery verdict; present only when the verdict is served.","type":"integer"},"proven_with_exceptions_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"unproven_count":{"description":"Recovery verdict; present only when the verdict is served.","type":"integer"}},"type":"object"}},"type":"object"},"ResilienceProgramNodeAssignment":{"properties":{"account_region_selectors":{"items":{"properties":{"account_id":{"type":"string"},"region":{"type":"string"}},"required":["account_id","region"],"type":"object"},"type":"array"},"class":{"description":"Authored Resilience class of this node. Optional so today's editor does not 400; omitted or null stores NULL and GET /estate/exposure falls back to the program default_class. `excluded` is not a node class.\n","enum":["critical","important","standard"],"nullable":true,"type":"string"},"ibm_scopes":{"items":{"type":"string"},"type":"array"},"path":{"description":"Ordered tag values along the spine, same as classify_estate.nodes[].path. Empty is the Default bucket. At an `__account__` level the value is the owner id; at an `__account_group__` level it is the Account Group name (or `Ungrouped`).\n","items":{"type":"string"},"type":"array"},"rpo":{"description":"Same shape as v3 policy r_rpo; null means inherit / none.","nullable":true,"properties":{"severity":{"enum":["critical","high","medium","low"],"type":"string"},"target_seconds":{"minimum":1,"type":"integer"}},"required":["target_seconds","severity"],"type":"object"},"subscription_regions":{"items":{"properties":{"region":{"type":"string"},"subscription_id":{"type":"string"}},"required":["subscription_id","region"],"type":"object"},"type":"array"},"updated_at":{"format":"date-time","type":"string"},"updated_by":{"type":"string"}},"required":["path","account_region_selectors","subscription_regions","ibm_scopes"],"type":"object"},"ResilienceProgramNodeAssignments":{"properties":{"assignments":{"items":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignment"},"type":"array"}},"required":["assignments"],"type":"object"},"ResilienceProgramNodeAssignmentsUpdate":{"properties":{"assignments":{"items":{"$ref":"#/components/schemas/ResilienceProgramNodeAssignment"},"type":"array"}},"required":["assignments"],"type":"object"},"ResilienceProgramOverride":{"description":"One audited per-asset class pin. Precedence in the classification pass: an active override outranks the program's manual_overrides map, which outranks the tag rules, which outrank default_class.\n","properties":{"asset_id":{"format":"uuid","type":"string"},"asset_kind":{"description":"`unknown` when the asset row is gone.","type":"string"},"asset_name":{"description":"Falls back to the asset id when the asset row is gone.","type":"string"},"commitment_key":{"description":"kind=relax only: the waived commitment, from the fixed registry (rrpo_target_seconds, backup_freshness_seconds, immutable_required, airgap_required, cross_region_required, hunt_cadence, hunt_types, in_policy). Immutable once set: changing a waiver is a new waiver.\n","nullable":true,"type":"string"},"engine_class_at_set":{"allOf":[{"$ref":"#/components/schemas/ResilienceProgramTier"}],"description":"What the rules alone said about this asset when the override was written. Frozen. Null when no program version was committed then.\n","nullable":true},"engine_class_current":{"allOf":[{"$ref":"#/components/schemas/ResilienceProgramTier"}],"description":"What the rules alone say about this asset now: computed per read. Equal to override_class means the override is a no-op.\n","nullable":true},"expires_at":{"description":"An expired override stops classifying but keeps status `active`, so the UI can present it as expired rather than silently dropping it.\n","format":"date-time","nullable":true,"type":"string"},"kind":{"description":"`class` pins override_class; `relax` keeps the asset's class and waives commitment_key. Deployments without the relaxation migration serve `class` on every record.\n","enum":["class","relax"],"type":"string"},"override_class":{"allOf":[{"$ref":"#/components/schemas/ResilienceProgramTier"}],"description":"Served as \"\" on kind=relax records (they pin no class)."},"override_id":{"format":"uuid","type":"string"},"reason":{"description":"At least 10 characters; the server enforces it.","type":"string"},"reason_category":{"description":"Open vocabulary: decommission, exception_approved, third_party_managed, temporary, other.\n","nullable":true,"type":"string"},"relaxed_to":{"description":"kind=relax only: the weakened value in the commitment's own vocabulary; null means fully waived. Immutable once set.\n","nullable":true,"type":"string"},"set_at":{"format":"date-time","type":"string"},"set_by":{"description":"Actor email from X-User-Email; empty for M2M callers.","type":"string"},"status":{"enum":["active","removed"],"type":"string"},"version":{"description":"Bumped on every write; send it back as If-Match.","type":"integer"}},"type":"object"},"ResilienceProgramOverrideBatchDeleteFailedItem":{"properties":{"error":{"type":"string"},"override_id":{"type":"string"}},"required":["override_id","error"],"type":"object"},"ResilienceProgramOverrideBatchDeleteRequest":{"properties":{"override_ids":{"items":{"format":"uuid","type":"string"},"maxItems":200,"minItems":1,"type":"array"}},"required":["override_ids"],"type":"object"},"ResilienceProgramOverrideBatchDeleteResponse":{"properties":{"failed":{"items":{"$ref":"#/components/schemas/ResilienceProgramOverrideBatchDeleteFailedItem"},"type":"array"},"removed":{"items":{"format":"uuid","type":"string"},"type":"array"}},"required":["removed","failed"],"type":"object"},"ResilienceProgramOverrideCreateRequest":{"description":"kind defaults to `class`, which requires override_class and forbids the commitment fields: the pre-relaxation body stays valid verbatim. kind=relax requires commitment_key (from the fixed registry), forbids override_class, and is refused with 503 RELAXATIONS_NOT_READY on a deployment without the relaxation migration.\n","properties":{"asset_id":{"description":"Must be an asset of this tenant.","format":"uuid","type":"string"},"commitment_key":{"description":"Required for kind=relax; from the commitment registry.","nullable":true,"type":"string"},"expires_at":{"description":"Must be in the future when supplied.","format":"date-time","nullable":true,"type":"string"},"kind":{"description":"Defaults to `class`.","enum":["class","relax"],"type":"string"},"override_class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"reason":{"minLength":10,"type":"string"},"reason_category":{"nullable":true,"type":"string"},"relaxed_to":{"description":"Optional for kind=relax; null/absent means fully waived.","nullable":true,"type":"string"}},"required":["asset_id","reason"],"type":"object"},"ResilienceProgramOverrideHistory":{"properties":{"items":{"items":{"properties":{"actor":{"type":"string"},"after_state":{"additionalProperties":true,"nullable":true,"type":"object"},"before_state":{"additionalProperties":true,"nullable":true,"type":"object"},"event_id":{"format":"uuid","type":"string"},"event_type":{"enum":["created","class_changed","reason_changed","expiry_changed","removed"],"type":"string"},"occurred_at":{"format":"date-time","type":"string"},"override_id":{"format":"uuid","type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"ResilienceProgramOverrideList":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ResilienceProgramOverride"},"type":"array"},"page":{"type":"integer"},"page_size":{"type":"integer"},"total":{"description":"The unpaged count for the applied filters.","type":"integer"}},"type":"object"},"ResilienceProgramOverridePatchRequest":{"description":"Absent fields are left alone; at least one must be present. An explicit null for expires_at clears the expiry.\n","properties":{"expires_at":{"format":"date-time","nullable":true,"type":"string"},"override_class":{"$ref":"#/components/schemas/ResilienceProgramTier"},"reason":{"minLength":10,"type":"string"},"reason_category":{"nullable":true,"type":"string"}},"type":"object"},"ResilienceProgramOverrideSummary":{"properties":{"active_total":{"type":"integer"},"by_kind":{"description":"An `exclusion` takes the asset out of the program; an `inclusion` pins it to a class inside the program; a `relaxation` waives one commitment without moving the asset (0 before the relaxation migration).\n","properties":{"exclusion":{"type":"integer"},"inclusion":{"type":"integer"},"relaxation":{"type":"integer"}},"type":"object"},"by_override_class":{"additionalProperties":{"type":"integer"},"description":"Always carries all four class keys, zeros included.","type":"object"},"expired_by_kind":{"description":"The expired subset, split the same way as `by_kind`.","properties":{"exclusion":{"type":"integer"},"inclusion":{"type":"integer"},"relaxation":{"type":"integer"}},"type":"object"},"expired_total":{"description":"Active records whose `expires_at` has passed. They still list (the record and its audit trail outlive the expiry) but the classifier has stopped applying them, so a client showing what is IN FORCE subtracts these from the totals above.\n","type":"integer"},"expiring_in_30d":{"type":"integer"},"stale_asset_count":{"type":"integer"}},"type":"object"},"ResilienceProgramResetResponse":{"properties":{"assignments_cleared":{"description":"How many node-assignment rows were deleted.","type":"integer"},"deleted_version":{"description":"The program version that was deactivated, or null when the tenant had no active program.\n","nullable":true,"type":"integer"},"policies_deleted":{"description":"How many of the plan's managed policies were deleted. Matching is across the tenant's whole `plan_id` lineage, not just the active program's id, because `created_via_plan_id` is stamped at create time and `plan_id` changes on almost every commit: a policy from an earlier generation would otherwise survive the reset. A client cannot do this matching itself, since after the reset the older plan ids are unrecoverable.\n","type":"integer"},"policies_failed":{"description":"Managed policies that matched the plan lineage but could not be deleted. The reset itself still succeeded; these need a manual delete. Omitted when empty.\n","items":{"type":"string"},"type":"array"},"snapshot":{"$ref":"#/components/schemas/ResilienceProgramSnapshot"},"spine_cleared":{"description":"Whether a configured spine was deleted.","type":"boolean"}},"type":"object"},"ResilienceProgramSnapshot":{"properties":{"as_of":{"format":"date-time","type":"string"},"at_risk_breakdown":{"deprecated":true,"items":{"properties":{"asset_count":{"type":"integer"},"asset_ids":{"description":"Capped at 200 ids per entry.","items":{"type":"string"},"type":"array"},"class":{"type":"string"},"finding_kind":{"type":"string"}},"type":"object"},"type":"array"},"at_risk_reason_breakdown":{"description":"Present with `verdict_model`. One entry per (reason, class) over the promised proven assets that are at risk.\n","items":{"$ref":"#/components/schemas/RecoveryReasonBreakdownEntry"},"type":"array"},"by_class":{"properties":{"critical":{"$ref":"#/components/schemas/ResilienceProgramClassMetrics"},"important":{"$ref":"#/components/schemas/ResilienceProgramClassMetrics"},"standard":{"$ref":"#/components/schemas/ResilienceProgramClassMetrics"}},"type":"object"},"classify_estate":{"$ref":"#/components/schemas/ResilienceProgramClassifyEstate"},"drift_breakdown":{"deprecated":true,"items":{"properties":{"asset_count":{"type":"integer"},"asset_ids":{"description":"Capped at 200 ids per entry.","items":{"type":"string"},"type":"array"},"cause":{"type":"string"},"class":{"type":"string"},"commitment_key":{"type":"string"},"covering_policy_ids":{"items":{"type":"string"},"type":"array"}},"type":"object"},"type":"array"},"exception_breakdown":{"description":"Present with `verdict_model`. One entry per (commitment_key, class) over the promised assets proven with exceptions.\n","items":{"$ref":"#/components/schemas/RecoveryExceptionBreakdownEntry"},"type":"array"},"program":{"$ref":"#/components/schemas/ResilienceProgramBlock"},"totals":{"description":"With `verdict_model` it also carries the RecoveryVerdictCounts fields, with proven_count + unproven_count = promised.\n","properties":{"at_risk":{"deprecated":true,"type":"integer"},"at_risk_by_reason":{"additionalProperties":{"type":"integer"},"description":"Recovery verdict. Assets per at-risk reason.","type":"object"},"at_risk_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"blind_spot":{"deprecated":true,"description":"Always 0 in the default-bucket model.","type":"integer"},"drift":{"deprecated":true,"type":"integer"},"exceptions":{"deprecated":true,"description":"Assets whose every blocker is waived by an active commitment relaxation (kind=relax governance override). 0 on deployments without the relaxation migration.\n","type":"integer"},"excluded":{"type":"integer"},"excluded_baseline":{"description":"Excluded by commit-time pins, tag rules or the default class. excluded_baseline + excluded_override = excluded.\n","type":"integer"},"excluded_override":{"description":"Excluded by an active governance override pinning `excluded`.\n","type":"integer"},"promised":{"type":"integer"},"provable":{"deprecated":true,"type":"integer"},"proven_count":{"description":"Recovery verdict; present only with `verdict_model`.","type":"integer"},"proven_with_exceptions_count":{"description":"Recovery verdict; subset of proven_count.","type":"integer"},"unproven_by_reason":{"additionalProperties":{"type":"integer"},"description":"Recovery verdict. Assets per unproven reason; an asset with several reasons counts under each.\n","type":"object"},"unproven_count":{"description":"Recovery verdict; present only with `verdict_model`. proven_count + unproven_count = promised.\n","type":"integer"}},"type":"object"},"unproven_reason_breakdown":{"description":"Present with `verdict_model`. One entry per (reason, class) over the promised unproven assets; an asset with several reasons appears under each, so the counts do not sum to unproven_count.\n","items":{"$ref":"#/components/schemas/RecoveryReasonBreakdownEntry"},"type":"array"},"verdict_evaluated_at":{"description":"When the served verdicts were evaluated; present with `verdict_model`.","format":"date-time","type":"string"},"verdict_model":{"description":"Present only when the recovery verdict is served for this tenant. Read the verdict fields only when it is present.\n","enum":["recovery_verdict_v1"],"type":"string"}},"type":"object"},"ResilienceProgramSpine":{"properties":{"configured":{"description":"False when the tenant has never saved a spine. The client renders the unconfigured state rather than inventing a hierarchy.\n","type":"boolean"},"estate_asset_count":{"type":"integer"},"keys":{"description":"The ordered tag keys, top level first. This is what the projection consumes.","items":{"type":"string"},"type":"array"},"levels":{"description":"The same keys decorated with live coverage, for the editor.","items":{"$ref":"#/components/schemas/ResilienceProgramSpineLevel"},"type":"array"},"root_name":{"description":"Author-supplied label for the tree's Root row; empty falls back to the program name.","type":"string"},"updated_at":{"format":"date-time","type":"string"},"updated_by":{"type":"string"}},"required":["keys","levels","configured","estate_asset_count"],"type":"object"},"ResilienceProgramSpineLevel":{"properties":{"asset_count":{"description":"Assets carrying this key right now. Zero means the key has left the estate since it was configured - legal, and shown rather than hidden.\n","type":"integer"},"distinct_values":{"type":"integer"},"key":{"type":"string"},"label":{"description":"What the tree's TYPE column shows for this level, authored by the customer. The tag key grouped on is rarely the word they want on screen (group by `Customer`, read it as \"BU\"). Empty means the client falls back to the key.\n","type":"string"}},"required":["key","label","asset_count","distinct_values"],"type":"object"},"ResilienceProgramSpineRecommendation":{"properties":{"estate_asset_count":{"description":"Total assets on the estate; the denominator for every asset_count.","type":"integer"},"keys":{"description":"The proposed ordered tag keys, top level first. Empty when no discovered key is worth grouping on; the client then keeps the unconfigured state rather than being handed a hierarchy anyway.\n","items":{"type":"string"},"type":"array"},"levels":{"description":"The same proposed keys decorated with live coverage. `label` is seeded to the key itself: naming a level is the customer's call, not a guess the seed makes for them.\n","items":{"$ref":"#/components/schemas/ResilienceProgramSpineLevel"},"maxItems":3,"type":"array"},"rejected":{"description":"Every discovered key the proposal passed over and why, ordered by key. Served so the seed can be read as reasoning rather than as a bare answer.\n","items":{"$ref":"#/components/schemas/ResilienceProgramSpineRecommendationSkip"},"type":"array"},"top_level_asset_count":{"description":"How many assets the proposed top level actually reaches; the rest land in the Default bucket. This is what lets the editor price a proposal before it is committed. Zero when nothing is proposed.\n","type":"integer"}},"required":["keys","levels","rejected","estate_asset_count","top_level_asset_count"],"type":"object"},"ResilienceProgramSpineRecommendationSkip":{"properties":{"key":{"description":"The discovered tag key that was not proposed.","type":"string"},"reason":{"description":"Human-readable explanation, not a code, so new reasons can be added without a breaking change. Currently one of \"no assets carry this key\", \"values look like identifiers, so a level here would be one group per asset\", \"only one distinct value, so a level here would group nothing\", or \"beyond the proposed depth; add it manually if you want it\".\n","type":"string"}},"required":["key","reason"],"type":"object"},"ResilienceProgramSpineUpdate":{"properties":{"levels":{"description":"The ordered levels, top level first. Each `key` must appear in GET /tag-keys. Duplicate keys are refused. An empty array means \"no hierarchy\".\n","items":{"properties":{"key":{"description":"The discovered tag key this level groups on.","type":"string"},"label":{"description":"What to call this level in the tree's TYPE column. Omit to fall back to the key.\n","maxLength":60,"type":"string"}},"required":["key"],"type":"object"},"maxItems":6,"type":"array"},"root_name":{"description":"Label for the tree's Root row. Omit to leave unset.","type":"string"}},"required":["levels"],"type":"object"},"ResilienceProgramTagKey":{"properties":{"asset_count":{"description":"Assets carrying this key.","type":"integer"},"distinct_values":{"description":"Distinct values, i.e. how many child nodes this level would yield.","type":"integer"},"identifier_like":{"description":"True when the values are identities rather than categories (hostnames, ids, ARNs). A level on such a key yields roughly one child per asset, which is a tree in name only, so the editor de-emphasises these keys and the /spine/recommend seed never proposes one. The test is the classify-estate `looksLikeIdentifier` rule reused verbatim: more than 20 distinct values, or at least 3 values of which more than 70% contain a digit. The reserved `__account__` and `__account_group__` entries are always false: owner ids look like identifiers, but they are the grouping dimension the editor offers.\n","type":"boolean"},"key":{"description":"The tag key exactly as ingested, case included, or one of the reserved literals: `__account__` for the Account/Subscription spine level, `__account_group__` for the Account Group spine level (values are Account Group names).\n","type":"string"},"sample_values":{"description":"Up to five values, most-used first, so the key is recognisable in a dropdown.","items":{"type":"string"},"type":"array"}},"required":["key","asset_count","distinct_values","identifier_like","sample_values"],"type":"object"},"ResilienceProgramTagKeys":{"properties":{"estate_asset_count":{"description":"Total assets on the estate; the denominator for every asset_count.","type":"integer"},"keys":{"items":{"$ref":"#/components/schemas/ResilienceProgramTagKey"},"type":"array"}},"required":["keys","estate_asset_count"],"type":"object"},"ResilienceProgramTier":{"description":"Resilience class value set; `excluded` is the opt-out bucket.","enum":["critical","important","standard","excluded"],"type":"string"},"ResilienceProgramTimeseries":{"properties":{"program_versions":{"items":{"properties":{"active_from":{"format":"date-time","type":"string"},"active_until":{"format":"date-time","nullable":true,"type":"string"},"version":{"type":"integer"}},"type":"object"},"type":"array"},"range":{"properties":{"from":{"type":"string"},"granularity":{"enum":["day"],"type":"string"},"to":{"type":"string"}},"type":"object"},"series":{"description":"Always exactly three entries (critical, important, standard).","items":{"properties":{"class":{"type":"string"},"points":{"items":{"properties":{"at_risk":{"deprecated":true,"type":"integer"},"at_risk_count":{"description":"Recovery verdict; null on a row written before the model.","nullable":true,"type":"integer"},"drift":{"deprecated":true,"type":"integer"},"promised":{"type":"integer"},"provable":{"deprecated":true,"type":"integer"},"proven_count":{"description":"Recovery verdict; null on a row written before the model.","nullable":true,"type":"integer"},"proven_with_exceptions_count":{"description":"Recovery verdict; null on a row written before the model.","nullable":true,"type":"integer"},"ts":{"format":"date-time","type":"string"},"unproven_count":{"description":"Recovery verdict; null on a row written before the model.","nullable":true,"type":"integer"},"verdict_model":{"description":"Recovery verdict; the key is present only when the verdict is served. `recovery_verdict_v1`, or null on a row written before the model.\n","nullable":true,"type":"string"}},"type":"object"},"type":"array"}},"type":"object"},"type":"array"}},"type":"object"},"RevertRuleRequest":{"properties":{"to_version":{"type":"integer"}},"required":["to_version"],"type":"object"},"RevokePATRequestBody":{"properties":{"token_ids":{"items":{"format":"uuid","type":"string"},"minItems":1,"type":"array"}},"required":["token_ids"],"type":"object"},"RuleAuditEntry":{"properties":{"action":{"description":"Stable SCREAMING_SNAKE_CASE action (RULE_CREATE, RULE_IMPORT, RULE_EDIT, RULE_DELETE, RULE_REVERT, POLICY_ATTACH, POLICY_DETACH, SIGNATURE_ENABLE, SIGNATURE_DISABLE).","type":"string"},"actor":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"details":{"description":"Per-action payload (e.g. {policy_id}, {from_version, to_version}, {changed}).","type":"object"},"id":{"format":"uuid","type":"string"}},"required":["id","action","actor","details","created_at"],"type":"object"},"RuleSignature":{"description":"One parsed signature (parser-v0: one per YARA rule block). The signature_id is stable across versions so tuning survives re-parses.","properties":{"body_preview":{"description":"First 200 characters of the signature's rule block.","type":"string"},"enabled":{"type":"boolean"},"last_match_at":{"format":"date-time","nullable":true,"type":"string"},"match_count_30d":{"type":"integer"},"name":{"type":"string"},"primitive":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"signature_id":{"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"required":["signature_id","name","primitive","severity","tags","enabled","body_preview","match_count_30d"],"type":"object"},"RuleVersion":{"description":"One immutable content snapshot.","properties":{"change_summary":{"type":"string"},"created_at":{"format":"date-time","type":"string"},"created_by":{"description":"Gateway-signed X-User-Id of the author ('' for M2M callers).","type":"string"},"snapshot":{"description":"The full rule wire shape at this version (minus bindings/signatures).","type":"object"},"version":{"type":"integer"}},"required":["version","change_summary","created_by","snapshot","created_at"],"type":"object"},"RunPolicyResponse":{"properties":{"job_id":{"description":"Parent job for the dispatched run. The per-connector child jobs carry it as their parent_job_id, so polling this one covers the whole run.","type":"string"}},"required":["job_id"],"type":"object"},"S3ChangelogOptions":{"properties":{"max_change_event_age_seconds":{"format":"int64","minimum":0,"type":"integer"},"min_change_events":{"format":"int64","minimum":0,"type":"integer"}},"type":"object"},"ScanClusterMetadata":{"description":"Kind-specific registration metadata, flattened. The populated fields follow\n`cluster_kind`: azure → `tenant_id`, `subscription_id`, `region`;\nibm → `account_id`, `region`; on_prem → `stack_id`, `stack_name`, `stack_account`;\ngcp → `project_id`, `region`.\n","properties":{"account_id":{"description":"IBM Cloud account id (ibm clusters)","type":"string"},"project_id":{"description":"GCP project id (gcp clusters)","type":"string"},"region":{"description":"Cloud region the cluster runs in (azure, ibm and gcp clusters)","type":"string"},"stack_account":{"description":"On-prem stack account (on_prem clusters)","type":"string"},"stack_id":{"description":"On-prem stack id (on_prem clusters)","type":"string"},"stack_name":{"description":"On-prem stack name (on_prem clusters)","type":"string"},"subscription_id":{"description":"Azure subscription id (azure clusters)","type":"string"},"tenant_id":{"description":"Azure AD tenant id (azure clusters)","type":"string"}},"type":"object"},"ScanOnlyEc2OrEbsOptions":{"properties":{"keep_last_clean_copy":{"type":"boolean"},"keep_latest_infected_copy":{"type":"boolean"}},"required":["keep_last_clean_copy","keep_latest_infected_copy"],"type":"object"},"ScanOnlyEfsOptions":{"additionalProperties":false,"type":"object"},"ScanOnlyFsxOntapOptions":{"properties":{"scan_scope":{"enum":["All","Filesystem","Snapshots"],"type":"string"}},"required":["scan_scope"],"type":"object"},"ScanOnlyS3Options":{"properties":{"changelog":{"$ref":"#/components/schemas/S3ChangelogOptions"},"compressed_tarball":{"description":"If true, a compressed tarball (.tar.gz) scan trigger job is submitted for the matched S3 bucket. Ignored for other asset types.\nRejected at create/update when combined with any of the following, because the scheduler would otherwise silently drop or change-gate the job: threat_hunt=true; uploaded_after set; changelog set; TreeSelector key or glob selectors; more than one prefix or more than one regex per selector. A TreeSelector regex is only valid when compressed_tarball=true and must be a valid regular expression.","type":"boolean"},"threat_hunt":{"type":"boolean"},"uploaded_after":{"format":"date-time","nullable":true,"type":"string"}},"required":["threat_hunt"],"type":"object"},"ScheduleResponse":{"properties":{"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"frequency":{"$ref":"#/components/schemas/Frequency"},"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","tenant_name","name","frequency","description","created_at","updated_at"],"type":"object"},"ScopeGrant":{"properties":{"access":{"description":"Write implies read.","enum":["read","write"],"type":"string"},"category":{"description":"One of inventory, security, protection, reporting, integrations, admin.","type":"string"}},"required":["category","access"],"type":"object"},"ScopePreviewRequest":{"properties":{"account_region_selectors":{"description":"AWS only: account/region scope pairs.","items":{"properties":{"account_id":{"type":"string"},"region":{"type":"string"}},"required":["account_id","region"],"type":"object"},"type":"array"},"name":{"description":"Display name echoed back in the response (optional).","type":"string"},"platform":{"enum":["AWS","Azure","IBM"],"type":"string"},"policy_yaml":{"description":"Azure/IBM only; the cluster policy document (`scan_policies: {...}` YAML), as stored in `cluster_options`.","type":"string"},"selectors":{"description":"AWS only; plan selectors exactly as accepted by the v2 policies API (`{\"criteria\": [...]}` objects).","items":{"type":"object"},"type":"array"},"subscription_ids":{"description":"Azure only: the draft's typed scope. When present, `policy_yaml` is AND-ed with these subscriptions before matching, exactly as a stored subscription-scoped policy is, so the preview reports what the saved policy would cover.","items":{"format":"uuid","type":"string"},"type":"array"}},"required":["platform"],"type":"object"},"Score":{"properties":{"scale":{"type":"string"},"value":{"format":"double","type":"number"}},"required":["value","scale"],"type":"object"},"Selector":{"additionalProperties":false,"properties":{"criteria":{"items":{"$ref":"#/components/schemas/SelectorCriterion"},"minItems":1,"type":"array"}},"required":["criteria"],"type":"object"},"SelectorAwsAsset":{"additionalProperties":false,"properties":{"account_id":{"pattern":"^[0-9]{12}$","type":"string"},"asset_type":{"$ref":"#/components/schemas/SelectorAwsAssetType"},"region":{"minLength":1,"type":"string"}},"required":["asset_type"],"type":"object"},"SelectorAwsAssetType":{"oneOf":[{"$ref":"#/components/schemas/SelectorAwsAssetTypeEc2"},{"$ref":"#/components/schemas/SelectorAwsAssetTypeEbs"},{"$ref":"#/components/schemas/SelectorAwsAssetTypeS3"},{"$ref":"#/components/schemas/SelectorAwsAssetTypeEfs"},{"$ref":"#/components/schemas/SelectorAwsAssetTypeFsxOntapFilesystem"},{"$ref":"#/components/schemas/SelectorAwsAssetTypeFsxOntapVolume"},{"$ref":"#/components/schemas/SelectorAwsAssetTypeEc2Ami"}]},"SelectorAwsAssetTypeEbs":{"additionalProperties":false,"properties":{"ebs":{"minLength":1,"type":"string"}},"required":["ebs"],"type":"object"},"SelectorAwsAssetTypeEc2":{"additionalProperties":false,"properties":{"ec2":{"minLength":1,"type":"string"}},"required":["ec2"],"type":"object"},"SelectorAwsAssetTypeEc2Ami":{"additionalProperties":false,"description":"One machine image by id (pick mode). Same rollout\ngates as `is_type` `ec2_ami`.\n","properties":{"ec2_ami":{"pattern":"^ami-[0-9a-z]+$","type":"string"}},"required":["ec2_ami"],"type":"object"},"SelectorAwsAssetTypeEfs":{"additionalProperties":false,"properties":{"efs":{"minLength":1,"type":"string"}},"required":["efs"],"type":"object"},"SelectorAwsAssetTypeFsxOntapFilesystem":{"additionalProperties":false,"properties":{"fsx_ontap_filesystem":{"minLength":1,"type":"string"}},"required":["fsx_ontap_filesystem"],"type":"object"},"SelectorAwsAssetTypeFsxOntapVolume":{"additionalProperties":false,"properties":{"fsx_ontap_volume":{"minLength":1,"type":"string"}},"required":["fsx_ontap_volume"],"type":"object"},"SelectorAwsAssetTypeS3":{"additionalProperties":false,"properties":{"s3":{"minLength":1,"type":"string"}},"required":["s3"],"type":"object"},"SelectorAwsSubAsset":{"discriminator":{"mapping":{"efs_object":"#/components/schemas/SelectorAwsSubAssetEfsObject","s3_object":"#/components/schemas/SelectorAwsSubAssetS3Object"},"propertyName":"kind_tag"},"oneOf":[{"$ref":"#/components/schemas/SelectorAwsSubAssetS3Object"},{"$ref":"#/components/schemas/SelectorAwsSubAssetEfsObject"}]},"SelectorAwsSubAssetEfsObject":{"additionalProperties":false,"properties":{"kind_tag":{"enum":["efs_object"],"type":"string"},"tree":{"$ref":"#/components/schemas/SelectorEfsTreeSelector"}},"required":["kind_tag","tree"],"type":"object"},"SelectorAwsSubAssetS3Object":{"additionalProperties":false,"properties":{"kind_tag":{"enum":["s3_object"],"type":"string"},"tree":{"$ref":"#/components/schemas/SelectorS3TreeSelector"}},"required":["kind_tag","tree"],"type":"object"},"SelectorCriterion":{"discriminator":{"mapping":{"assets":"#/components/schemas/SelectorCriterionAssets","aws_sub_assets":"#/components/schemas/SelectorCriterionAwsSubAssets","exclude_tags":"#/components/schemas/SelectorCriterionExcludeTags","has_tags":"#/components/schemas/SelectorCriterionHasTags","is_type":"#/components/schemas/SelectorCriterionIsType"},"propertyName":"kind_tag"},"oneOf":[{"$ref":"#/components/schemas/SelectorCriterionIsType"},{"$ref":"#/components/schemas/SelectorCriterionHasTags"},{"$ref":"#/components/schemas/SelectorCriterionExcludeTags"},{"$ref":"#/components/schemas/SelectorCriterionAssets"},{"$ref":"#/components/schemas/SelectorCriterionAwsSubAssets"}]},"SelectorCriterionAssets":{"additionalProperties":false,"properties":{"aws_assets":{"items":{"$ref":"#/components/schemas/SelectorAwsAsset"},"minItems":1,"type":"array"},"kind_tag":{"enum":["assets"],"type":"string"}},"required":["kind_tag","aws_assets"],"type":"object"},"SelectorCriterionAwsSubAssets":{"additionalProperties":false,"properties":{"aws":{"items":{"$ref":"#/components/schemas/SelectorAwsSubAsset"},"minItems":1,"type":"array"},"kind_tag":{"enum":["aws_sub_assets"],"type":"string"}},"required":["kind_tag","aws"],"type":"object"},"SelectorCriterionExcludeTags":{"additionalProperties":false,"description":"Exclude criterion: if the asset matches any of the specified tags\n(OR), it is excluded. Exclude criteria are lifted above include\nselectors and take precedence. An empty string value means any value\nfor that tag key excludes the asset. Same `tags` map shape as has_tags.\n","properties":{"kind_tag":{"enum":["exclude_tags"],"type":"string"},"tags":{"additionalProperties":{"type":"string"},"minProperties":1,"type":"object"}},"required":["kind_tag","tags"],"type":"object"},"SelectorCriterionHasTags":{"additionalProperties":false,"description":"Include criterion: the asset must have all of the specified tags with\nmatching values (AND). An empty string value means the tag key must be\npresent regardless of its value.\n","properties":{"kind_tag":{"enum":["has_tags"],"type":"string"},"tags":{"additionalProperties":{"type":"string"},"minProperties":1,"type":"object"}},"required":["kind_tag","tags"],"type":"object"},"SelectorCriterionIsType":{"additionalProperties":false,"properties":{"asset_type":{"description":"`ec2_ami` selects every machine image (AMI) the policy's cloud\nconnectors can see. `ami` is an accepted alias;\nit is stored, and returned, as `ec2_ami`. Adding AMI selectors must be enabled for your tenant (otherwise refused with VALIDATION_ERROR) and needs Cloud Connector 0.43.42 or later (CONNECTOR_VERSION_TOO_LOW when version checks are enforced). AMIs are scanned,\nnever backed up, and each AMI is scanned once.\n","enum":["ec2","ebs","s3","efs","fsx_ontap_filesystem","fsx_ontap_volume","ec2_ami","ami"],"type":"string"},"kind_tag":{"enum":["is_type"],"type":"string"}},"required":["kind_tag","asset_type"],"type":"object"},"SelectorEfsTreeGlob":{"additionalProperties":false,"properties":{"glob":{"minLength":1,"type":"string"}},"required":["glob"],"type":"object"},"SelectorEfsTreePath":{"additionalProperties":false,"properties":{"path":{"minLength":1,"type":"string"}},"required":["path"],"type":"object"},"SelectorEfsTreeSelector":{"oneOf":[{"$ref":"#/components/schemas/SelectorEfsTreePath"},{"$ref":"#/components/schemas/SelectorEfsTreeGlob"}]},"SelectorS3TreeGlob":{"additionalProperties":false,"properties":{"glob":{"minLength":1,"type":"string"}},"required":["glob"],"type":"object"},"SelectorS3TreeKey":{"additionalProperties":false,"properties":{"key":{"minLength":1,"type":"string"}},"required":["key"],"type":"object"},"SelectorS3TreePrefix":{"additionalProperties":false,"properties":{"prefix":{"minLength":1,"type":"string"}},"required":["prefix"],"type":"object"},"SelectorS3TreeRegex":{"additionalProperties":false,"properties":{"regex":{"description":"Select objects with a key matching the given regular expression. Rust regex syntax is expected.","minLength":1,"type":"string"}},"required":["regex"],"type":"object"},"SelectorS3TreeSelector":{"oneOf":[{"$ref":"#/components/schemas/SelectorS3TreePrefix"},{"$ref":"#/components/schemas/SelectorS3TreeGlob"},{"$ref":"#/components/schemas/SelectorS3TreeKey"},{"$ref":"#/components/schemas/SelectorS3TreeRegex"}]},"ServerCatalog":{"properties":{"databases":{"items":{"$ref":"#/components/schemas/ServerDatabase"},"maxItems":256,"type":"array"},"error":{"type":"string"},"observed_at":{"format":"date-time","type":"string"}},"required":["databases","observed_at","error"],"type":"object"},"ServerDatabase":{"properties":{"accessible":{"type":"boolean"},"can_monitor":{"type":"boolean"},"can_scan":{"type":"boolean"},"name":{"type":"string"},"reason":{"type":"string"}},"required":["name","accessible","can_scan","can_monitor","reason"],"type":"object"},"ServerInventory":{"properties":{"available":{"type":"boolean"},"catalog":{"$ref":"#/components/schemas/ServerCatalog"},"primary_database":{"type":"string"},"primary_selected":{"description":"False pauses primary monitoring while deployment control and discovery stay connected","type":"boolean"},"requested":{"type":"boolean"},"targets":{"items":{"$ref":"#/components/schemas/ServerTarget"},"type":"array"}},"required":["available","requested","primary_database","catalog","targets"],"type":"object"},"ServerSelection":{"additionalProperties":false,"properties":{"databases":{"items":{"type":"string"},"maxItems":32,"type":"array","uniqueItems":true},"primary_selected":{"description":"Select or deselect the primary database; omitted preserves its current selection","type":"boolean"}},"required":["databases"],"type":"object"},"ServerTarget":{"properties":{"database":{"type":"string"},"id":{"type":"string"},"monitor":{"type":"boolean"},"name":{"type":"string"},"publication":{"type":"string"},"slot":{"type":"string"}},"required":["id","name","database","monitor","slot","publication"],"type":"object"},"SeverityCounts":{"properties":{"critical":{"format":"int64","type":"integer"},"high":{"format":"int64","type":"integer"},"low":{"format":"int64","type":"integer"},"medium":{"format":"int64","type":"integer"}},"required":["critical","high","medium","low"],"type":"object"},"Subject":{"properties":{"id":{"type":"string"},"kind":{"type":"string"},"label":{"type":"string"}},"required":["kind","id","label"],"type":"object"},"SubscriptionRegionsResponse":{"properties":{"subscription_regions":{"description":"Distinct Azure (subscription, region) pairs. Never null.","items":{"$ref":"#/components/schemas/AzureSubscriptionRegion"},"type":"array"}},"required":["subscription_regions"],"type":"object"},"SuppressThreatRequestBody":{"properties":{"reason":{"type":"string"},"until":{"format":"date-time","type":"string"}},"required":["until","reason"],"type":"object"},"SystemEventCatalogEntry":{"description":"One entry in the operational event vocabulary.","properties":{"available":{"description":"Whether the owning service actually emits this kind yet. A kind is published here as soon as its identity is agreed, but stays false until an emitter exists: subscribing to it before then would arm something that silently never fires, so the API refuses it and the UI greys the row out.","example":false,"type":"boolean"},"description":{"example":"A Hunt Job failed to complete.","type":"string"},"event_group":{"description":"Display grouping for the Tenant Settings card.","enum":["job_health","connector_account","tenant_audit","reports","usage_licensing"],"type":"string"},"event_kind":{"description":"Stable identifier. Matches the prototype's `elastio:...` names so the served and designed vocabularies cannot drift by transcription.","example":"elastio:asset:iscan:failed","type":"string"},"severity_default":{"description":"Five-valued, unlike the four-valued violation severity: most operational kinds are lifecycle records that `low` would misrepresent.","enum":["critical","high","medium","low","info"],"type":"string"}},"required":["event_kind","description","event_group","severity_default","available"],"type":"object"},"SystemEventCatalogResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/SystemEventCatalogEntry"},"type":"array"}},"required":["entries"],"type":"object"},"SystemEventsStandardError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"SystemPolicy":{"properties":{"alert_ids":{"items":{"format":"uuid","type":"string"},"type":"array"},"all_event_kinds":{"description":"Follows the whole catalog, so kinds added later are included.","type":"boolean"},"created_at":{"format":"date-time","type":"string"},"description":{"type":"string"},"event_kinds":{"items":{"type":"string"},"type":"array"},"event_severities":{"description":"Per-event severity overrides, sorted by event_kind. Only overridden kinds are listed; a kind with no entry routes at its catalog severity_default. Always present (`[]` when there are none).","items":{"$ref":"#/components/schemas/SystemPolicyEventSeverity"},"type":"array"},"id":{"format":"uuid","type":"string"},"is_seeded":{"description":"Created automatically for every tenant; cannot be deleted.","type":"boolean"},"name":{"type":"string"},"scope":{"$ref":"#/components/schemas/SystemPolicyScope"},"status":{"enum":["enabled","disabled"],"type":"string"},"type":{"description":"system_events governs the kinds in event_kinds (or every kind when all_event_kinds). unprotected_assets governs asset findings for assets no enabled protection policy covers.","enum":["system_events","unprotected_assets"],"type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","name","description","status","type","is_seeded","all_event_kinds","event_kinds","event_severities","scope","alert_ids","created_at","updated_at"],"type":"object"},"SystemPolicyError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"SystemPolicyEventSeverity":{"description":"Overrides the catalog severity_default of one event kind on this policy, the way an asset policy's `violations[].severity_override` overrides a violation's severity. Alerts bound to the policy match the event against `criteria.severities` at this severity.","properties":{"event_kind":{"description":"A kind from the system events catalog (400 `INVALID_SYSTEM_EVENT_KIND` otherwise). Unless the policy sets `all_event_kinds` it must also be one of the policy's `event_kinds`; with `all_event_kinds` any catalog kind may carry an override, including one not yet available. At most one entry per kind (400 `INVALID_EVENT_SEVERITY`).","type":"string"},"severity_override":{"$ref":"#/components/schemas/SystemPolicyEventSeverityValue"}},"required":["event_kind","severity_override"],"type":"object"},"SystemPolicyEventSeverityValue":{"description":"The five-valued system event severity, as the catalog's severity_default. Accepted case-insensitively and stored lowercase; any other value is 400 `INVALID_EVENT_SEVERITY`.","enum":["critical","high","medium","low","info"],"type":"string"},"SystemPolicyList":{"properties":{"system_policies":{"items":{"$ref":"#/components/schemas/SystemPolicy"},"type":"array"}},"required":["system_policies"],"type":"object"},"SystemPolicyScope":{"additionalProperties":false,"description":"Optional account/tag narrowing, in the alert criteria key names; null means tenant-wide. Within a cloud the entries are OR'd, across clouds any match is enough, and tags must also match. An event with no account (for example a user change) never matches an account-scoped policy. On write, values are trimmed, repeats dropped and empty keys omitted; a scope that narrows nothing is stored as null. A blank id, an unknown key or field, or a tag operator other than and/or is 400 `INVALID_SCOPE`.","nullable":true,"properties":{"aws_account_id_regions":{"items":{"additionalProperties":false,"properties":{"account_id":{"type":"string"},"region":{"description":"Empty matches every region of the account.","type":"string"}},"required":["account_id"],"type":"object"},"type":"array"},"azure_subscription_id_resource_groups":{"items":{"additionalProperties":false,"properties":{"resource_group":{"type":"string"},"subscription_id":{"type":"string"}},"required":["subscription_id"],"type":"object"},"type":"array"},"ibm_scopes":{"items":{"additionalProperties":false,"properties":{"scope":{"type":"string"}},"required":["scope"],"type":"object"},"type":"array"},"ova_account_id_providers":{"items":{"additionalProperties":false,"properties":{"account_id":{"type":"string"},"backup_provider":{"type":"string"}},"required":["account_id","backup_provider"],"type":"object"},"type":"array"},"tags":{"additionalProperties":false,"properties":{"operator":{"properties":{"kind_tag":{"enum":["and","or"],"type":"string"}},"required":["kind_tag"],"type":"object"},"tags":{"items":{"additionalProperties":false,"properties":{"key":{"type":"string"},"value":{"description":"Omitted matches any value of the key.","type":"string"}},"required":["key"],"type":"object"},"type":"array"}},"required":["tags","operator"],"type":"object"}},"type":"object"},"SystemPolicyUpdate":{"properties":{"alert_ids":{"items":{"format":"uuid","type":"string"},"minItems":1,"type":"array"},"all_event_kinds":{"type":"boolean"},"description":{"type":"string"},"event_kinds":{"items":{"type":"string"},"type":"array"},"event_severities":{"description":"Omitted keeps the stored overrides (less any for kinds a changed `event_kinds` no longer covers); a list replaces them; `[]` clears them. A non-empty list on the Unprotected Assets policy is 400 `BAD_REQUEST`.","items":{"$ref":"#/components/schemas/SystemPolicyEventSeverity"},"type":"array"},"name":{"type":"string"},"scope":{"$ref":"#/components/schemas/SystemPolicyScope"},"status":{"enum":["enabled","disabled"],"type":"string"}},"type":"object"},"TenantLicense":{"description":"One license on the tenant: the decoded, verified, non-secret claims. The raw key and the encrypted `secrets` blob are never served.","properties":{"added_at":{"description":"When this tenant added the license (not `iat`).","format":"date-time","type":"string"},"added_by":{"description":"Email (or id) of the user who added it; empty for a non-user caller.","type":"string"},"entitlements":{"additionalProperties":true,"description":"The key's `params` verbatim, opaque per product.","example":{"max_capacity":"100TB"},"type":"object"},"expires_at":{"description":"The key's signed `exp`; null means the license never expires.","format":"date-time","nullable":true,"type":"string"},"id":{"description":"Server-assigned; not derived from the key material.","format":"uuid","type":"string"},"issued_at":{"description":"The key's signed `iat`, null when the key has none.","format":"date-time","nullable":true,"type":"string"},"issued_to":{"description":"`config.tenant` from the key, when present.","nullable":true,"type":"string"},"product":{"description":"The raw product id from the key. Not user-visible by itself.","example":"elastio-iscan","type":"string"},"product_name":{"description":"Display name from the server's product catalog, null for a product this build does not know.","example":"Elastio Hunt","nullable":true,"type":"string"},"status":{"description":"Server-computed on one clock. `expiring_soon` is within 30 days of `exp`; `perpetual` is a key with no `exp`.","enum":["active","expiring_soon","expired","perpetual"],"type":"string"}},"required":["id","product","product_name","issued_to","issued_at","expires_at","status","entitlements","added_at","added_by"],"type":"object"},"TenantLicenseListResponse":{"properties":{"licenses":{"items":{"$ref":"#/components/schemas/TenantLicense"},"type":"array"}},"required":["licenses"],"type":"object"},"TenantSettingsForbiddenBody":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error"],"type":"object"},"TenantSettingsResponse":{"properties":{"backup_stale_threshold_seconds":{"maximum":7776000,"minimum":1,"type":"integer"},"entropy_detection_notifications":{"enum":["enabled","disabled"],"type":"string"},"excluded_tags":{"items":{"$ref":"#/components/schemas/ExcludedTag"},"type":"array"},"session_absolute_timeout_seconds":{"type":"integer"},"session_idle_timeout_seconds":{"type":"integer"}},"required":["entropy_detection_notifications","excluded_tags","session_idle_timeout_seconds","session_absolute_timeout_seconds","backup_stale_threshold_seconds"],"type":"object"},"TenantSettingsStandardError":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"TestedBackup":{"properties":{"backup":{"allOf":[{"$ref":"#/components/schemas/JobResult"}],"nullable":true},"inventory":{"allOf":[{"$ref":"#/components/schemas/JobResult"}],"nullable":true},"iscan":{"allOf":[{"$ref":"#/components/schemas/JobResult"}],"nullable":true},"restore":{"allOf":[{"$ref":"#/components/schemas/JobResult"}],"nullable":true},"verification":{"allOf":[{"$ref":"#/components/schemas/JobResult"}],"nullable":true}},"required":["iscan","backup","restore","verification","inventory"],"type":"object"},"ThreatCategory":{"description":"One open (asset, kind) row of GET /api/v2/assets/{asset_id}/threats: the asset and its live attached EBS volumes / Azure disks, each listed under its own id.\n","properties":{"breakdown":{"items":{"$ref":"#/components/schemas/BreakdownEntry"},"type":"array"},"category":{"enum":["ransomware","malware","encryption","filesystem_error","pursuit"],"type":"string"},"database_status":{"allOf":[{"$ref":"#/components/schemas/DatabaseStatus"}],"nullable":true},"files_affected":{"description":"The count from the latest analysis.","format":"int64","type":"integer"},"finding_id":{"description":"The v2 finding id, threat:{asset_id}:{kind}.","type":"string"},"first_detected":{"description":"The latest analysis that reported this finding.","type":"string"},"severity":{"type":"string"},"total_size_bytes":{"format":"int64","nullable":true,"type":"integer"}},"required":["category","severity","first_detected","files_affected","total_size_bytes","breakdown","database_status","finding_id"],"type":"object"},"ThreatErrorResponse":{"properties":{"code":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"TimeWindow":{"properties":{"from":{"$ref":"#/components/schemas/PlanTime"},"to":{"$ref":"#/components/schemas/PlanTime"}},"required":["from","to"],"type":"object"},"ToggleRuleSignatureRequest":{"properties":{"enabled":{"type":"boolean"}},"required":["enabled"],"type":"object"},"ToggleRuleSignatureResponse":{"properties":{"signature":{"$ref":"#/components/schemas/RuleSignature"}},"required":["signature"],"type":"object"},"TokenDetails":{"properties":{"all_scopes":{"type":"boolean"},"created_at":{"format":"date-time","type":"string"},"expires_at":{"description":"Unset means the token never expires.","format":"date-time","type":"string"},"grants":{"items":{"$ref":"#/components/schemas/ScopeGrant"},"type":"array"},"id":{"format":"uuid","type":"string"},"last_used_at":{"format":"date-time","type":"string"},"name":{"type":"string"},"tenant_id":{"format":"uuid","type":"string"},"updated_at":{"format":"date-time","type":"string"},"user_id":{"format":"uuid","type":"string"}},"required":["id","name","user_id","tenant_id","all_scopes","grants"],"type":"object"},"UpdateAIProviderCredentialBody":{"description":"At least one of name or credential is required.","properties":{"credential":{"$ref":"#/components/schemas/CredentialPayload"},"name":{"maxLength":255,"type":"string"}},"type":"object"},"UpdatePATRequestBody":{"properties":{"all_scopes":{"type":"boolean"},"expires_at":{"format":"date-time","type":"string"},"grants":{"items":{"$ref":"#/components/schemas/ScopeGrant"},"type":"array"},"name":{"type":"string"}},"type":"object"},"UpdatePolicyRequest":{"description":"Same XOR rule as CreatePolicyRequest: provide either `frequency` or `schedule_id`, never both.","properties":{"account_region_selectors":{"items":{"$ref":"#/components/schemas/AccountRegionSelector"},"type":"array"},"data_classification_scan_options":{"$ref":"#/components/schemas/DataClassificationScanOptions"},"description":{"description":"Human-readable description for the policy","type":"string"},"execute_immediately":{"deprecated":true,"description":"Removed. Sending true on an AWS create or update is rejected with 400 POLICY_EXECUTE_REMOVED before any side effect; absent or false is accepted and has no effect.","type":"boolean"},"frequency":{"$ref":"#/components/schemas/Frequency"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanRequest"},"mode":{"allOf":[{"$ref":"#/components/schemas/Mode"}],"example":{"ec2_or_ebs":{"keep_last_clean_copy":true,"keep_latest_infected_copy":false},"efs":{},"kind_tag":"scan_only","s3":{"threat_hunt":true}}},"paused_until":{"format":"date-time","nullable":true,"type":"string"},"platform":{"default":"AWS","description":"Target platform","enum":["AWS"],"type":"string"},"protect_new_immediately":{"enum":["disabled","enabled"],"type":"string"},"pursuit_scan_options":{"$ref":"#/components/schemas/PursuitScanOptions"},"schedule_id":{"description":"Reference to a row in the schedules API. Mutually exclusive with `frequency`.","format":"uuid","nullable":true,"type":"string"},"selectors":{"example":[{"criteria":[{"kind_tag":"has_tags","tags":{"env":"prod"}}]}],"items":{"$ref":"#/components/schemas/Selector"},"minItems":1,"type":"array"},"skip_ebs_backup":{"type":"boolean"},"snapshot_import":{"enum":["skip","latest","all"],"type":"string"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"tags":{"additionalProperties":{"nullable":true,"type":"string"},"type":"object"},"vaults":{"items":{"$ref":"#/components/schemas/RequestedVault"},"type":"array"}},"required":["selectors","mode"],"type":"object"},"UpdatePolicyV2Request":{"description":"Body for PUT /shared-services/v2/policies/{name}. Name comes from the path parameter, not the body. `platform` is required and immutable. For Azure/IBM only `platform`, `description`, `cluster_name`, `subscription_ids` (Azure only), and `cluster_options` are accepted (any other field present → 400). An Azure policy may change its `subscription_ids` freely; an IBM `cluster_name` is immutable.","properties":{"account_region_selectors":{"items":{"$ref":"#/components/schemas/AccountRegionSelector"},"type":"array"},"cluster_name":{"description":"Legacy single-cluster target. Required for IBM and immutable there: a value differing from the stored cluster returns 409. For Azure it is the legacy shape, mutually exclusive with `subscription_ids`. Must be omitted for AWS.","nullable":true,"type":"string"},"cluster_options":{"allOf":[{"$ref":"#/components/schemas/ClusterOptions"}],"description":"Cluster policy options for Azure/IBM (carries `policy_yaml`). Must be omitted for AWS.","nullable":true},"data_classification_scan_options":{"$ref":"#/components/schemas/DataClassificationScanOptions"},"description":{"description":"Human-readable description for the policy","type":"string"},"execute_immediately":{"deprecated":true,"description":"Removed. For AWS policies, sending true is rejected with 400 POLICY_EXECUTE_REMOVED before any side effect; absent or false is accepted and has no effect. For Azure and IBM policies the field must be omitted entirely - presence, even false, is rejected by the non-AWS field allowlist.","type":"boolean"},"frequency":{"$ref":"#/components/schemas/Frequency"},"integrity_check":{"enum":["disabled","file_system"],"type":"string"},"iscan":{"$ref":"#/components/schemas/IscanRequest"},"mode":{"$ref":"#/components/schemas/Mode"},"paused_until":{"format":"date-time","nullable":true,"type":"string"},"platform":{"description":"Target platform. Required on v2 and immutable. AWS uses the v1 policy fields; Azure and IBM use `cluster_options`.","enum":["AWS","Azure","IBM","GCP"],"type":"string"},"protect_new_immediately":{"enum":["disabled","enabled"],"type":"string"},"pursuit_scan_options":{"$ref":"#/components/schemas/PursuitScanOptions"},"schedule_id":{"description":"Reference to a row in the schedules API. Mutually exclusive with `frequency`.","format":"uuid","nullable":true,"type":"string"},"selectors":{"items":{"$ref":"#/components/schemas/Selector"},"minItems":1,"type":"array"},"skip_ebs_backup":{"type":"boolean"},"snapshot_import":{"enum":["skip","latest","all"],"type":"string"},"status":{"enum":["enabled","disabled","paused_until"],"type":"string"},"subscription_ids":{"description":"Azure only: the typed scope, replacing the stored set; every cluster targeted before or after the change is recomposed and republished. Mutually exclusive with `cluster_name`.","items":{"format":"uuid","type":"string"},"minItems":1,"nullable":true,"type":"array"},"tags":{"additionalProperties":{"nullable":true,"type":"string"},"type":"object"},"vaults":{"items":{"$ref":"#/components/schemas/RequestedVault"},"type":"array"}},"required":["platform"],"type":"object"},"UpdatePolicyV3Request":{"allOf":[{"$ref":"#/components/schemas/UpdatePolicyV2Request"},{"properties":{"alert_ids":{"description":"Alert UUIDs bound to the policy, using PRESENCE semantics (unlike `violations`/`r_rpo`): present fully replaces the bound set; OMITTING the key preserves the existing bindings. Each id must be a well-formed, non-nil UUID with no duplicates (400 `INVALID_ALERT_IDS`). When alert synchronization is enabled, an update may not leave an ENABLED policy with zero bound alerts: a present `[]`, or an omit when no bindings exist, is rejected 400 `ALERT_REQUIRED`. A paused/disabled policy may still change its alert set (ingestion binds on existence, not status).","items":{"format":"uuid","type":"string"},"type":"array"},"ccl_severity_overrides":{"description":"Explicit CCL severity overrides (full replacement). Omitting the field clears the selection to `[]`. A type omitted from a present list keeps the catalog default. When the policy selects a non-empty `ccl_types` list, every override type must be in that list.","items":{"$ref":"#/components/schemas/CCLSeverityOverride"},"type":"array"},"expected_policy_id":{"description":"Optional conditional-update guard; the recovery vehicle after a create that returned 500 `COMMIT_OUTCOME_UNKNOWN` with a `policy_id`: when present, the update applies only while the policy named in the path still has exactly this canonical id. Enforced before anything runs, inside each ingestion reconciliation immediately after id resolution, and authoritatively inside the mutate itself: a mismatch is rejected 409 `EXPECTED_POLICY_ID_MISMATCH` with the policy (and any same-name replacement) untouched, in the database and in ingestion. A malformed or nil UUID (and an explicit `null`, which is never treated as omitted) is rejected 400 `VALIDATION_ERROR`. Only OMITTING the field keeps the update unconditional (existing behavior, unchanged).","format":"uuid","type":"string"},"hunt_rule_ids":{"description":"Hunt-rule UUIDs bound to the policy, using PRESENCE semantics (same as `alert_ids`): present fully replaces the bound set; OMITTING the key preserves the existing bindings. Each id must be a well-formed, non-nil UUID with no duplicates, and must refer to a live hunt rule with status `active` (400 `INVALID_HUNT_RULE_IDS` for a malformed, duplicate, or unknown id; 400 `HUNT_RULE_NOT_ACTIVE` for a `tuning` or `inactive` rule: those are not egested and would never run). When present, `iscan.hunt` is derived automatically (non-empty set = true, empty = false). AWS scheduled policies only.","items":{"format":"uuid","type":"string"},"type":"array"},"r_rpo":{"allOf":[{"$ref":"#/components/schemas/RRPOTarget"}],"description":"Per-policy Recovery RPO target (full replacement). Omitting it (or sending null) clears it to null. Validated before anything persists: a non-positive `target_seconds` is rejected 400 `INVALID_RRPO_TARGET` and an out-of-enum `severity` 400 `INVALID_RRPO_SEVERITY`.","nullable":true},"violations":{"description":"Per-policy violation selection (full replacement). Each code is validated against the catalog dictionary; omitting it clears the policy's violations to `[]`. A repeated code is rejected 400 `DUPLICATE_VIOLATION_CODE`.","items":{"$ref":"#/components/schemas/RequestedViolation"},"type":"array"}},"type":"object"}],"description":"Body for PUT /shared-services/v3/policies/{name}. A strict superset of UpdatePolicyV2Request, adding the `violations` list and the `r_rpo` target. A v3 update fully replaces both: an omitted or empty `violations` clears it to `[]`, and an omitted (or null) `r_rpo` clears it to null (a v2 update never touches either)."},"UpdateScheduleRequest":{"description":"Partial update: omitted fields are preserved.","properties":{"description":{"description":"Optional human-readable description. Omit the field to leave an existing description unchanged on PATCH; explicit JSON null is treated the same as omission.","type":"string"},"frequency":{"$ref":"#/components/schemas/Frequency"},"name":{"type":"string"}},"type":"object"},"UpdateVaultJobResponse":{"properties":{"job_id":{"type":"string"}},"type":"object"},"UpdateVaultRequestBody":{"properties":{"description":{"type":"string"},"safety_lock":{"type":"boolean"},"subnet_ids":{"items":{"type":"string"},"type":"array"},"vpc_id":{"type":"string"}},"required":["safety_lock"],"type":"object"},"UpgradeAwsRegionStacksRequestBody":{"properties":{"regions":{"items":{"pattern":"^[a-z]{2}(-gov)?-[a-z]+-\\d$","type":"string"},"maxItems":64,"minItems":1,"type":"array"},"target_version":{"description":"The plan's `target_version`, as approved by the tenant","maxLength":64,"type":"string"}},"required":["regions","target_version"],"type":"object"},"UpgradeAwsRegionStacksResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/UpgradeJob"},"type":"array"}},"required":["jobs"],"type":"object"},"UpgradeJob":{"properties":{"job_id":{"format":"uuid","type":"string"},"red_stack_id":{"type":"string"},"region":{"type":"string"}},"required":["region","red_stack_id","job_id"],"type":"object"},"UpgradePlanRegion":{"properties":{"current_version":{"description":"Deployed region stack version; empty when none is recorded","type":"string"},"red_stack_id":{"type":"string"},"region":{"type":"string"},"status":{"description":"`upgradable`, or why the region cannot be upgraded here. `migration_checkpoint`\nmeans the path moves Terraform state and goes through Elastio support.\n`unknown` is a value this service does not recognize yet.\n","enum":["upgradable","up_to_date","self_managed","not_active","account_template_outdated","no_upgrade_path","migration_checkpoint","newer_than_target","unknown_version","unknown"],"type":"string"},"steps":{"description":"Versions applied in order, from a dry run of the migration planner","items":{"type":"string"},"type":"array"},"target_version":{"description":"Version the region would move to; empty unless `status` is `upgradable`","type":"string"}},"required":["red_stack_id","region","current_version","target_version","steps","status"],"type":"object"},"ValidatePolicyYAMLRequest":{"description":"Body for the:validate preflight; a full v2 non-AWS create payload: `platform`, `name`, `policy_yaml`, and a target; `cluster_name` (IBM, or a legacy Azure policy) or `subscription_ids` (Azure); are required and `description` is optional, exactly as on create.","properties":{"cluster_name":{"description":"Legacy single-cluster target. Required for IBM; for Azure mutually exclusive with `subscription_ids`.","type":"string"},"description":{"description":"Optional policy description (validated as on create).","nullable":true,"type":"string"},"name":{"description":"The intended policy name.","type":"string"},"platform":{"description":"Target platform. Accepted case-insensitively and canonicalized server-side; the canonical forms are advertised here. `AWS` is rejected (it carries no `policy_yaml`).","enum":["Azure","IBM","GCP"],"type":"string"},"policy_yaml":{"description":"The multicloud scan-policy document to validate.","type":"string"},"subscription_ids":{"description":"Azure only: the typed scope. Each subscription is resolved to its scan cluster; an unresolvable one is reported as a `SUBSCRIPTION_UNRESOLVED` issue at `/subscription_ids/N`, and each resolved cluster is checked as `cluster_name` would be.","items":{"format":"uuid","type":"string"},"minItems":1,"type":"array"}},"required":["platform","name","policy_yaml"],"type":"object"},"ValidatePolicyYAMLResponse":{"description":"Result of a:validate call. `valid` is true iff `issues` is empty.","properties":{"issues":{"description":"The deterministically-sorted, capped issue set. Always an array: `[]` when valid, never null.","items":{"$ref":"#/components/schemas/ValidationIssue"},"type":"array"},"valid":{"type":"boolean"}},"required":["valid","issues"],"type":"object"},"ValidationIssue":{"description":"A single structured policy_yaml validation finding. Emitted on the:validate response and (for a `POLICY_YAML_INVALID` rejection) in `ErrorResponse.issues`.","properties":{"code":{"description":"Stable machine code, e.g. `SCHEMA_VIOLATION`, `POLICY_UNKNOWN_KEY`, `YAML_DUPLICATE_KEY`, `CLUSTER_NOT_FOUND`, `SUBSCRIPTION_UNRESOLVED`, `ISSUES_TRUNCATED`.","type":"string"},"column":{"description":"Best-effort 1-based source column; omitted when unavailable.","type":"integer"},"line":{"description":"Best-effort 1-based source line; omitted when unavailable.","type":"integer"},"message":{"description":"Human-readable description of the problem.","type":"string"},"path":{"description":"RFC 6901 JSON Pointer to the offending location in the document (empty string for request-level/preflight issues).","type":"string"},"severity":{"description":"Issue severity. Always `error` at launch; `warning` is reserved for future advisory issues.","enum":["error","warning"],"type":"string"}},"required":["code","severity","message","path"],"type":"object"},"VaultErrorResponse":{"properties":{"code":{"type":"string"},"details":{"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"},"VaultListItem":{"description":"One vault in a list response (field names match the JSON payload).","properties":{"account_id":{"type":"string"},"assets_count":{"format":"int64","type":"integer"},"clean_recovery_points_count":{"format":"int64","type":"integer"},"compute_configuration":{"additionalProperties":true,"type":"object"},"contaminated_recovery_points_count":{"format":"int64","type":"integer"},"description":{"type":"string"},"id":{"description":"Elastio vault ID.","type":"string"},"is_default":{"type":"boolean"},"last_integrity_check_errors":{"items":{"properties":{"kind":{"enum":["INFRASTRUCTURE","VPC"],"type":"string"},"message":{"type":"string"}},"type":"object"},"type":"array"},"name":{"description":"Cloud Connector vault ID or name.","type":"string"},"recovery_points_count":{"format":"int64","type":"integer"},"red_stack_id":{"type":"string"},"reduction_factor":{"format":"double","type":"number"},"region":{"type":"string"},"safety_lock":{"type":"boolean"},"shards":{"description":"Shard entries","items":{"additionalProperties":true,"properties":{"shard_name":{"type":"string"}},"type":"object"},"type":"array"},"soft_deleted":{"type":"boolean"},"subnet_ids":{"items":{"type":"string"},"type":"array"},"total_optimized_size":{"format":"int64","type":"integer"},"total_recovery_point_size":{"format":"int64","type":"integer"},"version":{"type":"string"},"vpc_id":{"type":"string"}},"type":"object"},"VerificationDiagnostic":{"properties":{"level":{"enum":["error","warning"],"type":"string"},"line":{"type":"integer"},"msg":{"type":"string"},"primitive":{"type":"string"}},"required":["level","msg"],"type":"object"},"VerificationFailedError":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"properties":{"diagnostics":{"items":{"$ref":"#/components/schemas/VerificationDiagnostic"},"type":"array"}},"required":["diagnostics"],"type":"object"}],"description":"400 body for a hunt create/patch rejected by the YARA save-gate (`code` `VERIFICATION_FAILED`). Extends the standard error envelope with `diagnostics`."},"ViolationItem":{"properties":{"asset_id":{"description":"The asset the violation is on: this asset, or one of its live attached EBS volumes / Azure disks.\n","type":"string"},"asset_kind":{"type":"string"},"asset_name":{"type":"string"},"code":{"type":"string"},"detected_at":{"type":"string"},"finding_id":{"type":"string"},"severity":{"type":"string"},"title":{"description":"The defect label from the violation definition (e.g. \"Not backed up\"); the code when the definition has no title.\n","type":"string"}},"required":["code","title","severity","detected_at","finding_id","asset_id","asset_name","asset_kind"],"type":"object"},"Violations":{"description":"Open violations of the asset and its live attached EBS volumes / Azure disks, severity from the policy override where one applies.\n","properties":{"by_severity":{"$ref":"#/components/schemas/SeverityCounts"},"earliest_detected":{"nullable":true,"type":"string"},"items":{"items":{"$ref":"#/components/schemas/ViolationItem"},"type":"array"}},"required":["by_severity","earliest_detected","items"],"type":"object"},"Vpc":{"properties":{"has_public_subnets":{"type":"boolean"},"id":{"type":"string"},"is_default":{"type":"boolean"},"subnets":{"items":{"$ref":"#/components/schemas/VpcSubnet"},"type":"array"},"tags":{"items":{"$ref":"#/components/schemas/VpcTag"},"type":"array"}},"required":["id","is_default","tags","subnets","has_public_subnets"],"type":"object"},"VpcSubnet":{"properties":{"id":{"type":"string"},"is_public":{"type":"boolean"},"name":{"type":"string"}},"required":["id","name","is_public"],"type":"object"},"VpcTag":{"properties":{"key":{"type":"string"},"value":{"type":"string"}},"required":["key","value"],"type":"object"},"YaraRef":{"description":"One hunt→library YARA attachment. `id`+`kind`+`version` pin a `rule_versions` row; `path` is what SQL/egest use. `latest_version` is read-only library HEAD.","properties":{"id":{"format":"uuid","type":"string"},"kind":{"enum":["file","ruleset"],"type":"string"},"latest_version":{"description":"Library HEAD (`MAX(version)`); not accepted on write.","readOnly":true,"type":"integer"},"path":{"type":"string"},"version":{"type":"integer"}},"required":["id","kind","path","version"],"type":"object"},"YaraRefDeleteBlockedError":{"allOf":[{"$ref":"#/components/schemas/ErrorResponse1"},{"properties":{"blocking_hunt_rules":{"items":{"$ref":"#/components/schemas/HuntRulePolicyRef"},"type":"array"}},"type":"object"}],"description":"409 body for a YARA file or ruleset delete blocked by live hunt `yara_refs` pins (`DELETE_BLOCKED`). Extends the standard error envelope with `blocking_hunt_rules`. Do not add that field to shared ErrorResponse."},"YaraRuleCreateRequest":{"properties":{"body":{"description":"Raw YARA text; must contain at least one rule block.","type":"string"},"name":{"description":"Defaults to the first parsed rule identifier.","type":"string"},"severity":{"default":"medium","enum":["low","medium","high","critical"],"type":"string"},"source":{"description":"Path-segment source (default `custom`); minted into `yara/<source>/<slug>.yar`.","type":"string"},"source_file_name":{"type":"string"},"status":{"default":"active","enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"required":["body"],"type":"object"},"YaraRuleResponse":{"description":"One stored YARA rule (read-only v1). severity/tags are denormalized at import time; signature_count/last_match_at stay 0/null until the import + detection phases land.","properties":{"body":{"description":"The raw YARA rule text.","type":"string"},"created_at":{"format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"kind":{"enum":["file"],"type":"string"},"last_match_at":{"format":"date-time","nullable":true,"type":"string"},"name":{"type":"string"},"path":{"description":"Immutable library path (`yara/<source>/<slug>.yar`), minted at create.","type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"signature_count":{"type":"integer"},"signatures":{"description":"Present on the detail response only; the list stays lean.","items":{"$ref":"#/components/schemas/RuleSignature"},"type":"array"},"source":{"description":"Derived path segment (e.g. `custom`); not hunt's CUSTOM|ELASTIO|IMPORTED.","type":"string"},"source_file_name":{"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"version":{"description":"Current content version (1 for rules that predate versioning).","type":"integer"},"version_count":{"type":"integer"}},"required":["id","tenant_name","name","kind","path","source_file_name","severity","status","tags","body","signature_count","version","version_count","created_at","updated_at"],"type":"object"},"YaraRuleUpdateRequest":{"description":"PATCH: omitted preserves; a body change re-parses signatures and bumps the version.","properties":{"body":{"type":"string"},"change_summary":{"type":"string"},"name":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"type":"object"},"YaraRulesetCreateRequest":{"properties":{"files":{"items":{"$ref":"#/components/schemas/YaraRulesetFileInput"},"type":"array"},"name":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"source":{"type":"string"},"source_file_name":{"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"type":"object"},"YaraRulesetFile":{"properties":{"body":{"description":"Present in version snapshots only; omitted on GET list/detail.","type":"string"},"name":{"type":"string"},"signature_count":{"type":"integer"},"size":{"type":"integer"}},"required":["name","size","signature_count"],"type":"object"},"YaraRulesetFileInput":{"properties":{"content":{"type":"string"},"name":{"type":"string"}},"required":["name","content"],"type":"object"},"YaraRulesetMultipartRequest":{"properties":{"files":{"items":{"format":"binary","type":"string"},"type":"array"},"name":{"type":"string"},"severity":{"type":"string"},"source":{"type":"string"},"status":{"type":"string"},"tags":{"type":"string"}},"type":"object"},"YaraRulesetResponse":{"properties":{"created_at":{"format":"date-time","type":"string"},"file_count":{"type":"integer"},"files":{"description":"Detail only; metadata without body.","items":{"$ref":"#/components/schemas/YaraRulesetFile"},"type":"array"},"id":{"format":"uuid","type":"string"},"kind":{"enum":["ruleset"],"type":"string"},"last_match_at":{"format":"date-time","nullable":true,"type":"string"},"manifest_hash":{"type":"string"},"name":{"type":"string"},"path":{"description":"Immutable library path (`yara/<source>/<slug>/`), minted at create.","type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"signature_count":{"type":"integer"},"signatures":{"items":{"$ref":"#/components/schemas/RuleSignature"},"type":"array"},"source":{"type":"string"},"source_file_name":{"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"},"tenant_name":{"type":"string"},"updated_at":{"format":"date-time","type":"string"},"version":{"type":"integer"},"version_count":{"type":"integer"}},"required":["id","tenant_name","name","kind","path","source_file_name","severity","status","tags","file_count","signature_count","manifest_hash","version","version_count","created_at","updated_at"],"type":"object"},"YaraRulesetUpdateRequest":{"properties":{"change_summary":{"type":"string"},"files":{"items":{"$ref":"#/components/schemas/YaraRulesetFileInput"},"type":"array"},"name":{"type":"string"},"severity":{"enum":["low","medium","high","critical"],"type":"string"},"status":{"enum":["active","tuning","inactive"],"type":"string"},"tags":{"items":{"type":"string"},"type":"array"}},"type":"object"},"EQLDraftRequest":{"type":"object","properties":{"prompt":{"type":"string","minLength":1,"maxLength":4000},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"}},"required":["prompt","periodStart","periodEnd"],"additionalProperties":false},"EQLDraft":{"type":"object","properties":{"status":{"type":"string","enum":["ready","clarification"]},"query":{"type":"string"},"explanation":{"type":"string"},"clarification":{"type":"string"}},"required":["status","query","explanation","clarification"],"additionalProperties":false},"EQLRequest":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":8192},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"format":{"type":"string","enum":["json","pdf"]},"description":{"type":"string","maxLength":500}},"required":["query","periodStart","periodEnd"],"additionalProperties":false},"EQLDataset":{"type":"object","properties":{"name":{"type":"string"},"title":{"type":"string"},"columns":{"type":"array","items":{"type":"string"}},"shape":{"type":"string","enum":["array","object"]},"platform":{"type":"string"}},"required":["name","title","columns","shape","platform"]},"EQLCatalog":{"type":"object","properties":{"version":{"type":"string"},"aiAvailable":{"type":"boolean"},"pdfAvailable":{"type":"boolean"},"schedulesAvailable":{"type":"boolean"},"datasets":{"type":"array","items":{"$ref":"#/components/schemas/EQLDataset"}},"limits":{"type":"object","properties":{"maxRows":{"type":"integer"},"maxQueryBytes":{"type":"integer"},"maxResponseBytes":{"type":"integer"},"maxPeriodDays":{"type":"integer"}}}},"required":["version","aiAvailable","pdfAvailable","schedulesAvailable","datasets","limits"]},"EQLResult":{"type":"object","properties":{"version":{"type":"string"},"columns":{"type":"array","items":{"type":"string"}},"data":{},"rowCount":{"type":"integer"},"truncated":{"type":"boolean"}},"required":["version","columns","data","rowCount","truncated"]},"EQLReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","enum":["processing","ready","failed"]},"query":{"type":"string","minLength":1,"maxLength":8192},"format":{"type":"string","enum":["json","pdf"]},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"columns":{"type":"array","items":{"type":"string"}},"shape":{"type":"string"},"rowCount":{"type":"integer"},"data":{},"error":{"type":"string"}},"required":["id","title","status","query"]},"EQLReportPage":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/EQLReport"}},"total":{"type":"integer"},"page":{"type":"integer"},"pageSize":{"type":"integer"}},"required":["items","total","page","pageSize"]},"EQLError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"EQLSchedule":{"type":"object","required":["id","name","template","period","cadence","cadence_config","format","enabled","created_at","last_run_at","next_run_at","sync_status","query"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"template":{"type":"string","enum":["eql"]},"period":{"$ref":"#/components/schemas/SchedulePeriod"},"cadence":{"$ref":"#/components/schemas/ScheduleCadence"},"cadence_config":{"$ref":"#/components/schemas/ScheduleCadenceConfig"},"format":{"type":"string","enum":["json","pdf"]},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string","description":"Email of the creating user. The key is omitted when no user\nidentity accompanied the create request: never emitted as\n`null`.\n"},"last_run_at":{"type":"string","format":"date-time","nullable":true,"description":"Scheduled fire instant of the newest run that created a report\n(the report itself may still be generating); `null` before the\nfirst report-creating run.\n"},"next_run_at":{"type":"string","format":"date-time","nullable":true,"description":"Best-effort next fire time from the scheduler; `null` while the\nschedule is disabled or the projection is unavailable (the\nresponse stays 200 in every case).\n"},"sync_status":{"$ref":"#/components/schemas/ScheduleSyncStatus"},"query":{"type":"string","minLength":1,"maxLength":8192}}},"EQLScheduleRequest":{"type":"object","required":["name","template","query"],"additionalProperties":false,"description":"Optional keys may be omitted (server defaults apply) but must not\nbe explicitly `null`; `delivery.webhook_url` is the contract's only\nnullable property.\n","properties":{"name":{"type":"string","minLength":1,"description":"Trimmed server-side; blank after trim is rejected."},"template":{"type":"string","enum":["eql"]},"period":{"$ref":"#/components/schemas/SchedulePeriod"},"cadence":{"$ref":"#/components/schemas/ScheduleCadence"},"cadence_config":{"$ref":"#/components/schemas/ScheduleCadenceConfig"},"format":{"type":"string","enum":["json","pdf"]},"enabled":{"type":"boolean"},"query":{"type":"string","minLength":1,"maxLength":8192}}},"EQLSchedulePatch":{"type":"object","additionalProperties":false,"description":"Partial CreateScheduleRequest: the same keys, all optional. Present\nkeys are merged over the stored schedule and the merged document is\nrevalidated through the full create path.\n","properties":{"name":{"type":"string","minLength":1},"template":{"type":"string","enum":["eql"]},"period":{"$ref":"#/components/schemas/SchedulePeriod"},"cadence":{"$ref":"#/components/schemas/ScheduleCadence"},"cadence_config":{"$ref":"#/components/schemas/ScheduleCadenceConfig"},"format":{"type":"string","enum":["json","pdf"]},"enabled":{"type":"boolean"},"query":{"type":"string","minLength":1,"maxLength":8192}}},"EQLScheduleList":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/EQLSchedule"}},"total":{"type":"integer"}},"required":["items","total"]},"ErrorCode":{"type":"string","enum":["VALIDATION_ERROR","UNAUTHORIZED","FORBIDDEN","REPORT_NOT_FOUND","REPORT_NOT_READY","SCHEDULE_NOT_FOUND","INTERNAL_ERROR"]},"ApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string"}}}}},"Platform":{"type":"string","enum":["aws","azure","onprem"]},"Template":{"type":"string","description":"Report template slug.","enum":["completed-scans","failed-scans","infected-files","assets-scanned","infected-assets","ransomware-resilience"]},"ReportStatus":{"type":"string","enum":["processing","ready","failed"]},"ReportSummary":{"type":"object","required":["id","title","template","format","platform","periodStart","periodEnd","description","status","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string","description":"Auto-generated as `<TemplateTitle>_<YYYY-MM-DD>_<YYYY-MM-DD>`."},"template":{"$ref":"#/components/schemas/Template"},"format":{"type":"string","description":"Report payload format (e.g. `json`)."},"platform":{"$ref":"#/components/schemas/Platform"},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"description":{"type":"string","description":"Optional free-form description; empty string when not set."},"generatedAt":{"type":"string","format":"date-time","description":"Omitted until the report has been generated."},"status":{"$ref":"#/components/schemas/ReportStatus"},"createdAt":{"type":"string","format":"date-time"}}},"ReportListResponse":{"type":"object","required":["items","total","page","pageSize"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReportSummary"}},"total":{"type":"integer","description":"Total matching rows across all pages."},"page":{"type":"integer"},"pageSize":{"type":"integer"}}},"CreateReportRequest":{"type":"object","required":["template","platform","periodStart","periodEnd"],"properties":{"template":{"$ref":"#/components/schemas/Template"},"platform":{"$ref":"#/components/schemas/Platform"},"periodStart":{"type":"string","format":"date-time","description":"RFC 3339 timestamp; must be strictly before `periodEnd`."},"periodEnd":{"type":"string","format":"date-time","description":"RFC 3339 timestamp; must not be in the future."},"description":{"type":"string","maxLength":500,"description":"Optional. Trimmed of leading/trailing whitespace; empty after trimming is treated as omitted. Max 500 UTF-8 runes."}}},"CreateReportResponse":{"type":"object","required":["id","status","title","format","createdAt"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/ReportStatus"},"title":{"type":"string"},"format":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"ReportDetail":{"type":"object","required":["id","title","template","format","platform","periodStart","periodEnd","description","createdAt","status","data"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"template":{"$ref":"#/components/schemas/Template"},"format":{"type":"string"},"platform":{"$ref":"#/components/schemas/Platform"},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"description":{"type":"string","description":"Empty string when not set."},"createdAt":{"type":"string","format":"date-time"},"generatedAt":{"type":"string","format":"date-time","description":"Omitted until the report has been generated."},"status":{"$ref":"#/components/schemas/ReportStatus","description":"Always `ready` in this response shape."},"data":{"description":"Report payload. Shape varies by template/platform pair: most\ntemplates emit a JSON array (e.g. one row per scan), some emit\nan object. Treat as opaque and validate per template.\n","oneOf":[{"type":"object"},{"type":"array","items":{}}]}}},"ReportFailureError":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["REPORT_GENERATION_FAILED"],"description":"Report-generation error code. Distinct from the HTTP `ApiError`\nenvelope: it identifies why the report job failed, not why the\nHTTP request failed.\n"},"message":{"type":"string"}}},"ReportStatusResponse":{"type":"object","required":["id","status"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"$ref":"#/components/schemas/ReportStatus"},"error":{"$ref":"#/components/schemas/ReportFailureError","description":"Present only when `status` is `failed`."}}},"V2Platform":{"type":"string","description":"v2 platform sentinel. v2 reports are platform-agnostic, so the only\naccepted value is `all`.\n","enum":["all"]},"V2Template":{"type":"string","description":"Report template slug. `machine-image-supply-chain` is the Machine image report.","enum":["asset-hunt-coverage","failed-hunts","recovery-readiness","active-threats","completed-hunts","evidence-report","machine-image-supply-chain"]},"FailureCode":{"type":"string","description":"Derived failure-cause classification for `failed-hunts` rows. The\nfull set is 15 values: `NO_STATUS_MESSAGE` (null/empty status\nmessage) and `UNKNOWN` (no classifier matched) bracket the 13\nspecific-cause codes.\n","enum":["NO_STATUS_MESSAGE","CONTAINER_IMAGE_PULL_FAILED","CONTAINER_START_FAILED","SCAN_THRESHOLD_NOT_MET","MOUNT_ERROR","IO_ERROR","ACCESS_DENIED","ANTIMALWARE_ERROR","CONNECTOR_ERROR","AZURE_SDK_ERROR","RESTORE_FAILED","SERVICE_ERROR","INTEGRITY_SCAN_FAILED","JOB_UPDATE_FAILED","UNKNOWN"]},"HuntResult":{"type":"string","description":"Persisted hunt-result verdict (`completed-hunts` rows): the\n`catalog` scan status mapped `good` → `clean`, `bad` →\n`threat_found`.\n","enum":["clean","threat_found"]},"HuntType":{"type":"string","description":"Hunt (scan) type discriminator for `completed-hunts` rows.\n","enum":["malware_scan","ransomware_scan","fs_check","entropy_scan"]},"ThreatSeverity":{"type":"string","description":"Derived severity of an `active-threats` finding: a pinned convention\ncomputed from the threat kind (`ransomware` → `critical`; `malware`,\n`encryption`, `filesystem_error` → `high`), mirroring the UI V3\nthreats view. Not a platform-wide severity taxonomy: catalog records\nno per-finding severity.\n","enum":["critical","high"]},"ThreatKind":{"type":"string","description":"Threat kind discriminator for `active-threats` rows (the raw catalog\nthreat kind).\n","enum":["malware","ransomware","filesystem_error","encryption"]},"ImageHuntStatus":{"type":"string","description":"Hunt verdict of a machine image's current version\n(Machine image report rows): `threat` when any check found a\nthreat, `clean` when malware and ransomware are both clean or not\napplicable, `never` otherwise.\n","enum":["clean","threat","never"]},"ImageOverallStatus":{"type":"string","description":"Pursuit-led verdict of a machine image's newest live version\n(Machine image report rows). Pursuit is supported on AWS\nWindows images only (row `pursuit_supported`).\n\nPursuit supported: `compromised_early` when Pursuit rated it medium,\nhigh or critical; otherwise `compromised_late` when Hunt found\nevidence (a threat verdict or an active threat); otherwise `clean`\nwhen Pursuit assessed it (none or low); otherwise `not_analyzed`. An\nimage Pursuit never assessed is never `clean`.\n\nPursuit not supported (Linux, Azure, or OS unknown): `compromised_late`\nwhen Hunt found evidence; otherwise `at_risk` when Hunt verdict is\nclean (no early-stage coverage is possible); otherwise\n`not_analyzed`.\n","enum":["compromised_early","compromised_late","at_risk","clean","not_analyzed"]},"ReportFilters":{"type":"object","description":"Optional per-report row filters for a v2 report. Each key is a string\narray: values within one key combine as OR, separate keys combine as\nAND, and an omitted or empty key means \"no filter\" (all rows). Only\nthe keys valid for the chosen `template` are accepted; any other key\nis rejected with `400`. Applicability by template:\n - `account_ids`: asset-hunt-coverage, failed-hunts, recovery-readiness, active-threats, completed-hunts, machine-image-supply-chain\n - `regions`: asset-hunt-coverage, failed-hunts, active-threats, completed-hunts, machine-image-supply-chain\n - `asset_kinds`: asset-hunt-coverage, recovery-readiness, completed-hunts\n - `coverage_status`: asset-hunt-coverage\n - `failure_codes`: failed-hunts\n - `results`: completed-hunts\n - `hunt_types`: completed-hunts\n - `severities`: active-threats\n - `threat_kinds`: active-threats\n - `hunt_status`: machine-image-supply-chain\n - `overall_status`: machine-image-supply-chain\n`evidence-report` accepts no filters.\n","additionalProperties":false,"properties":{"account_ids":{"type":"array","items":{"type":"string"},"description":"Cloud account identifiers (e.g. AWS account id)."},"regions":{"type":"array","items":{"type":"string"},"description":"Cloud regions."},"asset_kinds":{"type":"array","items":{"type":"string"},"description":"Asset kind discriminators."},"coverage_status":{"type":"array","items":{"type":"string"},"description":"Hunt-coverage buckets. Known values: `covered`, `overdue`,\n`never_hunted`, `no_policy`. Not constrained server-side; an\nunknown value simply matches no rows.\n"},"failure_codes":{"type":"array","items":{"$ref":"#/components/schemas/FailureCode"},"description":"Derived failure-cause codes (`failed-hunts` only)."},"results":{"type":"array","items":{"$ref":"#/components/schemas/HuntResult"},"description":"Hunt-result verdicts (`completed-hunts` only)."},"hunt_types":{"type":"array","items":{"$ref":"#/components/schemas/HuntType"},"description":"Hunt types (`completed-hunts` only)."},"severities":{"type":"array","items":{"$ref":"#/components/schemas/ThreatSeverity"},"description":"Derived threat severities (`active-threats` only)."},"threat_kinds":{"type":"array","items":{"$ref":"#/components/schemas/ThreatKind"},"description":"Threat kinds (`active-threats` only)."},"hunt_status":{"type":"array","items":{"$ref":"#/components/schemas/ImageHuntStatus"},"description":"Image hunt verdicts (Machine image report only)."},"overall_status":{"type":"array","items":{"$ref":"#/components/schemas/ImageOverallStatus"},"description":"Pursuit-led image verdicts (Machine image report only)."}}},"CreateReportRequestV2":{"type":"object","description":"POST /reporting/v2/reports body. Mirrors the v1 create body, but\n`platform` is fixed to `all`, `template` is a v2 slug, and an optional\n`filters` object selects rows. No other fields are accepted.\n","required":["template","platform","periodStart","periodEnd"],"properties":{"template":{"$ref":"#/components/schemas/V2Template"},"platform":{"$ref":"#/components/schemas/V2Platform"},"periodStart":{"type":"string","format":"date-time","description":"RFC 3339 timestamp; must be strictly before `periodEnd`."},"periodEnd":{"type":"string","format":"date-time","description":"RFC 3339 timestamp; must not be in the future."},"description":{"type":"string","maxLength":500,"description":"Optional. Trimmed of leading/trailing whitespace; empty after trimming is treated as omitted. Max 500 UTF-8 runes."},"filters":{"$ref":"#/components/schemas/ReportFilters"}}},"ReportSummaryV2":{"type":"object","description":"v2 report list item. Like ReportSummary but platform-agnostic with a v2 template.","required":["id","title","template","format","platform","periodStart","periodEnd","description","status","createdAt","rowCount","filters","createdBy"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string","description":"Auto-generated as `<TemplateTitle>_<YYYY-MM-DD>_<YYYY-MM-DD>`."},"template":{"$ref":"#/components/schemas/V2Template"},"format":{"type":"string","description":"Report payload format; `json` for v2."},"platform":{"$ref":"#/components/schemas/V2Platform"},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"description":{"type":"string","description":"Optional free-form description; empty string when not set."},"generatedAt":{"type":"string","format":"date-time","description":"Omitted until the report has been generated."},"status":{"$ref":"#/components/schemas/ReportStatus"},"createdAt":{"type":"string","format":"date-time"},"rowCount":{"type":"integer","nullable":true,"description":"Number of rows in the generated report body. `null` until the\nreport is `ready`, and `null` on ready reports generated before\nthis field existed (no backfill).\n"},"filters":{"$ref":"#/components/schemas/ReportFilters"},"createdBy":{"type":"string","nullable":true,"description":"Email of the creating user, from the gateway's validated identity.\n`null` for reports created before this field was recorded or when\nno user identity accompanied the create request.\n"}}},"ReportListResponseV2":{"type":"object","required":["items","total","page","pageSize"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ReportSummaryV2"}},"total":{"type":"integer","description":"Total matching rows across all pages."},"page":{"type":"integer"},"pageSize":{"type":"integer"}}},"ReportDetailV2":{"type":"object","description":"Full v2 report payload. `data` is a JSON array of row objects, except for\n`evidence-report`, whose `data` is the board evidence report document.\n","required":["id","title","template","format","platform","periodStart","periodEnd","description","createdAt","status","data","rowCount","filters","createdBy","contentSha256"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"template":{"$ref":"#/components/schemas/V2Template"},"format":{"type":"string"},"platform":{"$ref":"#/components/schemas/V2Platform"},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"description":{"type":"string","description":"Empty string when not set."},"createdAt":{"type":"string","format":"date-time"},"generatedAt":{"type":"string","format":"date-time","description":"Omitted until the report has been generated."},"status":{"$ref":"#/components/schemas/ReportStatus","description":"Always `ready` in this response shape."},"data":{"oneOf":[{"type":"array","description":"Report rows: one object per row, keyed by the template's\ncolumn set.\n","items":{"type":"object"}},{"type":"object","description":"`evidence-report` only: the board evidence report document\n(summary, per-group rows, one detail row per program asset,\nburn-down, `report_content_sha256`).\n"}]},"rowCount":{"type":"integer","nullable":true,"description":"Number of rows in the generated report body. `null` on ready\nreports generated before this field existed (no backfill) and\nfor `evidence-report`, whose body is one document.\n"},"filters":{"$ref":"#/components/schemas/ReportFilters"},"createdBy":{"type":"string","nullable":true,"description":"Email of the creating user, from the gateway's validated identity.\n`null` for reports created before this field was recorded or when\nno user identity accompanied the create request.\n"},"contentSha256":{"type":"string","nullable":true,"description":"SHA-256 the document was generated with, over its canonical JSON\nwith `report_content_sha256` removed: object keys sorted by UTF-16\ncode units at every depth, no whitespace, strings and numbers\nserialized as ECMAScript `JSON.stringify` does (RFC 8785 style).\nSet for `evidence-report`; `null` for every other template.\n"}}},"SchedulePeriod":{"type":"string","description":"Rolling window preset for the generated report.","enum":["last_24_hours","last_7_days","last_30_days","last_90_days"]},"ScheduleCadence":{"type":"string","enum":["hourly","daily","weekly","monthly"]},"ScheduleFormat":{"type":"string","description":"Stored for future delivery/export only; generated reports remain\nJSON regardless of this value.\n","enum":["csv","jsonl"]},"ScheduleCadenceConfig":{"type":"object","description":"Exact shape per cadence: `{}` (hourly), `{time_utc}` (daily),\n`{day_of_week, time_utc}` (weekly), `{day_of_month, time_utc}`\n(monthly). Required keys must be present and unknown keys are\nrejected. `time_utc` accepts `HH:MM` or `HH:MM:00` (non-zero\nseconds rejected) and is canonicalized to `HH:MM`; the timezone is\nalways UTC.\n","additionalProperties":false,"properties":{"day_of_week":{"type":"string","enum":["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]},"day_of_month":{"type":"integer","minimum":1,"maximum":28,"description":"Capped at 28 (400 above) so monthly schedules never skip short\nmonths.\n"},"time_utc":{"type":"string","pattern":"^\\d{2}:\\d{2}(:00)?$"}}},"ScheduleDelivery":{"type":"object","description":"Validated and stored only: nothing sends email or calls webhooks\nuntil a delivery capability ships. Each recipient must be a bare,\nsyntactically valid email address; `webhook_url` must be an\n`https` URL (or null).\n","additionalProperties":false,"properties":{"email_recipients":{"type":"array","items":{"type":"string","format":"email"}},"webhook_url":{"type":"string","nullable":true}}},"ScheduleSyncStatus":{"type":"string","description":"Convergence state of the schedule onto the shared scheduler.\nResponse-only and additive to the UI contract.\n","enum":["pending","synced","error"]},"ScheduleWire":{"type":"object","required":["id","name","template","period","cadence","cadence_config","format","filters","delivery","enabled","created_at","last_run_at","next_run_at","sync_status"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"template":{"$ref":"#/components/schemas/V2Template"},"period":{"$ref":"#/components/schemas/SchedulePeriod"},"cadence":{"$ref":"#/components/schemas/ScheduleCadence"},"cadence_config":{"$ref":"#/components/schemas/ScheduleCadenceConfig"},"format":{"$ref":"#/components/schemas/ScheduleFormat"},"filters":{"$ref":"#/components/schemas/ReportFilters"},"delivery":{"$ref":"#/components/schemas/ScheduleDelivery"},"enabled":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"created_by":{"type":"string","description":"Email of the creating user. The key is omitted when no user\nidentity accompanied the create request: never emitted as\n`null`.\n"},"last_run_at":{"type":"string","format":"date-time","nullable":true,"description":"Scheduled fire instant of the newest run that created a report\n(the report itself may still be generating); `null` before the\nfirst report-creating run.\n"},"next_run_at":{"type":"string","format":"date-time","nullable":true,"description":"Best-effort next fire time from the scheduler; `null` while the\nschedule is disabled or the projection is unavailable (the\nresponse stays 200 in every case).\n"},"sync_status":{"$ref":"#/components/schemas/ScheduleSyncStatus"}}},"ScheduleListResponse":{"type":"object","required":["items","total"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ScheduleWire"}},"total":{"type":"integer"}}},"CreateScheduleRequest1":{"type":"object","required":["name","template"],"additionalProperties":false,"description":"Optional keys may be omitted (server defaults apply) but must not\nbe explicitly `null`; `delivery.webhook_url` is the contract's only\nnullable property.\n","properties":{"name":{"type":"string","minLength":1,"description":"Trimmed server-side; blank after trim is rejected."},"template":{"$ref":"#/components/schemas/V2Template"},"period":{"$ref":"#/components/schemas/SchedulePeriod"},"cadence":{"$ref":"#/components/schemas/ScheduleCadence"},"cadence_config":{"$ref":"#/components/schemas/ScheduleCadenceConfig"},"format":{"$ref":"#/components/schemas/ScheduleFormat"},"filters":{"$ref":"#/components/schemas/ReportFilters"},"delivery":{"$ref":"#/components/schemas/ScheduleDelivery"},"enabled":{"type":"boolean"}}},"UpdateScheduleRequest1":{"type":"object","additionalProperties":false,"description":"Partial CreateScheduleRequest: the same keys, all optional. Present\nkeys are merged over the stored schedule and the merged document is\nrevalidated through the full create path.\n","properties":{"name":{"type":"string","minLength":1},"template":{"$ref":"#/components/schemas/V2Template"},"period":{"$ref":"#/components/schemas/SchedulePeriod"},"cadence":{"$ref":"#/components/schemas/ScheduleCadence"},"cadence_config":{"$ref":"#/components/schemas/ScheduleCadenceConfig"},"format":{"$ref":"#/components/schemas/ScheduleFormat"},"filters":{"$ref":"#/components/schemas/ReportFilters"},"delivery":{"$ref":"#/components/schemas/ScheduleDelivery"},"enabled":{"type":"boolean"}}}},"securitySchemes":{"authorization":{"type":"http","scheme":"bearer","description":"A personal access token (PAT) sent as `Authorization: Bearer <token>`. Tenant admins issue tokens from the Elastio console or with `POST /gateway/shared-services/v1/personal-access-tokens`."},"bearerAuth":{"type":"http","scheme":"bearer","description":"Integration channel token issued by Elastio for inbound partner events (Wiz)."}},"responses":{"AIProviderBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderStandardError"}}},"description":"The body was refused. `code` is `INVALID_PROVIDER` when provider is not `openai`, `amazon_bedrock`, or `azure_foundry`. `BAD_REQUEST` covers a missing field, a credential object whose fields do not match the provider, a non-https Azure base URL, a non-UUID id, or a body that is not a JSON object."},"AIProviderConflictError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderStandardError"}}},"description":"This tenant already has a credential for that provider (`ALREADY_EXISTS`)"},"AIProviderForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderStandardError"}}},"description":"Caller is not a tenant admin"},"AIProviderInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderStandardError"}}},"description":"Internal server error"},"AIProviderNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderStandardError"}}},"description":"No credential with that id on this tenant (`NOT_FOUND`)"},"AIProviderUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AIProviderStandardError"}}},"description":"Missing Authority header, or the gateway request signature did not verify"},"BadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Bad request"},"ConflictError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Conflict"},"DatabaseMonitoringBadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringError"}}},"description":"The request is the caller's to fix; `error` says how"},"DatabaseMonitoringForbidden":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringError"}}},"description":"The caller is not an admin"},"DatabaseMonitoringNotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringError"}}},"description":"The tenant has no such row. A row belonging to another tenant answers the same."},"DatabaseMonitoringUnauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatabaseMonitoringError"}}},"description":"No tenant on the request"},"DeploymentsBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Invalid request parameters"},"DeploymentsForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Caller is not an admin (set `X-User-Role` to `admin`)"},"DeploymentsInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Internal server error"},"DeploymentsNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Resource not found"},"DeploymentsNotImplementedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"The backend does not serve this operation yet"},"DeploymentsPreconditionFailedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Request cannot be applied in the current resource state (e.g. regional stacks still exist)"},"DeploymentsServiceUnavailableError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"The operation could not run right now; nothing was changed"},"DeploymentsUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Missing Authority header"},"DeploymentsUpgradeNotAllowedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"The region cannot be upgraded as asked (the plan targets another version now, the\nregion is not upgradable, or the path migrates Terraform state and must go through\nElastio support). `error` says which, in words meant for the tenant.\n"},"EvidenceBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceErrorResponse"}}},"description":"asset_id is required"},"EvidenceInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceErrorResponse"}}},"description":"Internal server error"},"EvidenceNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvidenceErrorResponse"}}},"description":"Tenant has no such live asset (a deleted or terminated asset answers 404 too)"},"ForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Insufficient role: admin required"},"InternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Internal server error"},"LicensesBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesStandardError"}}},"description":"The key was refused. `code` is one of `INVALID_LICENSE_KEY` (not an Elastio license key: wrong segment count, bad envelope, bad JSON, unexpected header alg / typ, missing kid or product, or no `key` in the body), `UNSUPPORTED_LICENSE_VERSION` (a genuine license whose envelope version or payload `ver` is newer than this backend), `UNKNOWN_LICENSE_KEY_ID` (`kid` is not in this deployment's key registry), `INVALID_LICENSE_SIGNATURE` (decodes, but the PS256 signature does not verify: altered or forged), `LICENSE_EXPIRED` (verifies, but `exp` is already in the past), or `BAD_REQUEST` (the body is not a JSON object)."},"LicensesConflictError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesStandardError"}}},"description":"The same key is already live on this tenant (`LICENSE_ALREADY_ADDED`)"},"LicensesForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesStandardError"}}},"description":"Caller is not a tenant admin"},"LicensesInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesStandardError"}}},"description":"Internal server error"},"LicensesNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesStandardError"}}},"description":"No live license with that id on this tenant (`NOT_FOUND`)"},"LicensesUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesStandardError"}}},"description":"Missing Authority header, or the gateway request signature did not verify"},"NotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Not found"},"PATBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PATErrorResponse"}}},"description":"Invalid request."},"PATForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PATErrorResponse"}}},"description":"Caller is not a tenant admin."},"PATInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PATErrorResponse"}}},"description":"Internal server error."},"PATNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PATErrorResponse"}}},"description":"Token not found."},"PATUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PATErrorResponse"}}},"description":"Missing or invalid authentication."},"PreconditionFailedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Precondition failed"},"RecoveryVerdictNotServedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"The recovery verdict is not served for this tenant: the `recovery-verdict` switch is off, no evaluation has completed yet, or the last one is older than four evaluation intervals. The client behaves exactly as before the verdict existed.\n"},"ResilienceProgramBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"Invalid parameters or body"},"ResilienceProgramConflictError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"The asset already has an active override"},"ResilienceProgramFamilyNotReadyError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"This deployment does not serve governance overrides yet: the service is running ahead of its migration, or the migration was rolled back under it. Distinct from a 500: nothing is broken, the store is not there. The program snapshot keeps working throughout.\n"},"ResilienceProgramForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"Admin role required"},"ResilienceProgramInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"Internal error"},"ResilienceProgramNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"No such override, or no such asset in this tenant"},"ResilienceProgramStaleVersionError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"The override changed since the client read it (If-Match mismatch)"},"ResilienceProgramUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResilienceProgramError"}}},"description":"Missing Authority header"},"SystemEventsInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemEventsStandardError"}}},"description":"Internal server error"},"SystemEventsSubscriptionsRetired":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemEventsStandardError"}}},"description":"`SUBSCRIPTIONS_RETIRED`: attach alerts to a System Policy (/shared-services/v3/system-policies) instead."},"SystemEventsUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemEventsStandardError"}}},"description":"Missing Authority header"},"SystemPolicyAlertSyncUnavailable":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyError"}}},"description":"Alerts could not be attached (ALERT_SYNC_UNAVAILABLE); retry."},"SystemPolicyBadRequest":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyError"}}},"description":"Invalid request: BAD_REQUEST (including any event severity override on the Unprotected Assets policy), ALERT_REQUIRED, INVALID_SYSTEM_EVENT_KIND (an unknown kind in event_kinds or event_severities, an unavailable kind in event_kinds, or an override for a kind the policy does not cover), INVALID_EVENT_SEVERITY (an unknown severity_override, or a kind listed twice in event_severities), INVALID_SCOPE or INVALID_ALERT_IDS."},"SystemPolicyConflict":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyError"}}},"description":"DUPLICATE_NAME, SEEDED_POLICY or ALERT_MIGRATION_IN_PROGRESS."},"SystemPolicyInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyError"}}},"description":"Internal error (INTERNAL_ERROR)."},"SystemPolicyNotFound":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyError"}}},"description":"No system policy with this id for the tenant (NOT_FOUND)."},"SystemPolicyUnauthorized":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemPolicyError"}}},"description":"Missing or invalid tenant authority."},"TenantSettingsBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantSettingsStandardError"}}},"description":"Invalid body or validation failure"},"TenantSettingsForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantSettingsForbiddenBody"}}},"description":"Caller is not a tenant admin"},"TenantSettingsInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantSettingsStandardError"}}},"description":"Internal server error"},"TenantSettingsUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantSettingsStandardError"}}},"description":"Missing Authority header"},"ThreatsBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatErrorResponse"}}},"description":"Invalid request."},"ThreatsForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatErrorResponse"}}},"description":"Caller is not a tenant admin."},"ThreatsInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatErrorResponse"}}},"description":"Internal server error."},"ThreatsUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreatErrorResponse"}}},"description":"Missing or invalid authentication."},"UnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse1"}}},"description":"Missing Authority header"},"VaultBadRequestError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"The request was invalid or incomplete."},"VaultConflictError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"The request conflicts with the current state (for example, a duplicate name)."},"VaultForbiddenError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"You are not allowed to perform this action."},"VaultInternalError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"Something went wrong on the server; try again later."},"VaultNotFoundError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"The requested vault or related resource was not found."},"VaultPreconditionFailedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"The vault is not in a state that allows this operation."},"VaultUnauthorizedError":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VaultErrorResponse"}}},"description":"Authentication or tenant context is missing or invalid."},"EQL400":{"description":"Invalid EQL request or query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"EQL401":{"description":"Missing tenant identity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"EQL403":{"description":"EQL feature disabled or caller not authorized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"EQL404":{"description":"EQL report or schedule not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"EQL429":{"description":"EQL admission or queue budget exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"EQL500":{"description":"EQL service unavailable or operation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EQLError"}}}},"ValidationError":{"description":"Request validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"Unauthorized":{"description":"Missing or empty `Authority` header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"Forbidden":{"description":"Caller is not `admin`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"NotFound":{"description":"Report not found or already deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"ScheduleNotFound":{"description":"Schedule not found: unknown id, another tenant's schedule, or\nalready deleted (all indistinguishable by design).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"ScheduleCapExceeded":{"description":"The tenant already holds the maximum number of live schedules;\ndelete one before creating another.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"NotReady":{"description":"Report exists but is not in `ready` status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"InternalError1":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"parameters":{"AdminRole":{"description":"Must be `admin` for this endpoint.","in":"header","name":"X-User-Role","required":true,"schema":{"type":"string"}},"CredentialID":{"in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},"DatabaseMonitoringDatabaseID":{"in":"path","name":"database_id","required":true,"schema":{"format":"uuid","type":"string"}},"DatabaseMonitoringIncidentID":{"in":"path","name":"incident_id","required":true,"schema":{"format":"uuid","type":"string"}},"DatabaseMonitoringPageSize":{"in":"query","name":"page_size","schema":{"default":50,"maximum":200,"minimum":1,"type":"integer"}},"DatabaseMonitoringPageToken":{"description":"The opaque cursor from the previous page","in":"query","name":"next_page_token","schema":{"type":"string"}},"DatabaseMonitoringRelation":{"description":"schema.table, lower-case","in":"path","name":"relation","required":true,"schema":{"pattern":"^[a-z_][a-z0-9_]{0,62}\\.[a-z_][a-z0-9_]{0,62}$","type":"string"}},"DeletionID":{"description":"The deletion record id.","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},"Limit":{"description":"Maximum number of tokens to return.","in":"query","name":"limit","schema":{"format":"int64","minimum":0,"type":"integer"}},"MembershipPageLimit":{"description":"Page size (1..1000, default 100)","in":"query","name":"limit","schema":{"default":100,"maximum":1000,"minimum":1,"type":"integer"}},"MembershipPageOffset":{"description":"Page offset (default 0)","in":"query","name":"offset","schema":{"default":0,"minimum":0,"type":"integer"}},"MembershipPolicyName":{"description":"Policy name (URL-encoded)","in":"path","name":"name","required":true,"schema":{"type":"string"}},"Offset":{"description":"Number of tokens to skip.","in":"query","name":"offset","schema":{"format":"int64","minimum":0,"type":"integer"}},"PolicyName":{"in":"path","name":"name","required":true,"schema":{"type":"string"}},"ScheduleID":{"description":"Schedule UUID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}},"UserRoleAdmin":{"description":"Must be `admin` for these endpoints.","in":"header","name":"X-User-Role","required":true,"schema":{"enum":["admin"],"type":"string"}},"ReportId":{"name":"id","in":"path","required":true,"description":"Report UUID.","schema":{"type":"string","format":"uuid"}},"ScheduleId":{"name":"id","in":"path","required":true,"description":"Schedule UUID.","schema":{"type":"string","format":"uuid"}},"XUserRoleAdmin":{"name":"X-User-Role","in":"header","required":false,"description":"Gateway-injected RBAC context. This operation requires `admin`;\nany other value (including `viewer`, missing, or empty) responds\n`403 FORBIDDEN`.\n","schema":{"type":"string","enum":["admin","viewer"]}}}},"x-tagGroups":[{"name":"Platform","tags":["System","Tenant Settings","Licenses","Plan","Billing","Early Access","AI Provider Credentials"]},{"name":"Identity & Access","tags":["Users","User Groups","Roles","Account Groups","Personal Access Tokens","Audit Logs"]},{"name":"Inventory & Deployments","tags":["Deployments","Assets","Search","Inventory","Asset Accounts","Tags","Azure Subscriptions","GCP Projects","IBM","OVA Accounts","Vault","Database Monitoring","Data"]},{"name":"Backups & Recovery Points","tags":["Backup"]},{"name":"Hunts & Investigations","tags":["Scans","Scan Jobs","Hunt Rules","Custom Hunts","Pursuit","Pursuit Scans","Threats","Ransomware","Data Classification"]},{"name":"Findings & Response","tags":["Incidents","Findings","Violations","Issues","Posture","Compliance","DRS"]},{"name":"Policies & Jobs","tags":["Policies","Policy Schedules","Policy Membership","System Policies","System Events","Jobs"]},{"name":"Recovery & Evidence","tags":["Resilience Program","Recovery Verdict","Recovery Analytics","Evidence","Security Metrics"]},{"name":"Reporting","tags":["Reports","Report Schedules","EQL"]},{"name":"Alerts & Integrations","tags":["Alerts","Webhooks","Slack","Splunk","VirusTotal","Wiz","GuardDuty"]}],"externalDocs":{"description":"Elastio Developer Portal","url":"https://developer.elastio.com"}}