Skip to main content
Use CostGraph’s OpenCost-compatible endpoints to read Kubernetes allocation, assets, and provider costs. You can query the hosted API directly or connect a client through a Kubernetes Service. Choose the connection your client supports. Check the compatibility limits before switching an existing client.

Before you begin

For an allocation request, you need a connected Kubernetes cluster with collected data and an API key from Settings > API keys. Give the key the operator:read scope for allocation and assets. Cloud cost queries need focus:read. Grant both if one client needs all three. The key identifies your CostGraph tenant, so you don’t need a separate tenant header.

Connect a client

Set your API key locally, then request the last 24 hours of allocation grouped by cluster and namespace.
This query includes the clusters in your tenant. Grouping by both fields keeps namespaces with the same name in different clusters separate. To select a cluster or namespace, add a filter.

Response

A successful response has code: 200 and a data array. Each array entry is an allocation set for one time step, keyed by allocation name. With no step, the request returns one set covering the whole window. This illustrative excerpt shows one namespace. Other allocation fields are omitted for readability. Your response contains dates, names, and costs from your tenant.
The namespace’s CPU, memory, storage, network, and load balancer costs add up to totalCost for the window. Idle cost is excluded unless you request includeIdle=true or shareIdle=true. If the request fails or returns no allocations, check the following. For another HTTP client, use https://api.costgraph.ai/api/v1/tenant/opencost as the base URL and send the same X-API-Key header. The available routes are
/allocation and /allocation/compute are aliases. The summary routes run the same allocation query and return fewer fields.

Serve the API inside the cluster

kubectl cost connects to a Kubernetes Service. Enable the operator’s OpenCost proxy to give it that connection. The proxy forwards requests to CostGraph using the operator’s configured API key. These examples use CostGraph Operator chart 0.8.0 and kubectl-cost v0.6.6. You need Helm, access to the cluster, and permission to port-forward to the proxy Pod. Follow the operator installation guide first if the operator isn’t installed. The commands assume the release is named costgraph-operator in the costgraph namespace. Match the release, namespace, and chart version to your installation. Check for an existing opencost Service in that namespace before enabling the proxy. An existing OpenCost installation may already own that name. Enable the proxy while retaining the release’s configured values.
The chart creates an opencost Service on port 9003 in the release namespace. Check that it exists.
The proxy calls api.costgraph.ai over HTTPS and adds a cluster filter from global.clusterName to allocation and asset queries. For a self-hosted backend, set openCostApi.config.apiHost to your backend’s HTTPS hostname. Read namespace costs through the Service.
The result is a namespace cost table for the requested day. --historical reports the window’s cost. Without it, the plugin projects a monthly rate. If you customize openCostApi.service.name or .port, use the matching client flags. Use --opencost only when the Service is in the opencost namespace with its default name and port. In v0.6.6, that flag sets the namespace to opencost even if you also pass --kubecost-namespace.

Replace Kubecost

The compatibility Service lets allocation clients connect using Kubecost’s conventions. It does not replace Kubecost’s full API or UI. If your client expects a Service named kubecost-cost-analyzer on port 9090 and an allocation route at /model/allocation, enable compatibility on the same operator release. Check that an existing Kubecost installation doesn’t already own that Service name in the release namespace.
Both Services use the same proxy. Verify the additional Service, then query it.
If the operator release is in the kubecost namespace, the plugin’s defaults already match and you can omit --kubecost-namespace. The namespace, controller, deployment, pod, node, and label views use allocation queries. kubectl cost predict requires a prediction endpoint that CostGraph does not serve. The TUI also requests Kubecost currency settings, which the proxy does not provide.

Query allocation

window is required. Everything else is optional. aggregate accepts cluster, node, namespace, controller, controllerKind, pod, container, and label:<key>. CostGraph composes names the way OpenCost does, joining the properties you asked for with /. A controller carries its kind and name, so aggregate=controller returns deployment:api. A property with no value returns __unallocated__. To group by one kind of controller, ask for it by name: deployment, statefulset, daemonset, job, or cronjob. Each returns the controllers of that kind and gathers everything else under __unallocated__, so the cost still adds up to the same total. label:<key> groups by a pod label. aggregate=label:team returns one allocation per team, and pods without the label land in __unallocated__. Combine it with anything else: aggregate=namespace,label:app.
CostGraph resolves a pod to the controller a person recognizes. A pod created by a CronJob belongs to the CronJob, not to the Job it ran in, so it appears under aggregate=cronjob rather than aggregate=job. OpenCost stops at the Job.

Filter the result

filter narrows the result using OpenCost’s filter syntax.
You can filter on cluster, node, namespace, controllerName, controllerKind, pod, and container, and combine terms with and, or, and not. Any other field returns 400 rather than being ignored. That includes label and annotation selectors such as label[app]:"web", and the services, provider, and account fields. Idle follows the filter. Filtering to one cluster reports that cluster’s idle, not every cluster’s.

Query assets

GET /assets returns the nodes and disks billed over the window, keyed the way OpenCost keys them. A node carries its instance type, the cores and bytes it offered over the window, and its cost split across CPU and memory. The two parts add back to the node’s bill. A disk carries its provisioned bytes and storage class. Load balancers aren’t reported.

Query cloud cost

GET /cloudCost returns what your vendors billed you, rather than how CostGraph allocated that spend to your workloads. This route reads billing data rather than cluster data, so it needs the focus:read scope. A key with only operator:read reads allocation and assets and gets 403 here. aggregate accepts invoiceEntityID, accountID, regionID, availabilityZone, provider, providerID, category, and service. It defaults to provider,service. Every vendor you connect appears here, software services and cloud providers alike, so aggregating by provider returns Datadog and GitHub next to AWS. kubernetesPercent reports 0, because CostGraph doesn’t yet attribute a billed resource back to the Kubernetes node that used it.

Cost model

CostGraph allocates CPU and memory cost based on the greater of a container’s request and its usage, following the OpenCost workload cost model. A container that reserves more than it uses is allocated the reservation cost. Storage, network, and load balancer costs use what the vendor charged. Idle is the part of a node’s bill that no container accounts for. CostGraph measures it per node, so an over-committed node can’t offset an empty one. Pass includeIdle=true and workload cost plus idle equals the cluster bill.

Storage

A volume’s cost reaches the container that mounts it. Each allocation lists the volumes behind it in pvs, and pvCost is their total. A volume mounted by several containers is divided between them, so the shares add back to the volume’s bill.

Network

CostGraph prices traffic by locality, so crossing a zone or leaving for the internet costs where staying inside a zone doesn’t. An edge charged in both directions gives half to each end. An edge charged one way gives the whole cost to that end. A workload’s traffic is then divided between the pods running it, so a controller sees the whole and a pod sees its share.

Load balancers

A load balancer’s cost reaches the pods its Service selects, divided between them. Credits and tax name no resource on the vendor’s bill, so they belong to no pod and are left out.

What CostGraph doesn’t serve

CostGraph supports allocation, asset, and cloud cost queries with the following limitations.

Limits

Two limits return 400. A request produces more than 10,000 sets, such as a 30-day window at a one-second step. A request returns more than 200,000 allocations. Widen the step or narrow the window.