メインコンテンツへスキップ

Public API — SaaS

The API is exclusively available for our paying customers, allowing them to interact with the platform programmatically.
Check the following information to get acquainted with the PerfectScale rate-limiting policy and authentication process.

情報

The PerfectScale public API is a premium feature available only with our EXPERT package for PerfectScale’s paying customers. Contact [email protected] to learn more about how to gain access to this feature.

PerfectScale API implements a rate-limiting policy to ensure fair usage and maintain the quality of service. The rate limit is set at 10 requests per minute per client.

Authentication

To interact with the PerfectScale API, a token is required. To get the token, follow the steps below:

  1. Retrieve Client Credentials:

    • Go to https://app.perfectscale.io.
    • Click on your user avatar located at the bottom left corner of the page.
    • Select Organization Settings from the menu.
    • In the pop-up window, navigate to the API Tokens tab.
    • Click on Generate Token.
    • Assign a Read Only Role to the new token.
    • Upon creation, you will be provided with a client_id (Client ID) and client_secret (Secret Key).
  2. Obtain Access Token:

    {
    "client_id": "your_client_id",
    "client_secret": "your_client_secret"
    }
    • The API will respond with a token payload, which will contain your access token.
  3. Access Other Endpoints:

    • With the obtained access token, you can make authorized requests to other endpoints of the PerfectScale API. Include the token in the Authorization header of your HTTP requests as follows:
    Authorization: Bearer your_access_token

Authentication endpoint

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

POST /auth/public_auth

Public authentication for clients

This endpoint allows clients to authenticate using their client credentials.

Request body

application/json (required): object

PropertyTypeRequiredDescription
client_idstringYesThe client identifier issued to the client during the registration process.
client_secretstringYesThe client secret issued to the client during the registration process.

Responses

StatusDescriptionBody
200Authentication successfulapplication/json: object
400Bad request, client credentials are missing or incorrect.
401Unauthorized, client authentication failed.
500Internal server error

200 application/json body

PropertyTypeRequiredDescription
access_tokenstringNoAccess token to be used for subsequent requests.
expires_inintegerNoThe number of seconds the token will be valid.

Workload

A representation of a workload within a Kubernetes cluster.

PropertyTypeRequiredDescription
idstringYesA unique identifier for the workload, usually following a namespace-type-name convention.
namestringYesA human-readable name for the workload.
typestringYesThe type of Kubernetes workload. Common types include Deployment, StatefulSet, and DaemonSet, but other string values can also be used to represent custom or extended workload types.
namespacestringYesThe Kubernetes namespace in which the workload resides.
firstSeenstring · date-timeYesThe timestamp when the workload was first observed, formatted as an ISO 8601 date-time string.
lastSeenstring · date-timeYesThe timestamp when the workload was last observed, formatted as an ISO 8601 date-time string.
runningMinutesintegerYesThe total number of minutes the workload has been running.
replicasCountsReplicasCountsYes
resilienceLevel"low", "medium", "high", "highest"YesThe resilience level of the workload, indicating its tolerance to failures or disruptions (configured on Perfectscale side).
muteStatusMuteStatusYes
costAnalysisCostAnalysisYes
workloadLabelsobjectYesKey-value pairs representing kubernets labels associated with the workload.
indicatorsarray of IndicatorYesA list of indicators providing insights into the performance and health of the workload.
containersobjectYesAn object holding detailed information about each container within the workload.

ReplicasCounts

An object representing the count statistics of replicas for a workload over a month period.

PropertyTypeRequiredDescription
maxCountintegerYesThe maximum count of replicas observed for the workload during the month period.
avgCountintegerYesThe average count of replicas observed for the workload during the month period.

MuteStatus

The mute status of a workload, indicating whether the workload is currently muted and when it will become unmuted.

PropertyTypeRequiredDescription
isMutedbooleanYesIndicates whether the workload is currently muted.
muteExpirystring · date-timeNoThe date and time when the workload will automatically become unmuted. If null, the mute status does not expire automatically.

Resources

Metrics detailing the resource allocation in terms of memory and CPU.

PropertyTypeRequiredDescription
memoryRequestMiBnumber · doubleYesThe amount of memory requested for the workload in MiB.
memoryLimitMiBnumber · doubleYesThe maximum amount of memory that can be allocated for the workload in MiB.
cpuRequestCoresnumber · doubleYesThe amount of CPU resources requested for the workload in cores.
cpuLimitCoresnumber · doubleYesThe maximum amount of CPU resources that can be allocated for the workload in cores.

Past30DaysCostAnalysis

Metrics detailing the total and wasted costs associated with the workload's resource consumption.

PropertyTypeRequiredDescription
totalCostnumber · doubleYesThe total cost incurred by the workload's resource consumption.
wastedCostnumber · doubleYesThe cost attributed to over-provisioned or inefficiently utilized resources.

Projected30DaysCostAnalysis

Metrics detailing the projected costs, recommended costs, and projected waste associated with the workload's resource consumption.

PropertyTypeRequiredDescription
projectedCostnumber · doubleYesThe projected cost of the workload's resource consumption for the next 30 days.
recommendedCostnumber · doubleYesThe recommended cost based on optimized resource allocation.
projectedWastenumber · doubleYesThe projected cost waste due to over-provisioned or inefficiently utilized resources for the next 30 days.

CostAnalysis

Analysis of the costs associated with the workload's resource consumption over the past 30 days and projected for the next 30 days.

PropertyTypeRequiredDescription
past30DaysPast30DaysCostAnalysisYes
projected30DaysProjected30DaysCostAnalysisYes

Indicator

An object representing key performance indicators that provide insights into the performance and health of the workload or container.

PropertyTypeRequiredDescription
name"OOM", "CpuThrottling", "CpuRequestNotSet", "MemRequestNotSet", "MemLimitNotSet", "UnderProvisionedMemRequest", "UnderProvisionedMemLimit", "UnderProvisionedCpuRequest", "UnderProvisionedCpuLimit", "OverProvisionedCpuRequest", "OverProvisionedMemRequest", "RestartsObserved"YesThe name of the indicator representing a specific aspect of performance or health.
type"none", "risk", "waste"YesThe type of indicator, categorizing it as either a risk, waste, or no issue (none).
severityLevel0, 1, 2, 3YesThe severity level of the indicator, ranging from 0 (no issue) to 3 (critical issue).

Container

Detailed information about a specific container within the workload, including its performance indicators and usage statistics.

PropertyTypeRequiredDescription
namestringYesThe name of the container.
runningMinutesintegerYesThe total number of minutes the container has been running.
indicatorsarray of IndicatorYesA list of indicators providing insights into the performance and health of the container.
resourcesobjectYesThe resource allocation details for the workload, including the current and recommended by PerfectScale allocation.
resources.currentResourcesYes
resources.recommendedResourcesYes
usageobjectYesAn object representing the resource usage statistics of a container, broken down into CPU and memory consumption.
usage.cpuCoresPercentilesYes
usage.memoryMiBPercentilesYes

Percentiles

An object representing percentile statistics of resource usage, providing insights into the distribution of usage values over a certain period.

PropertyTypeRequiredDescription
p90number · doubleYesThe 90th percentile value of resource usage, indicating that 90% of the usage values are below this value and 10% are above.
p95number · doubleYesThe 95th percentile value of resource usage, indicating that 95% of the usage values are below this value and 5% are above.
p100number · doubleYesThe 100th percentile value (or maximum value) of resource usage observed during the specified period.

Download OpenAPI specification

Clusters endpoint

GET /clusters

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters

Responses

StatusDescriptionBody
200OKapplication/json: object

200 application/json body

PropertyTypeRequiredDescription
dataarray of ClusterYes

Cluster

PropertyTypeRequiredDescription
uidstring · nullableYes
namestringYes
cloudClusterCloudNo
regionstring · nullableNo
createdAtstring · date-timeYes
lastTransmittedAtstring · date-timeYes

ClusterCloud

"aws", "gcp", "azure"

Download OpenAPI specification

GET /clusters/{cluster_uid}

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{cluster_uid}

Parameters

NameLocationRequiredTypeDescription
cluster_uidpathYesstring
periodqueryNostringThe period for which carbon emission is calculated

Responses

StatusDescriptionBody
200OKapplication/json: object

200 application/json body

PropertyTypeRequiredDescription
dataClusterDetailYes

ClusterDetail

PropertyTypeRequiredDescription
uidstring · nullableYes
namestringYes
cloudClusterCloudNo
regionstring · nullableNo
createdAtstring · date-timeYes
lastTransmittedAtstring · date-timeYes
emissionobjectYes

ClusterCloud

"aws", "gcp", "azure"

Download OpenAPI specification

Workloads endpoint

注意

Ensure that the following request includes the cluster_uid parameter, as it is mandatory. Follow the instructions provided to obtain this value.

GET /clusters/{cluster_uid}/workloads

List all workloads in a specified cluster

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{cluster_uid}/workloads

List all workloads in a specified cluster

Parameters

NameLocationRequiredTypeDescription
cluster_uidpathYesstringThe unique identifier for the cluster
periodqueryNoTimeWindowThe period for which data is calculated
expandEphemeralWorkloadsqueryNobooleanBy default, short-lived ephemeral workloads in large clusters are collapsed into a single aggregate row named "Collapsed Ephemeral Pods" (namespace "EphemeralPods", type "-") carrying their summed cost and no recommendations. The aggregate row has empty-string values for resilienceLevel, optimizationPolicy, cpuOptimizationPolicy, memoryOptimizationPolicy and optimizationPolicyTimeWindow, a single placeholder container named "-", and firstSeen/lastSeen spanning the collapsed workloads. Collapse eligibility is evaluated within the requested period's data window, so the same cluster may collapse for one period and not another. Set to true to return the full, uncollapsed workload list.

Responses

StatusDescriptionBody
200A list of workloadsapplication/json: object
404Cluster not found
500Internal server error

200 application/json body

PropertyTypeRequiredDescription
metaobjectYes
meta.countintegerYesThe total number of workloads in the specified cluster.
dataarray of WorkloadYes

TimeWindow

The time period for which the data is calculated (from 1h to 30d).

"1h", "4h", "12h", "1d", "3d", "7d", "14d", "30d"

Workload

PropertyTypeRequiredDescription
idstringYesA unique identifier for the workload, usually following a namespace-type-name convention.
namestringYesA human-readable name for the workload.
typestringYesThe type of Kubernetes workload. Common types include Deployment, StatefulSet, and DaemonSet, but other string values can also be used to represent custom or extended workload types.
namespacestringYesThe Kubernetes namespace in which the workload resides.
firstSeenstring · date-timeYesThe timestamp when the workload was first observed.
lastSeenstring · date-timeYesThe timestamp when the workload was last observed.
runningMinutesintegerYesThe total number of minutes the workload has been running.
replicasCountsReplicasCountsYes
resilienceLevel"low", "medium", "high", "highest"YesDeprecated: Use optimizationPolicy instead. The resilience level of the workload (configured on Perfectscale side). Mapping to optimizationPolicy values: - lowmaxSavings - mediumbalanced - highextraHeadroom - highestmaxHeadroom
optimizationPolicyOptimizationPolicyYesThe optimization policy applied to the workload.
optimizationPolicyTimeWindowOptimizationPolicyTimeWindowYesThe time window for optimization policy.
cpuOptimizationPolicyOptimizationPolicyYesThe CPU-specific optimization policy.
memoryOptimizationPolicyOptimizationPolicyYesThe memory-specific optimization policy.
memoryRequestEqualsLimitbooleanYesWhether memory request equals limit is enabled.
muteStatusMuteStatusYes
costAnalysisCostAnalysisYes
workloadLabelsobjectYesKey-value pairs representing kubernets labels associated with the workload.
indicatorsarray of IndicatorYesA list of indicators providing insights into the performance and health of the workload.
containersarray of ContainerYesAn object holding detailed information about each container within the workload.

ReplicasCounts

An object representing the count statistics of replicas for a workload over a month period.

PropertyTypeRequiredDescription
maxCountintegerYesThe maximum count of replicas observed for the workload during the month period.
avgCountintegerYesThe average count of replicas observed for the workload during the month period.

OptimizationPolicy

The optimization policy determining resource allocation strategy.

"balanced", "extraHeadroom", "maxHeadroom", "maxSavings"

OptimizationPolicyTimeWindow

The time window for optimization policy.

"14d", "21d", "30d", "45d", "policyDefault"

MuteStatus

PropertyTypeRequiredDescription
isMutedbooleanYesIndicates whether the workload is currently muted.
expiresstring · date-time · nullableYesThe date and time when the workload will automatically become unmuted. If null, the mute status does not expire automatically.

CostAnalysis

Analysis of the costs associated with the workload's resource consumption for the requested period.

PropertyTypeRequiredDescription
past30DaysPastPeriodCostAnalysisYesCost analysis data for a 30-day window when an explicit period is requested (including period=30d). When no period is specified the default 28-day window is used for backward compatibility.
pastPeriodPastPeriodCostAnalysisYes
next30DaysNextPeriodCostAnalysisYesProjected cost data for a 30-day window when an explicit period is requested (including period=30d). When no period is specified the default 28-day window is used for backward compatibility.
nextPeriodNextPeriodCostAnalysisYes

PastPeriodCostAnalysis

Metrics detailing the total and wasted costs associated with the workload's resource consumption over the analysed period.

PropertyTypeRequiredDescription
totalCostnumber · doubleYesThe total cost incurred by the workload's resource consumption.
wastedCostnumber · doubleYesThe cost attributed to over-provisioned or inefficiently utilized resources.
costPerHournumber · doubleYesThe cost of the workload per hour.

NextPeriodCostAnalysis

Metrics detailing the cost increase and potential savings associated with the workload's upcoming potential resource consumption.

PropertyTypeRequiredDescription
costIncreasenumber · doubleYesThe workload total cost increase.
potentialSavingsnumber · doubleYesThe potential savings for the workload.

Indicator

An object representing key performance indicators that provide insights into the performance and health of the workload or container.

PropertyTypeRequiredDescription
name"OOM", "CpuThrottling", "CpuRequestNotSet", "MemRequestNotSet", "MemLimitNotSet", "UnderProvisionedMemRequest", "UnderProvisionedMemLimit", "UnderProvisionedCpuRequest", "UnderProvisionedCpuLimit", "OverProvisionedCpuRequest", "OverProvisionedMemRequest", "RestartsObserved"YesThe name of the indicator representing a specific aspect of performance or health.
type"none", "risk", "waste"YesThe type of indicator, categorizing it as either a risk, waste, or no issue (none).
severityLevel0, 1, 2, 3YesThe severity level of the indicator, ranging from 0 (no issue) to 3 (critical issue).

Container

Detailed information about a specific container within the workload, including its performance indicators and usage statistics.

PropertyTypeRequiredDescription
namestringYesThe name of the container.
runningMinutesintegerYesThe total number of minutes the container has been running.
indicatorsarray of IndicatorYesA list of indicators providing insights into the performance and health of the container.
resourcesobjectYesThe resource allocation details for the workload, including the current and recommended by PerfectScale allocation.
resources.currentResourcesYes
resources.recommendedResourcesYes
usageobjectYesAn object representing the resource usage statistics of a container, broken down into CPU and memory consumption.
usage.cpuCoresPercentilesYes
usage.memoryMiBPercentilesYes

Resources

Metrics detailing the resource allocation in terms of memory and CPU.

PropertyTypeRequiredDescription
memoryRequestMiBnumber · doubleYesThe amount of memory requested for the workload in MiB.
memoryLimitMiBnumber · doubleYesThe maximum amount of memory that can be allocated for the workload in MiB.
cpuRequestCoresnumber · doubleYesThe amount of CPU resources requested for the workload in cores.
cpuLimitCoresnumber · doubleYesThe maximum amount of CPU resources that can be allocated for the workload in cores.

Percentiles

An object representing percentile statistics of resource usage, providing insights into the distribution of usage values over a certain period.

PropertyTypeRequiredDescription
p90number · doubleYesThe 90th percentile value of resource usage, indicating that 90% of the usage values are below this value and 10% are above.
p95number · doubleYesThe 95th percentile value of resource usage, indicating that 95% of the usage values are below this value and 5% are above.
p100number · doubleYesThe 100th percentile value (or maximum value) of resource usage observed during the specified period.

Download OpenAPI specification

Infrafit endpoint

The InfraFit API turns PerfectScale recommendations into automation-ready JSON, making it easy to embed cost and resource optimization directly into engineering workflows.

You can seamlessly use it for scheduled optimization checks, pre-deployment CI/CD guardrails, automated PRs, and continuous remediation.

For Karpenter, the API can return a ready-to-apply NodePool configuration, enabling teams to move from recommendation to implementation without manually translating dashboard insights into infrastructure code.

List all node groups with infra-fit data and recommendations

Returns node groups for a cluster, each containing utilization metrics, cost data, risk indicators, and actionable recommendations (instance-type or Karpenter configuration changes). Tenant resolved from service token.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{clusterUid}/node-groups

List all node groups with infra-fit data and recommendations

Returns node groups for a cluster, each containing utilization metrics, cost data, risk indicators, and actionable recommendations (instance-type or Karpenter configuration changes). Tenant resolved from service token.

Parameters

NameLocationRequiredTypeDescription
clusterUidpathYesstringCluster unique identifier
periodqueryNoInfraFitPeriodWindow for the node group's own utilization/idle-cost metrics (CPU, memory, running minutes, unrecognized-group detection). Does not affect recommendation savings/pricing math, which always uses a fixed 30-day window regardless of this value. Default P30D.
recommendationLimitqueryNointegerMax recommended node types per regular group (Karpenter always returns full change set)
hasRecommendationsqueryNobooleanFilter: true=only groups with actionable recs, false=only without, omit=all
includeMutedqueryNobooleanInclude muted recommendations
autoscalerTypequeryNoInfraFitAutoscalerTypeFilter by autoscaler type (e.g. cluster_autoscaler, karpenter)
pageSizequeryNointegerNumber of items per page (default 50, max 500)
pageTokenqueryNostringOpaque cursor token for pagination

Responses

StatusDescriptionBody
200List of node groupsapplication/json: object
400Invalid parametersapplication/problem+json: Problem
500Internal server errorapplication/problem+json: Problem

200 application/json body

PropertyTypeRequiredDescription
dataarray of InfraFitNodeGroupYes
metaInfraFitMetaYes

InfraFitPeriod

Analysis time period for infra-fit data.

"PT1H", "PT4H", "PT12H", "P1D", "P3D", "P1W", "P2W", "P4W", "P30D", "P45D"

InfraFitAutoscalerType

Autoscaler managing a node group

"karpenter", "cluster_autoscaler", "unknown"

InfraFitNodeGroup

A node group with utilization metrics, cost data, and recommendations.

PropertyTypeRequiredDescription
idstringYesNode pool identifier used in single-group requests
architecturesarray of InfraFitArchitectureYesCPU architectures present in the group
reservationsarray of InfraFitReservationYesReservation types present in the group
autoscalerTypeInfraFitAutoscalerTypeYesAutoscaler managing this group
nodesInfraFitNodesYes
runningMinutesintegerYesTotal running minutes across all nodes in the period
podsInfraFitPodsYes
costInfraFitCostYes
cpuInfraFitCpuStatsYes
memInfraFitMemStatsYes
gpuInfraFitGpuStats / nullYes
seenInfraFitSeenTimestampsYes
labelsobjectYesKubernetes labels on the node group
nodeTypesarray of InfraFitNodeTypeYesInstance types running in this group
recommendationsInfraFitRecommendationsYes

InfraFitArchitecture

CPU architecture of nodes in an InfraFit node group

"amd64", "arm64"

InfraFitReservation

Reservation type of nodes in an InfraFit node group

"on_demand", "spot", "reserved"

InfraFitNodes

Node count statistics for the analysis period

PropertyTypeRequiredDescription
minintegerYesMinimum observed node count in the period
maxintegerYesMaximum observed node count in the period
avgnumber · doubleYesAverage node count in the period

InfraFitPods

Pod count statistics for the node group

PropertyTypeRequiredDescription
capacityintegerYesMaximum number of pods the node group can schedule
allocatableintegerYesMaximum number of pods allocatable on the node group (Kubernetes limit per node × node count)
avgCountnumber · doubleYesAverage number of pods running in the group

InfraFitCost

Cost breakdown for the analysis period

PropertyTypeRequiredDescription
hourlyMoneyYes
timeframeMoneyYes
idleInfraFitCostIdleYes

Money

Monetary amount with currency

PropertyTypeRequiredDescription
amountstringYesDecimal string representation of the amount (e.g. "100.50")
currencystringYesISO 4217 currency code (e.g. "USD")

InfraFitCostIdle

Idle cost breakdown by resource type

PropertyTypeRequiredDescription
totalMoneyYes
cpuMoneyYes
gpuMoney / nullYes
memMoneyYes

InfraFitCpuStats

CPU utilization statistics (cores)

PropertyTypeRequiredDescription
requestedobjectYesCPU cores requested statistics
requested.minCoresnumber · doubleYesMinimum CPU cores requested over the requested period
requested.maxCoresnumber · doubleYesMaximum CPU cores requested over the requested period
requested.avgCoresnumber · doubleYesTime-weighted median CPU cores requested over the requested period (single aggregate, not per-datapoint)
requested.p80Coresnumber · doubleYes80th percentile CPU cores requested over the requested period
requested.p95Coresnumber · doubleYes95th percentile CPU cores requested over the requested period
requested.p99Coresnumber · doubleYes99th percentile CPU cores requested over the requested period
requested.p999Coresnumber · doubleYes99.9th percentile CPU cores requested over the requested period
usedobjectYesCPU cores used statistics
used.minCoresnumber · doubleYesMinimum CPU cores used over the requested period
used.maxCoresnumber · doubleYesMaximum CPU cores used over the requested period
used.avgCoresnumber · doubleYesTime-weighted median CPU cores used over the requested period (single aggregate, not per-datapoint)
used.p80Coresnumber · doubleYes80th percentile CPU cores used over the requested period
used.p95Coresnumber · doubleYes95th percentile CPU cores used over the requested period
used.p99Coresnumber · doubleYes99th percentile CPU cores used over the requested period
used.p999Coresnumber · doubleYes99.9th percentile CPU cores used over the requested period
idleCoresnumber · doubleYesIdle (unallocated) CPU cores — max(0, allocatable − avg used)

InfraFitMemStats

Memory utilization statistics (MiB)

PropertyTypeRequiredDescription
requestedobjectYesMemory requested statistics
requested.minMiBnumber · doubleYesMinimum memory requested in MiB over the requested period
requested.maxMiBnumber · doubleYesMaximum memory requested in MiB over the requested period
requested.avgMiBnumber · doubleYesTime-weighted median memory requested in MiB over the requested period (single aggregate, not per-datapoint)
requested.p80MiBnumber · doubleYes80th percentile memory requested in MiB over the requested period
requested.p95MiBnumber · doubleYes95th percentile memory requested in MiB over the requested period
requested.p99MiBnumber · doubleYes99th percentile memory requested in MiB over the requested period
requested.p999MiBnumber · doubleYes99.9th percentile memory requested in MiB over the requested period
usedobjectYesMemory used statistics
used.minMiBnumber · doubleYesMinimum memory used in MiB over the requested period
used.maxMiBnumber · doubleYesMaximum memory used in MiB over the requested period
used.avgMiBnumber · doubleYesTime-weighted median memory used in MiB over the requested period (single aggregate, not per-datapoint)
used.p80MiBnumber · doubleYes80th percentile memory used in MiB over the requested period
used.p95MiBnumber · doubleYes95th percentile memory used in MiB over the requested period
used.p99MiBnumber · doubleYes99th percentile memory used in MiB over the requested period
used.p999MiBnumber · doubleYes99.9th percentile memory used in MiB over the requested period
idleMiBnumber · doubleYesIdle (unallocated) memory in MiB — max(0, allocatable − avg used)

InfraFitGpuStats

GPU utilization statistics

PropertyTypeRequiredDescription
idleInfraFitIdleGpuYes
requestedInfraFitGpuSampleYes
usedInfraFitGpuSampleYes
architecturesarray of stringYesGPU architectures present in the group (e.g. ampere, hopper), sorted
sharingTypearray of stringYesActive GPU sharing mechanisms in lower_snake_case (e.g. "full", "time_slicing", "mps", "mig")

InfraFitIdleGpu

Idle (unallocated) GPU resources

PropertyTypeRequiredDescription
unitsnumber · doubleYesIdle (unallocated) GPU units — max(0, allocatable − avg used)
memoryMiBnumber · doubleYesIdle (unallocated) GPU memory in MiB — max(0, capacity − avg used)

InfraFitGpuSample

GPU sample statistics (time-weighted medians and percentiles)

PropertyTypeRequiredDescription
avgUnitsnumber · doubleYesTime-weighted median GPU units
minUnitsnumber · doubleYesMinimum GPU units over the period
maxUnitsnumber · doubleYesMaximum GPU units over the period
p80Unitsnumber · doubleYes80th percentile GPU units over the period
p95Unitsnumber · doubleYes95th percentile GPU units over the period
p99Unitsnumber · doubleYes99th percentile GPU units over the period
p999Unitsnumber · doubleYes99.9th percentile GPU units over the period
avgMemoryMiBnumber · doubleYesTime-weighted median GPU memory in MiB
minMemoryMiBnumber · doubleYesMinimum GPU memory in MiB over the period
maxMemoryMiBnumber · doubleYesMaximum GPU memory in MiB over the period
p80MemoryMiBnumber · doubleYes80th percentile GPU memory in MiB over the period
p95MemoryMiBnumber · doubleYes95th percentile GPU memory in MiB over the period
p99MemoryMiBnumber · doubleYes99th percentile GPU memory in MiB over the period
p999MemoryMiBnumber · doubleYes99.9th percentile GPU memory in MiB over the period

InfraFitSeenTimestamps

First and last observed timestamps

PropertyTypeRequiredDescription
firstTimestring · date-timeYesWhen first observed (RFC 3339 UTC)
lastTimestring · date-timeYesWhen last observed (RFC 3339 UTC)

InfraFitNodeType

Instance type breakdown within a node group

PropertyTypeRequiredDescription
idstringYesInstance type identifier (matches instance.type)
instanceInfraFitInstanceInfoYes
isSpotbooleanYesWhether this instance type runs on spot/preemptible capacity
nodesInfraFitNodesYes
costInfraFitCostYes
runningMinutesintegerYesTotal running minutes across all nodes of this instance type in the period
podsInfraFitPodsYes
cpuInfraFitCpuStatsYes
memInfraFitMemStatsYes
gpuInfraFitNodeTypeGpu / nullYes
seenInfraFitSeenTimestampsYes

InfraFitInstanceInfo

Instance type identity and capacity

PropertyTypeRequiredDescription
typestringYesCloud instance type identifier (e.g. m5.2xlarge)
familystringYesInstance family prefix shared by related instance types (e.g. m5)
architectureInfraFitArchitecture / nullYesCPU architecture of this instance type (null when unknown)
cpuInfraFitInstanceCpuYes
memInfraFitInstanceMemYes
gpuInfraFitInstanceGpu / nullYesGPU capacity, null for non-GPU instance types

InfraFitInstanceCpu

CPU capacity for an instance type

PropertyTypeRequiredDescription
capacityCoresnumber · doubleYesvCPU count per instance
allocatableCoresnumber · doubleYesAllocatable vCPU per instance after Kubernetes system-reserved resources are subtracted

InfraFitInstanceMem

Memory capacity for an instance type

PropertyTypeRequiredDescription
capacityMiBnumber · doubleYesMemory capacity per instance in MiB
allocatableMiBnumber · doubleYesAllocatable memory per instance in MiB after Kubernetes system-reserved resources are subtracted

InfraFitInstanceGpu

GPU capacity for an instance type

PropertyTypeRequiredDescription
capacityUnitsnumber · doubleYesGPU unit count per instance
allocatableUnitsnumber · doubleYesAllocatable GPU units per instance after Kubernetes system-reserved resources are subtracted
memCapacityMiBnumber · doubleYesTotal GPU memory capacity per instance in MiB

InfraFitNodeTypeGpu

GPU stats for an instance type

PropertyTypeRequiredDescription
idleInfraFitIdleGpuYes
requestedInfraFitGpuSampleYes
usedInfraFitGpuSampleYes
architecturesarray of stringYesGPU architectures present in the instance type (e.g. ampere, hopper), sorted

InfraFitRecommendations

Discriminated recommendations object. Routed by autoscalerType: cluster_autoscaler/managed → standard, karpenter → karpenter. Always present, never omitted.

InfraFitStandardRecommendations / InfraFitKarpenterRecommendations

InfraFitStandardRecommendations

Recommendations for Cluster-Autoscaler and managed node groups

PropertyTypeRequiredDescription
type"standard"Yes
hasChangesbooleanYesWhether any instance type changes are recommended
nodeTypesarray of InfraFitRecommendedNodeTypeYesRecommended instance types, capped at recommendationLimit

InfraFitRecommendedNodeType

A recommended instance type replacement

PropertyTypeRequiredDescription
idstringYesUnique identifier for this recommendation entry (matches instanceType)
instanceTypestringYesRecommended cloud instance type identifier (e.g. m6g.xlarge)
instanceFamilystringYesInstance family prefix of the recommended type (e.g. m6g)
hourlyCostMoneyYes
estimatedSavingsMoneyYes
estimatedSavingsPctnumber · doubleYesSavings as percentage of current group cost
nodeCountintegerYesRecommended number of nodes of this type

InfraFitKarpenterRecommendations

Recommendations for Karpenter-managed node pools

PropertyTypeRequiredDescription
type"karpenter"Yes
hasChangesbooleanYesWhether any configuration changes are recommended
currentConfigobjectYesCurrent raw Karpenter NodePool CR (full JSON)
recommendedConfigobjectYesPatched NodePool CR with all recommended changes applied
changesarray of InfraFitKarpenterChangeYesStructured change set (always full, not capped by recommendationLimit)

InfraFitKarpenterChange

A single Karpenter configuration change recommendation

PropertyTypeRequiredDescription
idstringYesUnique identifier for this change entry (matches path)
titlestringYesHuman-readable change title
pathstringYesJSONPath (RFC 9535 syntax) into the NodePool CR. Nested keys and array equality-filter selectors are supported, e.g. ".spec.disruption.consolidationPolicy" or ".spec.template.spec.requirements[?(@.key=="node.kubernetes.io/instance-type")]".
operationstringYesChange operation: "replace", "merge", or "remove". An empty operation is treated as "replace"; a replace with a null recommendedValue removes the field.
currentValueobjectYesCurrent value at the path (string, number, boolean, array, object, or null)
recommendedValueobjectYesRecommended value (string, number, boolean, array, object, or null)
rationalestringYesHuman-readable explanation for this change

InfraFitMeta

Response metadata for InfraFit endpoints

PropertyTypeRequiredDescription
timeframestringYesAnalysis period echoed from the period query parameter (e.g. "P30D")
paginationPaginationMetaNoCursor-based pagination metadata. Present in list responses; omitted for single-item responses.

PaginationMeta

Cursor-based pagination metadata for list responses.

PropertyTypeRequiredDescription
nextstring,nullYesOpaque cursor token for the next page, or null if this is the last page
prevstring,nullYesOpaque cursor token for the previous page, or null if this is the first page
pageSizeintegerYesNumber of items per page used for this response

Problem

RFC 9457 Problem Details error body, served as application/problem+json. code is a stable machine-readable identifier (e.g. filter_key_not_supported, not_found, internal_error); retryable indicates whether retrying the same request may succeed without client-side changes.

PropertyTypeRequiredDescription
typestringYesURI reference identifying the problem type.
titlestringYesShort, human-readable summary of the problem type.
statusintegerYesHTTP status code generated by the origin server for this occurrence of the problem.
detailstringNoHuman-readable explanation specific to this occurrence of the problem.
instancestringNoURI reference identifying the specific occurrence of the problem.
codestringYesStable machine-readable error code.
retryablebooleanYesWhether retrying the same request may succeed without client-side changes.

Download OpenAPI specification

Get a single node group with infra-fit data and recommendations

Returns a single node group by name. Same shape as one item from the list endpoint. Returns 404 if the group does not exist in the cluster.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{clusterUid}/node-groups/{nodeGroupName}

Get a single node group with infra-fit data and recommendations

Returns a single node group by name. Same shape as one item from the list endpoint. Returns 404 if the group does not exist in the cluster.

Parameters

NameLocationRequiredTypeDescription
clusterUidpathYesstringCluster unique identifier
nodeGroupNamepathYesstringNode group name
periodqueryNoInfraFitPeriodWindow for the node group's own utilization/idle-cost metrics (CPU, memory, running minutes, unrecognized-group detection). Does not affect recommendation savings/pricing math, which always uses a fixed 30-day window regardless of this value. Default P30D.
recommendationLimitqueryNointegerMax recommended node types per group (Karpenter always returns full change set)

Responses

StatusDescriptionBody
200Single node groupapplication/json: object
400Invalid parametersapplication/problem+json: Problem
404Cluster or node group not foundapplication/problem+json: Problem
500Internal server errorapplication/problem+json: Problem

200 application/json body

PropertyTypeRequiredDescription
dataInfraFitNodeGroupYes
metaInfraFitMetaYes

InfraFitPeriod

Analysis time period for infra-fit data.

"PT1H", "PT4H", "PT12H", "P1D", "P3D", "P1W", "P2W", "P4W", "P30D", "P45D"

InfraFitNodeGroup

A node group with utilization metrics, cost data, and recommendations.

PropertyTypeRequiredDescription
idstringYesNode pool identifier used in single-group requests
architecturesarray of InfraFitArchitectureYesCPU architectures present in the group
reservationsarray of InfraFitReservationYesReservation types present in the group
autoscalerTypeInfraFitAutoscalerTypeYesAutoscaler managing this group
nodesInfraFitNodesYes
runningMinutesintegerYesTotal running minutes across all nodes in the period
podsInfraFitPodsYes
costInfraFitCostYes
cpuInfraFitCpuStatsYes
memInfraFitMemStatsYes
gpuInfraFitGpuStats / nullYes
seenInfraFitSeenTimestampsYes
labelsobjectYesKubernetes labels on the node group
nodeTypesarray of InfraFitNodeTypeYesInstance types running in this group
recommendationsInfraFitRecommendationsYes

InfraFitArchitecture

CPU architecture of nodes in an InfraFit node group

"amd64", "arm64"

InfraFitReservation

Reservation type of nodes in an InfraFit node group

"on_demand", "spot", "reserved"

InfraFitAutoscalerType

Autoscaler managing a node group

"karpenter", "cluster_autoscaler", "unknown"

InfraFitNodes

Node count statistics for the analysis period

PropertyTypeRequiredDescription
minintegerYesMinimum observed node count in the period
maxintegerYesMaximum observed node count in the period
avgnumber · doubleYesAverage node count in the period

InfraFitPods

Pod count statistics for the node group

PropertyTypeRequiredDescription
capacityintegerYesMaximum number of pods the node group can schedule
allocatableintegerYesMaximum number of pods allocatable on the node group (Kubernetes limit per node × node count)
avgCountnumber · doubleYesAverage number of pods running in the group

InfraFitCost

Cost breakdown for the analysis period

PropertyTypeRequiredDescription
hourlyMoneyYes
timeframeMoneyYes
idleInfraFitCostIdleYes

Money

Monetary amount with currency

PropertyTypeRequiredDescription
amountstringYesDecimal string representation of the amount (e.g. "100.50")
currencystringYesISO 4217 currency code (e.g. "USD")

InfraFitCostIdle

Idle cost breakdown by resource type

PropertyTypeRequiredDescription
totalMoneyYes
cpuMoneyYes
gpuMoney / nullYes
memMoneyYes

InfraFitCpuStats

CPU utilization statistics (cores)

PropertyTypeRequiredDescription
requestedobjectYesCPU cores requested statistics
requested.minCoresnumber · doubleYesMinimum CPU cores requested over the requested period
requested.maxCoresnumber · doubleYesMaximum CPU cores requested over the requested period
requested.avgCoresnumber · doubleYesTime-weighted median CPU cores requested over the requested period (single aggregate, not per-datapoint)
requested.p80Coresnumber · doubleYes80th percentile CPU cores requested over the requested period
requested.p95Coresnumber · doubleYes95th percentile CPU cores requested over the requested period
requested.p99Coresnumber · doubleYes99th percentile CPU cores requested over the requested period
requested.p999Coresnumber · doubleYes99.9th percentile CPU cores requested over the requested period
usedobjectYesCPU cores used statistics
used.minCoresnumber · doubleYesMinimum CPU cores used over the requested period
used.maxCoresnumber · doubleYesMaximum CPU cores used over the requested period
used.avgCoresnumber · doubleYesTime-weighted median CPU cores used over the requested period (single aggregate, not per-datapoint)
used.p80Coresnumber · doubleYes80th percentile CPU cores used over the requested period
used.p95Coresnumber · doubleYes95th percentile CPU cores used over the requested period
used.p99Coresnumber · doubleYes99th percentile CPU cores used over the requested period
used.p999Coresnumber · doubleYes99.9th percentile CPU cores used over the requested period
idleCoresnumber · doubleYesIdle (unallocated) CPU cores — max(0, allocatable − avg used)

InfraFitMemStats

Memory utilization statistics (MiB)

PropertyTypeRequiredDescription
requestedobjectYesMemory requested statistics
requested.minMiBnumber · doubleYesMinimum memory requested in MiB over the requested period
requested.maxMiBnumber · doubleYesMaximum memory requested in MiB over the requested period
requested.avgMiBnumber · doubleYesTime-weighted median memory requested in MiB over the requested period (single aggregate, not per-datapoint)
requested.p80MiBnumber · doubleYes80th percentile memory requested in MiB over the requested period
requested.p95MiBnumber · doubleYes95th percentile memory requested in MiB over the requested period
requested.p99MiBnumber · doubleYes99th percentile memory requested in MiB over the requested period
requested.p999MiBnumber · doubleYes99.9th percentile memory requested in MiB over the requested period
usedobjectYesMemory used statistics
used.minMiBnumber · doubleYesMinimum memory used in MiB over the requested period
used.maxMiBnumber · doubleYesMaximum memory used in MiB over the requested period
used.avgMiBnumber · doubleYesTime-weighted median memory used in MiB over the requested period (single aggregate, not per-datapoint)
used.p80MiBnumber · doubleYes80th percentile memory used in MiB over the requested period
used.p95MiBnumber · doubleYes95th percentile memory used in MiB over the requested period
used.p99MiBnumber · doubleYes99th percentile memory used in MiB over the requested period
used.p999MiBnumber · doubleYes99.9th percentile memory used in MiB over the requested period
idleMiBnumber · doubleYesIdle (unallocated) memory in MiB — max(0, allocatable − avg used)

InfraFitGpuStats

GPU utilization statistics

PropertyTypeRequiredDescription
idleInfraFitIdleGpuYes
requestedInfraFitGpuSampleYes
usedInfraFitGpuSampleYes
architecturesarray of stringYesGPU architectures present in the group (e.g. ampere, hopper), sorted
sharingTypearray of stringYesActive GPU sharing mechanisms in lower_snake_case (e.g. "full", "time_slicing", "mps", "mig")

InfraFitIdleGpu

Idle (unallocated) GPU resources

PropertyTypeRequiredDescription
unitsnumber · doubleYesIdle (unallocated) GPU units — max(0, allocatable − avg used)
memoryMiBnumber · doubleYesIdle (unallocated) GPU memory in MiB — max(0, capacity − avg used)

InfraFitGpuSample

GPU sample statistics (time-weighted medians and percentiles)

PropertyTypeRequiredDescription
avgUnitsnumber · doubleYesTime-weighted median GPU units
minUnitsnumber · doubleYesMinimum GPU units over the period
maxUnitsnumber · doubleYesMaximum GPU units over the period
p80Unitsnumber · doubleYes80th percentile GPU units over the period
p95Unitsnumber · doubleYes95th percentile GPU units over the period
p99Unitsnumber · doubleYes99th percentile GPU units over the period
p999Unitsnumber · doubleYes99.9th percentile GPU units over the period
avgMemoryMiBnumber · doubleYesTime-weighted median GPU memory in MiB
minMemoryMiBnumber · doubleYesMinimum GPU memory in MiB over the period
maxMemoryMiBnumber · doubleYesMaximum GPU memory in MiB over the period
p80MemoryMiBnumber · doubleYes80th percentile GPU memory in MiB over the period
p95MemoryMiBnumber · doubleYes95th percentile GPU memory in MiB over the period
p99MemoryMiBnumber · doubleYes99th percentile GPU memory in MiB over the period
p999MemoryMiBnumber · doubleYes99.9th percentile GPU memory in MiB over the period

InfraFitSeenTimestamps

First and last observed timestamps

PropertyTypeRequiredDescription
firstTimestring · date-timeYesWhen first observed (RFC 3339 UTC)
lastTimestring · date-timeYesWhen last observed (RFC 3339 UTC)

InfraFitNodeType

Instance type breakdown within a node group

PropertyTypeRequiredDescription
idstringYesInstance type identifier (matches instance.type)
instanceInfraFitInstanceInfoYes
isSpotbooleanYesWhether this instance type runs on spot/preemptible capacity
nodesInfraFitNodesYes
costInfraFitCostYes
runningMinutesintegerYesTotal running minutes across all nodes of this instance type in the period
podsInfraFitPodsYes
cpuInfraFitCpuStatsYes
memInfraFitMemStatsYes
gpuInfraFitNodeTypeGpu / nullYes
seenInfraFitSeenTimestampsYes

InfraFitInstanceInfo

Instance type identity and capacity

PropertyTypeRequiredDescription
typestringYesCloud instance type identifier (e.g. m5.2xlarge)
familystringYesInstance family prefix shared by related instance types (e.g. m5)
architectureInfraFitArchitecture / nullYesCPU architecture of this instance type (null when unknown)
cpuInfraFitInstanceCpuYes
memInfraFitInstanceMemYes
gpuInfraFitInstanceGpu / nullYesGPU capacity, null for non-GPU instance types

InfraFitInstanceCpu

CPU capacity for an instance type

PropertyTypeRequiredDescription
capacityCoresnumber · doubleYesvCPU count per instance
allocatableCoresnumber · doubleYesAllocatable vCPU per instance after Kubernetes system-reserved resources are subtracted

InfraFitInstanceMem

Memory capacity for an instance type

PropertyTypeRequiredDescription
capacityMiBnumber · doubleYesMemory capacity per instance in MiB
allocatableMiBnumber · doubleYesAllocatable memory per instance in MiB after Kubernetes system-reserved resources are subtracted

InfraFitInstanceGpu

GPU capacity for an instance type

PropertyTypeRequiredDescription
capacityUnitsnumber · doubleYesGPU unit count per instance
allocatableUnitsnumber · doubleYesAllocatable GPU units per instance after Kubernetes system-reserved resources are subtracted
memCapacityMiBnumber · doubleYesTotal GPU memory capacity per instance in MiB

InfraFitNodeTypeGpu

GPU stats for an instance type

PropertyTypeRequiredDescription
idleInfraFitIdleGpuYes
requestedInfraFitGpuSampleYes
usedInfraFitGpuSampleYes
architecturesarray of stringYesGPU architectures present in the instance type (e.g. ampere, hopper), sorted

InfraFitRecommendations

Discriminated recommendations object. Routed by autoscalerType: cluster_autoscaler/managed → standard, karpenter → karpenter. Always present, never omitted.

InfraFitStandardRecommendations / InfraFitKarpenterRecommendations

InfraFitStandardRecommendations

Recommendations for Cluster-Autoscaler and managed node groups

PropertyTypeRequiredDescription
type"standard"Yes
hasChangesbooleanYesWhether any instance type changes are recommended
nodeTypesarray of InfraFitRecommendedNodeTypeYesRecommended instance types, capped at recommendationLimit

InfraFitRecommendedNodeType

A recommended instance type replacement

PropertyTypeRequiredDescription
idstringYesUnique identifier for this recommendation entry (matches instanceType)
instanceTypestringYesRecommended cloud instance type identifier (e.g. m6g.xlarge)
instanceFamilystringYesInstance family prefix of the recommended type (e.g. m6g)
hourlyCostMoneyYes
estimatedSavingsMoneyYes
estimatedSavingsPctnumber · doubleYesSavings as percentage of current group cost
nodeCountintegerYesRecommended number of nodes of this type

InfraFitKarpenterRecommendations

Recommendations for Karpenter-managed node pools

PropertyTypeRequiredDescription
type"karpenter"Yes
hasChangesbooleanYesWhether any configuration changes are recommended
currentConfigobjectYesCurrent raw Karpenter NodePool CR (full JSON)
recommendedConfigobjectYesPatched NodePool CR with all recommended changes applied
changesarray of InfraFitKarpenterChangeYesStructured change set (always full, not capped by recommendationLimit)

InfraFitKarpenterChange

A single Karpenter configuration change recommendation

PropertyTypeRequiredDescription
idstringYesUnique identifier for this change entry (matches path)
titlestringYesHuman-readable change title
pathstringYesJSONPath (RFC 9535 syntax) into the NodePool CR. Nested keys and array equality-filter selectors are supported, e.g. ".spec.disruption.consolidationPolicy" or ".spec.template.spec.requirements[?(@.key=="node.kubernetes.io/instance-type")]".
operationstringYesChange operation: "replace", "merge", or "remove". An empty operation is treated as "replace"; a replace with a null recommendedValue removes the field.
currentValueobjectYesCurrent value at the path (string, number, boolean, array, object, or null)
recommendedValueobjectYesRecommended value (string, number, boolean, array, object, or null)
rationalestringYesHuman-readable explanation for this change

InfraFitMeta

Response metadata for InfraFit endpoints

PropertyTypeRequiredDescription
timeframestringYesAnalysis period echoed from the period query parameter (e.g. "P30D")
paginationPaginationMetaNoCursor-based pagination metadata. Present in list responses; omitted for single-item responses.

PaginationMeta

Cursor-based pagination metadata for list responses.

PropertyTypeRequiredDescription
nextstring,nullYesOpaque cursor token for the next page, or null if this is the last page
prevstring,nullYesOpaque cursor token for the previous page, or null if this is the first page
pageSizeintegerYesNumber of items per page used for this response

Problem

RFC 9457 Problem Details error body, served as application/problem+json. code is a stable machine-readable identifier (e.g. filter_key_not_supported, not_found, internal_error); retryable indicates whether retrying the same request may succeed without client-side changes.

PropertyTypeRequiredDescription
typestringYesURI reference identifying the problem type.
titlestringYesShort, human-readable summary of the problem type.
statusintegerYesHTTP status code generated by the origin server for this occurrence of the problem.
detailstringNoHuman-readable explanation specific to this occurrence of the problem.
instancestringNoURI reference identifying the specific occurrence of the problem.
codestringYesStable machine-readable error code.
retryablebooleanYesWhether retrying the same request may succeed without client-side changes.

Download OpenAPI specification

List unevictable pods in a cluster

Returns the pods from the latest pre-computed unevictable-pods snapshot for the cluster (no request-time recompute). Tenant resolved from the auth token; a cluster belonging to another tenant returns 404.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{clusterUid}/unevictable-pods

List unevictable pods in a cluster

Returns the pods from the latest pre-computed unevictable-pods snapshot for the cluster (no request-time recompute). Tenant resolved from the auth token; a cluster belonging to another tenant returns 404.

Parameters

NameLocationRequiredTypeDescription
clusterUidpathYesstringCluster unique identifier
filterqueryNostringComposite filter expression: clauses of the form key[:op]:value joined by | (AND); op is optional and defaults to eq; comma-separate values within a clause for an IN match, e.g. filter=namespace:payments|blockedCostHourly:gte:10. Supported keys for this endpoint: namespace (eq), blockedCostHourly (eq/gte/lte, compares numerically on the underlying cost value, not the serialized Money object), reasonCode (eq), nodeGroup (eq), labels.<key> (eq). labels.<key> matches against the pod's Kubernetes labels — for example filter=labels.team:payments matches pods labeled team=payments. An unsupported key returns 400 with code: "filter_key_not_supported". Mute-status filtering is handled by the separate mute parameter, not this filter.
mutequeryNo"exclude", "include", "only"Muted-finding handling: exclude (default) hides pods whose workload has a dismissal rule; include returns all pods, flagging muted ones via mute/mutedByRule on each reason; only returns exclusively muted pods, for auditing what's been silenced.
sortByqueryNo"blockedCostHourly"Field to sort results by. blockedCostHourly sorts numerically on the underlying cost value, not the serialized Money object. Unset falls back to a stable but unspecified order (currently pod UID). Ties are always broken by UID for stable pagination.
sortOrderqueryNo"asc", "desc"Sort direction, applied only when sortBy is set.
pageSizequeryNointegerNumber of items per page (default 50, max 500)
pageTokenqueryNostringOpaque cursor token for pagination

Responses

StatusDescriptionBody
200List of unevictable podsapplication/json: object
202Raw snapshot exists but is still being processedapplication/json: object
400Invalid parametersapplication/problem+json: Problem
404Cluster or snapshot not foundapplication/problem+json: Problem
422Raw snapshot exists but processing failedapplication/problem+json: Problem
500Internal server errorapplication/problem+json: Problem

200 application/json body

PropertyTypeRequiredDescription
dataarray of UnevictablePodYes
metaobjectYes
meta.paginationPaginationMetaYes
meta.snapshotTimestring · date-timeYesTimestamp (RFC 3339, UTC) of the snapshot the data was read from
meta.algorithmVersionstringYesVersion of the unevictable-detection algorithm/library used to produce the snapshot
meta.summaryUnevictableSummaryYes

202 application/json body

PropertyTypeRequiredDescription
dataUnevictablePodsStatusYes

UnevictablePod

A single unevictable pod from the latest pre-computed snapshot for the cluster. Returned both as a list item and as the single-pod detail response — the detail response additionally populates siblingPodNames.

PropertyTypeRequiredDescription
namestringYes
namespacestringYes
idstringYes
workloadUnevictableWorkloadRefYes
reasonsarray of UnevictableReasonYesEmpty = pod is evictable; non-empty = unevictable.
phasestringYes
startTimestring · date-timeYesPod creation timestamp (RFC 3339 UTC).
labelsobjectNo
annotationsobjectNo
specUnevictablePodSpecNo
blockedNodeCountintegerNoNumber of nodes this pod blocks from scaling down.
blockedNodesarray of stringNoNames of the nodes this pod pins.
blockedCostHourlyMoneyNoHourly cost of the blocked nodes (Total Blocked Cost). Filtering (blockedCostHourly:gte:<amount>) and sorting compare numerically on the underlying cost value, not the serialized Money object.
clusterUidstringNo
mutebooleanNoTrue when the pod's workload is muted by a dismissal rule, muting all of its reasons.
siblingPodNamesarray of stringNoNames of other pods of the same workload id in this snapshot. Populated only by the single-pod detail endpoint.

UnevictableWorkloadRef

Identity of the pod's top-level owning workload.

PropertyTypeRequiredDescription
idstringYesCanonical workload id (namespace-kind-name) of the top-level controller.
namestringNoDenormalized workload name for display.
typestringYesKubernetes workload kind (e.g. Deployment, StatefulSet, DaemonSet).

UnevictableReason

PropertyTypeRequiredDescription
reasonstringYesShort reason code (e.g. "Topology-Locked", "PDB Violation").
reasonCodeUnevictableReasonCode / nullNoStable slug derived from the display reason. Null for unrecognised reasons.
detailsstringYesHuman-readable explanation.
remediationUnevictableRemediationNo
mutebooleanNoTrue when this reason is covered by a dismissal rule and therefore muted.
mutedByRuleUnevictableMutedByRule / nullNo

UnevictableReasonCode

Stable canonical identifier for an unevictable reason. Decoupled from the mutable display string.

"opt_out_annotation", "pod_disruption_budget", "strict_affinity", "strict_anti_affinity", "topology_locked", "taints_not_tolerated", "local_node_storage", "static_mirror_pod"

UnevictableRemediation

Reason-specific fix. current/recommended spec and the yaml diff are null for partial/informational cases.

PropertyTypeRequiredDescription
fixSummarystringYesOne-line plain-language fix.
risk"none", "low", "medium", "high"Yes
confidence"low", "medium", "high"Yes
currentSpecstring,nullNoRendered YAML of the current spec; null for partial/informational cases.
recommendedSpecstring,nullNoRendered YAML of the recommended spec; null for partial/informational cases.
yamlDiffstring,nullNoUnified diff string; null when there is no clean diff.

UnevictableMutedByRule

Summary of the dismissal rule that suppressed this finding.

PropertyTypeRequiredDescription
notestring,nullNo
createdBystringYesEmail of the user who created the rule.
createTimestring · date-timeYesWhen the rule was created (RFC 3339 UTC)

UnevictablePodSpec

Raw Kubernetes PodSpec fields used by detection, verbatim from the pod.

PropertyTypeRequiredDescription
nodestring,nullNoNode the pod is scheduled on (spec.nodeName); null for Pending pods.
nodeGroupstringNoNode group the pod's node belongs to; empty if the node's node group is unresolved.
priorityintegerNoKubernetes pod scheduling priority (spec.priority, from the pod's PriorityClass).
nodeSelectorobjectNo
affinityUnevictablePodAffinityNo
tolerationsarray of UnevictablePodTolerationNo
containersarray of UnevictablePodContainerNo
volumesarray of UnevictablePodVolumeNo
topologySpreadConstraintsarray of UnevictablePodTopologySpreadConstraintNo
ownerReferencesarray of UnevictablePodOwnerReferenceNoThe pod's metadata.ownerReferences, as the subset of fields described above. Omitted when the pod has no owner (e.g. static/mirror pods — see the static_mirror_pod reason code).

UnevictablePodAffinity

Simplified affinity block — only the sub-fields used by detection are modelled.

PropertyTypeRequiredDescription
nodeAffinityobjectNo
podAffinityobjectNo
podAntiAffinityobjectNo

UnevictablePodToleration

PropertyTypeRequiredDescription
keystringYes
operatorstringYes
valuestringNo
effectstringYes

UnevictablePodContainer

PropertyTypeRequiredDescription
namestringYes
imagestringYes
cpuRequestCoresnumber,null · doubleNoCPU requested for the container, in cores; null if unset.
cpuLimitCoresnumber,null · doubleNoCPU limit for the container, in cores; null if unset.
memoryRequestMiBnumber,null · doubleNoMemory requested for the container, in MiB; null if unset.
memoryLimitMiBnumber,null · doubleNoMemory limit for the container, in MiB; null if unset.
gpuRequestinteger,nullNoGPU units requested for the container (e.g. nvidia.com/gpu); null if unset. GPU requests/limits are always whole units.
gpuLimitinteger,nullNoGPU units the container is limited to (e.g. nvidia.com/gpu); null if unset. GPU requests/limits are always whole units.

UnevictablePodVolume

PropertyTypeRequiredDescription
namestringYes
hostPathstringNo
emptyDirstringNo
pvcClaimNamestringNo

UnevictablePodTopologySpreadConstraint

PropertyTypeRequiredDescription
maxSkewinteger · int32Yes
topologyKeystringYes
whenUnsatisfiablestringYes
labelSelectorobjectNo

UnevictablePodOwnerReference

A subset of the pod's Kubernetes OwnerReference fields (apiVersion, kind, name, controller) used for ownership detection; not a complete copy of metadata.ownerReferences (e.g. uid is omitted).

PropertyTypeRequiredDescription
apiVersionstringYes
kindstringYes
namestringYes
controllerboolean,nullNoTrue when this reference is the pod's managing controller.

Money

Monetary amount with currency

PropertyTypeRequiredDescription
amountstringYesDecimal string representation of the amount (e.g. "100.50")
currencystringYesISO 4217 currency code (e.g. "USD")

PaginationMeta

Cursor-based pagination metadata for list responses.

PropertyTypeRequiredDescription
nextstring,nullYesOpaque cursor token for the next page, or null if this is the last page
prevstring,nullYesOpaque cursor token for the previous page, or null if this is the first page
pageSizeintegerYesNumber of items per page used for this response

UnevictableSummary

Aggregate pod/node counts for the snapshot backing the listing response.

PropertyTypeRequiredDescription
totalPodsintegerYesTotal number of pods observed in the snapshot.
unevictablePodsintegerYesNumber of pods detected as unevictable in the snapshot.
muteintegerYesNumber of unevictable findings muted by a dismissal rule in this snapshot.
totalNodesintegerYesTotal number of nodes observed in the snapshot.
autoscalerTypestringNoDetected autoscaler, rolled up from per-node detection (canonical values, e.g. "cluster_autoscaler", "karpenter", "castai", "eks_auto_mode"). Omitted if not detected. Results written before PSD-9016 may carry the legacy hyphenated "cluster-autoscaler".

UnevictablePodsStatus

Snapshot processing status, returned on 202 (still processing) and 422 (processing failed) instead of pod/report data.

PropertyTypeRequiredDescription
status"processing", "failed"Yes

Problem

RFC 9457 Problem Details error body, served as application/problem+json. code is a stable machine-readable identifier (e.g. filter_key_not_supported, not_found, internal_error); retryable indicates whether retrying the same request may succeed without client-side changes.

PropertyTypeRequiredDescription
typestringYesURI reference identifying the problem type.
titlestringYesShort, human-readable summary of the problem type.
statusintegerYesHTTP status code generated by the origin server for this occurrence of the problem.
detailstringNoHuman-readable explanation specific to this occurrence of the problem.
instancestringNoURI reference identifying the specific occurrence of the problem.
codestringYesStable machine-readable error code.
retryablebooleanYesWhether retrying the same request may succeed without client-side changes.

Download OpenAPI specification

Per-pod unevictable report — one row per pod, with all its reasons combined

Issues view — one row per pod, carrying all of that pod's unevictable reasons. Served from the latest pre-computed snapshot (no request-time recompute). Tenant resolved from the auth token; a cluster belonging to another tenant returns 404.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{clusterUid}/unevictable-report

Per-pod unevictable report — one row per pod, with all its reasons combined

Issues view — one row per pod, carrying all of that pod's unevictable reasons. Served from the latest pre-computed snapshot (no request-time recompute). Tenant resolved from the auth token; a cluster belonging to another tenant returns 404.

Parameters

NameLocationRequiredTypeDescription
clusterUidpathYesstringCluster unique identifier
filterqueryNostringComposite filter expression: clauses of the form key[:op]:value joined by | (AND); op is optional and defaults to eq; comma-separate values within a clause for an IN match. Supported keys for this endpoint: namespace (eq), blockedCostHourly (eq/gte/lte, compares numerically on the underlying cost value, not the serialized Money object), nodeGroup (eq), labels.<key> (eq). labels.<key> matches against the pod's Kubernetes labels — for example filter=labels.team:payments matches pods labeled team=payments. An unsupported key returns 400 with code: "filter_key_not_supported". Mute-status filtering is handled by the separate mute parameter, not this filter.
mutequeryNo"exclude", "include", "only"Muted-finding handling: exclude (default) hides rows whose workload has a dismissal rule; include returns all rows, flagged via mute; only returns exclusively muted rows, for auditing what's been silenced.
sortByqueryNo"blockedCostHourly"Field to sort results by. blockedCostHourly sorts numerically on the underlying cost value, not the serialized Money object. Unset falls back to a stable but unspecified order (currently pod UID). Ties are always broken by UID for stable pagination.
sortOrderqueryNo"asc", "desc"Sort direction, applied only when sortBy is set.
pageSizequeryNointegerNumber of items per page (default 50, max 500)
pageTokenqueryNostringOpaque cursor token for pagination

Responses

StatusDescriptionBody
200List of unevictable pod issue rowsapplication/json: object
202Raw snapshot exists but is still being processedapplication/json: object
400Invalid parametersapplication/problem+json: Problem
404Cluster or snapshot not foundapplication/problem+json: Problem
422Raw snapshot exists but processing failedapplication/problem+json: Problem
500Internal server errorapplication/problem+json: Problem

200 application/json body

PropertyTypeRequiredDescription
dataarray of UnevictableReportRowYes
metaobjectYes
meta.paginationPaginationMetaYes
meta.snapshotTimestring · date-timeYesTimestamp (RFC 3339, UTC) of the snapshot the data was read from
meta.algorithmVersionstringYesVersion of the unevictable-detection algorithm/library used to produce the snapshot
meta.summaryUnevictableSummaryYes

202 application/json body

PropertyTypeRequiredDescription
dataUnevictablePodsStatusYes

UnevictableReportRow

One row of the per-pod issues view — a single unevictable pod with all its reasons combined.

PropertyTypeRequiredDescription
namestringYes
idstringYes
workloadUnevictableWorkloadRefYes
namespacestringYes
labelsobjectNo
nodestring,nullNoNode the pod is scheduled on; null for Pending pods.
nodeGroupstringNoNode group the pod's node belongs to; empty if the node's node group is unresolved.
reasonsarray of UnevictableReasonYesAll unevictable reasons for this pod.
mutebooleanYesTrue when the pod's workload is muted by a dismissal rule, muting all of its reasons.
priorityintegerNoKubernetes pod scheduling priority (from the pod's PriorityClass); same value as UnevictablePod.spec.priority.
blockedCostHourlyMoneyNoHourly cost of the blocked nodes. Filtering (blockedCostHourly:gte:<amount>) and sorting compare numerically on the underlying cost value, not the serialized Money object.

UnevictableWorkloadRef

Identity of the pod's top-level owning workload.

PropertyTypeRequiredDescription
idstringYesCanonical workload id (namespace-kind-name) of the top-level controller.
namestringNoDenormalized workload name for display.
typestringYesKubernetes workload kind (e.g. Deployment, StatefulSet, DaemonSet).

UnevictableReason

PropertyTypeRequiredDescription
reasonstringYesShort reason code (e.g. "Topology-Locked", "PDB Violation").
reasonCodeUnevictableReasonCode / nullNoStable slug derived from the display reason. Null for unrecognised reasons.
detailsstringYesHuman-readable explanation.
remediationUnevictableRemediationNo
mutebooleanNoTrue when this reason is covered by a dismissal rule and therefore muted.
mutedByRuleUnevictableMutedByRule / nullNo

UnevictableReasonCode

Stable canonical identifier for an unevictable reason. Decoupled from the mutable display string.

"opt_out_annotation", "pod_disruption_budget", "strict_affinity", "strict_anti_affinity", "topology_locked", "taints_not_tolerated", "local_node_storage", "static_mirror_pod"

UnevictableRemediation

Reason-specific fix. current/recommended spec and the yaml diff are null for partial/informational cases.

PropertyTypeRequiredDescription
fixSummarystringYesOne-line plain-language fix.
risk"none", "low", "medium", "high"Yes
confidence"low", "medium", "high"Yes
currentSpecstring,nullNoRendered YAML of the current spec; null for partial/informational cases.
recommendedSpecstring,nullNoRendered YAML of the recommended spec; null for partial/informational cases.
yamlDiffstring,nullNoUnified diff string; null when there is no clean diff.

UnevictableMutedByRule

Summary of the dismissal rule that suppressed this finding.

PropertyTypeRequiredDescription
notestring,nullNo
createdBystringYesEmail of the user who created the rule.
createTimestring · date-timeYesWhen the rule was created (RFC 3339 UTC)

Money

Monetary amount with currency

PropertyTypeRequiredDescription
amountstringYesDecimal string representation of the amount (e.g. "100.50")
currencystringYesISO 4217 currency code (e.g. "USD")

PaginationMeta

Cursor-based pagination metadata for list responses.

PropertyTypeRequiredDescription
nextstring,nullYesOpaque cursor token for the next page, or null if this is the last page
prevstring,nullYesOpaque cursor token for the previous page, or null if this is the first page
pageSizeintegerYesNumber of items per page used for this response

UnevictableSummary

Aggregate pod/node counts for the snapshot backing the listing response.

PropertyTypeRequiredDescription
totalPodsintegerYesTotal number of pods observed in the snapshot.
unevictablePodsintegerYesNumber of pods detected as unevictable in the snapshot.
muteintegerYesNumber of unevictable findings muted by a dismissal rule in this snapshot.
totalNodesintegerYesTotal number of nodes observed in the snapshot.
autoscalerTypestringNoDetected autoscaler, rolled up from per-node detection (canonical values, e.g. "cluster_autoscaler", "karpenter", "castai", "eks_auto_mode"). Omitted if not detected. Results written before PSD-9016 may carry the legacy hyphenated "cluster-autoscaler".

UnevictablePodsStatus

Snapshot processing status, returned on 202 (still processing) and 422 (processing failed) instead of pod/report data.

PropertyTypeRequiredDescription
status"processing", "failed"Yes

Problem

RFC 9457 Problem Details error body, served as application/problem+json. code is a stable machine-readable identifier (e.g. filter_key_not_supported, not_found, internal_error); retryable indicates whether retrying the same request may succeed without client-side changes.

PropertyTypeRequiredDescription
typestringYesURI reference identifying the problem type.
titlestringYesShort, human-readable summary of the problem type.
statusintegerYesHTTP status code generated by the origin server for this occurrence of the problem.
detailstringNoHuman-readable explanation specific to this occurrence of the problem.
instancestringNoURI reference identifying the specific occurrence of the problem.
codestringYesStable machine-readable error code.
retryablebooleanYesWhether retrying the same request may succeed without client-side changes.

Download OpenAPI specification

Get a single unevictable pod

Full detail for one pod (all reasons with the full remediation object), served from the latest pre-computed snapshot (no request-time recompute). Tenant resolved from the auth token; a cluster belonging to another tenant, or a pod not present in the latest snapshot, returns 404.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{clusterUid}/unevictable-pods/{podUid}

Get a single unevictable pod

Full detail for one pod (all reasons with the full remediation object), served from the latest pre-computed snapshot (no request-time recompute). Tenant resolved from the auth token; a cluster belonging to another tenant, or a pod not present in the latest snapshot, returns 404.

Parameters

NameLocationRequiredTypeDescription
clusterUidpathYesstringCluster unique identifier
podUidpathYesstringPod unique identifier

Responses

StatusDescriptionBody
200Single unevictable pod, returned directly (no envelope)application/json: UnevictablePod
202Raw snapshot exists but is still being processed, returned directly (no envelope)application/json: UnevictablePodsStatus
404Cluster or snapshot not found, or no pod with this uid in the latest snapshotapplication/problem+json: Problem
422Raw snapshot exists but processing failedapplication/problem+json: Problem
500Internal server errorapplication/problem+json: Problem

UnevictablePod

A single unevictable pod from the latest pre-computed snapshot for the cluster. Returned both as a list item and as the single-pod detail response — the detail response additionally populates siblingPodNames.

PropertyTypeRequiredDescription
namestringYes
namespacestringYes
idstringYes
workloadUnevictableWorkloadRefYes
reasonsarray of UnevictableReasonYesEmpty = pod is evictable; non-empty = unevictable.
phasestringYes
startTimestring · date-timeYesPod creation timestamp (RFC 3339 UTC).
labelsobjectNo
annotationsobjectNo
specUnevictablePodSpecNo
blockedNodeCountintegerNoNumber of nodes this pod blocks from scaling down.
blockedNodesarray of stringNoNames of the nodes this pod pins.
blockedCostHourlyMoneyNoHourly cost of the blocked nodes (Total Blocked Cost). Filtering (blockedCostHourly:gte:<amount>) and sorting compare numerically on the underlying cost value, not the serialized Money object.
clusterUidstringNo
mutebooleanNoTrue when the pod's workload is muted by a dismissal rule, muting all of its reasons.
siblingPodNamesarray of stringNoNames of other pods of the same workload id in this snapshot. Populated only by the single-pod detail endpoint.

UnevictableWorkloadRef

Identity of the pod's top-level owning workload.

PropertyTypeRequiredDescription
idstringYesCanonical workload id (namespace-kind-name) of the top-level controller.
namestringNoDenormalized workload name for display.
typestringYesKubernetes workload kind (e.g. Deployment, StatefulSet, DaemonSet).

UnevictableReason

PropertyTypeRequiredDescription
reasonstringYesShort reason code (e.g. "Topology-Locked", "PDB Violation").
reasonCodeUnevictableReasonCode / nullNoStable slug derived from the display reason. Null for unrecognised reasons.
detailsstringYesHuman-readable explanation.
remediationUnevictableRemediationNo
mutebooleanNoTrue when this reason is covered by a dismissal rule and therefore muted.
mutedByRuleUnevictableMutedByRule / nullNo

UnevictableReasonCode

Stable canonical identifier for an unevictable reason. Decoupled from the mutable display string.

"opt_out_annotation", "pod_disruption_budget", "strict_affinity", "strict_anti_affinity", "topology_locked", "taints_not_tolerated", "local_node_storage", "static_mirror_pod"

UnevictableRemediation

Reason-specific fix. current/recommended spec and the yaml diff are null for partial/informational cases.

PropertyTypeRequiredDescription
fixSummarystringYesOne-line plain-language fix.
risk"none", "low", "medium", "high"Yes
confidence"low", "medium", "high"Yes
currentSpecstring,nullNoRendered YAML of the current spec; null for partial/informational cases.
recommendedSpecstring,nullNoRendered YAML of the recommended spec; null for partial/informational cases.
yamlDiffstring,nullNoUnified diff string; null when there is no clean diff.

UnevictableMutedByRule

Summary of the dismissal rule that suppressed this finding.

PropertyTypeRequiredDescription
notestring,nullNo
createdBystringYesEmail of the user who created the rule.
createTimestring · date-timeYesWhen the rule was created (RFC 3339 UTC)

UnevictablePodSpec

Raw Kubernetes PodSpec fields used by detection, verbatim from the pod.

PropertyTypeRequiredDescription
nodestring,nullNoNode the pod is scheduled on (spec.nodeName); null for Pending pods.
nodeGroupstringNoNode group the pod's node belongs to; empty if the node's node group is unresolved.
priorityintegerNoKubernetes pod scheduling priority (spec.priority, from the pod's PriorityClass).
nodeSelectorobjectNo
affinityUnevictablePodAffinityNo
tolerationsarray of UnevictablePodTolerationNo
containersarray of UnevictablePodContainerNo
volumesarray of UnevictablePodVolumeNo
topologySpreadConstraintsarray of UnevictablePodTopologySpreadConstraintNo
ownerReferencesarray of UnevictablePodOwnerReferenceNoThe pod's metadata.ownerReferences, as the subset of fields described above. Omitted when the pod has no owner (e.g. static/mirror pods — see the static_mirror_pod reason code).

UnevictablePodAffinity

Simplified affinity block — only the sub-fields used by detection are modelled.

PropertyTypeRequiredDescription
nodeAffinityobjectNo
podAffinityobjectNo
podAntiAffinityobjectNo

UnevictablePodToleration

PropertyTypeRequiredDescription
keystringYes
operatorstringYes
valuestringNo
effectstringYes

UnevictablePodContainer

PropertyTypeRequiredDescription
namestringYes
imagestringYes
cpuRequestCoresnumber,null · doubleNoCPU requested for the container, in cores; null if unset.
cpuLimitCoresnumber,null · doubleNoCPU limit for the container, in cores; null if unset.
memoryRequestMiBnumber,null · doubleNoMemory requested for the container, in MiB; null if unset.
memoryLimitMiBnumber,null · doubleNoMemory limit for the container, in MiB; null if unset.
gpuRequestinteger,nullNoGPU units requested for the container (e.g. nvidia.com/gpu); null if unset. GPU requests/limits are always whole units.
gpuLimitinteger,nullNoGPU units the container is limited to (e.g. nvidia.com/gpu); null if unset. GPU requests/limits are always whole units.

UnevictablePodVolume

PropertyTypeRequiredDescription
namestringYes
hostPathstringNo
emptyDirstringNo
pvcClaimNamestringNo

UnevictablePodTopologySpreadConstraint

PropertyTypeRequiredDescription
maxSkewinteger · int32Yes
topologyKeystringYes
whenUnsatisfiablestringYes
labelSelectorobjectNo

UnevictablePodOwnerReference

A subset of the pod's Kubernetes OwnerReference fields (apiVersion, kind, name, controller) used for ownership detection; not a complete copy of metadata.ownerReferences (e.g. uid is omitted).

PropertyTypeRequiredDescription
apiVersionstringYes
kindstringYes
namestringYes
controllerboolean,nullNoTrue when this reference is the pod's managing controller.

Money

Monetary amount with currency

PropertyTypeRequiredDescription
amountstringYesDecimal string representation of the amount (e.g. "100.50")
currencystringYesISO 4217 currency code (e.g. "USD")

UnevictablePodsStatus

Snapshot processing status, returned on 202 (still processing) and 422 (processing failed) instead of pod/report data.

PropertyTypeRequiredDescription
status"processing", "failed"Yes

Problem

RFC 9457 Problem Details error body, served as application/problem+json. code is a stable machine-readable identifier (e.g. filter_key_not_supported, not_found, internal_error); retryable indicates whether retrying the same request may succeed without client-side changes.

PropertyTypeRequiredDescription
typestringYesURI reference identifying the problem type.
titlestringYesShort, human-readable summary of the problem type.
statusintegerYesHTTP status code generated by the origin server for this occurrence of the problem.
detailstringNoHuman-readable explanation specific to this occurrence of the problem.
instancestringNoURI reference identifying the specific occurrence of the problem.
codestringYesStable machine-readable error code.
retryablebooleanYesWhether retrying the same request may succeed without client-side changes.

Download OpenAPI specification

List unevictable muted workloads for a cluster

Read-only list of workloads that have an active mute (dismissal) rule for the cluster. Rules are created and removed via the web app / user API only; this endpoint does not expose write operations. Tenant resolved from the auth token; a cluster belonging to another tenant returns 404.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters/{clusterUid}/unevictable-muted-workloads

List unevictable muted workloads for a cluster

Read-only list of workloads that have an active mute (dismissal) rule for the cluster. Rules are created and removed via the web app / user API only; this endpoint does not expose write operations. Tenant resolved from the auth token; a cluster belonging to another tenant returns 404.

Parameters

NameLocationRequiredTypeDescription
clusterUidpathYesstringCluster unique identifier
pageSizequeryNointegerNumber of items per page (default 50, max 500)
pageTokenqueryNostringOpaque cursor token for pagination

Responses

StatusDescriptionBody
200List of muted workloads for the clusterapplication/json: object
400Invalid parametersapplication/problem+json: Problem
404Cluster not foundapplication/problem+json: Problem
500Internal server errorapplication/problem+json: Problem

200 application/json body

PropertyTypeRequiredDescription
dataarray of UnevictableMutedWorkloadYes
metaobjectYes
meta.paginationPaginationMetaYes

UnevictableMutedWorkload

PropertyTypeRequiredDescription
clusterUidstringYes
idstringYesCanonical workload id (namespace-kind-name) of the top-level controller.
namespacestringNo
workloadNamestringNoDenormalized workload name for display.
notestringNo
createdBystringYesEmail of the user who created the rule.
createTimestring · date-timeYesWhen the rule was created (RFC 3339 UTC)
updateTimestring · date-timeYesWhen the rule was last updated (RFC 3339 UTC)

PaginationMeta

Cursor-based pagination metadata for list responses.

PropertyTypeRequiredDescription
nextstring,nullYesOpaque cursor token for the next page, or null if this is the last page
prevstring,nullYesOpaque cursor token for the previous page, or null if this is the first page
pageSizeintegerYesNumber of items per page used for this response

Problem

RFC 9457 Problem Details error body, served as application/problem+json. code is a stable machine-readable identifier (e.g. filter_key_not_supported, not_found, internal_error); retryable indicates whether retrying the same request may succeed without client-side changes.

PropertyTypeRequiredDescription
typestringYesURI reference identifying the problem type.
titlestringYesShort, human-readable summary of the problem type.
statusintegerYesHTTP status code generated by the origin server for this occurrence of the problem.
detailstringNoHuman-readable explanation specific to this occurrence of the problem.
instancestringNoURI reference identifying the specific occurrence of the problem.
codestringYesStable machine-readable error code.
retryablebooleanYesWhether retrying the same request may succeed without client-side changes.

Download OpenAPI specification

Infrafit GitHub actions

The InfraFit GitHub Action turns PerfectScale Karpenter NodePool recommendations into ready-to-review pull requests. It fetches recommendations from the PerfectScale API, maps them to the matching Karpenter YAML files in your repository, applies the changes, and opens a PR with the diff. You can create one PR per cluster or combine changes into a single PR.

情報

If a recommendation cannot be applied automatically, the action creates a GitHub issue instead, so no recommendation is missed.

The action never changes a live cluster. All changes are proposed through pull requests, and your existing review and approval process remains the control point.

How it helps:

  • Reduces manual work. Recommendations are delivered as ready-to-review YAML changes instead of requiring engineers to update files by hand.
  • Keeps recommendations actionable. Changes appear directly in GitHub, where engineering teams already manage infrastructure work.
  • Fits GitOps workflows. Every change is reviewable, attributable, and recorded in git history. Engineers can approve, edit, or close each PR.
  • Requires no new infrastructure. The action runs on existing GitHub Actions runners and supports Anthropic, OpenAI, Amazon Bedrock, GitHub Copilot, Azure OpenAI, and OpenAI-compatible endpoints.
  • Keeps configuration aligned over time. Run the action on a schedule to continuously update Karpenter configuration as workload behavior changes.
情報

Access more information about Infrafit GitHub actions here.

How to get cluster_uid

There are two options available to obtain the cluster_uid.

  1. Get cluster_uid directly from PerfectScale UI:
    • Go to the Overview tab

    • Click the three-dot button located next to the needed cluster

      PerfectScale documentation illustration

      Get cluster UID

    • Click the Copy Cluster UID button -> now, your cluster_uid is copied.

      PerfectScale documentation illustration

      Cluster UID copied

  2. Get cluster_uid with the following command:
kubectl get namespace kube-system -o=jsonpath='{.metadata.uid}'
  1. Get the full list of clusters via API and extract cluster_uids from it.

Automation Audit Log Endpoint

The Automation Audit Log provides visibility into all actions performed by PerfectScale automation. This endpoint allows teams to programmatically access, retrieve, and filter audit logs and seamlessly integrate them into their existing systems or tools.

情報

The Automation Audit Log shows data from the last 30 days.

Get Automation Audit Logs with Cursor Pagination

Retrieves a list of automation audit log entries within a specified time range, using cursor-based pagination.

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

POST /automation/audit_logs

Get Automation Audit Logs with Cursor Pagination

Retrieves a list of automation audit log entries within a specified time range, using cursor-based pagination.

Request body

application/json: object

PropertyTypeRequiredDescription
fromstring · date-timeNoThe start of the time range in ISO 8601 format with UTC timezone (e.g., "2025-09-17T00:00:00Z"). If omitted, defaults to 00:00:00 UTC of the day that is 30 days ago from today. Constraints: - Must be in UTC timezone (ends with 'Z' or has '+00:00' offset) - Cannot be in the future - Cannot be before 00:00:00 UTC of 30 days ago from today - Must be before 'to' date when both are provided - Must be different from 'to' date Example: If today is 2025-10-17, the earliest allowed value is "2025-09-17T00:00:00Z"
tostring · date-timeNoThe end of the time range in ISO 8601 format with UTC timezone (e.g., "2025-10-17T23:59:59Z"). If omitted, defaults to the current time in UTC. Constraints: - Must be in UTC timezone (ends with 'Z' or has '+00:00' offset) - Cannot be in the future - Must be after 'from' date when both are provided - Must be different from 'from' date
page_sizeintegerNoThe maximum number of items to return. Defaults to 1000. Must be between 1 and 5000. Default: 1000 Minimum: 1 Maximum: 5000
page_tokenstringNoAn opaque token from the 'next' or 'prev' field in the response's pagination object, used to fetch the next/previous page. The token encodes both the boundary position and the page direction. Preferred over the deprecated 'after'/'before' fields.
afterstringNoDeprecated: use 'page_token' instead. An opaque token from the 'next' field in the response's pagination object, used to fetch the next page.
beforestringNoDeprecated: use 'page_token' instead. An opaque token from the 'prev' field in the response's pagination object, used to fetch the previous page.
cluster_uidsarray of stringNoFilter by cluster UIDs. Accepts multiple cluster UIDs to filter the audit logs.
namespacesarray of stringNoFilter by Kubernetes namespaces. Accepts multiple namespaces to filter the audit logs.

Responses

StatusDescriptionBody
200OKapplication/json: object

200 application/json body

PropertyTypeRequiredDescription
dataarray of AutomationLogEntryYes
metaobjectYes
meta.paginationPaginationNo

AutomationLogEntry

PropertyTypeRequiredDescription
started_atstring · date-timeYesTimestamp when the action started.
cluster_namestringYesName of the cluster.
cluster_uidstringYesID of the cluster.
workload_idstringYesID of the workload.
workload_namestringYesName of the workload.
workload_typestringYesType of deployment.
namespacestringYesNamespace of the workload.
labelsobjectYesLabels associated with the workload.
containerAutomatedLogsContainerYes
executedExecutionTypeYes
workload_indicatorsarray of IndicatorNoWorkload-level indicators addressed by the automation change.

AutomatedLogsContainer

Properties of the container.

PropertyTypeRequiredDescription
namestringYesName of the container.
cpuAutomatedLogsContainerCpuYes
memoryAutomatedLogsContainerMemoryYes
indicatorsarray of IndicatorNoContainer-level indicators addressed by the automation change.

AutomatedLogsContainerCpu

CPU related properties.

PropertyTypeRequiredDescription
cpuCoresRequestinteger · int64YesRequest of cpu before apply of automation.
recommendCpuCoresRequestinteger · int64YesRequest of cpu after apply of automation.
cpuCoresLimitsinteger · int64YesLimit of cpu before apply of automation.
recommendCpuCoresLimitsinteger · int64YesLimit of cpu after apply of automation.
cpuRequestImpactinteger · int64YesImpact of automation on cpu request value.
cpuLimitImpactinteger · int64YesImpact of automation on cpu limit value.
cpuRequestChangePercentnumber · doubleYesSingle instance cpu request change in %.
cpuLimitChangePercentnumber · doubleYesSingle instance cpu limit change in %.
cpuRequestChangeAbsoluteinteger · int64YesSingle instance cpu request absolute value change.
cpuLimitChangeAbsoluteinteger · int64YesSingle instance cpu limit absolute value change.

AutomatedLogsContainerMemory

Memory related properties.

PropertyTypeRequiredDescription
memMiBRequestinteger · int64YesRequest of memory before apply of automation.
recommendMemMiBRequestinteger · int64YesRequest of memory after apply of automation.
memMiBLimitsinteger · int64YesLimit of memory before apply of automation.
recommendMemMiBLimitsinteger · int64YesLimit of memory after apply of automation.
memMiBRequestImpactinteger · int64YesImpact of automation on memory request value.
memMiBLimitImpactinteger · int64YesImpact of automation on memory limit value.
memRequestChangePercentnumber · doubleYesSingle instance memory request change in %.
memLimitChangePercentnumber · doubleYesSingle instance memory limit change in %.
memMiBRequestChangeAbsoluteinteger · int64YesSingle instance memory request absolute value change.
memMiBLimitChangeAbsoluteinteger · int64YesSingle instance memory limit absolute value change.

Indicator

A risk/waste signal addressed by an automation change.

PropertyTypeRequiredDescription
namestringYesIndicator name.
typestringYesIndicator type (e.g. risk, waste, none).
severityintegerYesSeverity level (0 = none, higher = more severe).

ExecutionType

"regular-eviction", "inplace-resize", "cleanup"

Pagination

PropertyTypeRequiredDescription
has_nextbooleanYesDeprecated: derive from 'next' (true when 'next' is non-null).
nextstring · nullableYesAn opaque token to be used in the 'page_token' parameter to fetch the next page.
has_prevbooleanYesDeprecated: derive from 'prev' (true when 'prev' is non-null).
prevstring · nullableYesAn opaque token to be used in the 'page_token' parameter to fetch the previous page.
page_sizeintegerYesThe maximum number of items to return. Defaults to 1000. Must be between 1 and 5000.

Download OpenAPI specification

Deleting an API Token

In certain situations, you may find it necessary to delete an API token.

Follow these easy steps:

  1. Click on the Profile button in the bottom left corner and select Organization Settings.
  2. In the pop-up window, navigate to the API Tokens tab.
  3. Click the hamburger on the right-hand side, select Delete API Token, and click the Delete button.
PerfectScale documentation illustration

Delete API token

Deleting a cluster

情報

The endpoint removes the cluster from PerfectScale without deleting the cluster itself.

There may be situations where you need to remove a cluster from PerfectScale. You can seamlessly delete a cluster using Public API:

DELETE /clusters/{cluster_uid}

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

DELETE /clusters/{cluster_uid}

Parameters

NameLocationRequiredTypeDescription
cluster_uidpathYesstring

Responses

StatusDescriptionBody
200OK
404NotFound

Download OpenAPI specification

How to get cluster UID

To get a cluster UID with a few clicks, navigate to the Overview tab, hover over the needed cluster, and click the three dots button. Then click Copy Cluster UID so that it will be automatically copied to the clipboard.

PerfectScale documentation illustration

Get cluster UID

How to list all cluster UIDs

You can seamlessly list all the clusters' UIDs of the tenant by using the following API:

Server: https://api.app.perfectscale.io/public/v1

Authentication (auth): http — bearer — JWT

GET /clusters

List all clusters for a tenant

Responses

StatusDescriptionBody
200A list of all clustersapplication/json: object
400Bad Request
401Unauthorized
500Internal server error

200 application/json body

PropertyTypeRequiredDescription
dataarray of ClusterYes

Cluster

A Kubernetes cluster basic information.

PropertyTypeRequiredDescription
uidstringNoA unique identifier for the cluster. If it hasn't sent any information yet, value will be null
namestringNoName for the cluster. This is the name assigned when creating the cluster in PerfectScale Overview page
cloudstringNoCloud name - free text assigned when creating or updating the cluster in PerfectScale Overview page
regionstringNoRegion name - free text assigned when creating or updating the cluster in PerfectScale Overview page
createdAtstring · date-timeNoThe timestamp when the cluster was created, formatted as an ISO 8601 date-time string.
lastTransmittedAtstring · date-timeNoThe timestamp when the cluster transmitted data for the last time, formatted as an ISO 8601 date-time string.

Workload

A representation of a workload within a Kubernetes cluster.

PropertyTypeRequiredDescription
idstringYesA unique identifier for the workload, usually following a namespace-type-name convention.
namestringYesA human-readable name for the workload.
typestringYesThe type of Kubernetes workload. Common types include Deployment, StatefulSet, and DaemonSet, but other string values can also be used to represent custom or extended workload types.
namespacestringYesThe Kubernetes namespace in which the workload resides.
firstSeenstring · date-timeYesThe timestamp when the workload was first observed, formatted as an ISO 8601 date-time string.
lastSeenstring · date-timeYesThe timestamp when the workload was last observed, formatted as an ISO 8601 date-time string.
runningMinutesintegerYesThe total number of minutes the workload has been running.
replicasCountsReplicasCountsYes
resilienceLevel"low", "medium", "high", "highest"YesThe resilience level of the workload, indicating its tolerance to failures or disruptions (configured on Perfectscale side).
muteStatusMuteStatusYes
costAnalysisCostAnalysisYes
workloadLabelsobjectYesKey-value pairs representing kubernets labels associated with the workload.
indicatorsarray of IndicatorYesA list of indicators providing insights into the performance and health of the workload.
containersobjectYesAn object holding detailed information about each container within the workload.

ReplicasCounts

An object representing the count statistics of replicas for a workload over a month period.

PropertyTypeRequiredDescription
maxCountintegerYesThe maximum count of replicas observed for the workload during the month period.
avgCountintegerYesThe average count of replicas observed for the workload during the month period.

MuteStatus

The mute status of a workload, indicating whether the workload is currently muted and when it will become unmuted.

PropertyTypeRequiredDescription
isMutedbooleanYesIndicates whether the workload is currently muted.
muteExpirystring · date-timeNoThe date and time when the workload will automatically become unmuted. If null, the mute status does not expire automatically.

Resources

Metrics detailing the resource allocation in terms of memory and CPU.

PropertyTypeRequiredDescription
memoryRequestMiBnumber · doubleYesThe amount of memory requested for the workload in MiB.
memoryLimitMiBnumber · doubleYesThe maximum amount of memory that can be allocated for the workload in MiB.
cpuRequestCoresnumber · doubleYesThe amount of CPU resources requested for the workload in cores.
cpuLimitCoresnumber · doubleYesThe maximum amount of CPU resources that can be allocated for the workload in cores.

Past30DaysCostAnalysis

Metrics detailing the total and wasted costs associated with the workload's resource consumption.

PropertyTypeRequiredDescription
totalCostnumber · doubleYesThe total cost incurred by the workload's resource consumption.
wastedCostnumber · doubleYesThe cost attributed to over-provisioned or inefficiently utilized resources.

CostAnalysis

Analysis of the costs associated with the workload's resource consumption over the past 30 days and projected for the next 30 days.

PropertyTypeRequiredDescription
past30DaysPast30DaysCostAnalysisYes
costIncreasenumber · doubleYesThe increased cost associated with the workload.

Indicator

An object representing key performance indicators that provide insights into the performance and health of the workload or container.

PropertyTypeRequiredDescription
name"OOM", "CpuThrottling", "CpuRequestNotSet", "MemRequestNotSet", "MemLimitNotSet", "UnderProvisionedMemRequest", "UnderProvisionedMemLimit", "UnderProvisionedCpuRequest", "UnderProvisionedCpuLimit", "OverProvisionedCpuRequest", "OverProvisionedMemRequest", "RestartsObserved"YesThe name of the indicator representing a specific aspect of performance or health.
type"none", "risk", "waste"YesThe type of indicator, categorizing it as either a risk, waste, or no issue (none).
severityLevel0, 1, 2, 3YesThe severity level of the indicator, ranging from 0 (no issue) to 3 (critical issue).

Container

Detailed information about a specific container within the workload, including its performance indicators and usage statistics.

PropertyTypeRequiredDescription
namestringYesThe name of the container.
runningMinutesintegerYesThe total number of minutes the container has been running.
indicatorsarray of IndicatorYesA list of indicators providing insights into the performance and health of the container.
resourcesobjectYesThe resource allocation details for the workload, including the current and recommended by PerfectScale allocation.
resources.currentResourcesYes
resources.recommendedResourcesYes
usageobjectYesAn object representing the resource usage statistics of a container, broken down into CPU and memory consumption.
usage.cpuCoresPercentilesYes
usage.memoryMiBPercentilesYes

Percentiles

An object representing percentile statistics of resource usage, providing insights into the distribution of usage values over a certain period.

PropertyTypeRequiredDescription
p90number · doubleYesThe 90th percentile value of resource usage, indicating that 90% of the usage values are below this value and 10% are above.
p95number · doubleYesThe 95th percentile value of resource usage, indicating that 95% of the usage values are below this value and 5% are above.
p100number · doubleYesThe 100th percentile value (or maximum value) of resource usage observed during the specified period.

Download OpenAPI specification