API reference: Cost / FinOps
Cloud Control FinOps API: read the FOCUS-normalized cost payload (spend by cloud/service/tag, daily, anomalies, budgets), trigger ingestion, and create/update/delete budgets.
Read cost and manage budgets. Cost and budget reads are open to members; ingestion needs manage_cloud_accounts; budget writes need mutate_infra. Cross-org budget ids return 404.
GET
/api/finops/costSession or BearerThe FOCUS-normalized cost payload for your org. A never-connected org (or one with no cost yet) returns { empty: true }.
Example response
json
{ "spendByCloud": [ { "provider": "AWS", "amount": 70522.81 } ],
"spendByService": [ … ], "daily": [ … ],
"byTag": [ { "tag": "team:platform", "amount": … }, { "tag": "untagged", "amount": … } ],
"anomalies": [ { "provider": "AWS", "service": "Amazon EC2", "day": "…", "expected": …, "actual": … } ],
"budgets": [ { "id": 1, "name": "Prod monthly", "state": "warn" } ] }Errors
| Status | When |
|---|---|
401 | Not signed in / invalid token. |
POST
/api/finops/ingestmanage_cloud_accountsIngest billing for the org (also fired automatically by the connect-kick). Normalizes to FOCUS and detects anomalies.
Example response
json
{ "ok": true, "…": "ingest summary (records upserted, anomalies)" }Errors
| Status | When |
|---|---|
401 | Not signed in. |
403 | Caller lacks manage_cloud_accounts (audited cloud.rbac_denied). |
GET
/api/finops/budgetsSession or BearerList budgets for your org.
Example response
json
{ "budgets": [ { "id": 1, "name": "Prod monthly", "amountMonthly": 50000, "scopeKind": "all", "threshold": 0.8 } ] }Errors
| Status | When |
|---|---|
401 | Not signed in. |
POST
/api/finops/budgetsmutate_infraCreate a budget. Returns 201 with the created budget.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
name | body | yes | Budget name. |
amountMonthly | body | yes | Monthly amount. |
scopeKind | body | yes | Scope kind (for example all / provider / service / tag). |
scopeValue | body | no | Scope value when the scope is narrower than all. |
threshold | body | no | Warn fraction (for example 0.8). |
Example request
json
{ "name": "Prod monthly", "amountMonthly": 50000, "scopeKind": "all", "threshold": 0.8 }Example response
json
{ "ok": true, "budget": { "id": 1, "…": "…" } }Errors
| Status | When |
|---|---|
400 | Validation failed. |
403 | Viewer / lacks mutate_infra (audited). |
PATCH
/api/finops/budgets/{id}mutate_infraUpdate a budget in your org.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | yes | Budget id in your org. |
Example response
json
{ "ok": true, "budget": { "…": "…" } }Errors
| Status | When |
|---|---|
400 | Validation failed. |
403 | Lacks mutate_infra. |
404 | No such budget in your org. |
DELETE
/api/finops/budgets/{id}mutate_infraDelete a budget in your org.
Parameters
| Name | In | Required | Description |
|---|---|---|---|
id | path | yes | Budget id in your org. |
Example response
json
{ "ok": true }Errors
| Status | When |
|---|---|
403 | Lacks mutate_infra. |
404 | No such budget in your org. |