> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ankra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Savings model for the organisation

> The organisation's savings model: right-size and off-hours recommendations across the biggest priced clusters, the cost breakdowns they were read from, the clusters the fleet cannot price, and the waste scan, in the caller's display currency (`ankra cost savings`). One cluster counts once in the total, at its best lever. Bearer-PAT twin of the browser route of the same name under /org.



## OpenAPI

````yaml https://platform.ankra.app/openapi.json get /api/v1/org/cloud-cost/savings
openapi: 3.1.0
info:
  title: Ankra Platform API
  version: v1
  description: >-
    The Ankra platform HTTP contract. The /api/v1 surface is the public,
    bearer-authenticated API used by the Ankra CLI, MCP clients and automation;
    send a personal or service API token as `Authorization: Bearer <token>`.
    Browser routes under /org and /chat are served on api.platform.ankra.app
    (each declares that server); they and /oauth/access authenticate with the
    ankra_session cookie, and mutations also require the X-Ankra-CSRF header.
    Every operation declares the credential it accepts, and no operation is
    served without one. This document is published deliberately: it describes
    the contract only and carries no organisation data or credentials. Report
    security issues to security@ankra.ai (see /.well-known/security.txt).
servers:
  - url: https://platform.ankra.app
security:
  - BearerAuth: []
tags:
  - name: Onboarding
    description: >-
      Generate a first website from a prompt and deploy it to a new
      organisation's cluster.
  - name: Access Gate
    description: >-
      Private service sign-in and membership checks for trusted Ankra proxy
      relays.
  - name: Canvas Datasets
    description: >-
      Read the fixed, named datasets canvas dashboards bind their charts, tables
      and stats to.
  - name: Canvases
    description: >-
      Keep dashboards and pages in the organisation's canvas library, with
      revision history, undo and pins.
  - name: Canvas Pages
    description: >-
      Publish a chat canvas artifact at a public pages address and take it down
      again.
  - name: Cloud Delegation
    description: >-
      Platform browser consent and organisation-bound connections for Ankra
      Cloud.
  - name: Organisation IAM
    description: >-
      Custom organisation roles and scoped role assignments for member and
      service-account identities.
  - name: Clusters
    description: Create, inspect and manage clusters, and the stacks deployed on them.
  - name: Managed Clusters
    description: Provider-managed control planes, driven through one common surface.
  - name: Imported Clusters
    description: Clusters that already existed and were connected to Ankra.
  - name: Cluster Access
    description: Kubeconfigs, service-account tokens and per-cluster access grants.
  - name: Kubernetes
    description: Read and act on the Kubernetes objects inside a cluster.
  - name: AWS Clusters
    description: >-
      Provision and manage self-managed k3s / kubeadm clusters on AWS EC2 in
      your own VPC.
  - name: Ankra Cloud Clusters
    description: >-
      Provision and manage self-managed kubeadm / k3s clusters on Ankra Cloud
      servers: a private network, a NAT router and a bastion per cluster.
  - name: DigitalOcean Clusters
    description: Provision and manage DigitalOcean Kubernetes clusters.
  - name: Hetzner Clusters
    description: Provision and manage Hetzner Kubernetes clusters.
  - name: OVH Clusters
    description: Provision and manage OVH Kubernetes clusters.
  - name: Scaleway Clusters
    description: Provision and manage Scaleway Kapsule clusters.
  - name: UpCloud Clusters
    description: Provision and manage UpCloud Kubernetes clusters.
  - name: Applications
    description: Deploy, configure and observe applications across the fleet.
  - name: Pipelines
    description: >-
      Pipeline definitions, the approval of the authority they declare, and the
      caches pipelines keep between runs.
  - name: Workspaces
    description: >-
      Personal workspaces on the organisation's CI pool where a repository's
      heavy commands run, and the repository profiles they are built from.
  - name: Deploy Targets
    description: >-
      Environments, the hosts registered to receive deployments, and the
      releases deployed to them.
  - name: Deploy Provenance
    description: >-
      Whether an application's deploys verify signed provenance from the
      organisation's own pipeline, the keys that provenance is signed with, and
      a dry-run that verifies images without deploying.
  - name: Backups
    description: >-
      Backup vaults, restore points, protection posture and captures for stacks
      and application deployments; a completed capture is not a verified
      restore.
  - name: Stack Profiles
    description: Reusable stack definitions, their versions and sharing.
  - name: Services
    description: >-
      Versioned service packages and explicit sharing. Runtime admission is
      separate from publication.
  - name: Charts
    description: Browse the chart catalogue behind stacks and addons.
  - name: Helm
    description: Helm registries, credentials and the charts they expose.
  - name: Executions
    description: Long-running platform executions and their jobs.
  - name: Operations
    description: Cancel in-flight cluster operations and their jobs.
  - name: Chat
    description: Conversational sessions, plans and confirmable actions.
  - name: AI Management
    description: >-
      Customer agent lifecycle, authenticated identity and organisation
      automation controls.
  - name: AI Agent Runs
    description: Autonomous agent runs and their outcomes.
  - name: AI Tickets
    description: The AI ticket board, its sync connections and settings.
  - name: AI Playbooks
    description: Reusable playbooks the AI lanes execute.
  - name: AI Conditions
    description: Conditions that gate AI autonomy.
  - name: AI Remediation
    description: >-
      The organisation's auto-remediation policy: what the AI lanes may fix by
      themselves, and who approves the rest.
  - name: AI Engineering Handoffs
    description: Work the AI lanes escalate to a human engineer.
  - name: AI Environment
    description: The environment and base stacks AI demos deploy into.
  - name: AI Memory
    description: >-
      What the assistant has learned about you: your cross-session memories and
      learned profile.
  - name: MCP Servers
    description: >-
      Register the MCP servers the organisation's AI agents can call, choose
      their tools and grant them to roles.
  - name: Security
    description: Findings, advisories, SBOMs, compliance and posture.
  - name: Cost
    description: Cluster and fleet cost, rate cards and cost settings.
  - name: Decisions
    description: >-
      The decision ledger behind the Security and Cost queues: proposals a
      surface computed, the approve and set-aside decisions people took on them,
      and the receipts of running them.
  - name: Usage
    description: >-
      What your organisation used of Ankra - vCPU-hours, playgrounds, managed
      services, hosted logs and metrics, and AI - per meter and period, with how
      completely it was measured and whether a published rate applies.
  - name: Billing
    description: Subscription and spend caps.
  - name: Organisation
    description: Members, invitations, audit logs and organisation settings.
  - name: Account
    description: >-
      Your own account: the contact email Ankra mails when it differs from your
      sign-in address.
  - name: Account Tokens
    description: Personal access tokens for the API and CLI.
  - name: Credentials
    description: The shared credential store.
  - name: AWS Credentials
    description: >-
      AWS credentials: access keys or CloudFormation-onboarded STS roles for
      cost, EKS and self-managed provisioning.
  - name: Ankra Cloud Credentials
    description: >-
      Ankra Cloud API tokens, shared by the self-managed and managed Ankra Cloud
      lanes.
  - name: Azure Credentials
    description: Azure credentials and SSH keys.
  - name: DigitalOcean Credentials
    description: DigitalOcean credentials and SSH keys.
  - name: Hetzner Credentials
    description: Hetzner credentials and SSH keys.
  - name: HPE Morpheus Credentials
    description: HPE Morpheus credentials and the capacity and quotas behind them.
  - name: OVH Credentials
    description: OVH credentials and SSH keys.
  - name: Proxmox Credentials
    description: Proxmox VE credentials and the capacity and quotas behind them.
  - name: Scaleway Credentials
    description: Scaleway credentials.
  - name: UpCloud Credentials
    description: UpCloud credentials and SSH keys.
  - name: Data Source Credentials
    description: Credentials for metrics and log sources.
  - name: DNS Credentials
    description: Credentials for DNS providers.
  - name: Object Storage Buckets
    description: >-
      Buckets Ankra creates and manages on an organisation's own provider
      credentials.
  - name: DNS
    description: DNS zones and records, including custom organisation zones.
  - name: Cloudflare
    description: Cloudflare domains and the credentials behind them.
  - name: Avura
    description: >-
      The linked Avura organization, the domains it shares with Ankra Platform,
      and their DNS records.
  - name: Variables
    description: Organisation- and cluster-scoped variables.
  - name: Secret Slots
    description: >-
      Store secrets in Vault and reference them by ${SECRET_SLOT:<slot_id>}
      sentinel instead of by value.
  - name: SOPS
    description: Encrypt and decrypt values with the organisation SOPS config.
  - name: Alerts
    description: Alert integrations and ingest credentials.
  - name: Notifications
    description: Notification routes and their delivery targets.
  - name: Support
    description: Support tickets.
  - name: AI Settings
    description: Organisation AI provider, model catalog and per-function model settings
paths:
  /api/v1/org/cloud-cost/savings:
    get:
      tags:
        - Cost
      summary: Savings model for the organisation
      description: >-
        The organisation's savings model: right-size and off-hours
        recommendations across the biggest priced clusters, the cost breakdowns
        they were read from, the clusters the fleet cannot price, and the waste
        scan, in the caller's display currency (`ankra cost savings`). One
        cluster counts once in the total, at its best lever. Bearer-PAT twin of
        the browser route of the same name under /org.
      operationId: cloud_savings_api_v1_org_cloud_cost_savings_get
      parameters:
        - description: PAT organisation override.
          in: header
          name: x-ankra-organisation-id
          required: false
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CloudSavingsResponse'
          description: Successful response
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContractDetailError'
          description: >-
            Missing or malformed Authorization header, or business validation
            error
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContractDetailError'
          description: Unknown, expired, or revoked API token
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContractDetailError'
          description: >-
            Token may not use this surface (MCP-scoped token or service account
            restriction)
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
          description: Request validation error
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContractDetailError'
          description: Internal server error
      security:
        - BearerAuth: []
components:
  schemas:
    CloudSavingsResponse:
      description: >-
        The organisation's savings model. Each cluster is counted once, at its
        best lever, because idle spend sits inside what an off-hours stop
        reclaims: total_monthly_savings_cents is each cluster's best measured or
        billed lever, and estimated_monthly_savings_cents only what its best
        lever of any confidence adds above that, so the two never count one
        spend twice. Unanalysed clusters are priced clusters beyond the
        organisation's analysed limit or past the analysis time budget, and
        offline clusters are priced clusters whose agent has not checked in;
        neither is a cluster with nothing to save.
      properties:
        analysed_cluster_count:
          type: integer
        analysis_budget_exhausted:
          description: >-
            True when the analysis time budget
            (thresholds.analysis_budget_seconds), not the analysed-cluster
            limit, left some priced clusters unanalysed.
          type: boolean
        breakdowns:
          items:
            $ref: '#/components/schemas/CloudSavingsBreakdown'
          type: array
        currency:
          type: string
        estimated_monthly_savings_cents:
          description: >-
            What the clusters' best levers add, on estimates alone, above
            total_monthly_savings_cents: summed per cluster as its best lever of
            any confidence less its best measured or billed lever. Never counted
            in total_monthly_savings_cents.
          type: integer
        generated_at:
          type: string
          format: date-time
        namespaces:
          description: >-
            The costliest namespaces across the analysed clusters, at most
            twelve.
          items:
            $ref: '#/components/schemas/CloudSavingsNamespace'
          type: array
        priced_cluster_count:
          type: integer
        recommendations:
          items:
            $ref: '#/components/schemas/CloudSavingsRecommendation'
          type: array
        thresholds:
          $ref: '#/components/schemas/CloudSavingsThresholds'
        total_monthly_savings_cents:
          type: integer
        unanalysed_cluster_count:
          type: integer
        unanalysed_clusters:
          description: >-
            Every priced cluster unanalysed_cluster_count counts, costliest
            first, with why it was left out on this read: limit (past the
            organisation's analysed-cluster limit), budget (the analysis time
            budget ran out first), unreadable (its cost read failed; also in
            unreadable_clusters) or no_breakdown (its cost read had no priced
            breakdown). The analysed set is re-chosen on every read, so this is
            what explains a total that moved without anything being spent or
            saved.
          items:
            $ref: '#/components/schemas/CloudSavingsUnanalysedCluster'
          type: array
        unpriced_cluster_count:
          type: integer
        unpriced_clusters:
          items:
            $ref: '#/components/schemas/CloudSavingsUnpricedCluster'
          type: array
        stale_cluster_count:
          type: integer
        stale_clusters:
          description: >-
            Clusters priced before whose latest snapshot is older than the
            fleet's staleness window: metering has stalled, which is neither
            priced nor unpriced.
          items:
            $ref: '#/components/schemas/CloudSavingsUnpricedCluster'
          type: array
        unreadable_clusters:
          description: >-
            Priced clusters whose cost breakdown could not be read on this pass;
            counted as unanalysed, never as clusters with nothing to save.
          items:
            $ref: '#/components/schemas/CloudSavingsUnreadableCluster'
          type: array
        offline_clusters:
          description: >-
            Priced clusters whose agent has not checked in within the platform's
            check-in threshold. Their synced inventory is the last one the agent
            sent, so they keep their price and breakdown but are offered no
            recommendation of any kind; never clusters with nothing to save.
          items:
            $ref: '#/components/schemas/CloudSavingsOfflineCluster'
          type: array
        waste:
          $ref: '#/components/schemas/CloudSavingsWaste'
        withheld:
          description: >-
            Every schedulable, priced cluster worth parking that was not offered
            an off_hours_schedule, with the first failing reason:
            purpose_unconfirmed (no person chose its environment label),
            production (its label or stored criticality says production),
            off_hours_traffic (it served verified ingress requests inside the
            stop window), off_hours_workload (its own workloads were busy there)
            or activity_unmeasured (either activity signal could not be read,
            which is unknown, not idle). And every right-size that offers no
            step every plan-time check passed, as kind right_size with no money
            figure: no_safe_step (usage was measured and no smaller size passes;
            detail carries the ladder notes), does_not_fit (a pod, or the
            group's requests with one node down, do not fit the next size),
            peaks_exceed (the busiest node's 30-day CPU max or p99 is at or over
            the next size), no_headroom (the group's p95 CPU with one node down
            would be at or over half the next size's capacity), inventory_stale
            (the nodes, pods, budgets and volumes the fit check needs could not
            be read fresh, so it failed closed) or metrics_missing (no usage
            could be read). Never clusters with nothing to save.
          items:
            $ref: '#/components/schemas/CloudSavingsWithheld'
          type: array
      required:
        - currency
        - generated_at
        - total_monthly_savings_cents
        - estimated_monthly_savings_cents
        - recommendations
        - breakdowns
        - namespaces
        - analysed_cluster_count
        - unanalysed_cluster_count
        - unanalysed_clusters
        - analysis_budget_exhausted
        - priced_cluster_count
        - unpriced_cluster_count
        - unpriced_clusters
        - stale_cluster_count
        - stale_clusters
        - unreadable_clusters
        - offline_clusters
        - waste
        - thresholds
        - withheld
      type: object
    ContractDetailError:
      example:
        detail: Cluster not found
      properties:
        detail:
          oneOf:
            - type: string
            - additionalProperties: true
              properties: {}
              type: object
      required:
        - detail
      type: object
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          title: Detail
          type: array
      title: HTTPValidationError
      type: object
    CloudSavingsBreakdown:
      description: >-
        One analysed cluster's run rate split by billed component, with the idle
        and unallocated shares the recommendations read, the id of its best
        recommendation, its costliest namespaces, and its daily cost trend over
        the last thirty days (the same series GET
        /org/clusters/{cluster_id}/cost serves as trend), so the fleet's
        movement can be attributed to the clusters that moved it from this one
        read.
      properties:
        best_recommendation_id:
          anyOf:
            - type: string
            - type: 'null'
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
        components:
          items:
            $ref: '#/components/schemas/CloudSavingsComponent'
          type: array
        idle_monthly_cents:
          description: >-
            The cluster's unrequested capacity, not unused capacity: the monthly
            compute cost of allocatable capacity no pod requests, of the binding
            resource per node group, with control-plane nodes and autoscaled or
            resized node groups left out, averaged over the last seven days of
            hourly snapshots.
          type: integer
        monthly_cents:
          type: integer
        provider:
          type: string
        top_namespaces:
          items:
            $ref: '#/components/schemas/CloudSavingsNamespace'
          type: array
        trend:
          description: >-
            The cluster's daily run rate over the last thirty days, one point
            per day, carried verbatim from its cost read; always present on an
            analysed cluster.
          items:
            $ref: '#/components/schemas/CostTrendPoint'
          type: array
        unallocated_monthly_cents:
          type: integer
      required:
        - cluster_id
        - cluster_name
        - provider
        - monthly_cents
        - components
        - idle_monthly_cents
        - unallocated_monthly_cents
        - best_recommendation_id
        - top_namespaces
        - trend
      type: object
    CloudSavingsNamespace:
      description: >-
        One namespace's allocated share of its cluster's run rate: the
        dependency cost a lane drills into.
      properties:
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
        monthly_cents:
          type: integer
        namespace:
          type: string
        share_percent:
          type: integer
      required:
        - cluster_id
        - cluster_name
        - namespace
        - monthly_cents
        - share_percent
      type: object
    CloudSavingsRecommendation:
      description: >-
        One lever on one cluster. id is stable across reads (kind and cluster),
        so a ledger can reference it.
      properties:
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
        environment:
          anyOf:
            - type: string
            - type: 'null'
        confidence:
          description: >-
            What monthly_savings_cents rests on. measured: a right_size_idle,
            whose usage the metrics store answered for and planned at least one
            ladder step that passed the plan-time fit and sizing checks (a
            right-size that offers no step is in withheld, never a
            recommendation). billed: an off_hours_schedule taken on the
            cluster's billed compute. estimated: inferred from capacity less
            requests or hedged on the whole run rate with nothing observed
            behind it (every reduce_unallocated, and an off_hours_schedule on a
            cluster whose breakdown was not read). Only measured and billed
            savings without plan_required count towards
            total_monthly_savings_cents.
          enum:
            - measured
            - billed
            - estimated
          type: string
        evidence:
          $ref: '#/components/schemas/CloudSavingsEvidence'
        id:
          type: string
        kind:
          enum:
            - right_size_idle
            - reduce_unallocated
            - off_hours_schedule
          type: string
        monthly_cost_cents:
          type: integer
        monthly_savings_cents:
          type: integer
        provider:
          type: string
        share_percent:
          type: integer
        ladder:
          anyOf:
            - items:
                $ref: '#/components/schemas/CloudSavingsLadderStep'
              type: array
            - type: 'null'
          description: >-
            A right_size_idle recommendation's full step plan: each node group
            onto the next smaller priced size of the same vCPU class and
            architecture, one wave per step, priced per step from the cluster's
            own price book, stopping where the group's p95 would lose its
            headroom or approach the verification limits. Null when no step
            could be planned; ladder_notes says why for each group left out.
        total_ladder_savings_cents:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            The sum of the ladder's steps, never the unrequested-capacity
            ceiling; null when there is no ladder.
        ladder_notes:
          anyOf:
            - items:
                $ref: '#/components/schemas/CloudSavingsLadderNote'
              type: array
            - type: 'null'
          description: >-
            Why each node group left out of the ladder was left out (spiky,
            busy, silent, unpriced, spot, or bounded); a note with no group is
            about the whole cluster.
        autopilot_tier:
          enum:
            - hands-off
            - scheduled
            - managed
            - ephemeral
          type: string
          description: >-
            The cost autopilot tier this recommendation's change falls into at
            this read: the cluster's tier, except that an off_hours_schedule
            whose evidence.node_local_storage_state is not none is hands-off
            (proposal-only) whatever the cluster's tier.
        autopilot_tier_reason:
          description: >-
            Why the change is in that tier, as the card shows it: the cluster's
            sentence, followed for a hands-off off_hours_schedule by why it
            waits for a person (its stop deletes the worker servers, and claims
            keep data on their disks or the inventory could not tell).
          type: string
        plan_required:
          anyOf:
            - $ref: '#/components/schemas/CloudSavingsPlanRequired'
            - type: 'null'
          description: >-
            On a right_size_idle: non-null when the right-size is not one click
            - a person writes a maintenance plan (switchovers, order, window)
            first. Such a recommendation is in neither
            total_monthly_savings_cents nor estimated_monthly_savings_cents.
            Null for one-click right-sizes and the other kinds.
        preflight:
          anyOf:
            - $ref: '#/components/schemas/CloudSavingsRightSizePreflight'
            - type: 'null'
          description: >-
            On a right_size_idle: the plan-time fit check every offered step
            passed. A step it would refuse, or could not judge, is never
            offered; the right-size is then in withheld instead. Null for the
            other kinds.
        sizing:
          anyOf:
            - $ref: '#/components/schemas/CloudSavingsRightSizeSizing'
            - type: 'null'
          description: >-
            On a right_size_idle: the usage evidence the steps were sized on.
            Null for the other kinds.
        execution:
          anyOf:
            - $ref: '#/components/schemas/CloudSavingsRightSizeExecution'
            - type: 'null'
          description: >-
            On a right_size_idle: how the right-size runs. Null for the other
            kinds.
      required:
        - id
        - kind
        - cluster_id
        - cluster_name
        - provider
        - environment
        - monthly_savings_cents
        - monthly_cost_cents
        - share_percent
        - confidence
        - evidence
        - ladder
        - total_ladder_savings_cents
        - ladder_notes
        - autopilot_tier
        - autopilot_tier_reason
        - plan_required
        - preflight
        - sizing
        - execution
      type: object
    CloudSavingsThresholds:
      properties:
        analysed_cluster_limit:
          description: >-
            The organisation's analysed-cluster limit in effect (cost settings;
            8 unless it set its own).
          type: integer
        analysis_budget_seconds:
          description: >-
            How long one savings read may spend on per-cluster breakdowns before
            the rest are counted as unanalysed.
          type: integer
        snapshot_stale_after_hours:
          description: >-
            How old a cluster's latest cost snapshot may be before its metering
            counts as stopped: such a cluster is named in stale_clusters and
            left out of every total.
          type: integer
        minimum_off_hours_monthly_cents:
          type: integer
        minimum_savings_cents:
          type: integer
        off_hours_share:
          type: number
        unallocated_share_threshold:
          type: number
      required:
        - minimum_savings_cents
        - minimum_off_hours_monthly_cents
        - unallocated_share_threshold
        - off_hours_share
        - analysed_cluster_limit
        - analysis_budget_seconds
        - snapshot_stale_after_hours
      type: object
    CloudSavingsUnanalysedCluster:
      description: >-
        A priced cluster the savings read did not analyse, and why: never a
        cluster with nothing to save.
      properties:
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
        reason:
          enum:
            - limit
            - budget
            - unreadable
            - no_breakdown
          type: string
      required:
        - cluster_id
        - cluster_name
        - reason
      type: object
    CloudSavingsUnpricedCluster:
      properties:
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
        kind:
          type: string
      required:
        - cluster_id
        - cluster_name
        - kind
      type: object
    CloudSavingsUnreadableCluster:
      properties:
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
      required:
        - cluster_id
        - cluster_name
      type: object
    CloudSavingsOfflineCluster:
      description: >-
        A priced cluster whose agent has not checked in within the platform's
        check-in threshold: offered no recommendation, never read as having
        nothing to save.
      properties:
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
      required:
        - cluster_id
        - cluster_name
      type: object
    CloudSavingsWaste:
      description: >-
        The open cloud-waste findings. available is false when the waste scan
        could not be read, which is unknown waste, not no waste.
        total_monthly_cost_cents and unpriced_finding_count cover the findings
        that count toward this organisation's savings: a resource several
        organisations' credentials see counts only in the organisation its Ankra
        cluster label names, and in none without one, so it is counted once
        between them. finding_count is every finding listed.
      properties:
        available:
          type: boolean
        finding_count:
          type: integer
        has_data:
          type: boolean
        scanned_at:
          anyOf:
            - type: string
            - type: 'null'
        total_monthly_cost_cents:
          type: integer
        unpriced_finding_count:
          type: integer
        shared_not_counted_monthly_cost_cents:
          type: integer
          description: >-
            The priced monthly cost of the listed findings whose resource other
            Ankra organisations also see and whose cost counts in another
            organisation or in none; it is not in total_monthly_cost_cents.
        shared_not_counted_finding_count:
          type: integer
          description: >-
            How many of the listed findings count in another organisation or in
            none, priced or not; none of them is in unpriced_finding_count.
      required:
        - available
        - has_data
        - scanned_at
        - total_monthly_cost_cents
        - finding_count
        - unpriced_finding_count
        - shared_not_counted_monthly_cost_cents
        - shared_not_counted_finding_count
      type: object
    CloudSavingsWithheld:
      description: >-
        A lever the savings model withheld, and why, with no money figure: an
        off_hours_schedule the purpose gate did not offer, or a right_size that
        offers no step every plan-time check passed.
      properties:
        busy_hours:
          description: >-
            Hours inside the stop window over window_days in which the cluster's
            own workloads were busy. Omitted when not measured.
          type: integer
        cluster_id:
          type: string
          format: uuid
        cluster_name:
          type: string
        detail:
          description: >-
            For a right_size, why in sentences: the planner's ladder notes, each
            prefixed with its node group. Omitted for an off_hours_schedule.
          items:
            type: string
          type: array
        kind:
          enum:
            - off_hours_schedule
            - right_size
          type: string
        reason:
          enum:
            - purpose_unconfirmed
            - production
            - off_hours_traffic
            - off_hours_workload
            - activity_unmeasured
            - no_safe_step
            - does_not_fit
            - peaks_exceed
            - no_headroom
            - inventory_stale
            - metrics_missing
          type: string
        requests:
          description: >-
            Verified ingress requests inside the stop window over window_days.
            Omitted when not measured.
          type: integer
        window_days:
          description: >-
            How many days back the activity signals looked. Omitted when the
            purpose withheld the schedule before any activity was read.
          type: integer
      required:
        - cluster_id
        - cluster_name
        - kind
        - reason
      type: object
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          title: Location
          type: array
        msg:
          title: Message
          type: string
        type:
          title: Error Type
          type: string
      required:
        - loc
        - msg
        - type
      title: ValidationError
      type: object
    CloudSavingsComponent:
      properties:
        key:
          type: string
        label:
          type: string
        monthly_cents:
          type: integer
      required:
        - key
        - label
        - monthly_cents
      type: object
    CostTrendPoint:
      properties:
        day:
          type: string
          format: date-time
        monthly_cost_estimate_cents:
          type: integer
        fully_priced:
          type: boolean
          description: >-
            Every node and billed resource of the cluster was priced that day,
            so the run rate is the cluster's whole cost rather than a floor
            under it. A point exists only for a day the cluster was priced; a
            missing day is unknown, not zero.
      required:
        - day
        - monthly_cost_estimate_cents
        - fully_priced
      title: CostTrendPoint
      type: object
    CloudSavingsEvidence:
      description: >-
        The numbers a recommendation was computed from; members that do not
        apply to its kind are null.
      properties:
        idle_monthly_cents:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            Unrequested capacity, not unused capacity: the monthly compute cost
            of allocatable capacity no pod requests (binding resource per node
            group, control planes and autoscaled or resized groups left out),
            averaged over seven days. Usage is never read into it;
            unrequested_basis names the measure.
        unrequested_basis:
          anyOf:
            - enum:
                - requests_vs_allocatable_7d_avg
              type: string
            - type: 'null'
          description: >-
            How idle_monthly_cents was measured: requests_vs_allocatable_7d_avg.
            Null where the evidence carries no idle figure.
        off_hours_share_percent:
          anyOf:
            - type: integer
            - type: 'null'
        start_cron:
          anyOf:
            - type: string
            - type: 'null'
        stop_cron:
          anyOf:
            - type: string
            - type: 'null'
        stoppable_monthly_cents:
          anyOf:
            - type: integer
            - type: 'null'
        unallocated_monthly_cents:
          anyOf:
            - type: integer
            - type: 'null'
        unallocated_share_percent:
          anyOf:
            - type: integer
            - type: 'null'
        metrics_state:
          anyOf:
            - enum:
                - present
                - absent
                - unavailable
              type: string
            - type: 'null'
          description: >-
            On a right_size_idle recommendation: whether the cluster's usage
            could be read from the platform metrics store (present), the store
            holds no node series for it so no group can be sized (absent: a
            prerequisite, not a saving), or the store is not configured or could
            not be read (unavailable: unknown). Null for the other kinds and for
            a cluster priced by rate card or by its own bill.
        node_local_storage_state:
          anyOf:
            - enum:
                - present
                - none
                - unknown
              type: string
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: whether the cluster keeps
            persistent data on its worker nodes' own disks (local or hostPath
            volumes, or a local provisioner such as local-path, OpenEBS LocalPV
            or TopoLVM), read from the synced cluster inventory. The schedule's
            scale_to_zero stop deletes the worker servers and the start creates
            new ones, so that data is lost at every stop. present: at least one
            claim does; none: the inventory is synced and none does; unknown:
            the inventory holds no nodes for the cluster or could not be read.
            Only none says the cluster is safe, and neither other state is ever
            read as none: on present the decision ledger runs the schedule only
            with written consent; unknown is a warning shown to the person
            approving it. Null for the other kinds.
        node_local_pvc_count:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: how many persistent volume
            claims keep their data on a worker's disk. Null for the other kinds
            and when node_local_storage_state is unknown.
        node_local_pvc_names:
          anyOf:
            - type: array
              items:
                type: string
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: up to 25 of those claims as
            namespace/name, sorted. Null for the other kinds and when
            node_local_storage_state is unknown.
        environment_source:
          anyOf:
            - enum:
                - person
                - default
                - unknown
              type: string
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: how the cluster's
            environment label was set. Always person on an offered schedule: a
            schedule is offered only for a cluster whose purpose a person
            confirmed (see withheld). Null for the other kinds.
        environment_set_by:
          anyOf:
            - type: string
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: who chose the environment
            label (email, or the auth subject when the user has none), when
            known. Null for the other kinds.
        environment_set_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: when the environment label
            was chosen. Null for the other kinds.
        off_hours_window_days:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: how many days back the
            activity signals looked (14). Null for the other kinds.
        off_hours_requests:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: verified ingress requests
            the cluster served inside the would-be stop window (weeknights
            19:00-07:00 and weekends, in the schedule's timezone) over
            off_hours_window_days. An offered schedule is below the gate's small
            threshold, since an uptime probe counts as use. Null for the other
            kinds.
        off_hours_busy_hours:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            On an off_hours_schedule recommendation: hours inside the would-be
            stop window over off_hours_window_days in which the cluster's own
            workloads (every namespace outside the platform's) used at least a
            quarter of a CPU core on average. Null for the other kinds.
      type: object
    CloudSavingsLadderStep:
      properties:
        wave:
          type: integer
        group:
          type: string
        from_instance_type:
          type: string
        to_instance_type:
          type: string
        count:
          type: integer
        monthly_savings_cents:
          type: integer
        cumulative_monthly_savings_cents:
          type: integer
        verify_days:
          type: integer
      required:
        - wave
        - group
        - from_instance_type
        - to_instance_type
        - count
        - monthly_savings_cents
        - cumulative_monthly_savings_cents
        - verify_days
      title: CloudSavingsLadderStep
      type: object
    CloudSavingsLadderNote:
      properties:
        group:
          type: string
        reason:
          type: string
        code:
          description: >-
            The withheld reason the note stands for when a safety rule stopped
            the group (does_not_fit, peaks_exceed, no_headroom, inventory_stale,
            metrics_missing); omitted for a note that is no safety refusal.
          type: string
      required:
        - group
        - reason
      title: CloudSavingsLadderNote
      type: object
    CloudSavingsPlanRequired:
      description: >-
        Why a recommendation needs a written maintenance plan before it can run.
        The decision ledger recomputes the same reasons from the cluster as it
        is when an approved right-size runs, and refuses it on any of them.
      properties:
        reasons:
          items:
            enum:
              - production
              - purpose_unconfirmed
              - stateful_volumes
              - zero_disruption_pdb
              - single_instance_database
              - cross_plan_family
            type: string
          type: array
        detail:
          type: array
          items:
            type: string
      required:
        - reasons
        - detail
      type: object
    CloudSavingsRightSizePreflight:
      description: >-
        The plan-time fit check of an offered right-size, read from a fresh
        inventory: every pod fits one new node beside its DaemonSets, and the
        group's requests stay at or under 90% of what the remaining new nodes
        leave with one node down. state is always fits on a recommendation; a
        step it refuses or cannot judge is withheld.
      properties:
        state:
          enum:
            - fits
            - unknown
          type: string
        checked_at:
          type: string
          format: date-time
        n_minus_one_cpu_percent:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            The tightest step's group CPU requests as a percent of what the new
            nodes leave with one node down.
        n_minus_one_memory_percent:
          anyOf:
            - type: integer
            - type: 'null'
          description: The same for memory requests.
        largest_pod:
          anyOf:
            - $ref: '#/components/schemas/CloudSavingsRightSizePod'
            - type: 'null'
          description: The pod with the largest CPU request on a changed group.
      required:
        - state
        - checked_at
        - n_minus_one_cpu_percent
        - n_minus_one_memory_percent
        - largest_pod
      type: object
    CloudSavingsRightSizeSizing:
      description: >-
        The usage an offered right-size was sized on, over window_days, each the
        tightest step's figure after the change: the busiest node's CPU max and
        p99 against one new node (under 100%), and the group's p95 CPU against
        the new capacity left with one node down (under 50%).
      properties:
        window_days:
          type: integer
        node_max_cpu_percent_after:
          anyOf:
            - type: integer
            - type: 'null'
        node_p99_cpu_percent_after:
          anyOf:
            - type: integer
            - type: 'null'
        group_cpu_percent_after_n_minus_one:
          anyOf:
            - type: integer
            - type: 'null'
      required:
        - window_days
        - node_max_cpu_percent_after
        - node_p99_cpu_percent_after
        - group_cpu_percent_after_n_minus_one
      type: object
    CloudSavingsRightSizeExecution:
      description: >-
        How an offered right-size runs. method: in_place_resize (drain, power
        off, change the plan, power on) or replace (the nodes or the managed
        pool are re-created). nodes_at_once: how many nodes of the first wave's
        group are down at the same time, from the platform's resize lane rule.
        groups_changed of groups_total node groups. cpu_change and memory_change
        describe the first wave (null when neither applies). canary: the waves
        inside the first wave's group, as node counts (one node, a quarter, the
        rest).
      properties:
        method:
          enum:
            - in_place_resize
            - replace
          type: string
        nodes_at_once:
          type: integer
        groups_changed:
          type: integer
        groups_total:
          type: integer
        cpu_change:
          anyOf:
            - enum:
                - halves
                - reduces
              type: string
            - type: 'null'
        memory_change:
          anyOf:
            - enum:
                - same
                - reduces
              type: string
            - type: 'null'
        canary:
          items:
            type: integer
          type: array
      required:
        - method
        - nodes_at_once
        - groups_changed
        - groups_total
        - cpu_change
        - memory_change
        - canary
      type: object
    CloudSavingsRightSizePod:
      description: >-
        One pod as a right-size plan names it, with its summed container
        requests.
      properties:
        name:
          type: string
        namespace:
          type: string
        cpu_millicores:
          type: integer
        memory_bytes:
          type: integer
      required:
        - name
        - namespace
        - cpu_millicores
        - memory_bytes
      type: object
  securitySchemes:
    BearerAuth:
      bearerFormat: PAT
      scheme: bearer
      type: http

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.