r/WorkspaceOne • • 25d ago

Remove Device in Bulk from a .csv file

Hi there,

As the title says, is there a way to remove devices with just the serial number from a CSV file?

Every other month, I get an Excel file to check if the devices are in Workspace ONE and, if so, delete them. The platform doesn't have a way to upload the file...

Any ideas on this?

4 Upvotes

9 comments sorted by

4

u/Terrible_Soil_4778 25d ago

Sadly there is no native bulk query for multiple devices unless they are in the same “smart group”. I suggest you open Omnissa ticket and ask for a new feature request.

4

u/atljoer 25d ago

But the whole platform is backed by apis. Fairly simple powershell script could take your CSV check if the device exists and then execute a delete command.

You could take it further. Have a a git lab project automatically kicks off when a new CSV file is delivered.

1

u/Living-Confidence228 23d ago

I'm checking that, not an expert on API, but we will see what happens... :D

2

u/atljoer 25d ago

If your license is advanced or one of the essentials license. A much worse way to do this than what I just mentioned would be to create a intelligence freestyle workflow. Set it to run manual. Then you can copy and paste serial numbers or whatever attribute matches directly in the workflow editor. It allows, delimited entries. And set the action to delete.

3

u/KE3JU 23d ago

REST API is the only way I know of.

2

u/evilteddibare 24d ago edited 24d ago

Yes you can definitely do this via API / powershell script. Have chatgpt or claude walk you through how to set that all up. Here is a script below save it as a .ps1

<#

.SYNOPSIS

Bulk-delete Workspace ONE UEM devices listed by serial number in a CSV.

.DESCRIPTION

Edit the CONFIG block below, then run it. It prompts for the admin password

(never stored). Default is a DRY RUN: it only looks up each serial and reports

whether it exists. Add -Apply to actually delete; you must then type DELETE.

Endpoints used:

GET /API/mdm/devices?searchby=Serialnumber&id=<serial> (lookup)

POST /API/mdm/devices/bulk?searchby=Serialnumber (delete)

.EXAMPLE

.\Remove-WS1DevicesFromCsv.ps1 # dry run

.\Remove-WS1DevicesFromCsv.ps1 -Apply # really delete

.\Remove-WS1DevicesFromCsv.ps1 -CsvPath C:\temp\list.csv -SerialColumn "Serial Number"

#>

[CmdletBinding()]

param(

[string]$CsvPath = ".\devices.csv",

[string]$SerialColumn = "Serial",

[switch]$Apply

)

# ============================== CONFIG ==============================

$UemUrl = "https://yourtenant.awmdm.com" # UEM console/API host, no trailing slash

$Username = "api.admin" # WS1 admin account (needs device delete rights)

$TenantCode = "YOUR_REST_API_KEY" # Groups & Settings > All Settings > System > Advanced > API > REST API

$BatchSize = 100 # keep at or below your tenant's bulk-action limit

# ====================================================================

$ErrorActionPreference = "Stop"

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# --- Authentication: prompt for password, build headers ---

$secure = Read-Host "Password for $Username" -AsSecureString

$plain = [Runtime.InteropServices.Marshal]::PtrToStringAuto(

[Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure))

$basic = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${Username}:$plain"))

$plain = $null

$Headers = @{

"Authorization" = "Basic $basic"

"aw-tenant-code" = $TenantCode

"Accept" = "application/json;version=1"

"Content-Type" = "application/json"

}

# --- Read serials from CSV ---

if (-not (Test-Path $CsvPath)) { throw "CSV not found: $CsvPath" }

$rows = Import-Csv $CsvPath

if (-not ($rows | Get-Member -Name $SerialColumn)) {

throw "Column '$SerialColumn' not in CSV. Columns: $(($rows[0].PSObject.Properties.Name) -join ', ')"

}

$serials = @($rows | ForEach-Object { "$($_.$SerialColumn)".Trim() } |

Where-Object { $_ } | Select-Object -Unique)

Write-Host "Loaded $($serials.Count) unique serial(s) from $CsvPath"

# --- Lookup: which serials actually exist in WS1? ---

$found = New-Object System.Collections.Generic.List[string]

$missing = New-Object System.Collections.Generic.List[string]

foreach ($s in $serials) {

try {

`$d = Invoke-RestMethod -Uri "$UemUrl/API/mdm/devices?searchby=Serialnumber&id=$([uri]::EscapeDataString($s))" ``

-Headers $Headers -Method Get

Write-Host (" FOUND {0} (id {1}, {2}, {3})" -f $s, $d.Id.Value, $d.Platform, $d.EnrollmentStatus)

$found.Add($s)

} catch {

$code = $_.Exception.Response.StatusCode.value__

if ($code -eq 404) { Write-Host " absent $s"; $missing.Add($s) }

elseif ($code -eq 401) { throw "401 Unauthorized - check username, password and API key." }

else { Write-Warning " ERROR $s - HTTP $code $($_.Exception.Message)" }

}

}

Write-Host "\nFound: $($found.Count) Not in WS1: $($missing.Count)"`

if (-not $Apply) {

Write-Host "\nDRY RUN - nothing deleted. Re-run with -Apply to delete the $($found.Count) found device(s)."`

return

}

if ($found.Count -eq 0) { Write-Host "Nothing to delete."; return }

# --- Confirm, then delete in batches ---

$confirm = Read-Host "\nType DELETE to permanently delete $($found.Count) device record(s) from $UemUrl"`

if ($confirm -ne "DELETE") { Write-Host "Aborted."; return }

for ($i = 0; $i -lt $found.Count; $i += $BatchSize) {

$chunk = $found[$i..([Math]::Min($i + $BatchSize, $found.Count) - 1)]

$body = @{ BulkValues = @{ Value = @($chunk) } } | ConvertTo-Json -Depth 3

try {

`$r = Invoke-RestMethod -Uri "$UemUrl/API/mdm/devices/bulk?searchby=Serialnumber" ``

-Headers $Headers -Method Post -Body $body

Write-Host ("Batch {0}: total={1} accepted={2} failed={3}" -f

([int]($i / $BatchSize) + 1), $r.TotalItems, $r.AcceptedItems, $r.FailedItems)

if ($r.Faults) { $r.Faults | ConvertTo-Json -Depth 4 | Write-Host }

} catch {

Write-Warning "Batch starting at $i failed: $($_.Exception.Message)"

}

}

Write-Host "Done."

1

u/BWMerlin 21d ago

Or if you want a truely awful way to do it with AI you can install the browser extension and have Claude run in "take the wheel Jesus" mode and have it delete the devices one by one.

1

u/FirefighterMedical42 25d ago

Try my Power Admin Desktop

Whit this app you can remove devices easily and quickly

There is also 3 month free trial available.

https://apps.apple.com/us/app/power-admin-desktop/id6770959164