FinOps Costs
Read platform cost figures: cost per month, day, or any hourly, daily, weekly, or monthly point; cost by resource type, resource, organization, user, or namespace; the most expensive resources; CPU and memory efficiency; anomalies; the forecast; rightsizing savings; the dashboard's figures; and cost data collection health. Every figure comes from the same hourly cost record that budgets are charged from (see Where the figures come from).
All endpoints are read-only and require an API key in the X-API-Key header with the finops:read scope.
Every figure is scoped to the key's user: a platform administrator sees every cost on the platform, including the platform baseline; on a multi-tenant platform an organization's owners and admins see their organization's costs; anyone else sees the costs of their own workloads. Filters narrow within that scope and never widen it.
Amounts are US dollars, except the spend fields of the dashboard statistics, which are integer US cents. Days, weeks, and months are UTC.
Windows
Endpoints that take a window or period accept:
| Value | Meaning |
|---|---|
Nh, Nd, Ny (for example 24h, 7d, 1y) | The last N hours, days (24 hours each), or years (365 days each), in whole hours counted back from the current hour. The current hour is not included. |
mtd | This UTC calendar month so far |
lastweek | The previous UTC calendar week, Monday to Monday |
lastmonth | The previous UTC calendar month |
start,end | Two ISO 8601 instants or dates. A bare start date is its 00:00 UTC; a bare end date is included. |
Each hour's cost is added once the hour ends. An unknown window returns 400 validation-error.
Change on the previous period: where a response compares with the previous period, that period has the same length and ends where the window starts. The comparison is null when the recorded cost data does not cover all of the previous period, or when there was no cost in it.
Resource types: a resourceType filter takes a resource type such as app, addon, workflow, workspace, fine-tuning, self-hosted-model, automl, model-registry (model serving), build (image builds), data-forge, tool, mcp-gateway, scheduled-job, or project-job; platform-scaling (platform capacity caused by organizations' workloads) or platform:<organization ID> (one organization's); or platform (the platform baseline, which belongs to no organization).
Groupings: a groupBy takes resource_type, resource_id (each resource), org, user, or namespace.
Cost Point Object
{
"date": "2026-09-01T00:00:00Z",
"total": 1234.56
}
GET /api/v1/finops/costs/monthly
Cost per calendar month (UTC).
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
months | integer | No | The last N calendar months, this one included (default: 12, at least 1) |
year | integer | No | One calendar year's months instead (for example 2026) |
Response 200 OK
{
"data": {
"months": [
{ "date": "2026-08-01T00:00:00Z", "total": 8123.45 },
{ "date": "2026-09-01T00:00:00Z", "total": 7420.1 }
],
"summary": {
"averageMonthly": 7771.78,
"highestMonth": { "date": "2026-08-01T00:00:00Z", "total": 8123.45 },
"lowestMonth": { "date": "2026-09-01T00:00:00Z", "total": 7420.1 }
},
"start": "2025-10-01T00:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
Months with no recorded cost are not listed, and the average is over the months listed.
GET /api/v1/finops/costs/daily
Cost per UTC day over a date range.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
startDate | string | No | First day (YYYY-MM-DD or ISO 8601). Give with endDate |
endDate | string | No | Last day, included. Without both dates, the last 30 days |
resourceType | string | No | Only this resource type |
Response 200 OK
{
"data": {
"days": [
{ "date": "2026-09-28T00:00:00Z", "total": 410.22 }
],
"summary": {
"totalPeriod": 12306.6,
"dailyAverage": 410.22,
"previousPeriod": 11980.4,
"changePercent": 2.72,
"trend": "stable"
},
"start": "2026-08-30T14:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
changePercent compares with the previous period of the same length. trend is increasing (more than 5% up), decreasing (more than 5% down), stable, or null when there is no comparison.
GET /api/v1/finops/costs/forecast
Daily cost projected forward from a straight line fit to the last 90 whole days of daily cost, with 95% prediction bounds. Days with no recorded cost are left out of the fit. With fewer than 3 days of history there is no projection.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
months | integer | No | Months to project, 30 days each (1 to 12, default: 3) |
Response 200 OK
{
"data": {
"historical": [
{ "date": "2026-09-28", "cost": 410.22 }
],
"predictions": [
{
"date": "2026-09-29",
"predicted": 415.3,
"lowerBound": 362.8,
"upperBound": 467.8
}
],
"analysis": {
"trend": "increasing",
"monthlyGrowthRate": 0.021,
"confidence": "medium"
}
},
"meta": { "requestId": "req_abc123" }
}
monthlyGrowthRate is the line's growth over 30 days as a fraction of the average day (null with no projection). trend follows its sign. confidence is high, medium, or low, from how many of the 90 days have cost and how steady the daily cost was.
GET /api/v1/finops/costs/services
Cost by resource type (apps, workflows, workspaces, models, idle node capacity, shared services, storage, and so on) over a window or a date range.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
period | string | No | A window (default: 30d). Ignored when startDate and endDate are given |
startDate | string | No | Start of a date range (YYYY-MM-DD or ISO 8601). Give with endDate |
endDate | string | No | End of the range (a bare date is included) |
Response 200 OK
{
"data": {
"items": [
{
"groupKey": "self-hosted-model",
"name": "Self-hosted models",
"totalCost": 4321.0,
"cpuCost": 100.0,
"ramCost": 50.0,
"gpuCost": 4136.0,
"storageCost": 25.0,
"networkCost": 10.0,
"changePercent": 4.5
}
],
"totalCost": 9120.4,
"periodStart": "2026-08-30T14:00:00Z",
"periodEnd": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
Items are most expensive first. changePercent compares with the previous period of the same length.
GET /api/v1/finops/costs/anomalies
Resources whose cost on the last whole day moved from their usual day. A resource's usual day is its average daily cost over the earlier days of the lookback, counting only days it had cost, so a resource that stopped is not flagged.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
days | integer | No | Days to look back (default: 7) |
sensitivity | string | No | low (the day moved by at least 100%), medium (50%, the default), or high (25%) |
Response 200 OK
{
"data": {
"anomalies": [
{
"timestamp": "2026-09-28T00:00:00Z",
"resource": "ingest-pipeline",
"resourceId": "Wf8kLp2qZx7mNc4vR",
"resourceType": "workflow",
"expectedCost": 12.4,
"actualCost": 31.9,
"deviation": 1.5726,
"direction": "spike",
"severity": "high"
}
],
"period": { "days": 7, "sensitivity": "medium" }
},
"meta": { "requestId": "req_abc123" }
}
deviation is how far the day moved, as a fraction of the usual day. direction is spike or drop. severity is high when the day moved by at least twice the sensitivity's threshold, otherwise medium. Anomalies are largest first.
GET /api/v1/finops/costs/savings
Rightsizing savings over the last 30 days: resources whose pods used under 40% of the CPU and memory they requested, with the potential saving (the cost of the unused share of their CPU and memory).
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
category | string | No | rightsizing, the only category |
minSavings | number | No | Only recommendations saving at least this much (USD) |
Response 200 OK
{
"data": {
"recommendations": [
{
"resource": "workflow-worker-abc",
"resourceId": "Wf8kLp2qZx7mNc4vR",
"resourceType": "workflow",
"category": "rightsizing",
"currentCost": 200.0,
"potentialSavings": 60.0,
"efficiency": 0.3,
"recommendation": "Its pods used 30% of the CPU and memory they requested. Lower the requests to match usage."
}
],
"totalPotentialSavings": 60.0,
"window": { "start": "2026-08-30T14:00:00Z", "end": "2026-09-29T14:00:00Z" }
},
"meta": { "requestId": "req_abc123" }
}
Recommendations are largest saving first.
GET /api/v1/finops/dashboard
A FinOps overview: the last 30 days' statistics, daily cost over the last 30 days, the last 6 calendar months, and the 5 most expensive resources.
Scope: finops:read
Response 200 OK
{
"data": {
"stats": { "...": "Dashboard statistics, as GET /finops/dashboard/stats" },
"costTrend": { "...": "Daily cost, as GET /finops/costs/trends" },
"monthlyCosts": {
"months": [
{ "date": "2026-09-01T00:00:00Z", "total": 7420.1 }
],
"summary": {
"averageMonthly": 7420.1,
"highestMonth": { "date": "2026-09-01T00:00:00Z", "total": 7420.1 },
"lowestMonth": { "date": "2026-09-01T00:00:00Z", "total": 7420.1 }
}
},
"topDrivers": [ { "...": "Top driver, as GET /finops/costs/top-drivers" } ]
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/finops/dashboard/stats
The dashboard's statistics for a window.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
period | string | No | A window (default: 30d) |
Response 200 OK
{
"data": {
"totalSpend": 1230660,
"previousPeriodSpend": 1198040,
"spendTrend": 2.72,
"monthToDateSpend": 1159830,
"activeResources": 42,
"exhaustedBudgets": 1,
"anomalies": 2,
"budgetAlerts": 3,
"efficiencyScore": 38,
"start": "2026-08-30T14:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
| Field | Description |
|---|---|
totalSpend, previousPeriodSpend | Cost for the window and for the previous period of the same length, in cents. previousPeriodSpend is null when the recorded data does not cover all of that period |
spendTrend | Percent change on the previous period, or null |
monthToDateSpend | Cost this UTC calendar month so far, in cents |
activeResources | Tenant resources that had cost in the window |
exhaustedBudgets | Budgets in scope that reached their pause threshold |
anomalies | Cost anomalies in the window, at medium sensitivity |
budgetAlerts | exhaustedBudgets plus anomalies |
efficiencyScore | CPU and memory used as a percent of requested, or null with no measured pods |
GET /api/v1/finops/dashboard/top-drivers
The most expensive resources over a window. The same as GET /finops/costs/top-drivers, with the window named period.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | How many (default: 10, at most 100) |
period | string | No | A window (default: 30d) |
Response 200 OK
A list of top drivers, as GET /finops/costs/top-drivers.
GET /api/v1/finops/costs/realtime
Each resource's cost over a recent window (by default the last complete hour), with its parts and efficiency.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
window | string | No | A window (default: 1h) |
namespace | string | No | Only this Kubernetes namespace |
Response 200 OK
{
"data": {
"items": [
{
"name": "dev-dashboard",
"namespace": "org-acme",
"cpuCost": 0.021,
"ramCost": 0.009,
"gpuCost": 0,
"pvCost": 0.002,
"networkCost": 0,
"totalCost": 0.034,
"cpuEfficiency": 0.22,
"ramEfficiency": 0.41,
"efficiency": 0.315,
"resourceType": "app",
"resourceId": "hT7kQw2pLm9xRz4vB",
"orgId": "acme",
"userId": "okRpaKPh8B9asdKb2"
}
],
"totalCost": 1.87,
"window": "1h",
"start": "2026-09-29T13:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
pvCost is the resource's storage cost. Efficiency fields are usage as a fraction of requests, null where no measured pod ran.
GET /api/v1/finops/costs/historical
Cost per group over a date range.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
startDate | string | No | First day (YYYY-MM-DD or ISO 8601). Give with endDate |
endDate | string | No | Last day, included. Without both dates, the last 30 days |
groupBy | string | No | A grouping (default: resource_type) |
orgId | string | No | Only this organization |
userId | string | No | Only this user |
Response 200 OK
{
"data": {
"items": [
{
"group": "workflow",
"groupLabel": "Workflows",
"totalCost": 812.4,
"cpuCost": 420.1,
"ramCost": 188.3,
"storageCost": 96.2,
"networkCost": 12.8,
"gpuCost": 0
}
],
"totalCost": 9120.4,
"startDate": "2026-09-01T00:00:00Z",
"endDate": "2026-09-29T00:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/finops/costs/breakdown
Cost per group with its parts, its change on the previous period, and its efficiency. The Cost Explorer's breakdown table uses the same figures.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
window | string | No | A window (default: 30d) |
groupBy | string | No | A grouping (default: resource_type) |
resourceType | string | No | Only this resource type |
orgId | string | No | Only this organization |
userId | string | No | Only this user |
namespace | string | No | Only this Kubernetes namespace |
Response 200 OK
{
"data": {
"items": [
{
"group": "hT7kQw2pLm9xRz4vB",
"groupLabel": "dev-dashboard",
"totalCost": 24.6,
"computeCost": 21.3,
"cpuCost": 12.9,
"ramCost": 5.6,
"sharedCost": 2.8,
"gpuCost": 0,
"storageCost": 2.1,
"networkCost": 1.2,
"loadBalancerCost": 0,
"externalCost": 0,
"previousCost": 22.1,
"trend": 11.31,
"cpuEfficiency": 0.22,
"ramEfficiency": 0.41,
"efficiency": 0.315,
"resourceType": "app",
"resourceTypeLabel": "Apps",
"orgId": "acme",
"userId": "okRpaKPh8B9asdKb2",
"namespace": "org-acme"
}
],
"totalCost": 9120.4,
"groupBy": "resource_id",
"start": "2026-08-30T14:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
| Field | Description |
|---|---|
group, groupLabel | The group's key and name |
totalCost | Cost for the window |
computeCost | cpuCost plus ramCost plus sharedCost (the node overhead shared into them) |
gpuCost, storageCost, networkCost, loadBalancerCost, externalCost | The other parts of the cost |
previousCost, trend | Cost in the previous period and the percent change on it. previousCost is null when the recorded data does not cover all of that period; trend is also null when there was no cost in it |
cpuEfficiency, ramEfficiency, efficiency | CPU, memory, and their average used as a fraction of requested, null where no measured pod ran |
resourceType, resourceTypeLabel, orgId, userId, namespace | With groupBy=resource_id only: the resource's type, and its organization, user, and namespace when it has one |
Items are most expensive first.
GET /api/v1/finops/costs/efficiency
CPU (core-hours) and memory (byte-hours) that pods used against what they requested, overall and per group.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
window | string | No | A window (default: 30d) |
groupBy | string | No | A grouping (default: resource_type) |
resourceType | string | No | Only this resource type |
namespace | string | No | Only this Kubernetes namespace |
Response 200 OK
{
"data": {
"cpuRequestedCoreHours": 1840.5,
"cpuUsedCoreHours": 512.3,
"ramRequestedByteHours": 9876543210000,
"ramUsedByteHours": 4123456789000,
"cpuEfficiency": 0.278345,
"ramEfficiency": 0.417498,
"efficiency": 0.347922,
"groupBy": "resource_type",
"byGroup": [
{
"group": "app",
"groupLabel": "Apps",
"cpuRequestedCoreHours": 720.0,
"cpuUsedCoreHours": 158.4,
"ramRequestedByteHours": 3865470566400,
"ramUsedByteHours": 1352914698240,
"cpuEfficiency": 0.22,
"ramEfficiency": 0.35,
"efficiency": 0.285
}
],
"start": "2026-08-30T14:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
Groups are ordered by requested CPU, largest first. Cost that no pod of its own ran (a share of idle node capacity or of shared services) has no efficiency.
GET /api/v1/finops/costs/trends
Cost per hour, day, week (weeks start on Monday), or month (UTC) over a window, with the window's total, daily average, and change on the previous period.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
window | string | No | A window (default: 30d) |
granularity | string | No | hourly, daily (default), weekly, or monthly |
groupBy | string | No | Break each point down by this grouping |
resourceType | string | No | Only this resource type |
Response 200 OK
{
"data": {
"points": [
{
"timestamp": "2026-09-28T00:00:00Z",
"cost": 410.22,
"breakdown": [
{ "group": "self-hosted-model", "groupLabel": "Self-hosted models", "cost": 190.4 },
{ "group": "app", "groupLabel": "Apps", "cost": 88.7 }
]
}
],
"totalCost": 12306.6,
"previousPeriodCost": 11980.4,
"changePercent": 2.72,
"dailyAverage": 410.22,
"granularity": "daily",
"start": "2026-08-30T14:00:00Z",
"end": "2026-09-29T14:00:00Z"
},
"meta": { "requestId": "req_abc123" }
}
breakdown is present only with groupBy, most expensive first. Points with no recorded cost are not listed.
GET /api/v1/finops/costs/top-drivers
The most expensive resources over a window.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
window | string | No | A window (default: 30d) |
limit | integer | No | How many (default: 10, at most 100) |
Response 200 OK
{
"data": [
{
"name": "llama-70b",
"resourceId": "d-7c1e9a",
"resourceType": "self-hosted-model",
"resourceTypeLabel": "Self-hosted models",
"orgId": "acme",
"totalCost": 2890.5,
"computeCost": 210.3,
"cpuCost": 120.1,
"ramCost": 60.4,
"sharedCost": 29.8,
"gpuCost": 2640.0,
"storageCost": 35.2,
"networkCost": 5.0,
"loadBalancerCost": 0,
"externalCost": 0,
"previousCost": 2750.0,
"trend": 5.11,
"cpuEfficiency": 0.41,
"ramEfficiency": 0.63,
"efficiency": 0.52
}
],
"meta": { "requestId": "req_abc123" }
}
Fields are as in GET /finops/costs/breakdown, with name for the resource's name.
GET /api/v1/finops/data-health
Cost data collection health. Platform administrators only; other keys get 403 forbidden.
Scope: finops:read
Response 200 OK
| Field | Description |
|---|---|
status | healthy, degraded, or stale |
lastScrapeAt | When cost data was last collected |
lastDataAt | The latest complete cost hour |
recordCount | How many cost records there are |
coverage7d, coverage30d | Coverage of the last 7 and 30 days, as a percent |
gaps | Periods with missing cost data |
MCP tools
The same reads are available to agents as MCP tools: get_finops_costs_monthly, get_finops_costs_daily, get_finops_cost_forecast, get_finops_costs_by_service, get_finops_cost_anomalies, get_finops_savings_recommendations, get_finops_dashboard, get_finops_dashboard_stats, get_finops_dashboard_top_drivers, get_finops_costs_realtime, get_finops_costs_historical, get_finops_cost_breakdown, get_finops_cost_efficiency, get_finops_cost_trends, get_finops_cost_top_drivers, and get_finops_data_health.