Compliance Reports
Read compliance reports per standard and target, drill into failing controls, export snapshots, view score history, and read namespace-level compliance.
All paths are relative to /policies/api/v1. See Policies API v1 for authentication and conventions.
Endpoints
| Operation | Method | Path |
|---|---|---|
| Get compliance score or control history | GET | /compliance/kyverno/history |
| Get namespace compliance settings | GET | /compliance/kyverno/namespace-config |
| Update namespace compliance settings | PUT | /compliance/kyverno/namespace-config |
| List current namespace compliance reports | GET | /compliance/kyverno/namespace-reports |
| List compliance reports | GET | /compliance/kyverno/reports |
| Export a compliance snapshot | GET | /compliance/kyverno/reports/export |
| List targets with compliance reports | GET | /compliance/kyverno/reports/targets |
| Get a compliance report | GET | /compliance/kyverno/reports/{id} |
| Get a namespace compliance snapshot | GET | /compliance/kyverno/reports/{reportId}/namespaces/{namespace} |
| List failing resources for a report control | GET | /compliance/kyverno/reports/{id}/controls/{controlId}/findings |
| List namespace findings for a control | GET | /compliance/kyverno/reports/{reportId}/namespaces/{namespace}/controls/{controlId}/findings |
Reference
Get compliance score or control history
GET /policies/api/v1/compliance/kyverno/history
Without controlId, returns the score trend for a target and standard; points exist only when results changed, so charts should carry the last value forward. With controlId, returns one point per completed scan for that control. Range defaults to the last 90 days.
Roles: admin, platform, security, devops
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
targetId | string | Yes | — | Target ID (UUID) |
standard | string | Yes | — | Standard key |
controlId | string | No | — | Return control-level history for this control instead of score history |
from | string | No | — | ISO-8601 start; default 90 days before ’to' |
to | string | No | — | ISO-8601 end; default now |
Response 200 (application/json)
Array, ascending by time: score points {time, score, passControls, failControls, totalControls, level} or, with controlId, {time, controlId, status, passCount, failCount}
| Field | Type | Description |
|---|---|---|
time | string (date-time) | — |
score | number | 0-100 (score history) |
passControls | integer | — |
failControls | integer | — |
totalControls | integer | — |
level | string | green | yellow | red | unknown |
controlId | string | (control history) |
status | string | pass | fail | not_evaluated | not_automatable (control history) |
passCount | integer | (control history) |
failCount | integer | (control history) |
Errors
400— targetId/standard missing, targetId not a UUID, or invalid from/to400— Control history range exceeds the maximum points (default 5000; code CONTROL_HISTORY_RANGE_TOO_LARGE) - narrow from/to401— Not authenticated403— Caller’s role is not in the allowed roles
Get namespace compliance settings
GET /policies/api/v1/compliance/kyverno/namespace-config
Returns the namespace compliance settings for a cluster. If none have been saved, returns a disabled configuration at revision 0.
Roles: admin, security
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
targetId | string | Yes | — | Cluster ID (UUID) |
Response 200 (application/json)
NamespaceComplianceConfigDto
| Field | Type | Description |
|---|---|---|
targetId | string (uuid) | Cluster ID |
featureEnabled | boolean | Whether this deployment supports namespace compliance |
enabled | boolean | — |
mode | string | all | specific (nullable) |
namespaces | string[] | Selected namespaces (specific mode) |
revision | integer | Use as expectedRevision on update |
createdBy | string | — |
updatedBy | string | — |
createdAt | string (date-time) | — |
updatedAt | string (date-time) | — |
Errors
400— targetId not a UUID (INVALID_TARGET_ID)404— Cluster not found or inaccessible401— Not authenticated403— Caller’s role is not in the allowed roles
Update namespace compliance settings
PUT /policies/api/v1/compliance/kyverno/namespace-config
Saves which namespaces of a cluster get namespace-level compliance views: all namespaces or a specific list. Uses optimistic concurrency: expectedRevision must equal the current revision (0 to create).
Roles: admin, security
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
targetId | string | Yes | — | Cluster ID (UUID) |
Request body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | — |
mode | string | No | all | specific; required when enabled or namespaces non-empty |
namespaces | string[] | Yes | Valid Kubernetes namespace names; must be empty for all mode, non-empty for specific mode when enabled; use [] when none |
expectedRevision | integer | Yes | Current revision from GET (>=0) |
Response 200 (application/json)
NamespaceComplianceConfigDto
| Field | Type | Description |
|---|---|---|
targetId | string (uuid) | Cluster ID |
featureEnabled | boolean | Whether this deployment supports namespace compliance |
enabled | boolean | — |
mode | string | all | specific (nullable) |
namespaces | string[] | Selected namespaces (specific mode) |
revision | integer | Use as expectedRevision on update |
createdBy | string | — |
updatedBy | string | — |
createdAt | string (date-time) | — |
updatedAt | string (date-time) | — |
Errors
400— Invalid target, body, mode or namespace selection (e.g. ENABLED_REQUIRED, EXPECTED_REVISION_REQUIRED, NAMESPACES_REQUIRED, NAMESPACE_MODE_REQUIRED, NAMESPACES_NOT_ALLOWED, INVALID_NAMESPACE)404— Cluster not found or inaccessible409— Revision mismatch (CONFIG_REVISION_CONFLICT) or feature not available in this deployment (NAMESPACE_COMPLIANCE_UNAVAILABLE)401— Not authenticated403— Caller’s role is not in the allowed roles
Example
{"enabled":true,"mode":"specific","namespaces":["payments","web"],"expectedRevision":0}
List current namespace compliance reports
GET /policies/api/v1/compliance/kyverno/namespace-reports
For a cluster and namespace, returns the latest completed report per standard projected onto that namespace, along with the current scope state. Never falls back to an older snapshot; if the namespace is not selected or data is pending, availability explains why.
Roles: admin, platform, security, devops
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
targetId | string | Yes | — | Cluster ID (UUID) |
namespace | string | Yes | — | Kubernetes namespace |
standard | string | No | — | Filter by standard key |
page | integer | No | 0 | 0-based page |
size | integer | No | 50 | Page size, clamped to 1-100 |
Response 200 (application/json)
NamespaceComplianceReportsResponseDto
| Field | Type | Description |
|---|---|---|
targetId | string (uuid) | — |
namespace | string | — |
featureEnabled | boolean | — |
enabled | boolean | — |
mode | string | all | specific |
selectedNamespaces | string[] | Empty unless caller has admin/platform/security role |
configRevision | integer | — |
availability | string | disabled | not_selected | pending | available | no_data | projection_unavailable | unsupported_scope |
reason | string | — |
reports | object | Page: {content: T[], totalElements, totalPages, number (0-based page), size} of {parentReportId, targetId, namespace, standard, scanTimestamp, projectionVersion, availability, reason, summary: {score (nullable 0-100), passCount, failCount, totalCount, notEvaluatedCount, notAutomatableCount, level}} |
Errors
400— Invalid targetId or namespace404— Cluster or namespace not found or inaccessible401— Not authenticated403— Caller’s role is not in the allowed roles
List compliance reports
GET /policies/api/v1/compliance/kyverno/reports
Lists completed compliance reports. By default (latest=true) returns the most recent completed report for each target and standard combination as an unpaginated array; with latest=false returns all completed reports, newest first, paginated.
Roles: admin, platform, security, devops
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
targetId | string | No | — | Filter by target ID (UUID) |
targetType | string | No | — | Filter by target type, e.g. cluster |
standard | string | No | — | Filter by standard key |
level | string | No | — | Filter by level: green | yellow | red | unknown |
latest | boolean | No | true | Return only the latest report per target and standard |
page | integer | No | 0 | 0-based page (latest=false only) |
size | integer | No | 50 | Page size, clamped to 1-100 (latest=false only) |
Response 200 (application/json)
latest=true: ComplianceReportDto[]; latest=false: Page: {content: T[], totalElements, totalPages, number (0-based page), size} of ComplianceReportDto
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Report ID |
targetId | string (uuid) | Scanned target (cluster/repository) ID |
targetType | string | Target type, e.g. cluster, repository |
targetName | string | Target display name |
standard | string | Standard key, e.g. soc2 |
standardDisplayName | string | Human-readable standard name |
scanTimestamp | string (date-time) | When the scan ran |
status | string | Report status (lists only return completed) |
triggerType | string | scheduled | on_demand | published |
summary | object | {score (0-100, null if nothing evaluated), passCount, failCount, totalCount, notEvaluatedCount, notAutomatableCount, level: green|yellow|red|unknown} |
Errors
400— targetId is not a valid UUID401— Not authenticated403— Caller’s role is not in the allowed roles
Export a compliance snapshot
GET /policies/api/v1/compliance/kyverno/reports/export
Returns the most recent completed report for a target and standard at or before asOf, in the nctl snapshot JSON format (snake_case control fields) so it can be used with nctl compliance diff. Includes per-control findings and structured exception details.
Roles: admin, platform, security, devops
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
targetId | string | Yes | — | Target ID (UUID) |
standard | string | Yes | — | Standard key |
asOf | string | No | — | ISO-8601 date-time with offset; defaults to now |
Response 200 (application/json)
nctl-compatible snapshot
| Field | Type | Description |
|---|---|---|
id | string | Snapshot ID in yyyyMMdd-HHmmss form |
standard | string | — |
target | string | Target name |
targetType | string | — |
timestamp | string (date-time) | Scan time |
exceptions | string[] | Policy exceptions in effect |
exceptionDetails | object[] | {name, namespace, policies[], managed, requestedBy, approvedBy, reason, state, startTime, expiryTime, history[]} |
controls | object[] | {id, policy, policy_count, status, pass_count, fail_count, findings[]} |
Errors
400— targetId/standard missing, targetId not a UUID, or invalid asOf404— No completed snapshot at or before asOf401— Not authenticated403— Caller’s role is not in the allowed roles
List targets with compliance reports
GET /policies/api/v1/compliance/kyverno/reports/targets
Returns each target that has at least one completed compliance report, with its most recent name, ordered by type and name. Useful for populating target pickers.
Roles: admin, platform, security, devops
Response 200 (application/json)
Array of {targetId, targetName, targetType}
| Field | Type | Description |
|---|---|---|
targetId | string (uuid) | — |
targetName | string | — |
targetType | string | cluster | repository | cloud_account |
Errors
401— Not authenticated403— Caller’s role is not in the allowed roles
Get a compliance report
GET /policies/api/v1/compliance/kyverno/reports/{id}
Returns one compliance report with its per-control results. For failed scans, errorMessage explains the failure.
Roles: admin, platform, security, devops
Path parameters
| Name | Type | Description |
|---|---|---|
id | string | Report ID (UUID) |
Response 200 (application/json)
ComplianceReportDto with controls[]
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Report ID |
targetId | string (uuid) | Scanned target (cluster/repository) ID |
targetType | string | Target type, e.g. cluster, repository |
targetName | string | Target display name |
standard | string | Standard key, e.g. soc2 |
standardDisplayName | string | Human-readable standard name |
scanTimestamp | string (date-time) | When the scan ran |
status | string | Report status (lists only return completed) |
triggerType | string | scheduled | on_demand | published |
summary | object | {score (0-100, null if nothing evaluated), passCount, failCount, totalCount, notEvaluatedCount, notAutomatableCount, level: green|yellow|red|unknown} |
errorMessage | string | Set when status is failed |
controls | object[] | {controlId, status: pass|fail|not_evaluated|not_automatable, passCount, failCount, policiesTotal, policiesEvaluated, primaryPolicy, failingPolicies[], allPolicies[], notAutomatableReason} |
Errors
400— id is not a valid UUID404— Report not found in this tenant (empty body)401— Not authenticated403— Caller’s role is not in the allowed roles
Get a namespace compliance snapshot
GET /policies/api/v1/compliance/kyverno/reports/{reportId}/namespaces/{namespace}
Returns the immutable namespace-level view of a cluster compliance report, including per-control results. If no namespace data exists for that report, availability and reason explain why.
Roles: admin, platform, security, devops
Path parameters
| Name | Type | Description |
|---|---|---|
reportId | string | Parent cluster report ID (UUID) |
namespace | string | Kubernetes namespace |
Response 200 (application/json)
NamespaceComplianceReportDetailDto
| Field | Type | Description |
|---|---|---|
parentReportId | string (uuid) | — |
targetId | string (uuid) | — |
namespace | string | — |
standard | string | — |
scanTimestamp | string (date-time) | — |
projectionVersion | integer | — |
configRevision | integer | — |
selectionMode | string | all | specific |
selectedNamespaces | string[] | Empty unless caller has cluster-wide access |
availability | string | disabled | not_selected | pending | available | no_data | projection_unavailable | unsupported_scope |
reason | string | — |
summary | object | {score (nullable 0-100), passCount, failCount, totalCount, notEvaluatedCount, notAutomatableCount, level} |
controls | object[] | {controlId, status: pass|fail|not_evaluated|not_automatable, passCount, failCount, policiesTotal, policiesEvaluated, primaryPolicy, failingPolicies[], allPolicies[], notAutomatableReason} |
Errors
400— Invalid reportId (INVALID_REPORT_ID) or namespace (INVALID_NAMESPACE)404— Report, cluster or namespace not found or inaccessible500— Stored snapshot is invalid (NAMESPACE_SNAPSHOT_CORRUPT)401— Not authenticated403— Caller’s role is not in the allowed roles
List failing resources for a report control
GET /policies/api/v1/compliance/kyverno/reports/{id}/controls/{controlId}/findings
Returns a paginated list of the failing or warning resources captured for one control of a report, ordered by namespace, kind and name. Returns an empty page if no evidence was captured for the control (including older reports).
Roles: admin, platform, security, devops
Path parameters
| Name | Type | Description |
|---|---|---|
id | string | Report ID (UUID) |
controlId | string | Control ID within the standard, e.g. CC6.1 |
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 0 | 0-based page |
size | integer | No | 50 | Page size, clamped to 1-100 |
Response 200 (application/json)
Page: {content: T[], totalElements, totalPages, number (0-based page), size} of findings
| Field | Type | Description |
|---|---|---|
policyName | string | Kyverno policy |
ruleName | string | Policy rule |
resourceKind | string | Resource kind |
resourceName | string | Resource name |
resourceNamespace | string | Resource namespace |
message | string | Policy result message |
result | string | Policy result, e.g. fail or warn |
Errors
400— id is not a valid UUID (code INVALID_ID)404— Report not found in this tenant (code REPORT_NOT_FOUND)401— Not authenticated403— Caller’s role is not in the allowed roles
List namespace findings for a control
GET /policies/api/v1/compliance/kyverno/reports/{reportId}/namespaces/{namespace}/controls/{controlId}/findings
Returns a page of the retained failing-resource evidence for one control in a namespace snapshot. Evidence is sampled (up to 50 per control); totalElements counts retained findings and aggregateFailCount gives the true failure count.
Roles: admin, platform, security, devops
Path parameters
| Name | Type | Description |
|---|---|---|
reportId | string | Parent report ID (UUID) |
namespace | string | Kubernetes namespace |
controlId | string | Control ID |
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 0 | 0-based page |
size | integer | No | 50 | Page size, clamped to 1-100 |
Response 200 (application/json)
{content: Finding[], totalElements, totalPages, number, size, sampleLimit, sampled, aggregateFailCount}
| Field | Type | Description |
|---|---|---|
policyName | string | Kyverno policy |
ruleName | string | Policy rule |
resourceKind | string | Resource kind |
resourceName | string | Resource name |
resourceNamespace | string | Resource namespace |
message | string | Policy result message |
result | string | Policy result, e.g. fail or warn |
sampleLimit | integer | Max findings retained per control (50) |
sampled | boolean | True when failures exceed retained evidence |
aggregateFailCount | integer | Total failing evaluations |
Errors
400— Invalid reportId, namespace, or blank controlId404— Report/namespace not found or inaccessible, or CONTROL_NOT_FOUND409— No available namespace snapshot for this report (NAMESPACE_SNAPSHOT_UNAVAILABLE)500— NAMESPACE_SNAPSHOT_CORRUPT401— Not authenticated403— Caller’s role is not in the allowed roles