State & Resource Cost
The state endpoints price a single Terraform state and return a per-resource, per-component breakdown. All cost endpoints require authentication and return monetary fields as strings.
GET /api/v1/states/{state_id}/costs # latest snapshot + per-resource breakdown
POST /api/v1/states/{state_id}/costs/calculate # recompute now
GET /api/v1/states/{state_id}/costs/unsupported # resources that didn't contribute (gaps)
Price a State
Fetch the latest snapshot for a state:
curl -H "Authorization: Bearer $STATEGRAPH_API_KEY" \
http://localhost:8080/api/v1/states/$STATE_ID/costs
{
"snapshot_id": "…",
"calculated_at": "2026-06-09T06:15:01Z",
"currency": "USD",
"monthly_cost": "1509.640000",
"hourly_cost": "2.067000",
"resource_count": 24,
"supported_count": 24,
"priced_count": 12,
"coverage_percent": 50.0,
"instance_costs": [ … ]
}
A 404 means the state has never been priced; calculate it first.
The headline fields:
| Field | Meaning |
|---|---|
monthly_cost / hourly_cost |
Total estimated cost of the priced resources (string; absent if nothing is priced) |
currency |
Currency of the estimate (for example, USD) |
resource_count |
Resources in the state |
supported_count |
Resources whose type the pricing engine recognizes |
priced_count |
Resources that produced a non-zero price |
coverage_percent |
priced_count / resource_count; read every total next to this |
Per-Resource Breakdown
instance_costs[] holds one entry per resource, and each entry's components[] breaks the price into line items such as instance hours, storage, and requests. Here is a real aws_db_instance:
{
"address": "aws_db_instance.primary",
"type": "aws_db_instance",
"provider": "aws",
"monthly_cost": "656.270000",
"hourly_cost": "0.899000",
"supported": true,
"no_price": false,
"components": [
{
"name": "Database instance (on-demand, Multi-AZ, db.r6g.xlarge)",
"unit": "hours",
"price": "0.8990000000",
"hourly_quantity": "1",
"monthly_quantity": "730",
"hourly_cost": "0.899000",
"monthly_cost": "656.270000"
},
{
"name": "Storage (general purpose SSD, gp3)",
"unit": "GB",
"price": "0.0000000000",
"monthly_quantity": "200"
}
],
"tags": { "Team": "data", "Environment": "production", "Project": "acme" },
"cloud_resource_id": "arn:aws:rds:us-east-1:…:db:acme-primary"
}
Each resource also carries its tags, which power cost attribution, and its cloud_resource_id when one is known.
Calculate or Refresh
Trigger a fresh recompute. This returns 202 with a task and runs in the background; a new snapshot is written when it finishes. It returns 503 if the server has no pricing service configured.
curl -X POST -H "Authorization: Bearer $STATEGRAPH_API_KEY" \
http://localhost:8080/api/v1/states/$STATE_ID/costs/calculate
{ "id": "ca019a18-…", "state": "pending" }
Poll the task until it reaches a terminal state, then re-fetch the cost:
curl -H "Authorization: Bearer $STATEGRAPH_API_KEY" \
http://localhost:8080/api/v1/tasks/$TASK_ID
# { "id": "ca019a18-…", "state": "completed" }
Stop when state is completed; treat failed or aborted as an error. You normally don't need to do this by hand, since snapshots refresh on a schedule and after applies, but it is useful when cost data is missing or stale.
Coverage Gaps
List the resources that did not contribute to the totals, either unsupported types or recognized types with nothing billable (no_price):
curl -H "Authorization: Bearer $STATEGRAPH_API_KEY" \
http://localhost:8080/api/v1/states/$STATE_ID/costs/unsupported
{
"snapshot_id": "…",
"calculated_at": "2026-06-09T06:15:01Z",
"resources": [
{ "address": "aws_db_parameter_group.postgres16", "type": "aws_db_parameter_group",
"provider": "aws", "supported": true, "no_price": true },
{ "address": "aws_db_subnet_group.main", "type": "aws_db_subnet_group",
"provider": "aws", "supported": true, "no_price": true }
]
}
Surface this whenever you report a total. A high gap count usually means free-to-create resources, such as parameter groups, subnet groups, and IAM, rather than missing prices.
Next Steps
- Cost Attribution - Roll these per-state numbers up across the tenant
- Querying Cost Data - The same data as MQL tables for ad-hoc analysis