Skip to main content

FinOps

Track costs, set budgets, schedule resource actions, and organize resources into groups.

Overview

Four sub-resources live under client.finops:

  • Costs (client.finops.costs) -- Query spending data by month, day, or service, forecast future costs, detect anomalies, and identify savings opportunities.
  • Budgets (client.finops.budgets) -- Create spending limits with alerts, pause and resume tracking, and view budget summaries.
  • Schedules (client.finops.schedules) -- Automate start/stop actions on resources using cron expressions to reduce idle-time costs.
  • Resource Groups (client.finops.resource_groups) -- Tag and group resources together for aggregated cost tracking.

Costs

Monthly Breakdown

from strongly import Strongly

client = Strongly()

# Get monthly costs for the current year
monthly = client.finops.costs.monthly()
for month in monthly.get("months", []):
print(f"{month['month']}: ${month['total']:.2f}")

# Specific year and number of months
monthly = client.finops.costs.monthly(year=2025, months=6)
for month in monthly.get("months", []):
print(f"{month['month']}: ${month['total']:.2f}")

Daily Breakdown

from strongly import Strongly

client = Strongly()

# Get daily costs for a date range
daily = client.finops.costs.daily(
start_date="2026-01-01",
end_date="2026-01-31",
)
for day in daily.get("days", []):
print(f"{day['date']}: ${day['total']:.2f}")

# Filter by resource type
daily = client.finops.costs.daily(
start_date="2026-01-01",
end_date="2026-01-31",
resource_type="workspace",
)

Cost Forecast

from strongly import Strongly

client = Strongly()

forecast = client.finops.costs.forecast(months=3)
print(f"Forecasted spend (next 3 months): ${forecast.get('total_forecast'):.2f}")

for month in forecast.get("months", []):
print(f" {month['month']}: ${month['forecast']:.2f} (confidence: {month.get('confidence', 'N/A')})")

Cost by Service

from strongly import Strongly

client = Strongly()

services = client.finops.costs.services(period="month")
for svc in services.get("services", []):
print(f"{svc['name']}: ${svc['total']:.2f} ({svc.get('percentage', 0):.1f}%)")

# Filter by date range
services = client.finops.costs.services(
start_date="2026-01-01",
end_date="2026-01-31",
)

Anomaly Detection

from strongly import Strongly

client = Strongly()

anomalies = client.finops.costs.anomalies(days=30, threshold=2.0)
for a in anomalies.get("anomalies", []):
print(f"{a['date']}{a['resource']}: ${a['actual']:.2f} (expected: ${a['expected']:.2f})")

Savings Recommendations

from strongly import Strongly

client = Strongly()

savings = client.finops.costs.savings()
for rec in savings.get("recommendations", []):
print(f"{rec['category']}: {rec['description']} — save ${rec['estimated_savings']:.2f}/mo")

# Filter by category
savings = client.finops.costs.savings(category="idle-resources")

# Filter by minimum savings
savings = client.finops.costs.savings(min_savings=50.0)

Dashboard and Stats

from strongly import Strongly

client = Strongly()

# Full dashboard
dashboard = client.finops.costs.dashboard()
print(f"Current month spend: ${dashboard.get('current_month_spend'):.2f}")
print(f"Last month spend: ${dashboard.get('last_month_spend'):.2f}")
print(f"Month-over-month change: {dashboard.get('mom_change'):.1f}%")

# Summary stats for a period
stats = client.finops.costs.dashboard_stats(period="quarter")
print(f"Total spend: ${stats.get('total_spend'):.2f}")

# Top cost drivers
drivers = client.finops.costs.top_drivers(limit=5, period="month")
for d in drivers.get("drivers", []):
print(f" {d['name']}: ${d['cost']:.2f}")

Costs Method Reference

MethodDescriptionReturns
monthly(*, months=None, year=None)Get monthly cost breakdowndict
daily(*, start_date=None, end_date=None, resource_type=None)Get daily cost breakdowndict
forecast(*, months=None, model=None)Forecast future costsdict
services(*, period=None, start_date=None, end_date=None)Get costs by servicedict
anomalies(*, days=None, threshold=None)Detect cost anomaliesdict
savings(*, category=None, min_savings=None)Get savings recommendationsdict
dashboard()Get the cost dashboarddict
dashboard_stats(*, period=None)Get dashboard statisticsdict
top_drivers(*, limit=None, period=None)Get top cost driversdict

Budgets

Basic Usage

from strongly import Strongly

client = Strongly()

# List all budgets
for budget in client.finops.budgets.list():
pct = (budget.current_spend / budget.amount * 100) if budget.amount else 0
print(f"{budget.name}: ${budget.current_spend:.2f} / ${budget.amount:.2f} ({pct:.0f}%)")

Creating a Budget

from strongly import Strongly

client = Strongly()

budget = client.finops.budgets.create({
"name": "ML Team Monthly",
"description": "Monthly spending limit for the ML team",
"amount": 5000.00,
"currency": "USD",
"period": "monthly",
"scope": {
"level": "team",
"team": "ml-engineering",
},
"alerts": [
{"threshold": 0.75, "channel": "email"},
{"threshold": 0.90, "channel": "slack"},
{"threshold": 1.00, "channel": "email", "action": "notify-admin"},
],
})

print(f"Budget ID: {budget.id}")
print(f"Amount: ${budget.amount:.2f} {budget.currency}/{budget.period}")

Pausing and Resuming

from strongly import Strongly

client = Strongly()

budget_id = "budget-abc123"

# Pause tracking
paused = client.finops.budgets.pause(budget_id)
print(f"Status: {paused.status}")

# Resume tracking
resumed = client.finops.budgets.resume(budget_id)
print(f"Status: {resumed.status}")

# Reset spend counter
reset = client.finops.budgets.reset(budget_id)
print(f"Current spend: ${reset.current_spend:.2f}")

Budget Summary

from strongly import Strongly

client = Strongly()

summary = client.finops.budgets.summary()
print(f"Total budgets: {summary.get('total')}")
print(f"Over budget: {summary.get('over_budget')}")
print(f"Total allocated: ${summary.get('total_allocated'):.2f}")
print(f"Total spent: ${summary.get('total_spent'):.2f}")

Filtering and Searching

from strongly import Strongly

client = Strongly()

# Search by name
for b in client.finops.budgets.list(search="ML"):
print(b.name)

# Filter by status
for b in client.finops.budgets.list(status="active"):
print(f"{b.name}: ${b.current_spend:.2f}")

# Filter by scope level
for b in client.finops.budgets.list(scope_level="team"):
print(f"{b.name}{b.scope}")

# Only enabled budgets
for b in client.finops.budgets.list(enabled=True):
print(b.name)

Budget Model

FieldTypeDescription
idstrUnique budget identifier
namestrBudget name
descriptionstrHuman-readable description
scopedictScope definition (level, team, project, etc.)
budgetdictBudget configuration details
amountfloatBudget limit amount
currencystrCurrency code (default: USD)
periodstrBudget period (e.g., monthly, quarterly, annual)
current_spendfloatCurrent spend against this budget
statusstrCurrent status
enabledboolWhether the budget is enabled
organization_idstrOwning organization
alertslistAlert rules
created_atstrCreation timestamp
updated_atstrLast update timestamp

Budgets Method Reference

MethodDescriptionReturns
list(*, search=None, status=None, scope_level=None, enabled=None, limit=50)List budgets with optional filtersSyncPaginator[Budget]
create(body)Create a new budgetBudget
retrieve(budget_id)Get a budget by IDBudget
update(budget_id, body)Update budget fieldsBudget
delete(budget_id)Delete a budgetdict
pause(budget_id)Pause budget trackingBudget
resume(budget_id)Resume budget trackingBudget
reset(budget_id)Reset the spend counterBudget
summary()Get budget summary statisticsdict

Schedules

Schedules automate start/stop actions on resources using cron expressions. Use them to shut down idle workspaces overnight, scale down addons on weekends, or run cost-saving routines on a timer.

Basic Usage

from strongly import Strongly

client = Strongly()

# List all schedules
for sched in client.finops.schedules.list():
state = "enabled" if sched.enabled else "disabled"
print(f"{sched.name} ({state}) — next run: {sched.next_run}")

Creating a Schedule

from strongly import Strongly

client = Strongly()

sched = client.finops.schedules.create({
"name": "Stop dev workspaces overnight",
"description": "Shut down all dev workspaces at 8 PM and restart at 8 AM",
"cron": "0 20 * * 1-5",
"action": "stop",
"target": {
"resource_type": "workspace",
"tags": {"environment": "development"},
},
"scope": {
"level": "organization",
},
"enabled": True,
})

print(f"Schedule ID: {sched.id}")
print(f"Next run: {sched.next_run}")

Managing Schedule State

from strongly import Strongly

client = Strongly()

sched_id = "sched-abc123"

# Pause a schedule
paused = client.finops.schedules.pause(sched_id)
print(f"Status: {paused.status}")

# Resume it
resumed = client.finops.schedules.resume(sched_id)
print(f"Status: {resumed.status}")

# Trigger manual execution
client.finops.schedules.execute(sched_id)
print("Schedule executed manually")

Execution History

from strongly import Strongly

client = Strongly()

history = client.finops.schedules.history("sched-abc123")
for run in history.get("runs", []):
print(f"{run['executed_at']}{run['status']}{run.get('resources_affected', 0)} resources")

Filtering and Searching

from strongly import Strongly

client = Strongly()

# Search by name
for s in client.finops.schedules.list(search="overnight"):
print(s.name)

# Filter by status
for s in client.finops.schedules.list(status="active"):
print(f"{s.name} — next: {s.next_run}")

# Only enabled schedules
for s in client.finops.schedules.list(enabled=True):
print(f"{s.name}: {s.cron}")

Schedule Model

FieldTypeDescription
idstrUnique schedule identifier
namestrSchedule name
descriptionstrHuman-readable description
scopedictScope definition
scheduledictSchedule configuration details
statusstrCurrent status
enabledboolWhether the schedule is enabled
cronstrCron expression
actionstrAction to perform (e.g., start, stop, scale)
targetdictTarget resource definition
organization_idstrOwning organization
last_runstrLast execution timestamp
next_runstrNext scheduled execution
created_atstrCreation timestamp
updated_atstrLast update timestamp

Schedules Method Reference

MethodDescriptionReturns
list(*, search=None, status=None, scope_level=None, enabled=None, limit=50)List schedules with optional filtersSyncPaginator[Schedule]
create(body)Create a new scheduleSchedule
retrieve(schedule_id)Get a schedule by IDSchedule
update(schedule_id, body)Update schedule fieldsSchedule
delete(schedule_id)Delete a scheduledict
pause(schedule_id)Pause a scheduleSchedule
resume(schedule_id)Resume a scheduleSchedule
execute(schedule_id, body=None)Trigger manual executiondict
history(schedule_id)Get execution historydict

Resource Groups

Resource groups let you tag and organize resources for aggregated cost tracking. Group workspaces, addons, and apps by team, project, or environment.

Basic Usage

from strongly import Strongly

client = Strongly()

# List all resource groups
for group in client.finops.resource_groups.list():
print(f"{group.name}: {len(group.resources)} resources — ${group.total_cost:.2f}")

Creating a Resource Group

from strongly import Strongly

client = Strongly()

group = client.finops.resource_groups.create({
"name": "ML Infrastructure",
"description": "All resources used by the ML team",
"tags": {
"team": "ml-engineering",
"cost-center": "CC-1234",
},
})

print(f"Group ID: {group.id}")

Managing Resources

from strongly import Strongly

client = Strongly()

group_id = "rg-abc123"

# Add resources to the group
client.finops.resource_groups.add_resource(
group_id,
type="workspace",
resource_id="ws-abc123",
name="Training Workspace",
)

client.finops.resource_groups.add_resource(
group_id,
type="addon",
resource_id="addon-def456",
name="ML Database",
)

# View the group
group = client.finops.resource_groups.retrieve(group_id)
print(f"Total cost: ${group.total_cost:.2f}")
for res in group.resources:
print(f" {res.get('name')} ({res.get('type')})")

# Remove a resource
client.finops.resource_groups.remove_resource(group_id, "ws-abc123")

Filtering and Searching

from strongly import Strongly

client = Strongly()

# Search by name
for g in client.finops.resource_groups.list(search="ML"):
print(g.name)

# Filter by status
for g in client.finops.resource_groups.list(status="active"):
print(f"{g.name}: ${g.total_cost:.2f}")

ResourceGroup Model

FieldTypeDescription
idstrUnique group identifier
namestrGroup name
descriptionstrHuman-readable description
statusstrCurrent status
organization_idstrOwning organization
resourceslistList of grouped resources
tagsdictKey-value tags
total_costfloatAggregated cost of all resources in the group
created_atstrCreation timestamp
updated_atstrLast update timestamp

Resource Groups Method Reference

MethodDescriptionReturns
list(*, search=None, status=None, limit=50)List resource groupsSyncPaginator[ResourceGroup]
create(body)Create a resource groupResourceGroup
retrieve(group_id)Get a group by IDResourceGroup
update(group_id, body)Update group fieldsResourceGroup
delete(group_id)Delete a groupdict
add_resource(group_id, *, type, resource_id, name)Add a resource to the groupdict
remove_resource(group_id, resource_id)Remove a resource from the groupdict

Complete Example

from strongly import Strongly

def main():
client = Strongly()

# --- Review current spending ---
print("=== Cost Dashboard ===")
dashboard = client.finops.costs.dashboard()
print(f"This month: ${dashboard.get('current_month_spend'):.2f}")
print(f"Last month: ${dashboard.get('last_month_spend'):.2f}")

# Top cost drivers
drivers = client.finops.costs.top_drivers(limit=3, period="month")
print("\nTop cost drivers:")
for d in drivers.get("drivers", []):
print(f" {d['name']}: ${d['cost']:.2f}")

# --- Check for anomalies ---
print("\n=== Anomalies (last 30 days) ===")
anomalies = client.finops.costs.anomalies(days=30)
for a in anomalies.get("anomalies", []):
print(f" {a['date']}{a['resource']}: ${a['actual']:.2f} (expected ${a['expected']:.2f})")

# --- Get savings recommendations ---
print("\n=== Savings Opportunities ===")
savings = client.finops.costs.savings()
for rec in savings.get("recommendations", []):
print(f" {rec['description']} — save ${rec['estimated_savings']:.2f}/mo")

# --- Create a budget ---
print("\n=== Creating Budget ===")
budget = client.finops.budgets.create({
"name": "Q1 GPU Budget",
"description": "GPU compute budget for Q1 2026",
"amount": 10000.00,
"currency": "USD",
"period": "quarterly",
"scope": {"level": "organization"},
"alerts": [
{"threshold": 0.80, "channel": "email"},
{"threshold": 0.95, "channel": "slack"},
],
})
print(f"Budget: {budget.name} — ${budget.amount:.2f}")

# --- Create a cost-saving schedule ---
print("\n=== Creating Schedule ===")
sched = client.finops.schedules.create({
"name": "Weekend shutdown",
"description": "Stop dev workspaces Friday evening",
"cron": "0 18 * * 5",
"action": "stop",
"target": {
"resource_type": "workspace",
"tags": {"environment": "development"},
},
"scope": {"level": "organization"},
"enabled": True,
})
print(f"Schedule: {sched.name} — next run: {sched.next_run}")

# --- Group resources for tracking ---
print("\n=== Creating Resource Group ===")
group = client.finops.resource_groups.create({
"name": "Production ML",
"description": "All production ML infrastructure",
"tags": {"team": "ml", "env": "production"},
})
print(f"Group: {group.name} (ID: {group.id})")

# Add some resources
client.finops.resource_groups.add_resource(
group.id, type="workspace", resource_id="ws-prod-1", name="Inference Server",
)
client.finops.resource_groups.add_resource(
group.id, type="addon", resource_id="addon-prod-db", name="Model Store DB",
)

updated_group = client.finops.resource_groups.retrieve(group.id)
print(f"Resources in group: {len(updated_group.resources)}")
print(f"Total cost: ${updated_group.total_cost:.2f}")

# --- Forecast ---
print("\n=== 3-Month Forecast ===")
forecast = client.finops.costs.forecast(months=3)
for month in forecast.get("months", []):
print(f" {month['month']}: ${month['forecast']:.2f}")

# --- Budget summary ---
print("\n=== Budget Summary ===")
summary = client.finops.budgets.summary()
print(f"Total budgets: {summary.get('total')}")
print(f"Over budget: {summary.get('over_budget')}")
print(f"Total allocated: ${summary.get('total_allocated'):.2f}")

if __name__ == "__main__":
main()