FinOps Budgets
Read FinOps budgets: their scope, spend limit, alert and pause thresholds, email settings, current usage, and status.
Budgets are read-only through the REST API. Platform administrators and organization owners and admins create, edit, pause, resume, and delete them in the platform UI (see Budgets). The API lists and reads them; it never changes a budget.
Both endpoints require:
- An API key in the
X-API-Keyheader with thefinops:readscope. - An API key that belongs to a platform administrator, or to an owner or admin of an organization. Other keys get
403 forbidden.
Platform administrators see every budget on the platform, across all organizations. An organization owner or admin sees only their own organization's budgets; another organization's budget returns 404 not-found.
All money fields are integer US cents (150000 is $1,500.00). Every timestamp is an ISO 8601 UTC instant with an explicit Z cursor and millisecond precision, for example 2026-09-23T03:00:12.532Z. Convert it to local time for display.
Budget Object
{
"_id": "6ab33d857c6421ef14fa156c",
"name": "ML team monthly",
"description": "Cap for the ML team's workloads",
"organizationId": "org-acme",
"scope": {
"level": "resourceGroup",
"userId": null,
"resourceGroupId": "E4k5Ttqk7dtMpwbXx",
"resourceId": null,
"resourceType": null,
"tag": null
},
"budget": {
"amount": 150000,
"currency": "USD",
"type": "recurring",
"period": "monthly",
"resetDay": 1
},
"thresholds": [
{ "percent": 80, "action": "alert" },
{ "percent": 100, "action": "pause" }
],
"notifications": {
"mode": "digest",
"digestFrequency": "daily",
"digestHourOfDay": 9,
"digestDayOfWeek": 1,
"minSeverity": "warning",
"nextDigestAt": "2026-09-24T09:00:00.000Z",
"lastDigestSentAt": null
},
"usage": {
"current": 124310,
"percentUsed": 82.87,
"periodStart": "2026-09-01T00:00:00.000Z",
"periodEnd": "2026-10-01T00:00:00.000Z",
"lastUpdated": "2026-09-23T03:00:12.532Z"
},
"alertsSent": [
{ "percent": 80, "sentAt": "2026-09-21T14:00:05.118Z" }
],
"stoppedResources": [],
"enabled": true,
"status": "active",
"createdAt": "2026-09-01T16:02:41.284Z",
"updatedAt": "2026-09-23T03:00:12.532Z",
"createdBy": "okRpaKPh8B9asdKb2"
}
| Field | Description |
|---|---|
_id | Budget ID (24-character hex string). |
name, description | Name (up to 100 characters) and optional description (up to 500). |
organizationId | Organization the budget belongs to, or __platform__ for platform budgets and platform cost-bucket budgets. |
scope.level | platform, organization, user, resourceGroup, resourceType, resource, or tag. |
scope.userId | Set for user scope: the member whose resources count. |
scope.resourceGroupId | Set for resourceGroup scope. |
scope.resourceType | Set for resourceType and resource scopes: app, addon, workflow, self_hosted_model, fine_tuning, ai_gateway_request (resourceType scope only), workspace, agent, automl, avatar, job, model_serving, data_forge, workflow_tool, or platform (cost buckets, resource scope only). |
scope.resourceId | Set for resource scope: the resource ID, or cluster-idle, cluster-unallocated, cluster-unmounted for a platform cost bucket. |
scope.tag | Set for tag scope: { "key": "...", "value": "..." }. |
budget.amount | The limit, in cents. |
budget.type | recurring (resets every period) or total (never resets; counts all recorded spend in scope). |
budget.period | Recurring only: daily, weekly, or monthly. |
budget.resetDay | Weekly: 1-7 (Monday-Sunday). Monthly: 1-31 (clamped to the month's last day). Not set for daily or total budgets. |
thresholds[] | percent (1-200) and action (alert or pause). At most one pause. |
notifications.mode | immediate, digest, or off (bell notifications only). |
notifications.digestFrequency, digestHourOfDay, digestDayOfWeek | Digest schedule: hourly/daily/weekly, hour 0-23 UTC, day 0-6 (Sunday-Saturday). |
notifications.minSeverity | Lowest severity emailed: warning, error, or critical. Alerts below 100% are warnings, alerts at 100% or more are errors, and pause thresholds are critical. |
notifications.nextDigestAt, lastDigestSentAt | When the next digest is due and when the last one was sent (digest mode). |
usage.current | Spend in the current period, in cents. |
usage.percentUsed | current as a percent of amount. Can exceed 100. |
usage.periodStart, usage.periodEnd | The current period, from periodStart up to but not including periodEnd. Periods start at 00:00 UTC. null for total budgets. |
usage.lastUpdated | When usage was last evaluated. Budgets are evaluated when created, edited, or resumed, and hourly. |
alertsSent[] | Thresholds that have fired this period (percent, sentAt). Each fires once per period; the list clears at each reset and when the amount, type, period, scope, or thresholds change. |
stoppedResources[] | Workloads the pause threshold stopped: resourceType, resourceId, resourceName, stoppedAt, currentSpend (cents). Clears at each reset. |
enabled | false when an administrator paused the budget. |
status | active, paused (disabled by an administrator), or exhausted (spend is at or over the pause threshold: workloads in scope are paused and covered launches are refused). Alert-only budgets are never exhausted. |
createdAt, updatedAt | When the budget was created and last changed (including each evaluation). |
createdBy | User ID of the administrator who created the budget. |
GET /api/v1/finops/budgets
List budgets, newest first.
Scope: finops:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
scopeLevel | string | No | Only budgets of this scope: platform, organization, user, resourceGroup, resourceType, resource, tag |
status | string | No | Only budgets with this status: active, paused, exhausted |
q | string | No | Case-insensitive match on part of the name |
limit | integer | No | Page size (default 50, maximum 200) |
cursor | string | No | meta.nextCursor of the previous page; omit for the first page |
Example
curl -H "X-API-Key: $STRONGLY_API_KEY" \
"https://your-platform.example.com/api/v1/finops/budgets?status=exhausted&limit=20"
Response 200 OK
{
"data": [
{
"_id": "6ab33d857c6421ef14fa156c",
"name": "ML team monthly",
"scope": { "level": "resourceGroup", "resourceGroupId": "E4k5Ttqk7dtMpwbXx" },
"budget": { "amount": 150000, "currency": "USD", "type": "recurring", "period": "monthly", "resetDay": 1 },
"usage": { "current": 151020, "percentUsed": 100.68 },
"status": "exhausted"
}
],
"meta": {
"total": 1,
"limit": 20,
"nextCursor": null,
"requestId": "783fc8f0-67cb-49cd-829c-90f176be580f"
}
}
Each item is a full Budget object (shortened above). meta.total is the number of budgets matching the filters; page through them with cursor while meta.hasMore is true.
Errors
| Status | Code | When |
|---|---|---|
| 400 | validation-error | scopeLevel or status is not one of the listed values |
| 403 | forbidden / scope-required | The key's user is neither a platform administrator nor an owner or admin of an organization, or the key lacks finops:read |
| 502 | backend-unavailable | The budget service is not reachable. Try again shortly. |
GET /api/v1/finops/budgets/:id
Get one budget with its current usage and status.
Scope: finops:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Budget ID |
Response 200 OK
{
"data": { "...": "Budget object" },
"meta": { "requestId": "2496c9a7-98c9-4218-84b4-f43008bbcf32" }
}
data is the full Budget object.
Errors
| Status | Code | When |
|---|---|---|
| 404 | not-found | No budget has this ID (including IDs that are not 24-character hex) |
| 403 | forbidden / scope-required | The key's user is neither a platform administrator nor an owner or admin of an organization, or the key lacks finops:read |
| 502 | backend-unavailable | The budget service is not reachable. Try again shortly. |
MCP tools
The same reads are available to agents as MCP tools: list_finops_budgets (parameters scopeLevel, status, q) and get_finops_budget (parameter id).