Skip to content

Removing inactive systems

When users decommission devices or leave the organisation, their enrolled systems can linger in the portal indefinitely. This script uses the Enclave API to automatically remove systems that haven't connected for a configurable number of days, keeping your enrolled system list clean without manual intervention.

This is particularly useful for MSPs managing multiple customer tenants, where keeping track of individual device lifecycle events across every organisation isn't practical.

Tip

You can invoke the Enclave API from your scripting language of choice. Check out the OpenAPI specification for individual endpoint details.

Prerequisites

How it works

The script pages through the GET /org/{orgId}/systems endpoint, including disabled systems. For each system, it checks the lastSeen timestamp - or the enrolledAt timestamp if the system has never connected. Any system that hasn't been seen within the configured threshold (90 days by default) is removed via the DELETE /org/{orgId}/systems/{systemId} endpoint.

A test mode lets you preview which systems would be removed before making any changes.

The script

Save the following script as a .ps1 file.

  • -orgId, the organisation to run queries against.
  • -apiKey, the Enclave API key. Set the ENCLAVE_API_KEY environment variable as an alternative.
  • -maxInactiveDays, the maximum number of inactive days to allow before a system is removed. Defaults to 90.
  • -test, previews which systems would be removed without making any changes.
Param(
    [Parameter(Mandatory=$true)]
    [string]$orgId,

    [Parameter()]
    [string]$apiKey = "",

    [Parameter()]
    [ValidateRange(1, [int]::MaxValue)]
    [int]$maxInactiveDays = 90,

    [Parameter()]
    [switch]$test = $false
)

$ErrorActionPreference = "Stop"

if ($apiKey -eq "")
{
    $apiKey = $env:ENCLAVE_API_KEY
}

if ($apiKey -eq "")
{
    Write-Error "No API key provided; either specify the 'apiKey' argument, or set the ENCLAVE_API_KEY environment variable."
    return;
}

# Attach our api key to each request.
$headers = @{Authorization = "Bearer $apiKey"}
$contentType = "application/json";

$uri = "https://api.enclave.io/org/$orgId/systems?per_page=50&include_disabled=true";
$currentDate = Get-Date

# Begin our loop through the pages of systems.
do {

    $systems = Invoke-RestMethod -ContentType $contentType -Uri $uri -Headers $headers

    foreach ($system in $systems.items) {    
        # Get the lastSeen field, or use the enrolement date if the system has never connected.
        $lastSeenText = if ($system.lastSeen) { $system.lastSeen } else { $system.enrolledAt }
        $lastSeen = Get-Date $lastSeenText;

        # How long between today and the lastSeen date?
        $age = $currentDate - $lastSeen;

        # Anything not seen in the configured number of days will be removed.
        if ($age.TotalDays -gt $maxInactiveDays)
        {
            "Removing $($system.hostname) ($($system.systemId)) after $([math]::Round($age.TotalDays)) days of inactivity"

            if (!$test)
            {
                # Invoke our API to delete the system from the organisation.
                Invoke-RestMethod -Uri "https://api.enclave.io/org/$orgId/systems/$($system.systemId)" -Headers $headers -Method Delete | Out-Null
            }
        }
    }

    # Get the url to the next page of systems.
    $uri = $systems.links.next;

} while($uri);

Usage

Preview which systems would be removed (no changes are made):

.\cleanup-inactive-systems.ps1 -orgId "b87f2e1a3d9f" -apiKey $env:ENCLAVE_API_KEY -test

Remove systems inactive for more than 60 days:

.\cleanup-inactive-systems.ps1 -orgId "b87f2e1a3d9f" -apiKey $env:ENCLAVE_API_KEY -maxInactiveDays 60

Scheduling

To keep enrolled systems tidy automatically, run this script on a recurring schedule. Windows Task Scheduler, your RMM platform, or Azure Functions all work well. Set the ENCLAVE_API_KEY environment variable on the host so the scheduled task doesn't need the key in its command line arguments.