Skip to main content
The Export Service provides JSON-based export and import of Intune configurations for backup, migration, and tenant-to-tenant copy scenarios.

IExportService

The export interface provides paired methods for each resource type:
  • ExportXxxAsync(single, outputPath, migrationTable) - Export single resource
  • ExportXxxsAsync(collection, outputPath) - Export multiple resources (creates migration table)

Service Lifetime

IExportService is registered as transient (new instance per use).
services.AddIntuneCommanderCore(); // Registers IExportService as transient

var exportService = serviceProvider.GetRequiredService<IExportService>();
See ServiceCollectionExtensions.cs:61 for registration.

Export Format

Each resource type exports to its own subfolder with JSON files named by display name.

Directory Structure

C:\Exports\MyTenant\
  migration-table.json
  DeviceConfigurations\
    Windows 10 Baseline.json
    iOS Restrictions.json
  CompliancePolicies\
    Windows 10 Compliance.json
    Android Compliance.json
  Applications\
    Microsoft Edge.json
    Company Portal.json
  EndpointSecurity\
    Antivirus Policy.json
    Firewall Rules.json
  SettingsCatalog\
    Windows 11 Settings.json
  ...

Folder Names by Resource Type

Resource TypeFolder Name
Device configurationsDeviceConfigurations
Compliance policiesCompliancePolicies
ApplicationsApplications
Endpoint security intentsEndpointSecurity
Administrative templatesAdministrativeTemplates
Settings catalogSettingsCatalog
Enrollment configurationsEnrollmentConfigurations
App protection policiesAppProtectionPolicies
PowerShell scriptsDeviceManagementScripts
Shell scripts (macOS)DeviceShellScripts
Proactive remediationsDeviceHealthScripts
Autopilot profilesAutopilotProfiles
Terms and ConditionsTermsAndConditions
Scope tagsScopeTags
Role definitionsRoleDefinitions
See ExportService.cs:21 for folder path logic.

File Naming

Files are named {DisplayName}.json with invalid filename characters replaced by underscores:
var invalidChars = ['/', '\\', ':', '*', '?', '"', '<', '>', '|', '\0'];
var sanitized = displayName.Split(invalidChars).Join("_");
Collision handling: If a file with the same name exists, the ID is appended:
Windows 10 Policy.json
Windows 10 Policy_abc-123-def.json  # Second policy with same display name
See ExportService.cs:69 for sanitization logic.

Migration Table

The migration table tracks original IDs and remapped IDs for cross-tenant import.

Structure

{
  "entries": [
    {
      "objectType": "DeviceConfiguration",
      "originalId": "abc-123-original",
      "newId": "xyz-789-new",
      "name": "Windows 10 Baseline"
    },
    {
      "objectType": "CompliancePolicy",
      "originalId": "def-456-original",
      "newId": "uvw-012-new",
      "name": "Windows 10 Compliance"
    }
  ]
}

MigrationTable Model

public class MigrationTable
{
    public List<MigrationEntry> Entries { get; set; } = [];
    
    public void AddOrUpdate(MigrationEntry entry);
}

public class MigrationEntry
{
    public string ObjectType { get; set; }   // "DeviceConfiguration", "CompliancePolicy", etc.
    public string OriginalId { get; set; }   // ID from source tenant
    public string? NewId { get; set; }       // ID from destination tenant (set during import)
    public string Name { get; set; }         // Display name for reference
}
See MigrationTable.cs:6 for the complete model.

Export Methods

Device Configurations

Task ExportDeviceConfigurationAsync(
    DeviceConfiguration config, 
    string outputPath, 
    MigrationTable migrationTable, 
    CancellationToken cancellationToken = default);

Task ExportDeviceConfigurationsAsync(
    IEnumerable<DeviceConfiguration> configs, 
    string outputPath, 
    CancellationToken cancellationToken = default);
Example:
var configs = await configService.ListDeviceConfigurationsAsync(ct);

await exportService.ExportDeviceConfigurationsAsync(
    configs, 
    @"C:\Exports\MyTenant", 
    ct);

Console.WriteLine($"Exported {configs.Count} device configurations");
See ExportService.cs:15 for implementation.

Compliance Policies

Task ExportCompliancePolicyAsync(
    DeviceCompliancePolicy policy, 
    IReadOnlyList<DeviceCompliancePolicyAssignment> assignments, 
    string outputPath, 
    MigrationTable migrationTable, 
    CancellationToken cancellationToken = default);

Task ExportCompliancePoliciesAsync(
    IEnumerable<(DeviceCompliancePolicy Policy, IReadOnlyList<DeviceCompliancePolicyAssignment> Assignments)> policies, 
    string outputPath, 
    CancellationToken cancellationToken = default);
Example:
var policies = await complianceService.ListCompliancePoliciesAsync(ct);

// Fetch assignments for each policy
var policiesWithAssignments = new List<(DeviceCompliancePolicy, IReadOnlyList<DeviceCompliancePolicyAssignment>)>();

foreach (var policy in policies)
{
    var assignments = await complianceService.GetAssignmentsAsync(policy.Id, ct);
    policiesWithAssignments.Add((policy, assignments));
}

await exportService.ExportCompliancePoliciesAsync(
    policiesWithAssignments, 
    @"C:\Exports\MyTenant", 
    ct);
Export format:
{
  "policy": {
    "@odata.type": "#microsoft.graph.windows10CompliancePolicy",
    "id": "abc-123",
    "displayName": "Windows 10 Compliance",
    "passwordRequired": true,
    "passwordMinimumLength": 8
  },
  "assignments": [
    {
      "id": "assignment-123",
      "target": {
        "@odata.type": "#microsoft.graph.groupAssignmentTarget",
        "groupId": "group-456"
      }
    }
  ]
}
See ExportService.cs:89 and CompliancePolicyExport.cs for details.

Settings Catalog Policies

Task ExportSettingsCatalogPolicyAsync(
    DeviceManagementConfigurationPolicy policy, 
    IReadOnlyList<DeviceManagementConfigurationSetting> settings, 
    IReadOnlyList<DeviceManagementConfigurationPolicyAssignment> assignments, 
    string outputPath, 
    MigrationTable migrationTable, 
    CancellationToken cancellationToken = default);
Example:
var policies = await catalogService.ListSettingsCatalogPoliciesAsync(ct);

var policiesWithData = new List<(DeviceManagementConfigurationPolicy, IReadOnlyList<DeviceManagementConfigurationSetting>, IReadOnlyList<DeviceManagementConfigurationPolicyAssignment>)>();

foreach (var policy in policies)
{
    var settings = await catalogService.GetPolicySettingsAsync(policy.Id, ct);
    var assignments = await catalogService.GetAssignmentsAsync(policy.Id, ct);
    policiesWithData.Add((policy, settings, assignments));
}

await exportService.ExportSettingsCatalogPoliciesAsync(
    policiesWithData, 
    @"C:\Exports\MyTenant", 
    ct);
See ExportService.cs:557 and SettingsCatalogExport.cs for details.

PowerShell Scripts

Task ExportDeviceManagementScriptAsync(
    DeviceManagementScript script, 
    string outputPath, 
    MigrationTable migrationTable, 
    CancellationToken cancellationToken = default);
Example:
var scripts = await scriptService.ListDeviceManagementScriptsAsync(ct);

await exportService.ExportDeviceManagementScriptsAsync(
    scripts, 
    @"C:\Exports\MyTenant", 
    ct);
Script content (base64-encoded PowerShell) is included in the JSON. See ExportService.cs:1011 for implementation.

Import Service

IImportService

The import service reads exported JSON files and creates resources in the destination tenant with ID remapping.
public interface IImportService
{
    // Read single file
    Task<DeviceConfiguration?> ReadDeviceConfigurationAsync(
        string filePath, 
        CancellationToken cancellationToken = default);
    
    // Read entire folder
    Task<List<DeviceConfiguration>> ReadDeviceConfigurationsFromFolderAsync(
        string folderPath, 
        CancellationToken cancellationToken = default);
    
    // Read migration table
    Task<MigrationTable> ReadMigrationTableAsync(
        string folderPath, 
        CancellationToken cancellationToken = default);
    
    // Import to destination tenant
    Task<DeviceConfiguration> ImportDeviceConfigurationAsync(
        DeviceConfiguration config, 
        MigrationTable migrationTable, 
        CancellationToken cancellationToken = default);
    
    // ... repeated for all resource types
}
See IImportService.cs:6 for the complete interface.

Import Workflow

1. Read migration table
var importService = new ImportService(graphClient, groupResolver);
var migrationTable = await importService.ReadMigrationTableAsync(
    @"C:\Exports\SourceTenant", 
    ct);
2. Read exported files
var configs = await importService.ReadDeviceConfigurationsFromFolderAsync(
    @"C:\Exports\SourceTenant\DeviceConfigurations", 
    ct);
3. Import to destination tenant
foreach (var config in configs)
{
    // Import creates the resource and updates migration table with new ID
    var imported = await importService.ImportDeviceConfigurationAsync(
        config, 
        migrationTable, 
        ct);
    
    Console.WriteLine($"Imported: {config.DisplayName}");
    Console.WriteLine($"  Original ID: {config.Id}");
    Console.WriteLine($"  New ID: {imported.Id}");
}
4. Save updated migration table
await exportService.SaveMigrationTableAsync(
    migrationTable, 
    @"C:\Exports\SourceTenant", 
    ct);

ID Remapping

During import, the service:
  1. Strips read-only properties (Id, CreatedDateTime, LastModifiedDateTime)
  2. Remaps group assignment IDs using the migration table
  3. Creates the resource in the destination tenant
  4. Captures the new ID and updates the migration table
Example:
// Original assignment in exported JSON
{
  "target": {
    "@odata.type": "#microsoft.graph.groupAssignmentTarget",
    "groupId": "source-group-123"  // Group ID from source tenant
  }
}

// After import (group ID remapped to destination tenant)
{
  "target": {
    "@odata.type": "#microsoft.graph.groupAssignmentTarget",
    "groupId": "dest-group-789"  // Remapped to destination group
  }
}
See ImportService.cs for remapping logic.

Export All Resources

Example of exporting all supported resource types:
public async Task ExportAllAsync(
    string tenantId,
    string outputPath,
    CancellationToken ct)
{
    var exportService = _serviceProvider.GetRequiredService<IExportService>();
    
    // Device configurations
    var configs = await _configService.ListDeviceConfigurationsAsync(ct);
    await exportService.ExportDeviceConfigurationsAsync(configs, outputPath, ct);
    
    // Compliance policies
    var policies = await _complianceService.ListCompliancePoliciesAsync(ct);
    var policiesWithAssignments = new List<(DeviceCompliancePolicy, IReadOnlyList<DeviceCompliancePolicyAssignment>)>();
    foreach (var policy in policies)
    {
        var assignments = await _complianceService.GetAssignmentsAsync(policy.Id, ct);
        policiesWithAssignments.Add((policy, assignments));
    }
    await exportService.ExportCompliancePoliciesAsync(policiesWithAssignments, outputPath, ct);
    
    // Applications
    var apps = await _appService.ListApplicationsAsync(ct);
    var appsWithAssignments = new List<(MobileApp, IReadOnlyList<MobileAppAssignment>)>();
    foreach (var app in apps)
    {
        var assignments = await _appService.GetAssignmentsAsync(app.Id, ct);
        appsWithAssignments.Add((app, assignments));
    }
    await exportService.ExportApplicationsAsync(appsWithAssignments, outputPath, ct);
    
    // Settings catalog
    var catalogPolicies = await _catalogService.ListSettingsCatalogPoliciesAsync(ct);
    var catalogWithData = new List<(DeviceManagementConfigurationPolicy, IReadOnlyList<DeviceManagementConfigurationSetting>, IReadOnlyList<DeviceManagementConfigurationPolicyAssignment>)>();
    foreach (var policy in catalogPolicies)
    {
        var settings = await _catalogService.GetPolicySettingsAsync(policy.Id, ct);
        var assignments = await _catalogService.GetAssignmentsAsync(policy.Id, ct);
        catalogWithData.Add((policy, settings, assignments));
    }
    await exportService.ExportSettingsCatalogPoliciesAsync(catalogWithData, outputPath, ct);
    
    // PowerShell scripts
    var scripts = await _scriptService.ListDeviceManagementScriptsAsync(ct);
    await exportService.ExportDeviceManagementScriptsAsync(scripts, outputPath, ct);
    
    // ... continue for all resource types
    
    Console.WriteLine($"Export complete: {outputPath}");
}

Use Cases

Backup

Export all configurations to a timestamped folder for disaster recovery:
var timestamp = DateTime.Now.ToString("yyyy-MM-dd_HHmmss");
var backupPath = $@"C:\Backups\{tenantName}_{timestamp}";

await ExportAllAsync(tenantId, backupPath, ct);

Tenant Migration

Move configurations from one tenant to another:
  1. Export from source tenant
  2. Create matching groups in destination tenant (manually or via script)
  3. Update migration table with group ID mappings
  4. Import to destination tenant with ID remapping

Configuration Templates

Create reusable configuration templates:
  1. Build “gold” configurations in a lab tenant
  2. Export to version control (Git)
  3. Import to production tenants as needed

Disaster Recovery

Restore deleted policies from backup:
  1. Keep periodic exports
  2. On accidental deletion, read from backup
  3. Import to recreate the deleted resource

Limitations

Not Exported

  • Application binaries: Win32 app .intunewin packages are not exported (only metadata)
  • Certificates: Certificate files embedded in profiles are not extracted
  • Assignment filters: Filter definitions must be recreated manually
  • Conditional Access policies: Read-only (not exported to prevent lockout)

Manual Steps After Import

  • Group creation (groups are referenced by ID but not created)
  • Certificate upload (for SCEP/VPN profiles)
  • Win32 app re-upload (binary content)
  • Assignment filter recreation

Next Steps

API Overview

Return to API architecture overview

Graph Services

Explore Graph API service interfaces

Build docs developers (and LLMs) love