-
Notifications
You must be signed in to change notification settings - Fork 0
Get AzureResourcePaging
Get-AzureResourcePaging.ps1 handles OData pagination automatically for Microsoft Graph and Azure REST API endpoints. When Graph API responses span multiple pages (via @odata.nextLink), this function follows each link and aggregates all results into a single array, eliminating the need to write pagination loops in every script.
-
Automatic Page Following - Iterates
@odata.nextLinkuntil all pages are collected - Single Result Array - Returns all resources combined, regardless of page count
- Universal Compatibility - Works with any Microsoft Graph or Azure REST API endpoint that uses OData paging
- Minimal Dependencies - Requires only an authenticated headers hashtable
- PowerShell 5.1 or later
- An authenticated headers hashtable from Get-GraphHeaders
- Network access to the Microsoft Graph or Azure REST API endpoint
Type: String
Required: Yes
Description: The initial Microsoft Graph or Azure REST API endpoint URL to query. All subsequent @odata.nextLink pages are followed automatically.
Type: Hashtable
Required: Yes
Description: The authorization header hashtable returned by Get-GraphHeaders. Must contain a valid Bearer token.
$token = Get-GraphToken -TenantId "<tenant-id>" -ClientId "<client-id>" -ClientSecret "<secret>"
$headers = Get-GraphHeaders -accessToken $token
$allUsers = Get-AzureResourcePaging `
-URL "https://graph.microsoft.com/v1.0/users" `
-AuthHeader $headers
Write-Host "Total users: $($allUsers.Count)"$token = Get-GraphToken -TenantId "<tenant-id>" -ClientId "<client-id>" -ClientSecret "<secret>"
$headers = Get-GraphHeaders -accessToken $token
$allApps = Get-AzureResourcePaging `
-URL "https://graph.microsoft.com/v1.0/applications" `
-AuthHeader $headers
$allApps | Select-Object displayName, appId | Format-Table$token = Get-GraphToken -TenantId "<tenant-id>" -ClientId "<client-id>" -ClientSecret "<secret>"
$headers = Get-GraphHeaders -accessToken $token
# Use OData filter with paging
$url = "https://graph.microsoft.com/v1.0/users?`$filter=accountEnabled eq true&`$select=id,displayName,userPrincipalName"
$activeUsers = Get-AzureResourcePaging -URL $url -AuthHeader $headers
Write-Host "Active users: $($activeUsers.Count)"$token = Get-GraphToken -TenantId "<tenant-id>" -Scope @("https://management.azure.com/.default")
$headers = Get-GraphHeaders -accessToken $token
$subscriptionId = "<subscription-id>"
$url = "https://management.azure.com/subscriptions/$subscriptionId/resources?api-version=2021-04-01"
$allResources = Get-AzureResourcePaging -URL $url -AuthHeader $headersReturns an array ([array]) of all resource objects collected across all pages. The structure matches the individual items in the value property of each API response page.
Example output structure for /users endpoint:
@(
@{ id = "..."; displayName = "John Smith"; userPrincipalName = "john.smith@contoso.com" }
@{ id = "..."; displayName = "Jane Doe"; userPrincipalName = "jane.doe@contoso.com" }
# ... all remaining users from all pages
)- Makes initial GET request to the provided URL
- Extracts the
valuearray from the response - Checks for
@odata.nextLinkin the response - If present, repeats the GET request with the next link URL
- Continues until
@odata.nextLinkis null (no more pages) - Returns the aggregated array of all collected resources
Cause: Token expired mid-pagination on large datasets.
Solution: For very large tenants, re-acquire the token before calling this function. Tokens are valid for 1 hour.
Causes:
- The API endpoint returned no results
- Filter conditions excluded all items
- App lacks permissions to read the resource
Solution:
- Test the URL directly in Graph Explorer to confirm results
- Check permissions on the app registration
- Verify the filter syntax is correct
Cause: Too many API requests in a short time period.
Solution: Add retry logic around the call:
$maxRetries = 3
for ($i = 0; $i -lt $maxRetries; $i++) {
try {
$results = Get-AzureResourcePaging -URL $url -AuthHeader $headers
break
}
catch {
if ($_.Exception.Response.StatusCode.value__ -eq 429) {
Start-Sleep -Seconds 60
} else { throw }
}
}- Get-GraphToken - Acquire the access token needed for headers
- Get-GraphHeaders - Build the AuthHeader parameter
- Get-EnterpriseAppUsage - Uses this function for app enumeration
- v1.0 (2025-06-25) - Initial public release
- Overview
- Start-LyncCsvExporter
- Get-ComprehensiveLyncReport
- Get-LyncHealthReport
- Get-LyncInfrastructureReport
- Get-LyncServiceStatus
- Get-LyncUserRegistrationReport
- Export-ADLyncTeamsMigrationData
- New-Office365Accounts
- Sync-ContactsFromCsv
- Set-EmailToSharedAccount
- Set-SMTPForward
- Invoke-UserSignOutAndBlock
- Security Assessment Scripts (coming soon)
- Azure Automation (documentation pending)
- Get-GraphToken
- Get-GraphHeaders
- Get-AzureResourcePaging
- Get-EnterpriseAppUsage
- Get-ExchangeErrorsGraph
- Get-PBIWorkspaceUsageReport
- Intune Management (documentation pending)