This sample shows you how to create cost management groups in Turbo360 using the API. Use these scripts to bulk-configure groups during your initial setup, taking advantage of the bulk tag setting feature to scope each group to a specific set of tags across your chosen subscriptions.
After the initial setup, use the Turbo360 portal to manage and maintain your groups on an ongoing basis.
Scope
This script supports first-time group creation only. It does not update or delete existing groups.
A round-trip sample (export, modify, re-import) will be introduced in a future release.
Workflow
You have a Turbo360 account and are the account owner, so you can generate an API key.
Your Turbo360 account is configured and cost data is being imported.
Run the scripts below to create your groups for the first time.
Use Turbo360 to maintain your groups on an ongoing basis.
Script to create groups
The following section describes the parameters and provides the script for first-time group setup.
Parameters
Parameter | What is this value | Where do I get this value |
|---|---|---|
ParentId | The GUID of the parent node in the Turbo360 tree view under which the new group will be created. | Click the desired parent node in the tree view. The GUID appears in the browser URL. |
GroupName | The display name for the new tree view node. | |
ClientId | The client ID of the service principal you want this tree view node to use when accessing subscriptions. | Use the client ID configured in the Service Principals section of Cost Analyzer. |
SubscriptionIds | An array of Azure subscription IDs this group should cover. | Retrieve these from Azure, or from the cost imports section of Turbo360 Cost Analyzer where the import status for each subscription is displayed. |
FilterTagKey | The Azure tag name to use for filtering costs — for example, | This comes from your Azure tagging setup. |
FilterTagValues | An array of values for the chosen filter tag — for example:
| This comes from your Azure tagging setup. |
ApiKey | Your Turbo360 API key. | Generate this from the Turbo360 portal under your account settings. |
ApiHostName | The Turbo360 host name. For SaaS, use | Copy this from the browser URL when you are signed in to Turbo360. |
Script
The following example creates one cost management group. Add more calls to CreateGroups.ps1 to create additional groups in the same run.
$ApiHostName = "portal.turbo360.com"
$apiKey = "[Your Key Here]"
.\CreateGroups.ps1 `
-GroupName "Dev Team Group 2" `
-ParentId "[The parent group id]" `
-ClientId "{Azure Client ID Guid}" `
-SubscriptionIds @("{Azure Subscription Guid 1}", "{Azure Subscription Guid 2}") `
-FilterTagKey "{Tag Name}" `
-FilterValues @("{Tag Value 1}", "{Tag Value 2}") `
-ApiKey $apiKey `
-ApiHostName $ApiHostName `
-Description "Development team subscriptions"
Base script
This is the reusable base script for creating cost management groups for the first time.
<#
.SYNOPSIS
Create Cost Analyzer Groups in Turbo360
.DESCRIPTION
Creates a new Cost Analyzer group with the specified configuration. This script is designed for
one-time group creation and does not save or manage group configurations on disk.
.PARAMETER GroupName
The name of the group to create
.PARAMETER ParentId
The parent group ID under which to create the group
.PARAMETER ClientId
The service principal client ID to use for all subscriptions
.PARAMETER SubscriptionIds
Array of subscription IDs to include in the group
.PARAMETER FilterTagKey
The tag key to filter on (optional)
.PARAMETER FilterValues
Array of tag values to filter on (optional)
.PARAMETER Description
Description for the group (default: "Group created via PowerShell script")
.PARAMETER ApiKey
The API key for authenticating with Turbo360
.PARAMETER ApiHostName
The API host name (default: portal.turbo360.com). Use custom host for private hosting customers.
.PARAMETER LogRequests
Whether to log create requests to files (default: $false)
.EXAMPLE
.\CreateGroups.ps1 -GroupName "Production Group" -ParentId "414d81d1-e4cc-443c-94a4-21069cd78a6c" -ClientId "0f4b620d-4c52-4dfa-8d17-f831badae1ca" -SubscriptionIds @("sub1","sub2") -ApiKey "your-api-key"
.EXAMPLE
.\CreateGroups.ps1 -GroupName "Dev Group" -ParentId "414d81d1-e4cc-443c-94a4-21069cd78a6c" -ClientId "0f4b620d-4c52-4dfa-8d17-f831badae1ca" -SubscriptionIds @("sub1") -FilterTagKey "environment" -FilterValues @("dev") -ApiKey "your-api-key"
.EXAMPLE
.\CreateGroups.ps1 -GroupName "Private Group" -ParentId "414d81d1-e4cc-443c-94a4-21069cd78a6c" -ClientId "0f4b620d-4c52-4dfa-8d17-f831badae1ca" -SubscriptionIds @("sub1") -ApiKey "your-api-key" -ApiHostName "custom.domain.com"
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$GroupName,
[Parameter(Mandatory=$true)]
[string]$ParentId,
[Parameter(Mandatory=$true)]
[string]$ClientId,
[Parameter(Mandatory=$true)]
[string[]]$SubscriptionIds,
[Parameter(Mandatory=$true)]
[string]$ApiKey,
[Parameter(Mandatory=$false)]
[string]$ApiHostName = "portal.turbo360.com",
[Parameter(Mandatory=$false)]
[string]$FilterTagKey,
[Parameter(Mandatory=$false)]
[string[]]$FilterValues = @(),
[Parameter(Mandatory=$false)]
[string]$Description = "Group created via PowerShell script",
[Parameter(Mandatory=$false)]
[bool]$LogRequests = $false
)
# Configuration
$BaseUrl = "https://$ApiHostName/CostAnalyzer/Group"
Write-Host "Creating Cost Analyzer Group: $GroupName" -ForegroundColor Cyan
Write-Host ""
# Function to build service principals from configuration
function Get-ServicePrincipals {
Write-Host "Building service principals from configuration..." -ForegroundColor Cyan
# Map subscription IDs to the format needed for bulkScopeSelection
$MappedSPs = $SubscriptionIds | ForEach-Object {
@{
subscriptionId = $_
clientId = $ClientId
}
}
Write-Host "✓ Built $($MappedSPs.Count) service principal(s) with client ID: $ClientId" -ForegroundColor Green
return $MappedSPs
}
# Template for new group
$GroupTemplate = @{
parentId = $ParentId
name = $GroupName
description = $Description
bulkScopeSelection = @{
servicePrincipals = @()
filters = @()
}
selectedServicePrincipals = @()
}
# Add service principals to the template
$ServicePrincipals = Get-ServicePrincipals
if ($ServicePrincipals.Count -gt 0) {
$GroupTemplate.bulkScopeSelection.servicePrincipals = $ServicePrincipals
Write-Host "✓ Added $($ServicePrincipals.Count) service principal(s) to group template" -ForegroundColor Green
}
# Add filters to the template
if ($FilterTagKey -and $FilterValues.Count -gt 0) {
$Filter = @{
filterType = 0
filterValues = $FilterValues
tagKey = $FilterTagKey
}
$GroupTemplate.bulkScopeSelection.filters = @($Filter)
Write-Host "✓ Added filter with tag '$FilterTagKey' and $($FilterValues.Count) value(s)" -ForegroundColor Green
}
# Create API endpoint
$CreateUrl = "$BaseUrl/Create"
# Convert template to JSON
$Body = $GroupTemplate | ConvertTo-Json -Depth 10
# Optional: Log the request to a file
if ($LogRequests) {
$LogFolder = Join-Path $PSScriptRoot "logs"
if (-not (Test-Path $LogFolder)) {
New-Item -ItemType Directory -Path $LogFolder | Out-Null
}
$Timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$LogFileName = "create_request_$Timestamp.json"
$LogFilePath = Join-Path $LogFolder $LogFileName
$Body | Set-Content $LogFilePath
Write-Host "✓ Request logged to: $LogFilePath" -ForegroundColor Cyan
}
Write-Host ""
Write-Host "Sending create request to API..." -ForegroundColor Cyan
# Make POST request
try {
$Headers = @{
"accept" = "*/*"
"APIKey" = $ApiKey
"Content-Type" = "application/json"
}
$Response = Invoke-RestMethod -Uri $CreateUrl -Method Post -Headers $Headers -Body $Body
Write-Host "✓ Group created successfully!" -ForegroundColor Green
if ($Response.id) {
Write-Host "Group ID: $($Response.id)" -ForegroundColor Cyan
}
Write-Host ""
Write-Host "Operation completed successfully." -ForegroundColor Green
}
catch {
Write-Host "✗ Error creating group: $($_.Exception.Message)" -ForegroundColor Red
if ($_.ErrorDetails.Message) {
Write-Host "Details: $($_.ErrorDetails.Message)" -ForegroundColor Red
}
exit 1
}