Table of Contents
Archive and Unarchive Files with Graph API Calls
Recently, I covered how file-level archiving works for SharePoint Online and mentioned that the Microsoft Graph APIs for SharePoint support listing archived files and the archive and unarchive actions. In this article, I show how to use the APIs. A mixture of cmdlets from the Microsoft Graph PowerShell SDK (V2.35.1) and Graph requests are used because some of the functionality is not yet available through SDK cmdlets. This might change by the time you read this article.
First, let’s list the files in a drive (document library) to find any that might be archived. Two approaches are available: we can interrogate the drive or the underlying list (SharePoint Online is built from lists).
The Drive Approach to Finding Archived Files
This example shows how to create a Graph request against the beta drives API to find all items in the root of a drive. If you’re not familiar with using the Graph to navigate SharePoint Online drives, many of the concepts are covered in this article about creating a report of files in a document library. In this case, the code only retrieves files from the root folder and does not iterate through any child folders.
First, find the drive and root identifiers for the site we want to use and then build a request to find child items in the drive root:
$Drive = Get-MgSiteDefaultDrive -SiteId $Site.Id
$Root = Get-MgDriveRoot -DriveId $Drive.Id
$Uri = ("https://graph.microsoft.com/beta/drives/{0}/items/{1}/children" -f $Drive.Id, $Root.id)
[array]$Data = Invoke-MgGraphRequest -Uri $Uri -Method Get -OutputType PsObject | Select-Object -ExpandProperty Value
The data returned includes archived and unarchived files. It also includes folders. A client-side filter finds the archived files by looking for files with the archive status set to something other than null:
[array]$ArchivedFiles = $Data | Where-Object {$null -ne $_.file.mimetype -and $null -ne $_.file.archiveStatus}
We can now list the files found by the filter:
$ArchivedFiles | Select-Object @{ n = 'Name'; e = { $_.Name }}, @{ n = "Archive Status"; e = {$_.File.ArchiveStatus}}, @{ n = 'DriveItemId'; e = { $_.Id }}
Figure 1 shows the result:

The List Approach to Finding Archived Files
Most people will list SharePoint Online files by navigating through a drive because it’s the simplest and most straightforward method. However, it’s possible to find archived files in the list used for the document library. The first step is to select the list for the document library:
$List = Get-MgSiteList -SiteId $Site.Id | Where-Object {$_.displayName -eq 'Documents'}
The next step fetches the items from the list, expanding a hidden field called FileArchiveStatus:
[array]$Items = Get-MgSiteListItem -SiteId $Site.Id -ListId $List.Id -All -ExpandProperty "driveItem,fields(`$select=_FileArchiveStatus)"
Now we can find items where a value exists in the FileArchiveStatus field:
[array]$ArchivedItems = $Items | Where-Object {$_.Fields.AdditionalProperties['_FileArchiveStatus']}
Examining the list items won’t tell us much, so to expose the information, we go through the array of filtered items and extract and format the name, archive status, and identifier properties:
$ArchivedItems | Select-Object @{ n = 'Name'; e = { $_.DriveItem.Name } },
@{ n = 'Archive Status'; e = { $_.Fields.AdditionalProperties['_FileArchiveStatus'] } },@{ n = 'DriveItemId'; e = { $_.DriveItem.Id }
}
Name Archive Status DriveItemId
---- ------------- -----------
Travel Plans and Commitments.docx fullyArchived 01YRXQVKDSUUG6CT3SMVAKZKE7EJTW4PNI
ESPC19-Speaker-Information.pdf fullyArchived 01YRXQVKE7UNT6DCIXBVC35KGLVSYRHHDY
Ultra Confidential 12 Feb 2022.docx fullyArchived 01YRXQVKGDUZ4PKSH4HFGIQ2DOG3C7BOWV
TasksTemporary_.xlsx fullyArchived 01YRXQVKAWGQT6OY4FXRBJ6SZ7HUAOOMIO
The list approach works, but the drive method is easier to understand.
Archive Drive Items
Now that we know how to list archived files, let’s move on to how to use the archive and unarchive actions. One of the advantages of file-level archiving is that it supports selective archival of files that you want to keep but don’t want people to use. As an example, let’s find files that have not been modified in over two years and archive those files.
First, we set a date to check against use the drive method to find the unarchived files.
$CheckDate = (Get-Date).AddDays(-730)
[array]$UnarchivedFiles = $Data | Where-Object {$null -ne $_.file.mimetype -and $null -eq $_.file.archiveStatus}
A simple loop through the set of unarchived files finds any that haven’t been modified for over two years. If any such files are found, we run an archive request:
ForEach ($File in $UnarchivedFiles) {
If ($File.LastModifiedDateTime -le $CheckDate) {
Write-Host "Archiving" $File.Name
$Uri = ("https://graph.microsoft.com/beta/drives/{0}/items/{1}/archive" -f $Drive.Id, $File.Id)
Try {
Invoke-MgGraphRequest -Method POST -Uri $Uri -OutputType PSobject -ErrorAction Stop
Write-Host ("File {0} is now archived" -f $File.Name) -ForegroundColor Yellow
} Catch {
Write-Host ("Failed to archive file {0}" -f $File.Name) -ForegroundColor Red
}
}
}
Unarchive a Drive Item
We might make a mistake and need to unarchive a file. Unarchiving a file can be immediate, or it can take up to 24 hours before Microsoft 365 Archive can rehydrate the file by fetching it back from cold storage. In either case, the same code works. Here’s how to run an unarchive request using a drive item identifier that’s been chosen from a list of archived files:
$DriveItemID = '01YRXQVKE7UNT6DCIXBVC35KGLVSYRHHDY'
$Uri = ("https://graph.microsoft.com/beta/drives/{0}/items/{1}/unarchive" -f $Drive.Id, $DriveItemId)
Try {
$Response = Invoke-MgGraphRequest -Method POST -Uri $Uri -OutputType PSobject -ErrorAction Stop
} Catch {
Write-Host "Failure to unarchive file"
}
If the file is reactivated instantly, no response is returned. If reactivation requires rehydration, the response includes:
{
"archiveStatus": "reactivating"
}
Reporting the Storage Used for File-level Archiving
As a bonus, you might like to report the storage used for file-level archiving in a site. SharePoint Online makes the information available as a property returned by the Get-SPOSite cmdlet. For example:
$SiteId = "https://office365itpros.sharepoint.com/sites/confidentialstuff"
Get-SPOSite -Identity $SiteId | Select-Object @{ n = 'Archived Files Disk Space (MB)'; e = { $_.ArchivedFileDiskUsed/1MB } }
Archived Files Disk Space (MB)
------------------------------
16.65
Dealing with file-level archiving of SharePoint Online files through the Graph APIs isn’t difficult. At least, it’s not once the technique is explained.
Need help to write and manage PowerShell scripts for Microsoft 365, including Azure Automation runbooks? Get a copy of the Automating Microsoft 365 with PowerShell eBook, available standalone or as part of the Office 365 for IT Pros eBook bundle.