Thumbnail Moving sites to cold storage using code and Microsoft 365 Archive

Moving sites to cold storage using code and Microsoft 365 Archive

Moving sites to cold storage is a very relevant topic these days. For many companies the amount of data stored in SharePoint has quickly grown beyond the storage quota included with Microsoft 365 licenses. Growing beyond that means higher storage costs. Archiving sites that aren’t actively used is a way to help get the costs down. This post highlights the various means I found to archive SharePoint sites programmatically with Microsoft 365 Archive.

Setting up auth is outside of the scope of this post, but you’ll need to think about the following when executing any of the code examples below:

When running in the context of a signed in user you’ll need an Entra application with delegated AllSites.FullControl permissions on the SharePoint resource. The signed in user needs to have the SharePoint administrator (or Global administrator) role.

When running in the context of an application (Also called app only or workload identity), you’ll need the rather heavy Application permission scope Sites.FullControl.All on the SharePoint resource, because you’ll be working with the tenant administration site.

When using a .NET app to archive SharePoint sites, we can use CSOM through the nuget package “Microsoft.SharePointOnline.CSOM”. (Or for example the open source package “PnP.Framework”.)

Using the following code you’ll be able to archive sites:

// You require the following using statement.
using Microsoft.Online.SharePoint.TenantAdministration;

// You'll need to create a ClientContext based on the tenant administration site. 
// This is outside of the scope of this post, but for example:
//      var authManager = new PnP.Framework.AuthenticationManager(<some parameters>);
//      using var clientContext = authManager.GetContext("https://contoso-admin.sharepoint.com"); 

var tenant = new Tenant(clientContext);
var operation = tenant.ArchiveSiteByUrl("https://contoso.sharepoint.com/sites/sales");

clientContext.Load(operation, i => i.IsComplete);            
clientContext.ExecuteQuery();

// The following is really only needed if you want to make sure the code waits for the completion of the operation. 
while (!operation.IsComplete)
{
    System.Threading.Thread.Sleep(1000);
    operation.RefreshLoad();
    clientContext.ExecuteQuery();
}

In my tests, sites were almost instantly archived, which means we could also skip polling for the completion of the operation. However, with larger sites containing actual data it could potentially take longer, so I’ve included the example anyway.

Alternative methods that can be used are UnarchiveSiteByUrl, ArchiveSiteById and UnarchiveSiteById. With the last two you’ll need the SharePoint Site ID, which is a GUID that can be retrieved from the Site object.

You can also use the SharePoint REST API. However, this is not an API that’s officially supported for public use, so don’t come calling me when the endpoint changes 😅.

The HTTP call to archive the site is quite simple:

POST https://contoso-admin.sharepoint.com/_api/Microsoft_Online_SharePoint_TenantAdministration_Tenant/ArchiveSiteById('112132a9-0ad3-4b53-ab54-9707108ac685')

Unarchiving the site is as easy:

POST https://contoso-admin.sharepoint.com/_api/Microsoft_Online_SharePoint_TenantAdministration_Tenant/UnarchiveSiteById('112132a9-0ad3-4b53-ab54-9707108ac685')

Of course the GUID that is used in the examples is just a dummy GUID. On this API you’ll need the Site Id, which you can get by calling the following endpoint on the site that you want to archive: /_api/site?$select=Id.

The endpoints return an SpoOperation JSON object, just like the CSOM variants do. I did not do research into how to poll those for completion of the operation though.

❗ There’s currently no endpoint to archive sites by URL.

You can use scripting for automation purposes as well. For example using the CLI for Microsoft 365, which is a popular open source commandline tool for managing your Microsoft 365 Tenant. This tool can also be run in Azure Functions, bringing timely executed automation operations within your grasp.

Archiving and unarchiving sites can be done as follows:

m365 spo tenant site archive --url "https://contoso.sharepoint.com/sites/sales" --force

m365 spo tenant site unarchive --url "https://contoso.sharepoint.com/sites/sales" --force

Of course, PnP PowerShell needs to be mentioned here as well, as another popular tool for managing your Microsoft 365 Tenant. PnP PowerShell can be easily incorporated in PowerShell scripts running in the cloud, like Azure Automation Runbooks or Azure Functions.

Archiving and Reactivating sites using PnP PowerShell can be done as follows:

Set-PnPSiteArchiveState "https://contoso.sharepoint.com/sites/sales" -ArchiveState Archived -Force

Set-PnPSiteArchiveState "https://contoso.sharepoint.com/sites/sales" -ArchiveState Active -Force

Using PowerShell scripting with Microsofts own PowerShell tooling is of course available as well, using the following script.

Archiving and Reactivating sites using PnP PowerShell can be done as follows:

Set-SPOSiteArchiveState "https://contoso.sharepoint.com/sites/sales" -ArchiveState Archived -Confirm

Set-SPOSiteArchiveState "https://contoso.sharepoint.com/sites/sales" -ArchiveState Active -Confirm

Archiving and reactivating sites with Microsoft 365 Archive is actually quite easy. I’m hoping the examples will help you get started quickly! If you’ve got any questions, do drop me a DM!

🚀 Happy coding!!


sharepoint m365-archive
Support me by sharing this

More

More blogs

Updating and using the property bag in 2024
Updating and using the property bag in 2024

It's an old, but useful feature, and impacted by the change Microsoft is pushing with NoScript sites. Or is it? Here's how to use the property bag in 2024.

Read more
Extending Microsoft 365 with custom retention controls - Part 2
Extending Microsoft 365 with custom retention controls - Part 2

New release of a small Microsoft 365 extension I've developed to view & manage retention controls.

Read more
SPFx and the potential pitfall of partial page navigation
SPFx and the potential pitfall of partial page navigation

How you need to take partial page navigation into account when building SPFx customizations.

Read more

Thanks

Thanks for reading

Thanks for reading my blog, I hope you got what you came for. Blogs of others have been super important during my work. This site is me returning the favor. If you read anything you do not understand because I failed to clarify it enough, please drop me a post using my socials.


Warm regards,
Martin

Microsoft MVP | Microsoft 365 Architect

Microsoft MVP horizontal