A user-driven Windows Autopilot deployment goes sideways. The licence terms screen appears when the profile says to hide it, or the device gets the wrong name, or a user from the wrong tenant is told to start over. The portal shows a profile that looks correct. So you go to the device for ground truth, open AutopilotConfigurationFile.json, and find nine properties with names that appear nowhere in the Intune admin center. Then you check a second device and the file is not there at all. Neither of those things is a fault. Both are documented behaviour, and this post is the reference table that makes them make sense.
Microsoft documents exactly nine properties for AutopilotConfigurationFile.json, and that file only belongs to the Windows Autopilot for existing devices scenario. Most of what you set in the Intune profile blade never reaches that file, because the file is an offline hand-off for the out-of-box experience rather than a dump of the deployment profile. The Microsoft Graph resource is the real authoring surface, and Microsoft renamed half of its properties in May 2024, so a script written against the old names silently reads deprecated fields. This post maps every documented JSON property to its Graph property and its portal control, then lists the portal settings that are not in the JSON and says where they actually live.
The problem: nine field names that match no portal label
The Intune admin center gives you roughly a dozen switches when you build a Windows Autopilot deployment profile. Deployment mode. Join type. Microsoft Software License Terms. Privacy settings. Hide change account options. User account type. Allow pre-provisioned deployment. Language (Region). Automatically configure keyboard. Apply device name template. Plus a separate Enrollment Status Page, or ESP, profile that most people mentally file under the same feature.
Here is the path you took to set them.
Now here is what Microsoft documents inside the JSON file. Nine properties, and not one of them uses a portal label as its name.
Three things in that output cause most of the confusion. The first is that Test-Path returned False on your healthy device. The second is that a whole screen of portal switches has collapsed into a single number, 28. The third is that the two settings you cared about most, Language (Region) and Automatically configure keyboard, are simply absent. There is no property for them.
Why it happens: three surfaces, three vocabularies
An Autopilot deployment profile is expressed on three different surfaces. Each one was designed at a different time for a different consumer. They do not share a naming convention, because they were never meant to be read side by side.
Surface 1: the offline JSON
AutopilotConfigurationFile.json. A hand-off file that OOBE reads when no service-assigned profile is available. Nine documented properties, all using CloudAssigned naming.
Surface 2: Microsoft Graph
The windowsAutopilotDeploymentProfile resource. The real authoring surface, and what the portal blade writes to. camelCase naming.
Surface 3: the device registry
The Provisioning diagnostics key. What the operating system actually latched onto after the profile download. A mix of both vocabularies.
The JSON is a fallback, not an export
This is the point that unlocks everything else. Microsoft documents AutopilotConfigurationFile.json under Windows Autopilot for existing devices. That is the Configuration Manager task sequence scenario. You wipe an existing domain-joined machine, lay down a fresh Windows image, and inject a JSON file so the first OOBE run behaves like an Autopilot deployment without the hardware hash having been uploaded in advance.
Because it is a fallback, it only needs the fields required to bootstrap that one flow. It needs to know which tenant to talk to. It needs to know whether to Entra join or hybrid join. It needs to know which OOBE screens to suppress. It does not need to carry the Enrollment Status Page configuration, because that arrives later from Intune over the wire.
Two limits on the JSON that admins get wrong
The first limit is scenario coverage. Microsoft documents that the JSON file only supports user-driven Microsoft Entra ID and user-driven hybrid Microsoft Entra profiles. Self-deploying and pre-provisioning profiles are not supported through a JSON file, because those scenarios require Trusted Platform Module attestation. If you have read elsewhere that the JSON is the pre-provisioning artefact, that is wrong. Pre-provisioning needs a registered device and a service-assigned profile.
The second limit is lifetime. Windows deletes the file when Sysprep.exe runs with the /Generalize parameter. The Prepare Windows for Capture task in a Configuration Manager task sequence does exactly that. This is why the documented workaround is to remove that task and run a plain sysprep /oobe /reboot instead.
Graph renamed half its properties in May 2024
The Graph surface has its own trap. Microsoft published a second generation of property names and marked the originals deprecated. Both still appear in the resource documentation, which makes it easy to write a script against the wrong one. The current name is the one to use.
| Current Graph property | Deprecated predecessor | Portal control |
|---|---|---|
locale | language | Language (Region) |
outOfBoxExperienceSetting | outOfBoxExperienceSettings | The OOBE page as a whole |
hardwareHashExtractionEnabled | extractHardwareHash | Convert all targeted devices to Autopilot |
preprovisioningAllowed | enableWhiteGlove | Allow pre-provisioned deployment |
privacySettingsHidden | hidePrivacySettings | Privacy settings |
eulaHidden | hideEULA | Microsoft Software License Terms |
keyboardSelectionPageSkipped | skipKeyboardSelectionPage | Automatically configure keyboard |
escapeLinkHidden | hideEscapeLink | Hide change account options |
The singular outOfBoxExperienceSetting is the current shape, and it exists in the Graph v1.0 endpoint rather than only in beta. The plural outOfBoxExperienceSettings is documented as read-only and deprecated. Notice the rename pattern: the old shape used verb-first names such as hideEULA, and the new shape uses noun-first names such as eulaHidden. Once you see the pattern you can predict the rest.
keyboardSelectionPageSkipped contradicts itself. It says the page is hidden when the value is TRUE, then says the page is skipped when the value is FALSE. Trust the portal semantics instead: Automatically configure keyboard set to Yes is what skips the page, and that maps to TRUE. Verify on a test device rather than on the sentence.How to verify: file, registry, event log and Graph
Check all the surfaces, in this order, because each answers a different question. The file tells you what was injected. The registry tells you what the operating system accepted. The event log tells you the sequence of how it got there. Graph tells you what you authored.
Step 1: the file, if the scenario calls for one
The current Microsoft articles are precise about the file name and encoding, but they do not spell out the on-device folder. The path used by the documented task sequence step, and shown in Microsoft's own archived engineering blog, is the Provisioning folder under the Windows directory.
Two file-level requirements matter more than any property inside it. The file name must be exactly AutopilotConfigurationFile.json, and the encoding must be ASCII or ANSI. Microsoft states that OOBE will not follow the Autopilot experience if the file is saved as Unicode, as UTF-8, or under any other name. That is why the documented command uses Set-Content -Encoding Ascii rather than Out-File, which defaults to Unicode and can also truncate long lines.
Step 2: the registry, which is the real ground truth
On any device that received a profile from the Windows Autopilot deployment service, the settings land in the registry. This is the surface to check on a normal cloud-registered device. Microsoft documents six values under one key.
| Value | What Microsoft documents it as | What it tells you |
|---|---|---|
CloudAssignedTenantId | The GUID of the Entra tenant the device registered with. Blank if the device is not registered with Autopilot. | Blank here plus a missing JSON file means the device is not an Autopilot device at all. |
CloudAssignedTenantDomain | The Entra tenant the device is registered with, for example contosomn.onmicrosoft.com. Blank if not registered. | Confirms which tenant claimed the device. Mismatches here explain wrong-tenant sign-in errors. |
AadTenantId | The GUID of the Entra tenant the user signed into. | Compare it against CloudAssignedTenantId. A difference produces the belongs-to-another-organization message. |
TenantMatched | Set to 1 if the user tenant ID matches the tenant ID the device was registered with. If 0, the user is shown an error and forced to start over. | The fastest yes-or-no answer for a failed user-driven sign-in. |
IsAutopilotDisabled | If set to 1, the device is not registered with Autopilot. It can also mean the profile could not be downloaded because of connectivity, firewall or timeout. | Deliberately ambiguous. Read it with the event log to tell not-registered from could-not-reach-the-service. |
CloudAssignedOobeConfig | A bitmap that shows which Autopilot settings were configured. | The same number as in the JSON. Decode it rather than eyeballing it. |
CloudAssignedOobeConfig in the registry against the value in the JSON file when both exist. If they differ, the service-assigned profile won the precedence contest and your task sequence JSON never took effect. That one comparison saves an hour of guessing.Step 3: the event log, for the sequence
Autopilot writes its own channel. In Event Viewer, expand Applications and Services Logs.
These are the documented IDs for that channel. Read them as a story rather than as isolated errors, because a single warning early in the sequence is normal.
| Event ID | Type | What it means for field mapping |
|---|---|---|
| 100 | Warning | Autopilot policy not found. Typically transient while the device waits for the profile download. |
| 101 | Info | A numeric OOBE setting was retrieved and processed. This is where bitmask-derived values appear. |
| 103 | Info | A string OOBE setting was retrieved, such as the Entra tenant name. |
| 109 | Info | A state-related OOBE setting override was retrieved. |
| 111 | Info | The settings that control OOBE behaviour were retrieved successfully. |
| 153 | Info | Profile state changed, usually to ProfileState_Available. The device is ready to deploy. |
| 160 | Info | Autopilot is getting ready to download the profile settings. |
| 161 | Info | The Autopilot profile downloaded successfully. |
| 163 | Info | Download not required, the device is already provisioned. Sysprep /Generalize typically clears that state. |
| 164 | Info | Internet is available, so a policy download will be attempted. |
| 171 | Error | Failed to set TPM identity confirmed. An attestation problem, needed for self-deploying mode. |
| 172 | Error | Failed to set the Autopilot profile as available. Usually the companion to 171. |
| 807 | Error | ZtdDeviceIsNotRegistered. Check the hardware hash upload and the profile assignment. |
| 809 | Error | Assigned profile does not exist. The profile was deleted without cleanup. |
| 815 | Error | No profile assigned to the device and no default profile in the tenant. |
| 908 | Error | SerialNumberMismatch or ProductKeyIdMismatch between the Autopilot record and the hardware. |
Step 4: the Graph object, for what you actually authored
The portal blade is a view over the Graph resource, so reading Graph directly removes the label translation step entirely.
The @odata.type is doing real work here. An azureADWindowsAutopilotDeploymentProfile is an Entra join profile. An activeDirectoryWindowsAutopilotDeploymentProfile is a hybrid join profile, and it is the only one of the two that carries hybridAzureADJoinSkipConnectivityCheck and a domainJoinConfiguration relationship. That type distinction is what the JSON compresses into the single digit in CloudAssignedDomainJoinMethod.
The fix: the complete three-surface field map
This is the table to keep. Every documented JSON property, its Graph counterpart, the portal control that produces it, and what it actually does at OOBE time.
| JSON property | Graph equivalent | Portal control | What it actually does |
|---|---|---|---|
VersionNumber, optional | None | None | Identifies the format of the JSON file. Written by the conversion cmdlet, not by you. |
CloudAssignedTenantIdGUID, required | Implied by the tenant, not a profile property | None | The Entra tenant GUID to use. Documented as a GUID with no braces. |
CloudAssignedTenantDomainString, required | Implied by the tenant | None | The Entra tenant name, for example tenant.onmicrosoft.com. |
CloudAssignedOobeConfigNumber, required | The outOfBoxExperienceSetting Booleans | Microsoft Software License Terms, Privacy settings, User account type | A bitmap of which OOBE settings were configured. Three of its five documented bits correspond to portal switches. Two do not. |
CloudAssignedDomainJoinMethodNumber, required | The resource subtype, azureAD... or activeDirectory... | Join to Microsoft Entra ID as | 0 means Entra joined, 1 means Entra hybrid joined. The whole join decision in one digit. |
CloudAssignedForcedEnrollmentNumber, required | None | None | Specifies that the device must Entra join and enrol in MDM. 0 is not required, 1 is required. No portal switch exposes it. |
ZtdCorrelationIdGUID, required | None | None | Passed to Intune during registration as OfflineAutopilotEnrollmentCorrelator. Present only for offline registration. |
CloudAssignedAadServerDataEncoded JSON string, required | None | Entra organization branding, not the Autopilot blade | An embedded JSON string used for branding. Requires Entra organization branding to be enabled. |
CloudAssignedDeviceNameString, optional | deviceNameTemplate | Apply device name template | The name assigned to the computer. Follows the profile naming pattern, or an explicit name you set. |
Comment_File key that does not appear in the documented property table. Treat it as descriptive metadata written by the conversion cmdlet. Do not build logic on it, because it is not part of the documented contract.Where the bitmask fits, and where to stop
Microsoft documents five bits for CloudAssignedOobeConfig, and the same five appear in the registry documentation. Three map to portal controls. OobeUserNotLocalAdmin corresponds to User account type set to Standard. SkipExpressSettings corresponds to hiding Privacy settings. SkipEula corresponds to hiding Microsoft Software License Terms. The other two documented bits, SkipCortanaOptIn and SkipOemRegistration, have no portal switch at all. They are set by the service.
Rather than repeating the bit table here, decode the number using the dedicated walkthrough: CloudAssignedOobeConfig Decoded: Which OOBE Screens Your Profile Actually Skipped. The important point for field mapping is the direction of the relationship. Portal switches feed the bitmask. The bitmask does not enumerate portal switches, so you cannot reconstruct a profile from the number alone.
The settings that are not in the JSON at all
This is the list nobody writes down, and it is longer than the documented property table. Every row here is a portal control with no JSON representation.
| Portal control | Graph property | Where it actually lives |
|---|---|---|
| Deployment mode, user-driven or self-deploying | Expressed through userType and deviceUsageType | Service-side only. Self-deploying is not supported by a JSON file because it requires TPM attestation. |
| Language (Region) | locale | Service-side only. Delivered with the downloaded profile, never in the JSON. |
| Automatically configure keyboard | keyboardSelectionPageSkipped | Service-side only. Also requires Ethernet, because language selection precedes the Wi-Fi connection. |
| Hide change account options | escapeLinkHidden | Service-side only, and dependent on Entra company branding being configured. |
| Allow pre-provisioned deployment | preprovisioningAllowed | Service-side only. Pre-provisioning profiles cannot be delivered by JSON. |
| Convert all targeted devices to Autopilot | hardwareHashExtractionEnabled | A registration behaviour on the Basics page, not an OOBE behaviour. Nothing on the device reads it. |
| Create Profile: Windows PC or HoloLens | deviceType | Service-side only. Documented values include windowsPc, holoLens and virtualMachine. |
| Enrollment Status Page settings, all of them | enrollmentStatusScreenSettings | A separate blade under Windows Autopilot and a separate Graph complex type. Arrives from Intune after enrolment. |
| Scope tags | roleScopeTagIds | An Intune role-based access control construct. It never reaches the device. |
| Assignments, include and exclude groups | The assignments relationship | Service-side. The JSON has no concept of targeting, which is exactly why it works on unregistered hardware. |
| Skip Active Directory connectivity check, hybrid only | hybridAzureADJoinSkipConnectivityCheck | Only on the hybrid profile subtype. Domain and organizational unit come from a separate Domain Join device configuration profile. |
| Name and Description | displayName and description | Portal metadata. On the offline path the device profile name becomes OffilineAutoPilotProfile-<ZtdCorrelationId> instead, spelled exactly that way in the documentation. |
The console walkthrough that produces each surface
To set the portal controls that feed the profile:
- Sign in to the Microsoft Intune admin center.
- Select Devices in the left hand pane.
- Under By platform, select Windows.
- Under Device onboarding, select Enrollment.
- Under Windows Autopilot, select Deployment Profiles.
- Select Create Profile, then select Windows PC.
- On the Basics page, enter a Name and optional Description, then set Convert all targeted devices to Autopilot.
- On the Out-of-box experience (OOBE) page, set Deployment mode, then Join to Microsoft Entra ID as.
- Set Microsoft Software License Terms, Privacy settings, Hide change account options, User account type, Allow pre-provisioned deployment, Language (Region), Automatically configure keyboard and Apply device name template.
- On the Assignments page, choose Selected groups and pick the groups to include or exclude.
- On the Review + Create page, select Create.
To produce the JSON file for the existing-devices scenario, Microsoft documents the conversion through the WindowsAutopilotIntune module. Two details in that command are load-bearing. The profile is written into a per-profile subfolder, and the encoding is forced to ASCII.
Proof it worked: a clean read of all three surfaces
The companion script reads all three surfaces on the local device and prints each documented field with a plain-English explanation. It is read-only, it never writes, and it redacts tenant identifiers unless you explicitly ask for them.
Read the verdict line first, then work upward. If the documented registry count is below six on a device you believe is Autopilot-registered, the profile download is the thing to investigate, and event IDs 100, 160 and 815 will tell you which part failed.
Two of those undocumented values are worth naming because they explain a common false conclusion. CloudAssignedLanguage and CloudAssignedRegion exist in the registry even though there is no matching JSON property, which is why people assume the JSON must carry language settings somewhere. It does not. The service delivered those values over the wire.
One last framing makes the whole mapping easier to remember. The JSON file answers how to make an unregistered machine behave like an Autopilot device once. The Graph object answers what every device in a group should experience. The registry answers what this specific device actually got. Nine properties, roughly twenty Graph properties and six registry values are not three views of one thing. They are three answers to three different questions, and choosing the right surface first is most of the troubleshooting.
References
Microsoft official documentation:
- Windows Autopilot for existing devices — the documented JSON file property table, the file name and encoding requirements, and the precedence rule against a service-assigned profile.
- Configure Windows Autopilot profiles — every portal control on the OOBE page, and the exact click path.
- windowsAutopilotDeploymentProfile resource type — the Graph properties, plus the May 2024 deprecation notes for
language,outOfBoxExperienceSettings,extractHardwareHashandenableWhiteGlove. - outOfBoxExperienceSetting resource type, v1.0 — the current OOBE complex type, with the
userTypeanddeviceUsageTypeenum values. - Windows Autopilot troubleshooting FAQ — the Provisioning diagnostics registry values and the Autopilot event ID catalog.
- Windows Autopilot known issues — why Sysprep
/Generalizedeletes the JSON file, and the ANSI or ASCII encoding failure mode. - Create Windows Autopilot task sequence in Configuration Manager — the task sequence change that stops Sysprep removing the file.
- Speeding up Windows Autopilot for existing devices, archived Microsoft blog — the on-device Provisioning and Autopilot destination folder.
Community deep-dives, each fetched and verified as on topic:
| Author | Article | Why it is worth reading |
|---|---|---|
| Maurice Daly and Sandy Zeng, MSEndpointMgr | Autopilot and the perceived tenant security risk | Walks through what the offline JSON actually enables, field by field, and argues correctly that Autopilot is not a security boundary. |
| Rudy Ooms, call4cloud.nl | Step by step: how Windows retrieves the Autopilot profile | The clearest account of the online path, including how the profile is fetched during OOBE and where it is cached. That is the surface the JSON file stands in for. |
Related posts on this site:
- CloudAssignedOobeConfig Decoded: Which OOBE Screens Your Profile Actually Skipped — the full bit table for the one numeric field in the JSON.
- Autopilot Language, Region and Keyboard: The Profile Skips a Screen, It Does Not Install a Language — what
localeandkeyboardSelectionPageSkippedreally do. - Your Autopilot Profile Edit Didn't Apply: The Cache Nobody Checks — why a corrected profile does not reach an enrolled device.
- The ZTDID: The One Attribute That Proves a Device Is Really Autopilot-Registered — the identifier behind
ZtdCorrelationId.
The companion script Get-AutopilotProfileFieldReport.ps1 is read-only, ASCII-only, and runs on both Windows PowerShell 5.1 and PowerShell 7. It redacts tenant identifiers by default.
Download it from Imran76Awan/Windows-Autopilot-Scripts — no sign-in required. It is read-only: it reports and never changes a device or anything in Intune. Validate it in your own environment before relying on the output.