Updating Your Scripts: PowerShell and Python for the New Azure PAYG APIs
- Shannon

- Nov 1, 2025
- 3 min read
In my last post, I talked about what’s changing with Azure’s Pay-As-You-Go (PAYG) APIs and why the old Usage Details endpoint is being retired. Now it’s time to roll up our sleeves! If your FinOps automations rely on Microsoft.Commerce/UsageAggregates, you’ll need to migrate those scripts to use the Exports API or Cost Details API.
This post covers the exact code changes you need to make in PowerShell and Python (typically what I see most often with my customers and what I tend to gravitate toward in my world - if you'd like to see it in Bicep or Terraform, let me know!), shows what changes line by line, and provides enterprise-ready scripts you can drop straight into your code repositories.
Quick Recap
The legacy API was great when you only had a few resources, but it does not scale for modern Azure. The API unfortunately throttles easily, it uses inconsistent field names, and it returns data synchronously.
The new approach focuses on scheduled exports that drop CSV files into Azure Storage. Instead of “pulling” data every day, you now “subscribe” to cost data delivered on a schedule.
Here’s how the APIs compare:
Capability | Legacy Usage Details API | New Cost Details / Exports API |
Endpoint | /providers/Microsoft.Commerce/UsageAggregates | /providers/Microsoft.CostManagement/exports or /costdetails |
Data Format | JSON | CSV (Exports) or JSON (Cost Details) |
Delivery Method | API call on demand | Scheduled export or asynchronous job |
Scale | Throttled for large tenants | Handles large datasets efficiently |
PAYG Support | Yes | Exports only (Cost Details coming soon) |
Schema | Varied by offer type | Consistent across offers |
What Actually Changes in Scripts
When migrating, you’ll mainly touch three parts of your code:
The endpoint URL
The HTTP method
Where and how data is retrieved
PowerShell: Before and After
Before (Legacy API)
# Legacy Usage Details API (Deprecated)
$uri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Commerce/UsageAggregates?api-version=2015-06-01-preview"
$response = Invoke-RestMethod -Uri $uri -Headers @{ Authorization = "Bearer $token" }
$response.value | Select-Object usageStartTime, usageEndTime, resourceUri, quantity, meterCategory, costAfter (Modern API)
# Modern Exports API (Supported)
$uri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.CostManagement/exports/$exportName?api-version=2023-03-01"What changed:
The endpoint switched from Microsoft.Commerce to Microsoft.CostManagement
The verb changed from GET to PUT to create or update an export
You no longer parse $response.value; instead, your job reads CSVs from Blob Storage
Python: Before and After
Before (Legacy API)
url = f"https://management.azure.com/subscriptions/{subscription_id}/providers/Microsoft.Commerce/UsageAggregates?api-version=2015-06-01-preview"
response = requests.get(url, headers=headers)
data = response.json()
After (Modern API)
url = f"https://management.azure.com/subscriptions/{subscription_id}/providers/Microsoft.CostManagement/exports/{export_name}?api-version=2023-03-01"
response = requests.put(url, headers=headers, json=payload)
What changed:
The API path changed to Microsoft.CostManagement/exports
The request changed from GET to PUT
The response now confirms export creation instead of returning usage data directly
Enterprise-Ready Scripts
Both examples below are built for production use. They are parameterized, include basic logging, and can be used in pipelines like GitHub Actions or Azure DevOps.
PowerShell (Grab it on GitHub)
How to use it:
.\Create-Or-Update-AzCostExport.ps1 `
-SubscriptionId "00000000-0000-0000-0000-000000000000" `
-ResourceGroupName "finops-rg" `
-StorageAccountName "finopsstorage01" `
-ContainerName "exports" `
-TriggerNowThis script ensures:
The export job is created or updated safely
Data lands in Blob Storage daily
Optional immediate execution for validation
Python (Grab it on GitHub)
Script: create_or_update_cost_export.py
How to use it:
python scripts/create_or_update_cost_export.pyThis script works perfectly in CI/CD pipelines with azure-identity (early foreshadowing). The script does not require secrets when running inside Azure-hosted agents that use Managed Identity.
Pro Tip: The Subscription Model
Stop pulling data directly. Let Azure deliver it. Scheduled exports are far more reliable than constant API calls. They automatically handle retries and time windows, and they integrate easily with Azure Data Factory or Synapse (another early foreshadowing).
Next Up
In Blog 3, we will:
Put this onto a CICD pipeline with GitHub Actions (if you poke around my repository now, you'll see references to that coming, but it hasn't arrived...yet)
Ingest exported CSVs into Azure Data Factory
Build transformations for FinOps dashboards
Create a Power BI parameterized query that automatically pulls the latest data
If Blog 1 explained why to move and Blog 2 showed how, Blog 3 is where you’ll see the results.




Comments