A Microsoft offering that enables tracking of cloud usage and expenditures for Azure and other cloud providers.
Use the Cost Management Query API at the resource-group scope, filter on the ResourceType dimension, and group by ResourceId to return the cost of each matching resource.
PowerShell with Invoke-AzRestMethod
The Query API version 2025-03-01 supports resource-group scopes, custom periods, filters, aggregation, and grouping.^1^
Connect-AzAccount
$subscriptionId = (Get-AzContext).Subscription.Id
$resourceGroup = "my-resource-group"
$resourceType = "Microsoft.Compute/virtualMachines"
$from = (Get-Date).AddDays(-30).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
$to = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
$body = @{
type = "ActualCost"
timeframe = "Custom"
timePeriod = @{
from = $from
to = $to
}
dataset = @{
granularity = "None"
aggregation = @{
totalCost = @{
name = "PreTaxCost"
function = "Sum"
}
}
filter = @{
dimensions = @{
name = "ResourceType"
operator = "In"
values = @($resourceType)
}
}
grouping = @(
@{ type = "Dimension"; name = "ResourceId" }
)
}
} | ConvertTo-Json -Depth 10
$uri = "https://management.azure.com/subscriptions/[Subscription ID]" +
"/resourceGroups/[Resource Group] Group]/providers/Microsoft.CostManagement/query" +
"?api-version=2025-03-01"
$response = Invoke-AzRestMethod -Method POST -Uri $uri -Payload $body
$result = $response.Content | ConvertFrom-Json
$result.properties
Azure documents the same ActualCost, PreTaxCost, custom 30-day period, and dimension-filter pattern in an executable cost-query example.^2^
The returned properties object contains:
-
columns: column names and data types. -
rows: cost rows grouped byResourceId. -
nextLink: present if another response page must be retrieved.
To convert the column/row representation into PowerShell objects:
$names = @($result.properties.columns.name)
$costs = foreach ($row in $result.properties.rows) {
$item = [ordered]@{}
for ($i = 0; $i -lt $names.Count; $i++) {
$item[$names[$i]] = $row[$i]
}
[pscustomobject]$item
}
$costs | Format-Table -AutoSize
Filtering both dimensions explicitly
Using the resource-group URL already restricts the query to that resource group. If querying at subscription scope instead, combine ResourceGroup and ResourceType using and:
filter = @{
and = @(
@{ dimensions = @{
name = "ResourceGroup"; operator = "In"; values = @($resourceGroup)
}}
@{ dimensions = @{
name = "ResourceType"; operator = "In"; values = @($resourceType)
}}
)
}
In that case, change the URI scope to:
$uri = "https://management.azure.com/subscriptions/[Subscription ID]/providers/" +
"Microsoft.CostManagement/query?api-version=2025-03-01"
Resource group, Resource type, and ResourceId are supported Cost Management grouping/filtering properties.^3^
Azure PowerShell cmdlet alternative
Invoke-AzCostManagementQuery from Az.CostManagement exposes the equivalent scope, timeframe, aggregation, filter, and grouping parameters.^4^ For a compound filter, however, constructing the REST body directly is generally clearer than composing several in-memory query-filter objects.
Important cost interpretation details
- Grouping by
ResourceIdgives individual-resource rows when the charge includes an Azure Resource Manager resource ID. - Not every charge has a resource group, resource type, or resource ID. Purchases, support, Marketplace items, and some classic charges can therefore be absent from this filtered result or appear under non-resource categories.^3^
- A VM query for
Microsoft.Compute/virtualMachinesdoes not automatically include separately charged disks, public IP addresses, or other related resources with different resource types. Cost Management does not automatically understand every dependency relationship. - The caller needs at least Cost Management Reader or Contributor at the queried resource-group or subscription scope. EA accounts must also have the applicable view-charges setting enabled.^5^
For large, unaggregated datasets, use the asynchronous Cost Details Report API instead; the Query API is the appropriate choice for this filtered and aggregated per-resource report.^6^
References
- Query - Usage
- Builds a date range for the last 30 days and constructs a JSON query to request daily pre-tax cost data for a specific Azure resource ID from Azure Cost Managem...
- Group and filter options in Cost Analysis and Budgets
- Creates a filter with specific dimensions and invokes the AzCostManagementQuery cmdlet to query usage data for a given subscription scope with monthly granulari...
- Assign access to Cost Management data
- Automation scenarios for billing and cost management