components:
    responses:
        BadGateway:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Upstream internal service returned 5xx or was unreachable. error.code = UPSTREAM_UNAVAILABLE.
        BadRequest:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: 'Malformed input — bad UUID, unknown filter key, bad cursor. error.code one of: BAD_REQUEST, INVALID_COST_MODE, INVALID_CLUSTER_ID, INVALID_CURSOR.'
        Forbidden:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: 'Token valid but lacks scope OR cluster ACL. error.code one of: FORBIDDEN, CLUSTER_ACCESS_DENIED.'
        GatewayTimeout:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Upstream call exceeded the proxy's 60s deadline. error.code = UPSTREAM_TIMEOUT.
        Gone:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Cursor expired (older than 24h) or query parameters changed since cursor was issued. error.code = CURSOR_EXPIRED.
        NotFound:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: 'Resource identifier well-formed but not found. error.code one of: CLUSTER_NOT_FOUND, NAMESPACE_NOT_FOUND, WORKLOAD_NOT_FOUND, NODE_NOT_FOUND, NODE_GROUP_NOT_FOUND, RECOMMENDATION_NOT_FOUND, TEAM_NOT_FOUND, DEPARTMENT_NOT_FOUND.'
        PayloadTooLarge:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Request body exceeded the 1 MiB cap on POST endpoints. error.code = BAD_REQUEST.
        RateLimited:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Per-key request quota exceeded (default 100/min). Includes Retry-After header. error.code = RATE_LIMITED.
        ServerError:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Unhandled server error. error.code = INTERNAL_ERROR.
        Unauthorized:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Missing or invalid Bearer token. error.code = UNAUTHORIZED.
        Unavailable:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: 'Rate-limit backend unavailable (fail-closed) or general service unavailable. error.code one of: RATE_LIMIT_UNAVAILABLE, SERVICE_UNAVAILABLE.'
        Validation:
            content:
                application/json:
                    schema:
                        properties:
                            data:
                                type: "null"
                            error:
                                allOf:
                                    - $ref: '#/components/schemas/ErrorBody'
                                nullable: true
                            meta:
                                $ref: '#/components/schemas/MetaBase'
                        required:
                            - meta
                        type: object
            description: Input parsed but semantically invalid (e.g. cost_mode=foo, status=garbage). error.code = VALIDATION_ERROR or INVALID_COST_MODE.
    schemas:
        CapacityCPU:
            properties:
                allocatable_cores:
                    format: double
                    type: number
                total_cores:
                    format: double
                    type: number
            type: object
        CapacityGPU:
            properties:
                allocatable:
                    type: integer
                model:
                    type: string
                total:
                    type: integer
            type: object
        CapacityMemory:
            properties:
                allocatable_bytes:
                    format: int64
                    type: integer
                total_bytes:
                    format: int64
                    type: integer
            type: object
        CapacityPods:
            properties:
                allocatable:
                    type: integer
            type: object
        CapacityStorage:
            properties:
                total_bytes:
                    format: int64
                    type: integer
            type: object
        Cluster:
            description: Cluster resource. OMITS cost.cost_mode entirely (one physical bill).
            properties:
                capacity:
                    properties:
                        cpu:
                            $ref: '#/components/schemas/CapacityCPU'
                        gpu:
                            $ref: '#/components/schemas/CapacityGPU'
                        memory:
                            $ref: '#/components/schemas/CapacityMemory'
                        pods:
                            $ref: '#/components/schemas/CapacityPods'
                        storage:
                            $ref: '#/components/schemas/CapacityStorage'
                    type: object
                cost:
                    properties:
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Cluster
                    type: string
                metadata:
                    properties:
                        agent_version:
                            type: string
                        availability_zones:
                            items:
                                type: string
                            type: array
                        created_at:
                            type: string
                        discovery_source:
                            type: string
                        environment:
                            enum:
                                - production
                                - non-production
                                - staging
                                - dev
                            type: string
                        is_stale:
                            description: True when last_seen_at is NULL or older than 180s. When true, utilization/cost are from the last successful agent snapshot, not live.
                            type: boolean
                        k8s_version:
                            type: string
                        last_seen_at:
                            description: Last agent heartbeat. See is_stale for staleness derivation.
                            type: string
                        name:
                            type: string
                        provider:
                            enum:
                                - aws
                                - gcp
                                - azure
                                - on-prem
                            type: string
                        region:
                            type: string
                        service:
                            description: 'Derived from provider: aws→EKS, gcp→GKE, azure→AKS, on-prem→Kubernetes.'
                            enum:
                                - EKS
                                - GKE
                                - AKS
                                - Kubernetes
                            type: string
                        status:
                            enum:
                                - pending
                                - active
                                - disconnected
                                - error
                                - discovered
                            type: string
                    type: object
                utilization:
                    properties:
                        counts:
                            properties:
                                containers:
                                    type: integer
                                cronjobs:
                                    type: integer
                                daemonsets:
                                    type: integer
                                deployments:
                                    type: integer
                                jobs:
                                    type: integer
                                namespaces:
                                    type: integer
                                nodes:
                                    type: integer
                                persistent_volumes:
                                    type: integer
                                pods:
                                    type: integer
                                running_containers:
                                    type: integer
                                running_pods:
                                    type: integer
                                statefulsets:
                                    type: integer
                                workloads:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/UtilizationCPU'
                        gpu:
                            $ref: '#/components/schemas/UtilizationGPU'
                        memory:
                            $ref: '#/components/schemas/UtilizationMemory'
                    type: object
            required:
                - id
                - kind
                - metadata
                - capacity
                - utilization
                - cost
            type: object
        CostAllocationRow:
            description: Single resource row. Public-api intentionally exposes a narrow subset of saas-api's internal CostAllocationRow shape; new fields added upstream are filtered server-side and will not surface here without an explicit spec change. `totalCost` is wire-formatted as Money (`amount` decimal string + `currency`) for parity with every other money-bearing /v1 endpoint.
            properties:
                cluster:
                    type: string
                clusterName:
                    type: string
                co2Kg:
                    format: double
                    type: number
                id:
                    type: string
                namespace:
                    type: string
                nodeUid:
                    type: string
                podUid:
                    type: string
                pods:
                    type: integer
                totalCost:
                    $ref: '#/components/schemas/Money'
                workloadKind:
                    type: string
                workloadName:
                    type: string
                workloadUid:
                    type: string
            required:
                - id
                - workloadName
                - workloadKind
                - namespace
                - cluster
                - totalCost
                - co2Kg
            type: object
        CostExplorerQueryParams:
            description: Body for /v1/cost-explorer/query. `end_date` is INCLUSIVE (server bumps +1 day internally). `cluster_ids` is intersected with the API key's allowed cluster set before forwarding; an empty value forwards as the full allowed set.
            properties:
                cluster_ids:
                    items:
                        type: string
                    type: array
                cost_mode:
                    $ref: '#/components/schemas/CostMode'
                end_date:
                    description: YYYY-MM-DD. Inclusive.
                    format: date
                    type: string
                export:
                    description: Switches per-page cap to 10 000. UI clients MUST leave this false.
                    type: boolean
                filter_expression:
                    $ref: '#/components/schemas/FilterExpression'
                granularity:
                    description: Time-bucket for daily-breakdown outputs.
                    enum:
                        - daily
                        - weekly
                        - monthly
                    type: string
                group_by:
                    $ref: '#/components/schemas/GroupBy'
                page:
                    type: integer
                per_page:
                    type: integer
                projected:
                    description: false (default) returns observed cost matching cloud billing; true scales partial-collection days up to 1440-minute equivalents.
                    type: boolean
                search:
                    type: string
                sort_by:
                    type: string
                sort_order:
                    enum:
                        - asc
                        - desc
                    type: string
                start_date:
                    description: YYYY-MM-DD. Inclusive.
                    format: date
                    type: string
                view_mode:
                    enum:
                        - detail
                        - grouped
                    type: string
            type: object
        CostExplorerQueryResponse:
            description: Paginated cost-explorer query response. `items` is an array of CostAllocationRow.
            properties:
                excludedClusterIds:
                    items:
                        type: string
                    type: array
                items:
                    items:
                        $ref: '#/components/schemas/CostAllocationRow'
                    type: array
                pagination:
                    $ref: '#/components/schemas/PaginationMeta'
                summary:
                    $ref: '#/components/schemas/CostExplorerSummary'
            required:
                - items
                - summary
                - pagination
            type: object
        CostExplorerSummary:
            description: Aggregate KPIs. `dataCompleteness` is the [0,1] ratio of collected-vs-expected minute snapshots; below ~0.98 usually indicates an agent outage or backfill in progress.
            properties:
                changePercentage:
                    format: double
                    type: number
                dataCompleteness:
                    format: double
                    type: number
                periodCost:
                    format: double
                    type: number
                previousPeriodCost:
                    format: double
                    type: number
                queryTimeMs:
                    format: int64
                    type: integer
                scannedResources:
                    type: integer
                topNamespace:
                    type: string
                topNamespaceCost:
                    format: double
                    type: number
            required:
                - periodCost
                - previousPeriodCost
                - changePercentage
                - scannedResources
                - queryTimeMs
                - dataCompleteness
            type: object
        CostMode:
            description: Idle cluster capacity distribution mode.
            enum:
                - fully_loaded
                - workload_only
            type: string
        CostTrendBucket:
            description: One point in a cost-trend time series. total_cost includes all hourly cost components (run_rate folds CPU + RAM + GPU + storage + PV + management; breakdown ModeLoaded additionally folds idle + overhead).
            properties:
                bucket_start:
                    description: RFC 3339 UTC anchor of the bucket (toStartOfHour for hourly, toDate for daily/weekly/monthly).
                    format: date-time
                    type: string
                total_cost:
                    $ref: '#/components/schemas/Money'
            required:
                - bucket_start
                - total_cost
            type: object
        CostTrendScopeRef:
            description: 'Identifies the specific entity the cost-trend series is for. Field presence varies by scope: cluster→cluster_id only; namespace→cluster_id+namespace; workload→cluster_id+workload_uid; node-group→cluster_id+node_group; organization→omitted entirely.'
            properties:
                cluster_id:
                    type: string
                namespace:
                    type: string
                node_group:
                    type: string
                workload_uid:
                    type: string
            type: object
        CostTrendSeries:
            description: Cost-trend time series. `granularity` is always the post-resolution value (hourly/daily/weekly/monthly — never the request-time `auto` alias). `type` echoes the requested ?type=. `points` is always an array (never null); empty series serialize as `[]`. `excluded_cluster_ids` is only populated on organization scope when some clusters were pruned from the rollup.
            properties:
                end:
                    type: string
                excluded_cluster_ids:
                    items:
                        type: string
                    type: array
                granularity:
                    description: Post-resolution. Never `auto`.
                    enum:
                        - hourly
                        - daily
                        - weekly
                        - monthly
                    type: string
                kind:
                    enum:
                        - CostTrend
                    type: string
                points:
                    items:
                        $ref: '#/components/schemas/CostTrendBucket'
                    type: array
                scope:
                    enum:
                        - cluster
                        - namespace
                        - workload
                        - node-group
                        - organization
                    type: string
                scope_ref:
                    $ref: '#/components/schemas/CostTrendScopeRef'
                start:
                    type: string
                type:
                    enum:
                        - run_rate
                        - breakdown
                    type: string
            required:
                - kind
                - scope
                - start
                - end
                - granularity
                - type
                - points
            type: object
        Department:
            properties:
                assigned_pvs:
                    type: integer
                assigned_workloads:
                    type: integer
                cost:
                    properties:
                        cost_mode:
                            enum:
                                - fully_loaded
                                - workload_only
                            type: string
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Department
                    type: string
                metadata:
                    properties:
                        created_at:
                            type: string
                        description:
                            type: string
                        name:
                            type: string
                        origin:
                            type: string
                        owner_email:
                            type: string
                        updated_at:
                            type: string
                    type: object
                teams:
                    type: integer
            required:
                - id
                - kind
                - metadata
                - teams
                - assigned_workloads
                - assigned_pvs
                - cost
            type: object
        ErrorBody:
            description: Error body emitted under `error` on failed responses. The HTTP status code is in the response status line; the request URL is the one the client made; the request_id is at `meta.request_id`. No need to duplicate any of them here.
            properties:
                code:
                    description: Stable machine-readable identifier.
                    enum:
                        - UNAUTHORIZED
                        - FORBIDDEN
                        - CLUSTER_ACCESS_DENIED
                        - BAD_REQUEST
                        - VALIDATION_ERROR
                        - INVALID_COST_MODE
                        - INVALID_CLUSTER_ID
                        - INVALID_CURSOR
                        - CURSOR_EXPIRED
                        - CLUSTER_NOT_FOUND
                        - NAMESPACE_NOT_FOUND
                        - WORKLOAD_NOT_FOUND
                        - NODE_NOT_FOUND
                        - NODE_GROUP_NOT_FOUND
                        - RECOMMENDATION_NOT_FOUND
                        - TEAM_NOT_FOUND
                        - DEPARTMENT_NOT_FOUND
                        - RATE_LIMITED
                        - RATE_LIMIT_UNAVAILABLE
                        - SERVICE_UNAVAILABLE
                        - UPSTREAM_UNAVAILABLE
                        - UPSTREAM_TIMEOUT
                        - INTERNAL_ERROR
                    type: string
                details:
                    description: Optional per-field problem descriptors. Empty/absent on most errors.
                    items:
                        additionalProperties: true
                        properties:
                            allowed:
                                items:
                                    type: string
                                type: array
                            field:
                                type: string
                            reason:
                                type: string
                        type: object
                    type: array
                message:
                    description: Human-readable explanation of this occurrence.
                    type: string
            required:
                - code
                - message
            type: object
        Filter:
            description: Single field-operator-values predicate.
            properties:
                field:
                    type: string
                operator:
                    enum:
                        - eq
                        - ne
                        - in
                        - not_in
                        - contains
                    type: string
                values:
                    items:
                        type: string
                    type: array
            required:
                - field
                - operator
                - values
            type: object
        FilterExpression:
            description: Advanced AND/OR filter expression across groups.
            properties:
                group_operator:
                    enum:
                        - AND
                        - OR
                    type: string
                groups:
                    items:
                        $ref: '#/components/schemas/FilterGroup'
                    type: array
            type: object
        FilterGroup:
            description: Group of filters combined within a single AND-group.
            properties:
                filters:
                    items:
                        $ref: '#/components/schemas/Filter'
                    type: array
                label_filters:
                    items:
                        $ref: '#/components/schemas/LabelFilter'
                    type: array
            type: object
        GroupBy:
            description: Aggregation dimension for cost-explorer queries. `cluster` is intentionally NOT offered on the public API — the underlying axis currently fails in saas-api; for fleet-wide cost breakdown use /v1/organization/dashboard.
            enum:
                - workload
                - namespace
                - controller_kind
                - pod
                - container
                - deployment
                - statefulset
                - daemonset
                - node
                - instance_type
            type: string
        LabelFilter:
            description: Kubernetes label predicate. `values` is omitted for `exists` / `not_exists`.
            properties:
                key:
                    type: string
                operator:
                    enum:
                        - eq
                        - ne
                        - exists
                        - not_exists
                    type: string
                values:
                    items:
                        type: string
                    type: array
            required:
                - key
                - operator
            type: object
        MetaBase:
            properties:
                applied_at:
                    format: date-time
                    type: string
                pagination:
                    $ref: '#/components/schemas/Pagination'
                request_id:
                    type: string
            required:
                - request_id
                - applied_at
            type: object
        MetaWithCostMode:
            allOf:
                - $ref: '#/components/schemas/MetaBase'
                - properties:
                    cost_mode:
                        description: Echoed only on endpoints that accept ?cost_mode= (namespaces/workloads/pods/teams/departments/organization-dashboard). Omitted on cluster/node/recommendation/organization-snapshot endpoints.
                        enum:
                            - fully_loaded
                            - workload_only
                        type: string
                  type: object
        Money:
            description: Money amount with currency. `amount` is a decimal STRING (never a JSON number) to eliminate float drift.
            properties:
                amount:
                    example: "12.4700"
                    pattern: ^\d+\.\d{4}$
                    type: string
                currency:
                    example: USD
                    type: string
            required:
                - amount
                - currency
            type: object
        Namespace:
            description: Namespace resource. INCLUDES cost.cost_mode (echo of ?cost_mode=). Capacity OMITTED entirely when no ResourceQuota is set.
            properties:
                capacity:
                    description: Present only when the namespace has a ResourceQuota.
                    properties:
                        cpu:
                            properties:
                                quota_cores:
                                    format: double
                                    type: number
                            type: object
                        memory:
                            properties:
                                quota_bytes:
                                    format: int64
                                    type: integer
                            type: object
                    type: object
                cost:
                    properties:
                        cost_mode:
                            enum:
                                - fully_loaded
                                - workload_only
                            type: string
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Namespace
                    type: string
                metadata:
                    properties:
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        created_at_k8s:
                            type: string
                        department:
                            $ref: '#/components/schemas/NestedRef'
                        labels:
                            additionalProperties:
                                type: string
                            type: object
                        last_seen_at:
                            type: string
                        name:
                            type: string
                        team:
                            $ref: '#/components/schemas/NestedRef'
                        uid_k8s:
                            type: string
                    type: object
                utilization:
                    properties:
                        counts:
                            properties:
                                containers:
                                    type: integer
                                cronjobs:
                                    type: integer
                                daemonsets:
                                    type: integer
                                deployments:
                                    type: integer
                                jobs:
                                    type: integer
                                persistent_volumes:
                                    type: integer
                                pods:
                                    type: integer
                                running_pods:
                                    type: integer
                                statefulsets:
                                    type: integer
                                workloads:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/UtilizationCPU'
                        memory:
                            $ref: '#/components/schemas/UtilizationMemory'
                    type: object
                workloads_top_5:
                    description: Populated only on GET /v1/clusters/{cid}/namespaces/{ns} (detail endpoint).
                    items:
                        properties:
                            cost:
                                properties:
                                    current_run_rate_hourly:
                                        $ref: '#/components/schemas/Money'
                                type: object
                            id:
                                type: string
                            kind:
                                type: string
                            name:
                                type: string
                        type: object
                    type: array
            required:
                - id
                - kind
                - metadata
                - utilization
                - cost
            type: object
        NestedRef:
            description: Canonical cross-resource reference. {id, name} always.
            properties:
                id:
                    type: string
                name:
                    type: string
            required:
                - id
                - name
            type: object
        Node:
            description: Node resource. OMITS cost.cost_mode (one physical bill).
            properties:
                capacity:
                    properties:
                        cpu:
                            $ref: '#/components/schemas/CapacityCPU'
                        ephemeral_storage:
                            $ref: '#/components/schemas/CapacityStorage'
                        gpu:
                            $ref: '#/components/schemas/CapacityGPU'
                        memory:
                            $ref: '#/components/schemas/CapacityMemory'
                        pods:
                            $ref: '#/components/schemas/CapacityPods'
                    type: object
                cost:
                    properties:
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                        on_demand_equivalent_hourly:
                            $ref: '#/components/schemas/Money'
                        pricing_source:
                            type: string
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Node
                    type: string
                metadata:
                    properties:
                        architecture:
                            enum:
                                - amd64
                                - arm64
                            type: string
                        availability_zone:
                            type: string
                        capacity_type:
                            enum:
                                - on-demand
                                - spot
                                - reserved
                                - karpenter
                            type: string
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        created_at_k8s:
                            type: string
                        instance_type:
                            type: string
                        is_ready:
                            type: boolean
                        is_schedulable:
                            type: boolean
                        is_spot:
                            type: boolean
                        kubelet_version:
                            type: string
                        labels:
                            additionalProperties:
                                type: string
                            type: object
                        last_seen_at:
                            type: string
                        name:
                            type: string
                        node_group:
                            type: string
                        node_role:
                            type: string
                        operating_system:
                            type: string
                        provider_id:
                            type: string
                        region:
                            type: string
                    type: object
                utilization:
                    properties:
                        counts:
                            properties:
                                pods:
                                    type: integer
                                running_pods:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/NodeUtilizationCPU'
                        gpu:
                            $ref: '#/components/schemas/UtilizationGPU'
                        memory:
                            $ref: '#/components/schemas/NodeUtilizationMemory'
                    type: object
            required:
                - id
                - kind
                - metadata
                - capacity
                - utilization
                - cost
            type: object
        NodeGroup:
            description: Aggregate over node_metadata GROUP BY node_group. Note `instance_types` is a plural array.
            properties:
                capacity:
                    properties:
                        cpu:
                            $ref: '#/components/schemas/CapacityCPU'
                        memory:
                            $ref: '#/components/schemas/CapacityMemory'
                    type: object
                cost:
                    properties:
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                        spot_savings_vs_ondemand_hourly:
                            $ref: '#/components/schemas/Money'
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - NodeGroup
                    type: string
                metadata:
                    properties:
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        instance_types:
                            items:
                                type: string
                            type: array
                        name:
                            type: string
                        oldest_node_created_at_k8s:
                            type: string
                        ondemand_count:
                            type: integer
                        spot_count:
                            type: integer
                        spot_percentage:
                            format: double
                            type: number
                        status:
                            enum:
                                - healthy
                                - degraded
                            type: string
                        zones:
                            items:
                                type: string
                            type: array
                    type: object
                nodes:
                    description: Reserved for future expansion (member nodes). NOT currently populated by any endpoint — domain field exists but repository never fills it. Always omitted in responses today.
                    items:
                        $ref: '#/components/schemas/Node'
                    type: array
                utilization:
                    properties:
                        counts:
                            properties:
                                nodes:
                                    type: integer
                                pods:
                                    type: integer
                                ready_nodes:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/NodeUtilizationCPU'
                        memory:
                            $ref: '#/components/schemas/NodeUtilizationMemory'
                    type: object
            required:
                - id
                - kind
                - metadata
                - capacity
                - utilization
                - cost
            type: object
        NodeUtilizationCPU:
            properties:
                used_cores:
                    format: double
                    type: number
                utilization_percent:
                    format: double
                    type: number
            type: object
        NodeUtilizationMemory:
            properties:
                used_bytes:
                    format: int64
                    type: integer
                utilization_percent:
                    format: double
                    type: number
            type: object
        Organization:
            description: Tenant-level snapshot — single resource returned by GET /v1/organization. OMITS cost.cost_mode (mode-invariant).
            properties:
                capacity:
                    properties:
                        cpu:
                            $ref: '#/components/schemas/CapacityCPU'
                        gpu:
                            $ref: '#/components/schemas/CapacityGPU'
                        memory:
                            $ref: '#/components/schemas/CapacityMemory'
                        storage:
                            $ref: '#/components/schemas/CapacityStorage'
                    type: object
                cost:
                    properties:
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Organization
                    type: string
                metadata:
                    properties:
                        created_at:
                            type: string
                        domain:
                            type: string
                        is_active:
                            type: boolean
                        name:
                            type: string
                        plan_type:
                            type: string
                    type: object
                utilization:
                    properties:
                        counts:
                            properties:
                                clusters:
                                    type: integer
                                connected_clusters:
                                    type: integer
                                containers:
                                    type: integer
                                namespaces:
                                    type: integer
                                nodes:
                                    type: integer
                                persistent_volumes:
                                    type: integer
                                pods:
                                    type: integer
                                recommendations:
                                    type: integer
                                workloads:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/UtilizationCPU'
                        memory:
                            $ref: '#/components/schemas/UtilizationMemory'
                    type: object
            required:
                - id
                - kind
                - metadata
                - capacity
                - utilization
                - cost
            type: object
        OrganizationDashboard:
            description: The /v1/organization/dashboard body. The ONLY endpoint where MTD / savings figures live. Only hourly snapshot values and the ClickHouse-actual month-to-date number are surfaced — clients derive any monthly projection client-side from current_run_rate_hourly × 730.
            properties:
                month_to_date:
                    properties:
                        billed_cost:
                            $ref: '#/components/schemas/Money'
                        calendar:
                            properties:
                                days_elapsed:
                                    type: integer
                                days_in_month:
                                    type: integer
                                month:
                                    type: string
                                month_start_at:
                                    type: string
                            type: object
                    type: object
                organization_id:
                    type: string
                savings:
                    properties:
                        current_hourly_potential:
                            $ref: '#/components/schemas/Money'
                        recommendation_count:
                            type: integer
                    type: object
                snapshot:
                    $ref: '#/components/schemas/Organization'
                top_clusters:
                    items:
                        properties:
                            cluster:
                                $ref: '#/components/schemas/NestedRef'
                            current_run_rate_hourly:
                                $ref: '#/components/schemas/Money'
                            month_to_date_cost:
                                $ref: '#/components/schemas/Money'
                        type: object
                    type: array
            required:
                - organization_id
                - snapshot
                - month_to_date
                - savings
                - top_clusters
            type: object
        Pagination:
            properties:
                has_more:
                    type: boolean
                limit:
                    maximum: 500
                    minimum: 1
                    type: integer
                next_cursor:
                    description: Opaque cursor for the next page. Empty when no more pages.
                    type: string
                total_count:
                    description: Total items matching the filter (filter set excludes cursor + limit). Populated when the request supplies ?include_total=true on any paginated list endpoint. Computed via a separate COUNT(*) — opt-in because count is unbounded by the page size and may be slower than the page query on large tables.
                    type: integer
            type: object
        PaginationMeta:
            description: Offset/page-based pagination (distinct from cursor-based `Pagination` used elsewhere — cost-explorer is paged so totals are cheap).
            properties:
                page:
                    type: integer
                perPage:
                    type: integer
                totalCount:
                    type: integer
                totalPages:
                    type: integer
            required:
                - page
                - perPage
                - totalCount
                - totalPages
            type: object
        Pod:
            properties:
                capacity:
                    properties:
                        cpu:
                            properties:
                                limit_cores:
                                    format: double
                                    type: number
                            type: object
                        memory:
                            properties:
                                limit_bytes:
                                    format: int64
                                    type: integer
                            type: object
                    type: object
                cost:
                    properties:
                        cost_mode:
                            description: Phase 2.2 — currently mode-cosmetic, amount identical across modes.
                            enum:
                                - fully_loaded
                                - workload_only
                            type: string
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Pod
                    type: string
                metadata:
                    properties:
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        created_at_k8s:
                            type: string
                        has_emptydir:
                            type: boolean
                        has_hostpath:
                            type: boolean
                        host_ip:
                            type: string
                        host_network:
                            type: boolean
                        labels:
                            additionalProperties:
                                type: string
                            type: object
                        last_seen_at:
                            type: string
                        name:
                            type: string
                        namespace:
                            type: string
                        node:
                            $ref: '#/components/schemas/NestedRef'
                        phase:
                            enum:
                                - Pending
                                - Running
                                - Succeeded
                                - Failed
                                - Unknown
                            type: string
                        pod_ip:
                            type: string
                        priority_class:
                            type: string
                        qos_class:
                            enum:
                                - Guaranteed
                                - Burstable
                                - BestEffort
                            type: string
                        reason:
                            type: string
                        workload:
                            properties:
                                kind:
                                    type: string
                                name:
                                    type: string
                                uid:
                                    type: string
                            type: object
                    type: object
                utilization:
                    properties:
                        counts:
                            properties:
                                containers:
                                    type: integer
                                ready_containers:
                                    type: integer
                                running_containers:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/UtilizationCPU'
                        memory:
                            $ref: '#/components/schemas/UtilizationMemory'
                        oom_kills_total:
                            format: int64
                            type: integer
                        restarts_total:
                            format: int64
                            type: integer
                    type: object
            required:
                - id
                - kind
                - metadata
                - capacity
                - utilization
                - cost
            type: object
        Recommendation:
            description: Cost/efficiency recommendation. Bespoke shape (NOT the 4-block standard).
            properties:
                applied:
                    properties:
                        config:
                            additionalProperties: true
                            type: object
                    type: object
                current:
                    properties:
                        config:
                            additionalProperties: true
                            type: object
                        hourly_cost:
                            $ref: '#/components/schemas/Money'
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Recommendation
                    type: string
                metadata:
                    properties:
                        cause:
                            type: string
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        created_at:
                            type: string
                        data_points_analyzed:
                            type: integer
                        description:
                            type: string
                        namespace:
                            type: string
                        priority:
                            description: 'Server-derived from estimated_hourly × 730 (HoursPerMonth): ≥ $50/mo → high, ≥ $10/mo → medium, else low.'
                            enum:
                                - low
                                - medium
                                - high
                            type: string
                        recommendation_type:
                            enum:
                                - workload_rightsizing
                            type: string
                        resource_name:
                            type: string
                        resource_type:
                            enum:
                                - Deployment
                                - StatefulSet
                                - DaemonSet
                                - Pod
                                - Node
                            type: string
                        resource_uid:
                            type: string
                        risk_level:
                            enum:
                                - low
                                - medium
                                - high
                            type: string
                        status:
                            enum:
                                - pending
                                - applied
                                - dismissed
                                - archived
                            type: string
                        title:
                            type: string
                        updated_at:
                            type: string
                    type: object
                metrics_snapshot:
                    additionalProperties: true
                    description: Present only on detail endpoint.
                    type: object
                recommended:
                    properties:
                        config:
                            additionalProperties: true
                            type: object
                    type: object
                savings:
                    properties:
                        estimated_hourly:
                            $ref: '#/components/schemas/Money'
                    type: object
            required:
                - id
                - kind
                - metadata
                - current
                - recommended
                - applied
                - savings
            type: object
        Team:
            properties:
                assigned_pvs:
                    type: integer
                assigned_workloads:
                    type: integer
                cost:
                    properties:
                        cost_mode:
                            description: Live CostQL-backed; modes return genuinely different amounts.
                            enum:
                                - fully_loaded
                                - workload_only
                            type: string
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Team
                    type: string
                metadata:
                    properties:
                        created_at:
                            type: string
                        department:
                            $ref: '#/components/schemas/NestedRef'
                        description:
                            type: string
                        last_seen_at:
                            type: string
                        name:
                            type: string
                        origin:
                            description: k8s or kubeadapt — not strictly validated server-side.
                            type: string
                        owner_email:
                            type: string
                        updated_at:
                            type: string
                    type: object
            required:
                - id
                - kind
                - metadata
                - assigned_workloads
                - assigned_pvs
                - cost
            type: object
        TeamAssignment:
            properties:
                id:
                    type: string
                kind:
                    enum:
                        - TeamAssignment
                    type: string
                metadata:
                    properties:
                        assigned_by_user_id:
                            nullable: true
                            type: string
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        created_at:
                            type: string
                        entity_identifier:
                            type: string
                        entity_name:
                            type: string
                        entity_namespace:
                            type: string
                        entity_type:
                            description: Common values are workload and namespace; server accepts any string and forwards to SQL — non-canonical values just return 0 rows.
                            type: string
                        source:
                            description: 'Common values: user_manual, k8s_label, namespace_auto, backfill_v1. Not strictly validated.'
                            type: string
                        team:
                            $ref: '#/components/schemas/NestedRef'
                        updated_at:
                            type: string
                        weight_percentage:
                            format: double
                            type: number
                    type: object
            required:
                - id
                - kind
                - metadata
            type: object
        UtilizationCPU:
            properties:
                requested_cores:
                    format: double
                    type: number
                used_cores:
                    format: double
                    type: number
                utilization_percent:
                    format: double
                    type: number
            type: object
        UtilizationGPU:
            properties:
                memory_total_bytes:
                    format: int64
                    type: integer
                memory_used_bytes:
                    format: int64
                    type: integer
                utilization_percent:
                    format: double
                    type: number
            type: object
        UtilizationMemory:
            properties:
                requested_bytes:
                    format: int64
                    type: integer
                used_bytes:
                    format: int64
                    type: integer
                utilization_percent:
                    format: double
                    type: number
            type: object
        Workload:
            description: 'Workload resource — Deployment, StatefulSet, DaemonSet, Job, CronJob, and CRD kinds (Argo Rollout, NatsCluster, EphemeralRunner, etc.) all share this shape. Note: the `?kind=` filter only accepts Deployment/StatefulSet/DaemonSet — to find Jobs/CronJobs/CRDs you cannot filter, just list and read workload_kind.'
            properties:
                capacity:
                    properties:
                        cpu:
                            properties:
                                limit_cores:
                                    format: double
                                    type: number
                            type: object
                        memory:
                            properties:
                                limit_bytes:
                                    format: int64
                                    type: integer
                            type: object
                    type: object
                cost:
                    properties:
                        cost_mode:
                            description: 'Echo of the requested mode. Note: Phase 2.2 — `fully_loaded` and `workload_only` currently return identical amounts for this resource; the allocation overlay is not yet implemented.'
                            enum:
                                - fully_loaded
                                - workload_only
                            type: string
                        current_run_rate_hourly:
                            $ref: '#/components/schemas/Money'
                        last_updated_at:
                            type: string
                    type: object
                id:
                    type: string
                kind:
                    enum:
                        - Workload
                    type: string
                metadata:
                    properties:
                        cluster:
                            $ref: '#/components/schemas/NestedRef'
                        created_at_k8s:
                            type: string
                        has_hpa:
                            type: boolean
                        is_paused:
                            type: boolean
                        is_suspended:
                            type: boolean
                        labels:
                            additionalProperties:
                                type: string
                            type: object
                        last_seen_at:
                            type: string
                        name:
                            type: string
                        namespace:
                            type: string
                        service_account_name:
                            type: string
                        status:
                            type: string
                        status_reason:
                            type: string
                        workload_kind:
                            description: 'Actual K8s kind: Deployment, StatefulSet, DaemonSet, Job, CronJob, or a CRD kind like Rollout/NatsCluster.'
                            type: string
                    type: object
                utilization:
                    properties:
                        counts:
                            properties:
                                containers:
                                    type: integer
                                pods:
                                    type: integer
                                running_pods:
                                    type: integer
                            type: object
                        cpu:
                            $ref: '#/components/schemas/UtilizationCPU'
                        memory:
                            $ref: '#/components/schemas/UtilizationMemory'
                        replicas:
                            properties:
                                available:
                                    type: integer
                                desired:
                                    type: integer
                                unavailable:
                                    type: integer
                                updated:
                                    type: integer
                            type: object
                    type: object
            required:
                - id
                - kind
                - metadata
                - capacity
                - utilization
                - cost
            type: object
    securitySchemes:
        BearerAuth:
            bearerFormat: ka_live_<32 base62>
            description: API key minted via the Kubeadapt dashboard. Carries tenant_id, scope set, and optional per-cluster allowlist.
            scheme: bearer
            type: http
info:
    contact:
        email: support@kubeadapt.io
        name: Kubeadapt Support
        url: https://docs.kubeadapt.io/api/v1/
    description: Customer-facing read API for Kubernetes cost & resource visibility. Every response uses the universal `{data, meta, error}` envelope. On success the `error` key is omitted; on error `data` is null and `error` is `{code, message, details}`. Default rate limit is **100 requests per minute per API key** (configurable via `RATE_LIMIT_PER_MINUTE` env on the server). Heartbeat-based staleness threshold is **180 seconds** — clusters whose last agent heartbeat is older than this report `metadata.is_stale=true` and are excluded from `counts.connected_clusters`. See https://docs.kubeadapt.io/api/v1/ for full contract documentation.
    license:
        name: Proprietary
    title: Kubeadapt Public API
    version: v1
openapi: 3.1.0
paths:
    /health:
        get:
            responses:
                "200":
                    description: OK
            security: []
            summary: Service health (legacy)
            tags:
                - Health
    /health/live:
        get:
            responses:
                "200":
                    description: OK
            security: []
            summary: Liveness probe
            tags:
                - Health
    /health/ready:
        get:
            responses:
                "200":
                    description: OK
                "503":
                    description: PG unreachable
            security: []
            summary: Readiness probe (pings PG)
            tags:
                - Health
    /v1/clusters:
        get:
            description: 'Cluster inventory across the API key''s allowed clusters. Default sort is `cost.current_run_rate_hourly DESC`. **REJECTS** ?cost_mode=. Required scope: `clusters:read`.'
            parameters:
                - description: Page size 1..500, default 100.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Opaque pagination token from a previous response.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of clusters matching the filter (excludes cursor + limit). Returned at meta.pagination.total_count.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: 'Filter by provider (csv). Allowed: aws,gcp,azure,on-prem.'
                  in: query
                  name: provider
                  required: false
                  schema:
                    type: string
                - description: Filter by region (csv).
                  in: query
                  name: region
                  required: false
                  schema:
                    type: string
                - description: 'Filter by environment (csv). Allowed: production,non-production,staging,dev.'
                  in: query
                  name: environment
                  required: false
                  schema:
                    type: string
                - description: 'Filter by cluster status (csv). Allowed: pending,active,disconnected,error,discovered.'
                  in: query
                  name: status
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Cluster'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List clusters
            tags:
                - Clusters
            x-required-scope: clusters:read
    /v1/clusters/{cluster_id}:
        get:
            description: 'Single cluster body. **REJECTS** ?cost_mode=. Required scope: `clusters:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Cluster'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get cluster by ID
            tags:
                - Clusters
            x-required-scope: clusters:read
    /v1/clusters/{cluster_id}/cost-trend:
        get:
            description: 'Hourly / daily / weekly / monthly cost trend for one cluster. Required scope: `clusters:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: Window start, unix epoch seconds (UTC).
                  in: query
                  name: start
                  required: true
                  schema:
                    type: integer
                - description: Window end, unix epoch seconds (UTC). Must be > start. Window must not exceed 5 years.
                  in: query
                  name: end
                  required: true
                  schema:
                    type: integer
                - description: Trend mode. `run_rate` projects each bucket's burn rate to a full month (avg(cost_hourly) × 730). `breakdown` returns actual cost summed per bucket (gold layer; rejects hourly).
                  in: query
                  name: type
                  required: false
                  schema:
                    enum:
                        - run_rate
                        - breakdown
                    type: string
                - description: Bucket size. `auto` (default) resolves to hourly for windows ≤14d, daily otherwise. Explicit `hourly` is capped at 60-day windows. `breakdown` rejects `hourly`.
                  in: query
                  name: granularity
                  required: false
                  schema:
                    enum:
                        - auto
                        - hourly
                        - daily
                        - weekly
                        - monthly
                    type: string
                - description: Cost attribution mode. Cluster + organization endpoints default to `fully_loaded`. Namespace and workload endpoints default to `workload_only` (entity detail views exclude idle/overhead share).
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/CostTrendSeries'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
                "503":
                    $ref: '#/components/responses/Unavailable'
            summary: Cluster cost trend
            tags:
                - Trends
            x-required-scope: clusters:read
    /v1/clusters/{cluster_id}/namespaces:
        get:
            description: 'Required scope: `namespaces:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: Page size 1..500, default 100.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of namespaces matching the filter. Returned at meta.pagination.total_count.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: 'fully_loaded (default) or workload_only. Phase 2.2: amount is currently identical across modes for namespace cost — only meta.cost_mode and cost.cost_mode change.'
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
                - description: Minimum hourly cost (decimal).
                  in: query
                  name: min_cost_hourly
                  required: false
                  schema:
                    type: number
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Namespace'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List namespaces in cluster
            tags:
                - Namespaces
            x-required-scope: namespaces:read
    /v1/clusters/{cluster_id}/namespaces/{namespace}:
        get:
            description: 'Detail endpoint — includes `workloads_top_5` (top 5 workloads by run-rate cost) inline. Required scope: `namespaces:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: K8s namespace name.
                  in: path
                  name: namespace
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Namespace'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get namespace by name
            tags:
                - Namespaces
            x-required-scope: namespaces:read
    /v1/clusters/{cluster_id}/namespaces/{namespace}/cost-trend:
        get:
            description: 'Cost trend for one namespace within a cluster. Default cost_mode is `workload_only`. Required scope: `namespaces:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: K8s namespace name (the human-readable name, not the metadata.uid).
                  in: path
                  name: namespace
                  required: true
                  schema:
                    type: string
                - description: Window start, unix epoch seconds (UTC).
                  in: query
                  name: start
                  required: true
                  schema:
                    type: integer
                - description: Window end, unix epoch seconds (UTC). Must be > start. Window must not exceed 5 years.
                  in: query
                  name: end
                  required: true
                  schema:
                    type: integer
                - description: Trend mode. `run_rate` projects each bucket's burn rate to a full month (avg(cost_hourly) × 730). `breakdown` returns actual cost summed per bucket (gold layer; rejects hourly).
                  in: query
                  name: type
                  required: false
                  schema:
                    enum:
                        - run_rate
                        - breakdown
                    type: string
                - description: Bucket size. `auto` (default) resolves to hourly for windows ≤14d, daily otherwise. Explicit `hourly` is capped at 60-day windows. `breakdown` rejects `hourly`.
                  in: query
                  name: granularity
                  required: false
                  schema:
                    enum:
                        - auto
                        - hourly
                        - daily
                        - weekly
                        - monthly
                    type: string
                - description: Cost attribution mode. Cluster + organization endpoints default to `fully_loaded`. Namespace and workload endpoints default to `workload_only` (entity detail views exclude idle/overhead share).
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/CostTrendSeries'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
                "503":
                    $ref: '#/components/responses/Unavailable'
            summary: Namespace cost trend
            tags:
                - Trends
            x-required-scope: namespaces:read
    /v1/clusters/{cluster_id}/node-groups:
        get:
            description: '**REJECTS** ?cost_mode=. Required scope: `nodes:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/NodeGroup'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List node-groups in cluster
            tags:
                - Nodes
            x-required-scope: nodes:read
    /v1/clusters/{cluster_id}/node-groups/{name}:
        get:
            description: 'Detail endpoint — includes member `nodes` array. **REJECTS** ?cost_mode=. Required scope: `nodes:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: Node-group label value.
                  in: path
                  name: name
                  required: true
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/NodeGroup'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get single node-group by name
            tags:
                - Nodes
            x-required-scope: nodes:read
    /v1/clusters/{cluster_id}/node-groups/{name}/cost-trend:
        get:
            description: 'Cost trend for one node-group (the union of nodes sharing the node_group label). URL-encoded names with `:` / `,` are decoded server-side. **REJECTS** `?cost_mode=` — nodes carry a single physical cloud bill, so the aggregate is mode-invariant; `meta.cost_mode` is omitted from the response. Required scope: `nodes:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: Node-group label value. URL-encode characters such as `:` and `,`.
                  in: path
                  name: name
                  required: true
                  schema:
                    type: string
                - description: Window start, unix epoch seconds (UTC).
                  in: query
                  name: start
                  required: true
                  schema:
                    type: integer
                - description: Window end, unix epoch seconds (UTC). Must be > start. Window must not exceed 5 years.
                  in: query
                  name: end
                  required: true
                  schema:
                    type: integer
                - description: Trend mode. `run_rate` projects each bucket's burn rate to a full month (avg(cost_hourly) × 730). `breakdown` returns actual cost summed per bucket (gold layer; rejects hourly).
                  in: query
                  name: type
                  required: false
                  schema:
                    enum:
                        - run_rate
                        - breakdown
                    type: string
                - description: Bucket size. `auto` (default) resolves to hourly for windows ≤14d, daily otherwise. Explicit `hourly` is capped at 60-day windows. `breakdown` rejects `hourly`.
                  in: query
                  name: granularity
                  required: false
                  schema:
                    enum:
                        - auto
                        - hourly
                        - daily
                        - weekly
                        - monthly
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/CostTrendSeries'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
                "503":
                    $ref: '#/components/responses/Unavailable'
            summary: Node-group cost trend
            tags:
                - Trends
            x-required-scope: nodes:read
    /v1/clusters/{cluster_id}/nodes:
        get:
            description: '**REJECTS** ?cost_mode=. Required scope: `nodes:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of nodes matching the filter.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: csv.
                  in: query
                  name: node_group
                  required: false
                  schema:
                    type: string
                - description: csv (filter — response field is plural `instance_types` on node-group endpoints).
                  in: query
                  name: instance_type
                  required: false
                  schema:
                    type: string
                - description: csv.
                  in: query
                  name: zone
                  required: false
                  schema:
                    type: string
                - description: Filter by spot_instance=true|false.
                  in: query
                  name: is_spot
                  required: false
                  schema:
                    type: boolean
                - description: Filter by is_ready=true|false.
                  in: query
                  name: is_ready
                  required: false
                  schema:
                    type: boolean
                - description: 'csv. Common: amd64, arm64.'
                  in: query
                  name: architecture
                  required: false
                  schema:
                    type: string
                - description: 'csv. Common: on-demand, spot, reserved, karpenter.'
                  in: query
                  name: capacity_type
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Node'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List nodes in cluster
            tags:
                - Nodes
            x-required-scope: nodes:read
    /v1/clusters/{cluster_id}/workloads:
        get:
            description: 'Required scope: `workloads:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of workloads matching the filter.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: 'fully_loaded (default) or workload_only. Phase 2.2: amount identical across modes — only echo differs.'
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
                - description: Filter by namespace (csv).
                  in: query
                  name: namespace
                  required: false
                  schema:
                    type: string
                - description: 'Workload kind csv. Allowed values: Deployment,StatefulSet,DaemonSet. Job/CronJob and CRD kinds (Rollout, NatsCluster, etc.) cannot be filtered but DO appear in unfiltered list responses with their actual `metadata.workload_kind`.'
                  in: query
                  name: kind
                  required: false
                  schema:
                    type: string
                - description: Only workloads with/without HPA.
                  in: query
                  name: has_hpa
                  required: false
                  schema:
                    type: boolean
                - description: Filter by team name (csv). Resolved via team_assignments.
                  in: query
                  name: team
                  required: false
                  schema:
                    type: string
                - description: Filter by department name (csv). Two-hop via teams.
                  in: query
                  name: department
                  required: false
                  schema:
                    type: string
                - description: Minimum hourly cost.
                  in: query
                  name: min_cost_hourly
                  required: false
                  schema:
                    type: number
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Workload'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List workloads in cluster
            tags:
                - Workloads
            x-required-scope: workloads:read
    /v1/clusters/{cluster_id}/workloads/by-uid/{workload_uid}/cost-trend:
        get:
            description: 'Cost trend for one workload identified by k8s metadata.uid. Default cost_mode is `workload_only`. Required scope: `workloads:read`.'
            parameters:
                - description: Cluster UUID.
                  in: path
                  name: cluster_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: K8s metadata.uid of the workload.
                  in: path
                  name: workload_uid
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: Window start, unix epoch seconds (UTC).
                  in: query
                  name: start
                  required: true
                  schema:
                    type: integer
                - description: Window end, unix epoch seconds (UTC). Must be > start. Window must not exceed 5 years.
                  in: query
                  name: end
                  required: true
                  schema:
                    type: integer
                - description: Trend mode. `run_rate` projects each bucket's burn rate to a full month (avg(cost_hourly) × 730). `breakdown` returns actual cost summed per bucket (gold layer; rejects hourly).
                  in: query
                  name: type
                  required: false
                  schema:
                    enum:
                        - run_rate
                        - breakdown
                    type: string
                - description: Bucket size. `auto` (default) resolves to hourly for windows ≤14d, daily otherwise. Explicit `hourly` is capped at 60-day windows. `breakdown` rejects `hourly`.
                  in: query
                  name: granularity
                  required: false
                  schema:
                    enum:
                        - auto
                        - hourly
                        - daily
                        - weekly
                        - monthly
                    type: string
                - description: Cost attribution mode. Cluster + organization endpoints default to `fully_loaded`. Namespace and workload endpoints default to `workload_only` (entity detail views exclude idle/overhead share).
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/CostTrendSeries'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
                "503":
                    $ref: '#/components/responses/Unavailable'
            summary: Workload cost trend
            tags:
                - Trends
            x-required-scope: workloads:read
    /v1/cost-explorer/query:
        post:
            description: 'Proxies a cost-explorer query to the internal SaaS API. `cluster_ids` in the body are intersected with the API key''s allowed cluster set BEFORE forwarding; requests containing only disallowed clusters yield an empty result, not an error. `end_date` is INCLUSIVE (the server bumps +1 day internally). Request body is capped at 1 MiB. Each item exposes a narrow subset of fields (id, workloadName, workloadKind, namespace, cluster, clusterName, workloadUid, pods, totalCost, co2Kg). Required scope: `cost_explorer:read`.'
            requestBody:
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/CostExplorerQueryParams'
                required: true
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/CostExplorerQueryResponse'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "413":
                    $ref: '#/components/responses/PayloadTooLarge'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
                "502":
                    $ref: '#/components/responses/BadGateway'
                "504":
                    $ref: '#/components/responses/GatewayTimeout'
            summary: Run cost-explorer query
            tags:
                - CostExplorer
            x-required-scope: cost_explorer:read
    /v1/departments:
        get:
            description: 'Required scope: `departments:read`.'
            parameters:
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Opaque pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: 'csv. Common: k8s, kubeadapt.'
                  in: query
                  name: origin
                  required: false
                  schema:
                    type: string
                - description: fully_loaded (default) or workload_only.
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Department'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List departments
            tags:
                - Departments
            x-required-scope: departments:read
    /v1/departments/{dept_id}:
        get:
            description: 'Required scope: `departments:read`.'
            parameters:
                - description: Department UUID.
                  in: path
                  name: dept_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: fully_loaded (default) or workload_only.
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Department'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get department by ID
            tags:
                - Departments
            x-required-scope: departments:read
    /v1/namespaces:
        get:
            description: 'Cross-cluster flat list. Optional ?cluster_id= csv to scope. Required scope: `namespaces:read`.'
            parameters:
                - description: Page size 1..500, default 100.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of namespaces matching the filter. Returned at meta.pagination.total_count.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: 'fully_loaded (default) or workload_only. Phase 2.2: amount is currently identical across modes for namespace cost — only meta.cost_mode and cost.cost_mode change.'
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
                - description: Minimum hourly cost (decimal).
                  in: query
                  name: min_cost_hourly
                  required: false
                  schema:
                    type: number
                - description: CSV of cluster UUIDs.
                  in: query
                  name: cluster_id
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Namespace'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List namespaces (cross-cluster)
            tags:
                - Namespaces
            x-required-scope: namespaces:read
    /v1/node-groups:
        get:
            description: 'Aggregate over node_metadata GROUP BY node_group. Returns full list (no pagination — node-group cardinality is bounded). **REJECTS** ?cost_mode=. Required scope: `nodes:read`.'
            parameters:
                - description: csv.
                  in: query
                  name: cluster_id
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/NodeGroup'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List node-groups (cross-cluster)
            tags:
                - Nodes
            x-required-scope: nodes:read
    /v1/nodes:
        get:
            description: '**REJECTS** ?cost_mode= (node has one physical bill). Required scope: `nodes:read`.'
            parameters:
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of nodes matching the filter.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: csv.
                  in: query
                  name: node_group
                  required: false
                  schema:
                    type: string
                - description: csv (filter — response field is plural `instance_types` on node-group endpoints).
                  in: query
                  name: instance_type
                  required: false
                  schema:
                    type: string
                - description: csv.
                  in: query
                  name: zone
                  required: false
                  schema:
                    type: string
                - description: Filter by spot_instance=true|false.
                  in: query
                  name: is_spot
                  required: false
                  schema:
                    type: boolean
                - description: Filter by is_ready=true|false.
                  in: query
                  name: is_ready
                  required: false
                  schema:
                    type: boolean
                - description: 'csv. Common: amd64, arm64.'
                  in: query
                  name: architecture
                  required: false
                  schema:
                    type: string
                - description: 'csv. Common: on-demand, spot, reserved, karpenter.'
                  in: query
                  name: capacity_type
                  required: false
                  schema:
                    type: string
                - description: csv.
                  in: query
                  name: cluster_id
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Node'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List nodes (cross-cluster)
            tags:
                - Nodes
            x-required-scope: nodes:read
    /v1/nodes/{node_uid}:
        get:
            description: '**REJECTS** ?cost_mode=. Required scope: `nodes:read`.'
            parameters:
                - description: k8s metadata.uid.
                  in: path
                  name: node_uid
                  required: true
                  schema:
                    format: uuid
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Node'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get node by k8s UID
            tags:
                - Nodes
            x-required-scope: nodes:read
    /v1/organization:
        get:
            description: 'Tenant identity + aggregate capacity / utilization / cost across allowed clusters. **REJECTS** ?cost_mode= with 422 (org bill is one physical number). Required scope: `organization:read`.'
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Organization'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Tenant snapshot
            tags:
                - Organization
            x-required-scope: organization:read
    /v1/organization/dashboard:
        get:
            description: 'Dashboard with month-to-date billed cost, projected monthly, savings potential, top-N clusters by run rate, and recommendation count by type. **The only endpoint where MTD / projected / savings live.** Required scope: `organization:read`.'
            parameters:
                - description: Cost attribution mode. Default fully_loaded.
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
                - description: Number of top clusters by cost to embed. Range 1..20, default 5.
                  in: query
                  name: top_clusters_limit
                  required: false
                  schema:
                    type: integer
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/OrganizationDashboard'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Tenant dashboard
            tags:
                - Organization
            x-required-scope: organization:read
    /v1/organizations/dashboard/cost-trend:
        get:
            description: 'Fleet-wide cost trend across all clusters the API key is permitted to see. Non-admin keys with an empty allowed-cluster list receive a 200 envelope with `points: []` and `excluded_cluster_ids: []` (NOT a 403). Default cost_mode is `fully_loaded`. Required scope: `organization:read`.'
            parameters:
                - description: Window start, unix epoch seconds (UTC).
                  in: query
                  name: start
                  required: true
                  schema:
                    type: integer
                - description: Window end, unix epoch seconds (UTC). Must be > start. Window must not exceed 5 years.
                  in: query
                  name: end
                  required: true
                  schema:
                    type: integer
                - description: Trend mode. `run_rate` projects each bucket's burn rate to a full month (avg(cost_hourly) × 730). `breakdown` returns actual cost summed per bucket (gold layer; rejects hourly).
                  in: query
                  name: type
                  required: false
                  schema:
                    enum:
                        - run_rate
                        - breakdown
                    type: string
                - description: Bucket size. `auto` (default) resolves to hourly for windows ≤14d, daily otherwise. Explicit `hourly` is capped at 60-day windows. `breakdown` rejects `hourly`.
                  in: query
                  name: granularity
                  required: false
                  schema:
                    enum:
                        - auto
                        - hourly
                        - daily
                        - weekly
                        - monthly
                    type: string
                - description: Cost attribution mode. Cluster + organization endpoints default to `fully_loaded`. Namespace and workload endpoints default to `workload_only` (entity detail views exclude idle/overhead share).
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/CostTrendSeries'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
                "503":
                    $ref: '#/components/responses/Unavailable'
            summary: Organization dashboard cost trend
            tags:
                - Trends
            x-required-scope: organization:read
    /v1/recommendations:
        get:
            description: 'Sorted by estimated_hourly_savings DESC. **REJECTS** ?cost_mode= (savings mode-agnostic). Required scope: `recommendations:read`.'
            parameters:
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: csv.
                  in: query
                  name: cluster_id
                  required: false
                  schema:
                    type: string
                - description: csv.
                  in: query
                  name: namespace
                  required: false
                  schema:
                    type: string
                - description: csv. Public API surfaces only `workload_rightsizing`; other internal types (spot_conversion, node_group_rightsizing, abandoned_workload, orphaned_resources) require the in-product dashboard.
                  in: query
                  name: recommendation_type
                  required: false
                  schema:
                    type: string
                - description: 'csv. Allowed: pending,applied,dismissed,archived. When omitted, results are filtered to status IN (pending, dismissed) AND recommendation_type = ''workload_rightsizing''.'
                  in: query
                  name: status
                  required: false
                  schema:
                    type: string
                - description: 'csv. Allowed: low, medium, high.'
                  in: query
                  name: risk_level
                  required: false
                  schema:
                    type: string
                - description: 'csv. Allowed: high, medium, low (server-derived bucket from monthly savings).'
                  in: query
                  name: priority
                  required: false
                  schema:
                    type: string
                - description: 'csv. Allowed: Deployment, StatefulSet, DaemonSet, Pod, Node.'
                  in: query
                  name: resource_type
                  required: false
                  schema:
                    type: string
                - description: csv.
                  in: query
                  name: workload_uid
                  required: false
                  schema:
                    type: string
                - description: Minimum hourly savings.
                  in: query
                  name: min_savings_hourly
                  required: false
                  schema:
                    type: number
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Recommendation'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List recommendations
            tags:
                - Recommendations
            x-required-scope: recommendations:read
    /v1/recommendations/{rec_id}:
        get:
            description: 'Detail endpoint — includes `metrics_snapshot`. **REJECTS** ?cost_mode=. Required scope: `recommendations:read`.'
            parameters:
                - description: Recommendation UUID.
                  in: path
                  name: rec_id
                  required: true
                  schema:
                    format: uuid
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Recommendation'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get recommendation by ID
            tags:
                - Recommendations
            x-required-scope: recommendations:read
    /v1/teams:
        get:
            description: 'Live MTD run-rate cost via CostQL (genuinely mode-aware). Required scope: `teams:read`.'
            parameters:
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Opaque pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: csv (UUIDs).
                  in: query
                  name: department_id
                  required: false
                  schema:
                    type: string
                - description: 'csv. Common values: k8s, kubeadapt. Not strictly validated server-side.'
                  in: query
                  name: origin
                  required: false
                  schema:
                    type: string
                - description: fully_loaded (default) or workload_only.
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Team'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List teams
            tags:
                - Teams
            x-required-scope: teams:read
    /v1/teams/{team_id}:
        get:
            description: 'Required scope: `teams:read`.'
            parameters:
                - description: Team UUID.
                  in: path
                  name: team_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: fully_loaded (default) or workload_only.
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Team'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get team by ID
            tags:
                - Teams
            x-required-scope: teams:read
    /v1/teams/{team_id}/assignments:
        get:
            description: 'Required scope: `teams:read`.'
            parameters:
                - description: Team UUID.
                  in: path
                  name: team_id
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Opaque pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: 'csv. Common values: workload, namespace (server forwards any string to SQL; non-canonical values just return 0 rows).'
                  in: query
                  name: entity_type
                  required: false
                  schema:
                    type: string
                - description: csv (UUIDs).
                  in: query
                  name: cluster_id
                  required: false
                  schema:
                    type: string
                - description: 'csv. Common values: user_manual, k8s_label, namespace_auto, backfill_v1.'
                  in: query
                  name: source
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/TeamAssignment'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaBase'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List team assignments
            tags:
                - Teams
            x-required-scope: teams:read
    /v1/workloads:
        get:
            description: 'Required scope: `workloads:read`.'
            parameters:
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of workloads matching the filter.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: 'fully_loaded (default) or workload_only. Phase 2.2: amount identical across modes — only echo differs.'
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
                - description: Filter by namespace (csv).
                  in: query
                  name: namespace
                  required: false
                  schema:
                    type: string
                - description: 'Workload kind csv. Allowed values: Deployment,StatefulSet,DaemonSet. Job/CronJob and CRD kinds (Rollout, NatsCluster, etc.) cannot be filtered but DO appear in unfiltered list responses with their actual `metadata.workload_kind`.'
                  in: query
                  name: kind
                  required: false
                  schema:
                    type: string
                - description: Only workloads with/without HPA.
                  in: query
                  name: has_hpa
                  required: false
                  schema:
                    type: boolean
                - description: Filter by team name (csv). Resolved via team_assignments.
                  in: query
                  name: team
                  required: false
                  schema:
                    type: string
                - description: Filter by department name (csv). Two-hop via teams.
                  in: query
                  name: department
                  required: false
                  schema:
                    type: string
                - description: Minimum hourly cost.
                  in: query
                  name: min_cost_hourly
                  required: false
                  schema:
                    type: number
                - description: CSV of cluster UUIDs.
                  in: query
                  name: cluster_id
                  required: false
                  schema:
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Workload'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List workloads (cross-cluster)
            tags:
                - Workloads
            x-required-scope: workloads:read
    /v1/workloads/{workload_uid}:
        get:
            description: 'k8s metadata.uid lookup. Required scope: `workloads:read`.'
            parameters:
                - description: k8s metadata.uid.
                  in: path
                  name: workload_uid
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: fully_loaded (default) or workload_only.
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        $ref: '#/components/schemas/Workload'
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: Get workload by k8s UID
            tags:
                - Workloads
            x-required-scope: workloads:read
    /v1/workloads/{workload_uid}/pods:
        get:
            description: 'The only pod-introspection surface in v1 — pods cannot be enumerated flat or by cluster, only as a workload''s children. Required scope: `workloads:read`.'
            parameters:
                - description: k8s metadata.uid.
                  in: path
                  name: workload_uid
                  required: true
                  schema:
                    format: uuid
                    type: string
                - description: 1..500.
                  in: query
                  name: limit
                  required: false
                  schema:
                    type: integer
                - description: Pagination token.
                  in: query
                  name: cursor
                  required: false
                  schema:
                    type: string
                - description: Include total count of pods owned by this workload.
                  in: query
                  name: include_total
                  required: false
                  schema:
                    type: boolean
                - description: 'fully_loaded (default) or workload_only. Phase 2.2: amount identical across modes.'
                  in: query
                  name: cost_mode
                  required: false
                  schema:
                    enum:
                        - fully_loaded
                        - workload_only
                    type: string
                - description: csv.
                  in: query
                  name: namespace
                  required: false
                  schema:
                    type: string
                - description: csv.
                  in: query
                  name: node_uid
                  required: false
                  schema:
                    type: string
                - description: 'csv. Allowed: Pending,Running,Succeeded,Failed,Unknown.'
                  in: query
                  name: phase
                  required: false
                  schema:
                    type: string
                - description: 'csv. Allowed: Guaranteed,Burstable,BestEffort.'
                  in: query
                  name: qos_class
                  required: false
                  schema:
                    type: string
                - description: Filter by hostPath volume presence.
                  in: query
                  name: has_hostpath
                  required: false
                  schema:
                    type: boolean
                - description: Filter by emptyDir volume presence.
                  in: query
                  name: has_emptydir
                  required: false
                  schema:
                    type: boolean
                - description: Filter by hostNetwork=true|false.
                  in: query
                  name: host_network
                  required: false
                  schema:
                    type: boolean
            responses:
                "200":
                    content:
                        application/json:
                            schema:
                                properties:
                                    data:
                                        items:
                                            $ref: '#/components/schemas/Pod'
                                        type: array
                                    error:
                                        allOf:
                                            - $ref: '#/components/schemas/ErrorBody'
                                        nullable: true
                                    meta:
                                        $ref: '#/components/schemas/MetaWithCostMode'
                                required:
                                    - meta
                                type: object
                    description: Standard envelope. `data` is the resource (object or array), `meta` carries request_id/applied_at/pagination/cost_mode, `error` is omitted on success.
                "400":
                    $ref: '#/components/responses/BadRequest'
                "401":
                    $ref: '#/components/responses/Unauthorized'
                "403":
                    $ref: '#/components/responses/Forbidden'
                "404":
                    $ref: '#/components/responses/NotFound'
                "410":
                    $ref: '#/components/responses/Gone'
                "422":
                    $ref: '#/components/responses/Validation'
                "429":
                    $ref: '#/components/responses/RateLimited'
                "500":
                    $ref: '#/components/responses/ServerError'
            summary: List pods for workload
            tags:
                - Workloads
            x-required-scope: workloads:read
security:
    - BearerAuth: []
servers:
    - url: https://public-api.kubeadapt.io
tags:
    - description: Unauthenticated liveness/readiness probes.
      name: Health
    - description: 'Tenant snapshot, dashboard, settings. Scope: organization:read.'
      name: Organization
    - description: 'Cluster inventory. Scope: clusters:read.'
      name: Clusters
    - description: 'K8s namespace listings with cost-mode echo. Scope: namespaces:read.'
      name: Namespaces
    - description: 'Workloads (Deployments, StatefulSets, DaemonSets via ?kind=) plus the workload-scoped pod sub-list. Scope: workloads:read.'
      name: Workloads
    - description: 'Node inventory + node-group aggregates. Scope: nodes:read.'
      name: Nodes
    - description: 'Cost / efficiency recommendations with savings projections. Scope: recommendations:read.'
      name: Recommendations
    - description: 'Team identity + assignments. Scope: teams:read.'
      name: Teams
    - description: 'Department identity + counts. Scope: departments:read.'
      name: Departments
    - description: 'Proxy for the internal cost-explorer service. Returns paginated cost rows + KPI summary. Scope: cost_explorer:read.'
      name: CostExplorer
    - description: Cost-trend time series for clusters, namespaces, workloads, node-groups, and the organization dashboard. Hourly granularity reads silver tables directly; daily/weekly/monthly go through CostQL gold. Scope is per-resource (clusters/namespaces/workloads/nodes/organization).
      name: Trends
