Fix Windows Autopilot Reports and Graph API When Only 50 Deployment Records Show Up
If your Windows Autopilot deployment report suddenly tops out at 50 rows, or your Graph query for Autopilot events never returns more than 50 devices, do not waste time hunting for a missing filter or assuming older deployments disappeared. Microsoft documents this as a real backend behavior change.
Since the Intune 2411 reporting backend update, the Windows Autopilot deployment report and the AutopilotEvents Microsoft Graph API return 50 records at a time. That is not the same as losing data. It means your collection method is incomplete. The fix is to either page through the Graph results with skipToken or move to the export API with report name AutopilotV1DeploymentStatus when you need the full dataset.
For Autopilot admins, this matters fast. A 50-row ceiling breaks incident review, hides older failures in large waves, produces bad rollout metrics, and makes it look like Intune has less history than it actually does. The right response is not to keep clicking refresh. The right response is to switch to the Microsoft-supported retrieval path.
Quick Fix Checklist
Use this order when the portal or Graph call seems stuck at 50 records:
- Confirm the symptom is a hard 50-record ceiling, not a filter mistake.
- If you are using Graph, check whether the response includes pagination state and move to the next page instead of rerunning page one.
- Use
skipTokenfor additional pages ofdeviceManagement/autopilotEvents. - If you need complete reporting for all devices, switch to the export API.
- Use report name
AutopilotV1DeploymentStatusfor the Windows Autopilot deployment report export. - Pull only the columns you actually need so the export finishes faster.
- Keep the AutopilotEvents API for targeted troubleshooting and the export job for bulk reporting.
- Update your runbooks and scripts so the 50-row limit stops surprising the next admin.
If your current script only does one GET against deviceManagement/autopilotEvents, it is incomplete for production use.
What Microsoft Is Actually Saying
Microsoft’s current Windows Autopilot known issues page says this directly:
In Intune's 2411 release, we've updated the backend infrastructure of the Windows Autopilot deployment report for consistency with other Intune reports. With this change, the Windows Autopilot deployment report and the AutopilotEvents Microsoft Graph API now return 50 records at a time.
Microsoft then gives two supported ways to get past that limit:
- use the
skipTokenparameter for more pages from the AutopilotEvents Graph API - use the export API with
reportNameAutopilotV1DeploymentStatusto get all records
That wording is important because it tells you this is not a random tenant defect and not a device-side Autopilot failure. It is a reporting and retrieval behavior you need to account for in tooling.
Why This Trips Up Enterprise Admins
This issue is easy to misread because the first 50 records often look perfectly normal. The problem only becomes obvious when:
- your wave had more than 50 deployments
- you are trying to find a device that does not appear in the first page
- your service desk compares the portal grid to a larger CSV from another source
- your script reports lower failure counts than the rollout team expects
- older devices seem to vanish after a new batch starts
In other words, the data is still there, but your retrieval method is lying by omission.
That makes this a real troubleshooting issue, not a minor reporting annoyance. If you are trying to answer questions like these, a 50-record ceiling is operationally dangerous:
- Which serial numbers failed in yesterday’s pre-provisioning batch?
- Did the same deployment profile fail across more than one location?
- Are we seeing
failure,successWithTimeout, orsuccessOnRetryat scale? - Did the account setup phase fail only for one user group?
- Did a pilot improve after an ESP change, or are we only seeing the newest 50 rows?
Which Tool to Use for Which Job
Microsoft’s documentation points to two different paths because they solve different admin problems.
Use deviceManagement/autopilotEvents when you need targeted troubleshooting
The deviceManagementAutopilotEvent resource is still useful when you want record-level detail for one device, one serial number, one user, or one troubleshooting session.
Microsoft’s Graph beta documentation shows that this resource exposes useful fields such as:
deviceSerialNumberuserPrincipalNamewindowsAutopilotDeploymentProfileDisplayNameenrollmentStatedeploymentStatedeviceSetupStatusaccountSetupStatusdeploymentStartDateTimedeploymentEndDateTimedeploymentDurationdeploymentTotalDurationenrollmentFailureDetails
That makes it good for incident triage. It is not the best bulk export path anymore unless you also build pagination into your script.
Use exportJobs when you need the full report
When the goal is all deployments, all failures, all rows for CAB evidence, or a complete CSV/JSON artifact, Microsoft points admins to the export API instead.
The key value from the known-issues page is:
AutopilotV1DeploymentStatus
That report name is the practical way around the 50-row ceiling when your question is bigger than one page of Graph results.
Fix Path 1: Page the AutopilotEvents Graph API with skipToken
If your existing workflow already uses Graph, the fastest repair is to stop assuming one response equals the full dataset.
Microsoft’s List deviceManagementAutopilotEvents doc shows the collection endpoint as:
GET https://graph.microsoft.com/beta/deviceManagement/autopilotEvents
The Autopilot known-issues page then says to use the skipToken parameter to retrieve additional pages. In practice, that means your script needs to keep going until there are no more pages left.
Minimal Graph PowerShell pattern
Connect-MgGraph -Scopes "DeviceManagementManagedDevices.Read.All"
$uri = "https://graph.microsoft.com/beta/deviceManagement/autopilotEvents"
$all = @()
while ($uri) {
$page = Invoke-MgGraphRequest -Method GET -Uri $uri
$all += $page.value
if ($page.'@odata.nextLink') {
$uri = $page.'@odata.nextLink'
}
else {
$uri = $null
}
}
$all.Count
That pattern matters because many older Intune scripts were written for the first page only. They still run successfully, but they now return incomplete results.
Target one serial number without pulling everything
If you are troubleshooting a single device, narrow the call instead of exporting the world:
$serial = "SERIAL-NUMBER-HERE"
$uri = "https://graph.microsoft.com/beta/deviceManagement/autopilotEvents?`$filter=deviceSerialNumber eq '$serial'"
Invoke-MgGraphRequest -Method GET -Uri $uri
That keeps AutopilotEvents useful for deep triage while avoiding a bulky export for every ticket.
What to review in the result
For real Autopilot troubleshooting, these fields usually tell the story fastest:
deploymentStateenrollmentStatedeviceSetupStatusaccountSetupStatusdeploymentStartDateTimedeploymentEndDateTimeenrollmentFailureDetails
If your script is only returning the first 50 devices, you will get the wrong answer even if you are reading the right properties.
Fix Path 2: Use the Export API for Full Windows Autopilot Reporting
When you need a complete dataset, the export API is the better operator workflow.
Microsoft’s Graph v1.0 docs show the export job create endpoint as:
POST https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs
And the job-status endpoint as:
GET https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs/{deviceManagementExportJobId}
The create doc also matters because it confirms the job supports:
reportNamefilterselectformatstatusurlexpirationDateTime
That gives you a cleaner, repeatable reporting path than trying to manually join lots of paged API responses later.
Practical export job example
Connect-MgGraph -Scopes "DeviceManagementManagedDevices.ReadWrite.All"
$body = @{
reportName = 'AutopilotV1DeploymentStatus'
format = 'json'
select = @(
'DeviceName',
'DeviceSerialNumber',
'UPN',
'DeploymentState',
'DeploymentStartDateTime',
'DeploymentEndDateTime',
'DeploymentDuration',
'DeploymentTotalDuration',
'FailureReason',
'FailureDetails',
'EspDeviceSetupFailureDetails',
'EspUserSetupFailureDetails'
)
} | ConvertTo-Json -Depth 5
$job = Invoke-MgGraphRequest `
-Method POST `
-Uri 'https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs' `
-Body $body `
-ContentType 'application/json'
$jobId = $job.id
Do {
Start-Sleep -Seconds 5
$status = Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/v1.0/deviceManagement/reports/exportJobs/$jobId"
} Until ($status.status -in @('completed','failed'))
$status.status
$status.url
Once the status is completed, download the file from the temporary URL Microsoft returns.
Why export is often the better admin workflow
Use export when you need to:
- compare large deployment waves
- hand evidence to operations or leadership
- archive a point-in-time dataset
- sort and pivot outside the Intune portal
- preserve fields for post-incident review
This is also the cleaner path when the question is not “Why did this one laptop fail?” but “What happened across 800 laptops?”
Common Pitfalls
A few mistakes keep this issue alive longer than it should.
1. Treating the first page as the full dataset
This is the most common problem. The API call succeeds, so the script looks healthy. But the result is incomplete.
2. Using the bulk export path for every single help-desk ticket
For one serial number, AutopilotEvents is often faster. Use the export API when you really need all rows.
3. Ignoring the API version difference
Microsoft’s current docs expose deviceManagement/autopilotEvents in Graph beta. The export job path is available in v1.0. If you standardize everything on one version without checking the actual doc support, you can build unnecessary friction into your workflow.
4. Pulling too many columns by default
A giant export with every possible field slows down investigations. Pick the columns that answer the question in front of you.
5. Blaming the portal before proving the retrieval path
If the first 50 rows look real, admins often assume the missing devices were deleted or that Intune stopped collecting data. Microsoft’s own known-issues page already tells you the simpler answer: page the results or export the report.
A Practical Workflow I Would Use
If I were fixing this in a production Intune reporting script, I would use this order:
- Reproduce the 50-row ceiling in the current script.
- Confirm the script only reads the first page.
- Add support for
@odata.nextLinkandskipToken. - Test again on a tenant or filter that should return more than 50 records.
- Keep the paged API path for targeted lookups.
- Add a second command for full exports using
AutopilotV1DeploymentStatus. - Document when the team should use each path.
That split usually gives the cleanest result:
- Graph paging for targeted investigations
- export jobs for full operational reporting
Bottom Line
If Windows Autopilot reporting seems to stop at 50 devices, the data is not automatically gone and your rollout is not automatically broken. Microsoft documents that the Autopilot deployment report and AutopilotEvents Graph API now return 50 records at a time after the Intune 2411 backend change.
The fix is straightforward:
- use
skipTokenand follow the next page for AutopilotEvents - use
AutopilotV1DeploymentStatusthrough the export API when you need the full report
Once you update your scripts and runbooks, this stops being a mystery and becomes a normal pagination problem.