# Azure MCA Subscription Creation via API - Issue Report ## Summary I'm unable to create Azure subscriptions programmatically using `New-AzSubscriptionAlias` (PowerShell) or the equivalent REST API, despite being able to create subscriptions successfully through the Azure Portal. ## Environment - **Tenant ID**: `dbae5170-785d-4dd5-9fce-7374b50c5f1b` - **Agreement Type**: Microsoft Customer Agreement (MCA) - **PowerShell Modules**: - Az.Accounts: 5.3.0 - Az.Subscription: 0.12.0 - Az.Billing: 2.2.0 - Az.Resources: 8.1.0 ## Billing Configuration - **Billing Account**: `b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31` - **Billing Profile**: Mark Burton (`OFMC-ENGO-BG7-PGB`) - **Invoice Section**: Mark Burton (`22OA-5CJL-PJA-PGB`) - **Complete Billing Scope**: ``` /providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB ``` ## What Works ✅ **Manual subscription creation via Azure Portal**: - Navigate to: Home → Subscriptions → Add - Enter subscription name - Click Review + Create → Create - Subscription is created successfully within seconds I have successfully created multiple subscriptions this way: `test`, `entra-test`, and `Sandbox`. ## What Doesn't Work ❌ **Programmatic subscription creation via API**: ```powershell New-AzSubscriptionAlias ` -AliasName "apitest-81182" ` -SubscriptionName "APITest-1006-112821" ` -BillingScope "/providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB" ` -Workload "DevTest" ``` **Error**: ``` [Forbidden] : You do not have sufficient permissions on the specified invoice section to create an Azure subscription. Refer(http://aka.ms/mca-section-invoice) to set the right permissions and try again ``` ## Roles and Permissions Tested I've tested with multiple user types and role combinations: ### Test 1: Microsoft Account (live.com) - User: `mark.burton@gnomica.co.uk` (Microsoft Account / External user) - Roles verified via REST API: - ✅ Invoice Section Owner (`30000000-aaaa-bbbb-cccc-100000000000`) - ✅ Azure Subscription Creator (`30000000-aaaa-bbbb-cccc-100000000006`) - **Result**: API call fails with "insufficient permissions" ### Test 2: Entra ID User - User: `gnomica-admin@markburtongnomicaco.onmicrosoft.com` (native Entra ID user) - Roles assigned: - ✅ Invoice Section Owner - ✅ Azure Subscription Creator - ✅ Global Administrator (Entra ID) - **Result**: API call fails with same "insufficient permissions" error ## API Endpoint Used According to Microsoft documentation ([link](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement)), `New-AzSubscriptionAlias` calls: ``` PUT https://management.azure.com/providers/Microsoft.Subscription/aliases/{aliasName}?api-version=2021-10-01 ``` With request body: ```json { "properties": { "billingScope": "/providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB", "displayName": "APITest-1006-112821", "workload": "DevTest" } } ``` ## Observations 1. **Portal works immediately**: No role propagation delays, no special permissions needed beyond what I already have 2. **API fails consistently**: Both PowerShell and direct REST API calls fail with identical error 3. **Role verification issue**: When trying to verify roles programmatically via: ``` GET https://management.azure.com/providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB/billingRoleAssignments?api-version=2019-10-01-preview ``` Response: `401 Unauthorized` (even though Azure Portal shows I have the roles) 4. **Unique alias requirement**: Documentation mentions each subscription alias must be unique, but my aliases are always random and unique ## Questions 1. **Is there a different/preview API version** that the Azure Portal uses for MCA subscription creation? 2. **Are there additional hidden permissions** required beyond "Invoice Section Owner" and "Azure Subscription Creator"? 3. **Is there a known limitation** with using Microsoft Accounts (live.com) vs native Entra ID users for API-based subscription creation? 4. **Has anyone successfully used `New-AzSubscriptionAlias`** with an MCA billing account? If so, what was your exact role and user type? ## My Hypothesis The Azure Portal may be using an internal/preview API that is not publicly documented or available via the standard REST API or PowerShell cmdlets. This would explain why: - Portal creation works instantly - API calls fail despite having correct roles - Role verification APIs return 401 (suggesting different authentication paths) ## Complete Test Scripts I've created comprehensive PowerShell test scripts to reproduce and document this issue. Below are the full scripts: ### Test Script 1: Main Diagnostic Test ```powershell # test-subscription-creation.ps1 $ErrorActionPreference = "Stop" Write-Host "═══════════════════════════════════════════════════════════" Write-Host "Azure MCA Subscription Creation Test" Write-Host "═══════════════════════════════════════════════════════════`n" # PART 1: Environment Diagnostics Write-Host "PART 1: Environment Diagnostics" Write-Host "─────────────────────────────────────" $context = Get-AzContext Write-Host "✓ Logged in as: $($context.Account.Id)" Write-Host " Tenant ID: $($context.Tenant.Id)" # Check PowerShell modules Write-Host "`nPowerShell Modules:" $modules = @('Az.Accounts', 'Az.Subscription', 'Az.Billing', 'Az.Resources') foreach ($mod in $modules) { $installed = Get-Module -ListAvailable -Name $mod | Select-Object -First 1 if ($installed) { Write-Host " ✓ $mod : $($installed.Version)" } } # Get billing details Write-Host "`nBilling Configuration:" $billingAccount = Get-AzBillingAccount | Select-Object -First 1 Write-Host " Account ID: $($billingAccount.Name)" Write-Host " Display Name: $($billingAccount.DisplayName)" Write-Host " Agreement Type: $($billingAccount.AgreementType)" $billingProfile = Get-AzBillingProfile -BillingAccountName $billingAccount.Name | Select-Object -First 1 Write-Host " Billing Profile: $($billingProfile.DisplayName)" $invoiceSection = Get-AzInvoiceSection -BillingAccountName $billingAccount.Name -BillingProfileName $billingProfile.Name | Select-Object -First 1 Write-Host " Invoice Section: $($invoiceSection.DisplayName)" $billingScope = "/providers/Microsoft.Billing/billingAccounts/$($billingAccount.Name)/billingProfiles/$($billingProfile.Name)/invoiceSections/$($invoiceSection.Name)" Write-Host " Billing Scope: $billingScope" # PART 2: Test Subscription Creation Write-Host "`n`nPART 2: Test Subscription Creation" Write-Host "─────────────────────────────────────────────────────" $subscriptionName = "APITest-$(Get-Date -Format 'MMdd-HHmmss')" $aliasName = "apitest-$(Get-Random -Maximum 99999)" Write-Host "Attempting to create subscription:" Write-Host " Name: $subscriptionName" Write-Host " Alias: $aliasName" Write-Host " Billing Scope: $billingScope" try { $result = New-AzSubscriptionAlias ` -AliasName $aliasName ` -SubscriptionName $subscriptionName ` -BillingScope $billingScope ` -Workload "DevTest" Write-Host "`n✓✓✓ SUCCESS! Subscription created via API ✓✓✓" Write-Host " Subscription ID: $($result.SubscriptionId)" } catch { Write-Host "`n✗✗✗ FAILED to create subscription via API ✗✗✗" Write-Host "Error: $($_.Exception.Message)" if ($_.ErrorDetails.Message) { try { $errorObj = $_.ErrorDetails.Message | ConvertFrom-Json Write-Host "`nDetailed Error:" Write-Host " Code: $($errorObj.error.code)" Write-Host " Message: $($errorObj.error.message)" } catch { Write-Host "`nRaw Error Details:" Write-Host $_.ErrorDetails.Message } } } Write-Host "`n═══════════════════════════════════════════════════════════" Write-Host "Test Complete" Write-Host "═══════════════════════════════════════════════════════════`n" ``` ### How to Run the Test ```powershell # Login to Azure Connect-AzAccount # Save the script above as test-subscription-creation.ps1 # Run the test pwsh -File ./test-subscription-creation.ps1 ``` ## Complete Test Output Here's the actual output from running the test script: ``` ═══════════════════════════════════════════════════════════ Azure MCA Subscription Creation Test ═══════════════════════════════════════════════════════════ PART 1: Environment Diagnostics ───────────────────────────────── ✓ Logged in as: mark.burton@gnomica.co.uk Tenant ID: dbae5170-785d-4dd5-9fce-7374b50c5f1b PowerShell Modules: ✓ Az.Accounts : 5.3.0 ✓ Az.Subscription : 0.12.0 ✓ Az.Billing : 2.2.0 ✓ Az.Resources : 8.1.0 Billing Configuration: Account ID: b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31 Display Name: Mark Burton Agreement Type: MicrosoftCustomerAgreement Billing Profile: Mark Burton Invoice Section: Mark Burton Billing Scope: /providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB PART 2: Test Subscription Creation ───────────────────────────────────────────────────── Attempting to create subscription: Name: APITest-1006-112821 Alias: apitest-81182 Billing Scope: /providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB ✗✗✗ FAILED to create subscription via API ✗✗✗ Error: [Forbidden] : You do not have sufficient permissions on the specified invoice section to create an Azure subscription. Refer(http://aka.ms/mca-section-invoice) to set the right permissions and try again ✗ CONCLUSION: API subscription creation FAILED for mark.burton@gnomica.co.uk ``` ### Test with Entra ID User Same test run with native Entra ID user (`gnomica-admin@markburtongnomicaco.onmicrosoft.com`) who has: - Invoice Section Owner role - Azure Subscription Creator role - Global Administrator role Result: **Identical failure** with same "insufficient permissions" error. ## Billing Role Assignment Details For transparency, here's how roles were verified and assigned: ### Verifying Existing Roles (REST API) ```powershell $token = (Get-AzAccessToken).Token $headers = @{ "Authorization" = "Bearer $token" "Content-Type" = "application/json" } $uri = "https://management.azure.com/providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB/billingRoleAssignments?api-version=2019-10-01-preview" $roleAssignments = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers ``` **Result**: `401 Unauthorized` (even though Portal shows roles exist) ### Role Definition IDs Used According to [Microsoft documentation](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/understand-mca-roles): - **Invoice Section Owner**: `30000000-aaaa-bbbb-cccc-100000000000` - **Azure Subscription Creator**: `30000000-aaaa-bbbb-cccc-100000000006` ### Attempting Role Assignment (REST API) ```powershell $userId = "3971978b-5ed4-4586-8701-93a58488663e" # gnomica-admin $tenantId = "dbae5170-785d-4dd5-9fce-7374b50c5f1b" $roleDefId = "30000000-aaaa-bbbb-cccc-100000000006" # Azure Subscription Creator $body = @{ properties = @{ principalId = $userId principalTenantId = $tenantId roleDefinitionId = "/providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB/billingRoleDefinitions/$roleDefId" } } | ConvertTo-Json $uri = "https://management.azure.com/providers/Microsoft.Billing/billingAccounts/b5003c3e-ab90-55a9-57bb-a6c4db47eea8:ae7044f9-36e3-4e73-a5d7-97f0261a14a1_2019-05-31/billingProfiles/OFMC-ENGO-BG7-PGB/invoiceSections/22OA-5CJL-PJA-PGB/billingRoleAssignments/${roleDefId}_${userId}?api-version=2019-10-01-preview" Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -Body $body ``` **Result**: `401 Unauthorized` ## Portal vs API Comparison | Action | Azure Portal | REST API / PowerShell | |--------|--------------|----------------------| | Create subscription | ✅ Works instantly | ❌ Forbidden error | | View billing roles | ✅ Shows roles correctly | ❌ 401 Unauthorized | | Assign billing roles | ✅ Works via IAM blade | ❌ 401 Unauthorized | | Account type tested | MSA + Entra ID | MSA + Entra ID | | Roles assigned | Invoice Section Owner + Creator | Invoice Section Owner + Creator | ## API Versions Tested - **Subscription creation**: `api-version=2021-10-01` - **Billing role assignments**: `api-version=2019-10-01-preview` Also tried: - `api-version=2020-09-01` - `api-version=2019-10-01-preview` All failed with same errors. ## References - [Microsoft Docs: Create MCA subscriptions programmatically](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement) - [Billing role definitions](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/understand-mca-roles) - [Subscription Alias API Reference](https://learn.microsoft.com/en-us/rest/api/subscription/2021-10-01/alias/create) ## Request for Help Has anyone successfully created MCA subscriptions programmatically using `New-AzSubscriptionAlias` or the REST API? If so, please share: 1. Your exact user type (MSA vs Entra ID) 2. Roles assigned 3. API version used 4. Any special tenant or billing configuration Any insights would be greatly appreciated!