Skip to main content
Microsoft IntuneIntermediate

Export Windows Autopilot devices with Graph PowerShell: serial, group tag and profile status

Updated 18 October 2026What changed

Checked against the Microsoft Graph v1.0 and beta windowsAutopilotDeviceIdentity resources, the list and updateDeviceProperties API pages, the Graph PowerShell cmdlet references, and Microsoft's Autopilot device attribute and device group documentation.

On this page14 sections

Short answer: Get-MgDeviceManagementWindowsAutopilotDeviceIdentity calls the Graph v1.0 endpoint, and v1.0 does not have deploymentProfileAssignmentStatus or deploymentProfileAssignedDateTime. Select those properties from the v1.0 cmdlet and you get empty columns, not an error. Use the beta cmdlet, Get-MgBetaDeviceManagementWindowsAutopilotDeviceIdentity, when you need profile assignment data.

This tutorial is for Intune admins who need a reliable export of Windows Autopilot registrations: serial numbers, group tags, profile status, display names and the Intune and Entra records they link to. It covers the v1.0 and beta differences, an export script, filters for the devices that will not deploy, bulk updates of group tags and device names, and a raw REST version for support cases.

Scope and prerequisites

The examples assume:

  • An Intune-licensed tenant. Microsoft notes that the Graph API for Intune requires an active Intune licence.
  • The Microsoft Graph PowerShell SDK, with these modules:
    • Microsoft.Graph.Authentication for Connect-MgGraph and Invoke-MgGraphRequest
    • Microsoft.Graph.DeviceManagement.Enrollment for the v1.0 cmdlets
    • Microsoft.Graph.Beta.DeviceManagement.Enrollment for the beta cmdlet that returns profile status
    • Microsoft.Graph.DeviceManagement, only for the managed device lookup in the display name section
  • An account or app with DeviceManagementServiceConfig.Read.All for reading. Updating group tags or device names needs DeviceManagementServiceConfig.ReadWrite.All. Do not request the write scope for a read-only export.

Output shown in this article is placeholder shape only. Replace <serial-number>, <group-tag> and similar values with your own.

PowerShell
Install-Module Microsoft.Graph.Authentication -Scope CurrentUser
Install-Module Microsoft.Graph.DeviceManagement.Enrollment -Scope CurrentUser
Install-Module Microsoft.Graph.Beta.DeviceManagement.Enrollment -Scope CurrentUser
Install-Module Microsoft.Graph.DeviceManagement -Scope CurrentUser

v1.0 versus beta: which properties you actually get

This is the table to keep open. It comes from Microsoft's v1.0 and beta resource definitions.

PropertyAPINotes
serialNumber, manufacturer, modelv1.0 and betaHardware identity from the import
groupTagv1.0 and betaMaps to the OrderID attribute used in dynamic group rules
purchaseOrderIdentifierv1.0 and betaMaps to PurchaseOrderId in dynamic group rules
enrollmentStatev1.0 and betav1.0 values: unknown, enrolled, pendingReset, failed, notContacted. Beta adds blocked
lastContactedDateTimev1.0 and betaLast Intune contact for the Autopilot record
displayNamev1.0 and betaThe Device name field on the Autopilot record. See the display name section below
userPrincipalName, addressableUserNamev1.0 and betaPopulated when a user is assigned to the device
managedDeviceIdv1.0 and betaLinks to the Intune managed device once enrolled
azureActiveDirectoryDeviceIdv1.0 and betaMarked "to be deprecated". Beta adds azureAdDeviceId
deploymentProfileAssignmentStatusBeta onlyunknown, assignedInSync, assignedOutOfSync, assignedUnkownSyncState, notAssigned, pending, failed
deploymentProfileAssignedDateTimeBeta onlyWhen the profile was set
deploymentProfileAssignmentDetailedStatusBeta onlyFor example hardwareRequirementsNotMet
remediationState, userlessEnrollmentStatusBeta onlyBeta-only operational fields

assignedUnkownSyncState is spelled that way in the API. If you filter on it, match Microsoft's spelling, not the dictionary one.

Microsoft supports the Intune beta APIs but says they are subject to more frequent change, and recommends v1.0 when possible. A sensible split: use v1.0 for anything that only needs serial, group tag and enrolment state, and use beta only for profile assignment fields.

Step 1: Connect with the least privilege you need

PowerShell
Connect-MgGraph -Scopes "DeviceManagementServiceConfig.Read.All" -NoWelcome
Get-MgContext | Select-Object Account, TenantId, Scopes

Expected output shape:

Text
Account                 TenantId                              Scopes
-------                 --------                              ------
<admin>@<tenant-domain> <tenant-id>                           {DeviceManagementServiceConfig.Read.All, openid, profile...}

If Scopes does not include the permission, stop. Every later call returns a permissions error, and in a large script that is easy to misread as "no devices found".

Step 2: Export every Autopilot device to CSV

-All follows paging for you. Without it you only get the first page of results, which looks like a complete list in a small test tenant and silently truncates in a real one.

PowerShell
$devices = Get-MgBetaDeviceManagementWindowsAutopilotDeviceIdentity -All

$devices |
    Select-Object SerialNumber, Manufacturer, Model, GroupTag,
        PurchaseOrderIdentifier, EnrollmentState,
        DeploymentProfileAssignmentStatus,
        @{ n = 'ProfileAssignedUtc'; e = { $_.DeploymentProfileAssignedDateTime } },
        @{ n = 'LastContactedUtc';   e = { $_.LastContactedDateTime } },
        DisplayName, UserPrincipalName, ManagedDeviceId, AzureAdDeviceId, Id |
    Export-Csv -Path .\autopilot-devices.csv -NoTypeInformation -Encoding utf8

"Exported {0} Autopilot devices" -f $devices.Count

Expected output shape:

Text
Exported <count> Autopilot devices

Compare that count with the Windows Autopilot devices total in the Intune admin centre. If they differ, check you used -All and that you are signed in to the right tenant.

If you must stay on v1.0, use Get-MgDeviceManagementWindowsAutopilotDeviceIdentity -All and remove the three DeploymentProfile* columns and AzureAdDeviceId from the Select-Object. Leaving them in just produces empty columns that look like data.

Step 3: Find one device by serial or a group by tag

The filters below run in PowerShell after the export. That is slower than a server-side filter, but it behaves the same in every tenant and is easy to audit.

PowerShell
$serial = '<serial-number>'
$devices | Where-Object SerialNumber -eq $serial |
    Format-List SerialNumber, GroupTag, EnrollmentState,
        DeploymentProfileAssignmentStatus, DeploymentProfileAssignedDateTime,
        DisplayName, ManagedDeviceId

Expected output shape:

Text
SerialNumber                      : <serial-number>
GroupTag                          : <group-tag or blank>
EnrollmentState                   : notContacted
DeploymentProfileAssignmentStatus : assignedInSync
DeploymentProfileAssignedDateTime : <date/time>
DisplayName                       : <device name or blank>
ManagedDeviceId                   : <blank until enrolled>

For a whole batch by group tag:

PowerShell
$tag = '<group-tag>'
$devices | Where-Object GroupTag -eq $tag |
    Group-Object DeploymentProfileAssignmentStatus |
    Select-Object Name, Count

A blank or misspelt GroupTag is a common reason a device never joins the dynamic group that the profile targets. Compare the tags in this output with the exact [OrderID]: value in the group rule.

Step 4: List the devices that will not deploy

A device is ready for a user-driven deployment when it has a profile assigned and in sync. This report lists everything else, oldest first.

PowerShell
$devices |
    Where-Object { $_.DeploymentProfileAssignmentStatus -ne 'assignedInSync' } |
    Sort-Object LastContactedDateTime |
    Select-Object SerialNumber, GroupTag, DeploymentProfileAssignmentStatus,
        DeploymentProfileAssignmentDetailedStatus, EnrollmentState |
    Format-Table -AutoSize

Read the status column as a routing decision, not a diagnosis:

StatusWhat to check first
notAssignedGroup tag, the dynamic group rule, and whether the profile is assigned to that group
pendingNothing yet. Profile assignment is not instant; re-run the report later before changing anything
assignedOutOfSync or assignedUnkownSyncStateWhether someone recently changed the profile or the group, then re-check
failedDeploymentProfileAssignmentDetailedStatus, for example hardwareRequirementsNotMet
unknownRe-export. If it persists, open the device in the Intune admin centre

If notAssigned devices all share one blank or misspelt group tag, fix the tag (Step 6) rather than editing the dynamic group. For import-side failures, such as rows that never appear at all, use Autopilot device not importing.

Display name versus computer name

People often search for windowsAutopilotDeviceIdentity displayName "computer name" because the two are easy to confuse.

  • displayName is the Device name field on the Autopilot device record. You can edit it in Devices > Windows > Windows enrollment > Devices or with updateDeviceProperties. Microsoft's Autopilot device attribute documentation notes that device names can be set for all devices but are ignored for Microsoft Entra hybrid join, where the name comes from the domain join profile.
  • The computer name of an enrolled device lives on the Intune managed device record. Use managedDeviceId to read it rather than trusting the Autopilot displayName.
PowerShell
Connect-MgGraph -Scopes "DeviceManagementServiceConfig.Read.All","DeviceManagementManagedDevices.Read.All" -NoWelcome

$devices | Where-Object ManagedDeviceId | ForEach-Object {
    $managed = Get-MgDeviceManagementManagedDevice -ManagedDeviceId $_.ManagedDeviceId
    [pscustomobject]@{
        SerialNumber       = $_.SerialNumber
        AutopilotName      = $_.DisplayName
        IntuneDeviceName   = $managed.DeviceName
        NamesMatch         = $_.DisplayName -eq $managed.DeviceName
    }
} | Where-Object { -not $_.NamesMatch } | Format-Table -AutoSize

Expected output shape:

Text
SerialNumber      AutopilotName   IntuneDeviceName   NamesMatch
------------      -------------   ----------------   ----------
<serial-number>                   <computer-name>    False

A blank AutopilotName is normal when you use a naming template in the deployment profile instead of per-device names. This report makes one call per enrolled device, so run it against a filtered list in large tenants.

Step 5: Raw REST for support cases

Support engineers often ask for the raw JSON. Invoke-MgGraphRequest returns hashtables by default, so Select-Object prints empty columns; ask for PSObject output instead, and follow @odata.nextLink so you do not stop at the first page.

PowerShell
$uri = 'https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities'
$all = while ($uri) {
    $page = Invoke-MgGraphRequest -Method GET -Uri $uri -OutputType PSObject
    $page.value
    $uri = $page.'@odata.nextLink'
}

$all | Where-Object serialNumber -eq '<serial-number>' |
    ConvertTo-Json -Depth 3 | Set-Content .\autopilot-device.json

Check the JSON before attaching it to a case. It contains the serial number, product key field, user principal name and object IDs.

Step 6: Bulk-update group tags or device names

This step writes to the tenant. Reconnect with the write scope only for this step, and run it with -WhatIf first.

Prepare a CSV with exactly these headers:

Text
SerialNumber,GroupTag
<serial-number-1>,<new-group-tag>
<serial-number-2>,<new-group-tag>
PowerShell
Connect-MgGraph -Scopes "DeviceManagementServiceConfig.ReadWrite.All" -NoWelcome

$changes = Import-Csv .\group-tag-changes.csv
$bySerial = @{}
Get-MgDeviceManagementWindowsAutopilotDeviceIdentity -All |
    ForEach-Object { $bySerial[$_.SerialNumber] = $_ }

foreach ($row in $changes) {
    $device = $bySerial[$row.SerialNumber]
    if (-not $device) { Write-Warning "Not registered: $($row.SerialNumber)"; continue }
    if ($device.GroupTag -ceq $row.GroupTag) { continue }

    Update-MgDeviceManagementWindowsAutopilotDeviceIdentityDeviceProperty `
        -WindowsAutopilotDeviceIdentityId $device.Id `
        -BodyParameter @{ groupTag = $row.GroupTag } -WhatIf
}

When the -WhatIf output lists only the devices you expect, remove -WhatIf and run it again. To set device names instead, use a DisplayName column and @{ displayName = $row.DisplayName }, and remember names are ignored for hybrid join.

The update sends only the property you include. After the change, the dynamic group based on OrderID has to re-evaluate and the profile has to reassign. Re-run Step 4 later instead of assuming the change took effect immediately.

Validation checklist

  • Get-MgContext shows the expected tenant and only the scopes this task needs
  • The export count matches the Windows Autopilot devices total in the Intune admin centre
  • Profile status columns are populated, which proves you used the beta cmdlet
  • Devices that are not assignedInSync are explained by group tag, group rule or profile assignment
  • Bulk updates ran with -WhatIf first and the change list was reviewed
  • Exported files containing serials and UPNs are stored and deleted like any other device inventory

Common mistakes

MistakeWhat you seeFix
Selecting profile status from the v1.0 cmdletEmpty DeploymentProfileAssignmentStatus columnUse Get-MgBetaDeviceManagementWindowsAutopilotDeviceIdentity
Forgetting -AllCounts that stop at a page boundaryAdd -All, or follow @odata.nextLink in raw REST
Raw REST without -OutputType PSObjectSelect-Object shows blank columnsAdd -OutputType PSObject
Treating displayName as the live computer nameNames that do not match devices in IntuneRead DeviceName from the managed device via managedDeviceId
Fixing tags by editing the dynamic groupGroup rule grows exceptionsCorrect the groupTag on the device records instead
Requesting ReadWrite for a reportOver-privileged automation accountUse Read.All for exports; ReadWrite only for Step 6

When not to use this approach

  • Unattended production automation on beta. Beta properties can change. If a scheduled job only needs serial, tag and enrolment state, use v1.0 and keep the beta call in an interactive report.
  • As proof that a device will deploy. assignedInSync means a profile is assigned. It does not prove the Enrollment Status Page, apps or join will succeed; see Autopilot Enrollment Status Page stuck.
  • Windows Autopilot device preparation. Device preparation does not depend on Autopilot registration or deployment profiles in the same way, so profile status is not the right health signal there. See Autopilot v1 vs Device Preparation v2.

Primary Sources

Microsoft Intune

Product link

Manage, secure, and report on all your endpoints from a single cloud-native console.

This is a Microsoft product link, not an advert and not an affiliate placement. AdminSignal has no affiliate arrangement for Intune.

Open Intune
Jack Hadcroft, Band 6 Endpoint Specialist and author of AdminSignal

Jack Hadcroft

LinkedIn

Band 6 Endpoint Specialist and author of AdminSignal

Technical claims are reviewed against current Microsoft documentation. Lab or tenant checks are named only when they were done.

Independent publication. About · Editorial policy