There are many ways to export information from Intune. For example, you can use Log Analytics, the Data Warehouse or the Graph API. But if you want to export several thousand devices or apps via Graph, it can happen that Graph has a paging. Paging means that you only get a certain number of entries with one call and then you have to make another call for the next range. This means for you that you have to write a script that loops through the pages.
Another problem if you want to export e.g. all Discovered apps you have to loop through all devices because this attribute is not shared in List calls. But if you have several 10k or 100k devices this takes a long time.
But there is a Graph Report API that is designed to export large amounts of data and provide it to you as a CSV on a really easy way. How you can use it I will explain in this blog.

How does it work
- Open the Graph Explorer
- Click on the right top to login

- Change the method to POST
- Copy the following URL in the address bar
https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs

- Now we have to build the body. Here it depends on what you want to export.
ReportName (Export Parameter) |
---|
DeviceCompliance |
DeviceNonCompliance |
Devices |
DetectedAppsAggregate |
FeatureUpdatePolicyFailuresAggregate |
DeviceFailuresByFeatureUpdatePolicy |
DetectedAppsRawData |
FeatureUpdateDeviceState |
UnhealthyDefenderAgents |
DefenderAgents |
ActiveMalware |
Malware |
AllAppsList |
AppInstallStatusAggregate |
DeviceInstallStatusByApp |
UserInstallStatusAggregateByApp |
ComanagedDeviceWorkloads |
ComanagementEligibilityTenantAttachedDevices |
DeviceRunStatesByProactiveRemediation |
DevicesWithInventory |
FirewallStatus |
GPAnalyticsSettingMigrationReadiness |
QualityUpdateDeviceErrorsByPolicy |
QualityUpdateDeviceStatusByPolicy |
MAMAppProtectionStatus |
MAMAppConfigurationStatus |
- In this example we export all discovered apps
{
"reportName": "DetectedAppsRawData",
"localizationType": "LocalizedValuesAsAdditionalColumn"
}
- In this Example we export all devices with an filter for OwnerType and select only the DeviceName
{
"reportName": "Devices",
"filter":"(OwnerType eq '1')",
"localizationType": "LocalizedValuesAsAdditionalColumn",
"select": [
"DeviceName"
]
}
- You have to copy this body in the request body field in the graph explorer
- Click Run query to request the report

- Now you have to append the value in id to the url. This must look like this:
https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('DetectedAppsRawData_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx')

- Change the method to GET
- Clean the request body field
- Click Run query to trigger the report creation

- Now you have triggered the report creation. The report will be generated in the backend. You have to run the same query in some seconds or minutes again (depending on the size)
- Click Run Query to get the download URL

- Copy the value in the url tag (Download URL) to the browser address bar to download the CSV report.
- The download of the CSV will started (File is zipped)

How use the export api via PowerShell
To automate and make the process easier I have written a PowerShell script which Init and start the export and wait until the export is completed. After that it downloads the zip file and unpacked this to provide the csv. To use this script follow this steps
- You can find an script in my GitHub repository or in this post to export the CSV via PowerShell
<#
Version: 1.0
Author: Jannik Reinhard (jannikreinhard.com)
Script: Get-GraphExportApiReport
Description:
Get an CSV Report from the Graph API
Release notes:
Version 1.0: Init
#>
function Get-AuthToken {
[cmdletbinding()]
param
(
[Parameter(Mandatory=$true)]
$User
)
$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User
$tenant = $userUpn.Host
$AadModule = Get-Module -Name "AzureAD" -ListAvailable
if ($AadModule -eq $null) {
Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
$AadModule = Get-Module -Name "AzureADPreview" -ListAvailable
}
$adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
Add-Type -Path $adal
Add-Type -Path $adalforms
$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceAppIdURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/$Tenant"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"
$userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")
$authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result
$authHeader = @{
'Content-Type'='application/json'
'Authorization'="Bearer " + $authResult.AccessToken
'ExpiresOn'=$authResult.ExpiresOn
}
return $authHeader
}
#################################################################################################
########################################### Start ###############################################
#################################################################################################
$reportName = 'DetectedAppsRawData'
#Get auth toke
if(-not $global:authToken.Authorization){
if($User -eq $null -or $User -eq ""){
$User = Read-Host -Prompt "Please specify your user principal name for Azure Authentication"
Write-Host
}
$global:authToken = Get-AuthToken -User $User
}
$body = @"
{
"reportName": "$reportName",
"localizationType": "LocalizedValuesAsAdditionalColumn"
}
"@
$id = (Invoke-RestMethod -Uri https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs -Headers $authToken -Method POST -Body $body).id
$status = (Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('$id')" -Headers $authToken -Method GET).status
while (-not ($status -eq 'completed')) {
$response = Invoke-RestMethod -Uri "https://graph.microsoft.com/beta/deviceManagement/reports/exportJobs('$id')" -Headers $authToken -Method Get
$status = ($response).status
}
Invoke-WebRequest -Uri $response.url -OutFile "./intuneExport.zip"
Expand-Archive "./intuneExport.zip" -DestinationPath "./intuneExport"
## Copy the file to an storage or do some actions
- Download the script and insert the report you want to have in the $reportName variable

- Run the script and you get as output the unzipped csv file
Seems there is a problem with the bulk export: “PostExportJobAsync not supported for reportType DiscoveredAppsRawData”
LikeLike
Seems there is a problem with the API: “PostExportJobAsync not supported for reportType DiscoveredAppsRawData”
LikeLike
Did you use Post?
LikeLike