Intune sits on top of Microsoft Graph — every action you take in the Intune admin center is a Graph API call. That is good news: anything you can do in the portal you can script. Inventory all 5,000 devices, find which ones are non-compliant, push a configuration profile to a group, remote-wipe a stolen laptop — all from PowerShell, all auditable.
This guide covers the most common Intune operations, the scopes they need, and the patterns to get them right. Free PDF cheat sheet at the bottom.
Table of Contents
Required scopes
DeviceManagementManagedDevices.Read.All— read inventoryDeviceManagementManagedDevices.PrivilegedOperations.All— wipe / retire / fresh startDeviceManagementConfiguration.Read.All— read configuration profilesDeviceManagementConfiguration.ReadWrite.All— create / modify profilesDeviceManagementApps.Read.All— read app inventory
Device inventory
Connect-MgGraph -Scopes "DeviceManagementManagedDevices.Read.All"
# All devices
$devices = Get-MgDeviceManagementManagedDevice -All
$devices.Count # 4,832
# Pull useful columns
$devices | Select-Object DeviceName, OperatingSystem, OsVersion,
Manufacturer, Model, ComplianceState, LastSyncDateTime,
UserPrincipalName |
Sort-Object LastSyncDateTime -Descending |
Select-Object -First 20
Compliance status
# Compliance state distribution
$devices | Group-Object ComplianceState |
Format-Table Name, Count -AutoSize
# Non-compliant Windows devices
$badWin = $devices | Where-Object {
$_.OperatingSystem -eq 'Windows' -and $_.ComplianceState -ne 'compliant'
}
# Per-policy compliance (most useful)
$badWin | ForEach-Object {
$states = Get-MgDeviceManagementManagedDeviceCompliancePolicyState `
-ManagedDeviceId $_.Id |
Where-Object State -ne 'compliant'
[PSCustomObject]@{
Device = $_.DeviceName
UPN = $_.UserPrincipalName
Policies = ($states | ForEach-Object { $_.DisplayName }) -join '; '
}
} | Export-Csv .\noncompliant.csv -NoTypeInformation
Filter by OS, model, last sync
# Devices not synced in 30 days
$stale = $devices | Where-Object {
$_.LastSyncDateTime -lt (Get-Date).AddDays(-30)
}
# By model
$devices | Where-Object Model -like 'Surface*' |
Group-Object Model | Format-Table Name, Count
# Server-side filter for huge tenants
Get-MgDeviceManagementManagedDevice -All `
-Filter "operatingSystem eq 'iOS' and lastSyncDateTime lt 2025-01-01T00:00:00Z"
Configuration profiles
# List all device configuration profiles
Get-MgDeviceManagementDeviceConfiguration -All |
Select-Object DisplayName, Id,
@{n='Type';e={$_.AdditionalProperties.'@odata.type' -replace '#microsoft.graph.',''}}
# Get one profile in full
$p = Get-MgDeviceManagementDeviceConfiguration -DeviceConfigurationId $profileId
$p | ConvertTo-Json -Depth 10
Creating profiles via Graph is supported but the JSON body is large and very specific to the profile type. For most teams, manage profiles in the portal and script the assignment instead.
Assign profiles to groups
$profileId = ""
$groupId = (Get-MgGroup -Filter "displayName eq 'Pilot-Group'").Id
$body = @{
assignments = @(
@{
target = @{
"@odata.type" = "#microsoft.graph.groupAssignmentTarget"
groupId = $groupId
}
}
)
}
Invoke-MgGraphRequest -Method POST `
-Uri "/v1.0/deviceManagement/deviceConfigurations/$profileId/assign" `
-Body $body
Remote actions: sync, wipe, retire, restart
# Force a check-in (sync) - low-risk, useful after policy change
Invoke-MgGraphRequest -Method POST `
-Uri "/v1.0/deviceManagement/managedDevices/$deviceId/syncDevice"
# Restart Windows device
Invoke-MgGraphRequest -Method POST `
-Uri "/v1.0/deviceManagement/managedDevices/$deviceId/rebootNow"
# Wipe (factory reset, KEEP enrollment)
Invoke-MgGraphRequest -Method POST `
-Uri "/v1.0/deviceManagement/managedDevices/$deviceId/wipe" `
-Body @{ keepEnrollmentData = $true; keepUserData = $false }
# Retire (remove company data, leave personal data alone)
Invoke-MgGraphRequest -Method POST `
-Uri "/v1.0/deviceManagement/managedDevices/$deviceId/retire"
# Delete the device record (after retire)
Remove-MgDeviceManagementManagedDevice -ManagedDeviceId $deviceId
For a stolen device, the right sequence is: retire (wipe corporate data immediately), then wipe when the device next checks in (full factory reset). Privileged operations require the explicit privileged scope.
Managed app inventory
# All apps deployed via Intune
Get-MgDeviceAppManagementMobileApp -All |
Select-Object DisplayName, Publisher, CreatedDateTime,
@{n='Type';e={$_.AdditionalProperties.'@odata.type' -replace '#microsoft.graph.',''}}
# Apps installed on a specific device
Get-MgDeviceManagementManagedDeviceDetectedApp -ManagedDeviceId $deviceId
Cheat sheet
The full reference on a single PDF: Intune Graph API Cheat Sheet.
FAQ
Where do I find the device ID?
Get-MgDeviceManagementManagedDevice -Filter "deviceName eq 'LAPTOP-X1'" or via the Intune admin center on the device's overview page.
Why does compliance show "unknown"?
Either the device has not checked in since enrollment (no compliance evaluation has run), or there is no compliance policy assigned to the user/device. Trigger a sync via the Graph API and re-check after 5 minutes.
Can I bulk-wipe a list of devices?
Yes — loop through the IDs and call the wipe endpoint for each. Add a small Start-Sleep between calls to avoid throttling. Always test on one device first.
What is the difference between wipe and retire?
Wipe = factory reset (everything gone). Retire = remove only company-managed apps and data (personal data on BYOD devices stays). Pick retire for off-boarded employees on personal devices, wipe for lost or stolen.
Can I create configuration profiles through Graph?
Yes — but the JSON body is profile-type specific and verbose. Most teams find it more practical to author profiles in the portal and use Graph for assignment, reporting, and bulk operations.
How do I avoid throttling for tenant-wide reports?
Use -All with the SDK (it handles paging and back-off), $select to limit returned columns, and process the result in memory rather than re-querying per device.
Are remote actions logged?
Yes — every action shows in the Intune admin center under the device's "Activity" tab and in Azure Monitor logs if you stream Intune audit data there.