Empirum REST API Technical Reference and Implementation
Explore the Empirum REST API for seamless integration, efficient data handling, and enhanced application performance.
Table of Contents
Overview
The Empirum REST API provides programmatic access to Matrix42 Empirum. Customers and partners can use it to integrate Empirum with third-party systems (ITSM, CMDB, SIEM, reporting platforms, orchestration tools) and to automate recurring administrative tasks such as software rollouts, reinstallations, patch remediation, inventory exports and fleet health checks.
This article explains how to connect to the API, how authentication and authorization work, which conventions apply to all endpoints, and how to automate common tasks with PowerShell.
Typical Use Cases
- Synchronize Empirum computers and hardware inventory into a CMDB or asset management system.
- Trigger software deployments, reinstallations or uninstallations from an ITSM workflow or self-service portal.
- Import software packages from the PackageStore as part of a packaging pipeline.
- Build dashboards and reports on failed deployments, missing patches, stale agents, low disk space, BitLocker status or battery wear.
- Orchestrate patch management: approve patches, maintain PM groups and start emergency patching for critical vulnerabilities.
- Maintain deployment groups, group membership and Empirum variables from an external source of truth.
Prerequisites
- Matrix42 Empirum with the Empirum REST API service installed and configured on the Empirum Server using Empirum DBUtil (see Installing and Configuring the REST API below), reachable over HTTPS from the system that calls the API.
- An API principal (client credentials) with the roles required for the planned tasks. The initial API principal is created in Empirum DBUtil; further principals can be created in the web-based principal management (
/admin) or through the API by a principal with the roleadmin.manage. - For the PowerShell examples: PowerShell 7.x is recommended. Windows PowerShell 5.1 works for most examples, but does not support
-SkipCertificateCheck. - The server certificate of the REST API host must be trusted by the calling system, or the certificate check must be handled explicitly (test environments only).
Installing and Configuring the REST API
The Empirum REST API runs as a service on the Empirum Server. It is installed and configured with Empirum DBUtil, in the same way as all other Empirum services.
Install the Service
- Log on to the Empirum Server with an account that has administrative rights for Empirum.
- Start Empirum DBUtil.
- Install the Empirum REST API service in the same way as the other Empirum services and complete its configuration.
- Verify that the service is running and reachable, for example with
GET /healthfrom the system that will call the API.
Create the Initial API Principal
Empirum DBUtil provides a dedicated menu item to create the initial API principal. Use it to create the first principal with the role admin.manage. This principal can then create and manage all further principals, either in the web-based principal management at /admin or through the Admin endpoints of the API (see Authentication and Authorization).
Use the initial principal only for administration. Create separate, least-privilege principals for each integration or script instead of using the administrative principal in automation.
Connecting to the API
Base URL
All endpoints are relative to the base URL of your REST API host. The port depends on your installation (the reference installation uses port 5443):
https://empirum-api.contoso.local:5443/Use GET /health (no authentication) to check that the service is reachable, and GET /api/system to read the Empirum database version, patch management catalog metadata and the REST API assembly version.
API Versioning
Every operation accepts the optional HTTP header api-version. The current and default value is 1. Send the header explicitly in integrations so that your scripts keep working when later API versions are introduced.
api-version: 1Interactive Documentation
The API is described by an OpenAPI 3 specification (Matrix42.Empirum.RestApi | v1). You can import the specification into tools such as Postman, Insomnia or any OpenAPI-compatible client generator to explore endpoints and generate client code.
Authentication and Authorization
All endpoints (except /health and the token endpoint) require a JSON Web Token (JWT) in the Authorization header:
Authorization: Bearer eyJhbGciOiJ...Step 1: Create an API Principal
The REST API knows two kinds of principals:
- Local principals – client credentials (client ID and secret) managed directly in the REST API. Recommended for scripts, service accounts and partner integrations.
- Identity Provider principals – clients or users from an external identity provider, identified by subject type, subject ID and issuer.
The initial principal is created in Empirum DBUtil (see Create the Initial API Principal). With this principal, or any other principal with the role admin.manage, an administrator creates additional principals either in the web-based principal management or through the API.
Web-Based Principal Management
The REST API service hosts a web-based principal management at the path /admin. No additional installation is required. Open it in a browser on any system that can reach the API service:
https://empirum-api.contoso.local:5443/adminSign in with a principal that has the role admin.manage. In the web interface, administrators can:
- Create local principals (client credentials) and copy the generated client secret.
- Manage Identity Provider principals (clients and users).
- Assign and change roles, descriptions and expiry dates.
- Revoke, restore and delete principals.
The web-based principal management uses the same principal store as the Admin endpoints of the API. Changes made in one are immediately visible in the other.
Principal Management via API
To automate principal management, create local principals with POST /api/admin/local-principals:
{
"description": "ServiceNow integration - software rollout",
"roles": [ "computer.read", "package.read", "group.read", "group.write", "activation.execute" ],
"expiresAtUtc": "2027-09-30T00:00:00Z"
}The response contains the clientId and the plaintextKey (client secret).
Whether created in the web interface or through the API, store the client secret (plaintextKey) immediately in a secure location (for example a password vault or the PowerShell SecretManagement module). Treat it like a password. Never hard-code it in scripts or store it in source control.
Local principals can be updated (PUT /api/admin/local-principals/{id}), revoked or restored (PATCH /api/admin/local-principals/{id}/revoke) and deleted (DELETE /api/admin/local-principals/{id}). GET /api/admin/roles returns all assignable roles with descriptions.
Step 2: Request an Access Token
Request a short-lived token with POST /api/auth/token. The body is sent as application/x-www-form-urlencoded with the fields grant_type, client_id and client_secret (OAuth 2.0 client credentials flow, RFC 6749).
POST /api/auth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&client_id=YOUR-CLIENT-ID&client_secret=YOUR-SECRETResponse:
{
"access_token": "eyJhbGciOiJ...",
"token_type": "Bearer",
"expires_in": 3600
}Tokens are short-lived. Evaluate expires_in (seconds) and request a new token shortly before it expires instead of requesting a token for every call. The PowerShell helper functions below handle this automatically.
Roles
Each operation requires a specific role, listed as "Requires role" in the operation description of the OpenAPI specification. Roles follow the pattern {entity}.{read|write} for data access and {action}.execute for actions. Grant each principal only the roles it needs.
| Role | Grants access to |
|---|---|
computer.read |
Computers, inventory, issues, health, deployment and patch status, distribution history, tasks, backend queues, depot sync jobs |
computer.write |
Create, update and delete computers; set computer variables |
group.read |
Deployment groups, members, assignments, distribution options, depot servers, group variables |
group.write |
Create, update and delete groups; assign computers, packages, PXE boot images, OS image SKUs, Agent Templates, Language Packs, Variable Configurations and Software Classes |
package.read |
Software packages, package status, Agent Templates, OS imports, Language Packs, PXE boot images, Software Classes, Variable Configurations and Variable Definitions |
package.write |
Package import, hash generation, "Ready to Install" (operational) flag |
activation.execute |
Activate and deactivate computers and groups, software uninstall, trigger depot sync |
reinstall.execute |
Trigger and cancel enforced software reinstalls |
scan.execute |
Force inventory or patch rescans |
reboot.execute |
Request a reboot via Silent Reboot Logic (SRL) |
pm.read |
Patch catalog, PM groups, their products, patches and assignments |
pm.write |
Create PM groups, add or remove products and patches, assign PM groups to tree nodes |
pm.approve |
Approve and revoke patches and products |
pm.execute |
Start and remove emergency patching |
admin.manage |
Principal and role administration |
API Conventions
Identifiers
-
Computers are identified by their Empirum
client_id(integer), for example/api/computer/4711. - Groups, packages, Agent Templates, OS images and Language Packs are identified by GUIDs.
- Tracking IDs (GUIDs) are returned by asynchronous operations such as package import and deployment tasks.
If you only know a hostname, serial number, MAC address or UUID, resolve the client_id first with POST /api/computer/search.
Paging
List and search endpoints are paged with the query parameters skip (number of items to skip) and top (page size). Paged responses have the following structure:
{
"items": [ ... ],
"skip": 0,
"top": 100,
"totalCount": 2350,
"hasMore": true
}Continue requesting pages with an increased skip value as long as hasMore is true.
List vs. Search Endpoints
Most resources offer a GET list endpoint with simple query filters and a POST .../search endpoint that accepts a JSON filter object. Search filters combine all provided criteria; text criteria are substring matches. Example for POST /api/computer/search:
{
"domain": "CONTOSO",
"osName": "Windows 11",
"manufacturer": "Dell",
"lastSeenAfter": "2026-09-01T00:00:00Z"
}Timestamps
All timestamps are ISO 8601 and UTC (for example 2026-09-25T08:30:00Z). Convert to local time in your client if required.
Asynchronous Operations
Empirum executes many actions asynchronously. An API call records the intent (for example an activation or a reinstall group); the Empirum agent executes it at its next contact. Use the following endpoints to follow up:
| Operation | How to track it |
|---|---|
| Package import | Poll GET /api/packages/import/{trackingId} (Pending, Running, Success, Failed) |
| Deployment tasks (install, uninstall, reinstall, OS install) |
GET /api/tasks and GET /api/tasks/{trackingId} (1 = Running, 2 = Finished, 3 = Failed) |
| Software deployment on a computer |
GET /api/computer/{id}/software-deployment (status Pending, Success, Failed) |
| Fleet-wide status of one package | GET /api/packages/{id}/status |
| Backend jobs (patch download, hash creation, import) |
GET /api/queues – an empty list means the backend is idle |
The Patch Management Fix package (Matrix42\PMClient-Fix) legitimately stays in status Pending until a patch scan detects a missing patch approved for the device's PM groups. This is by design and not a stuck deployment.
Error Handling
The API uses standard HTTP status codes:
| Status | Meaning |
|---|---|
200 / 201
|
Success / resource created |
202 |
Accepted – the job was queued (for example package import) |
400 |
Invalid request (for example missing required field, invalid folder path) |
401 / 403
|
Missing or expired token / principal lacks the required role |
404 |
Resource not found |
409 |
Conflict with the current state – the body contains a machine-readable code
|
Conflict responses contain a code and a message, for example:
{
"code": "ScanPackageNotAssigned",
"clientId": 4711,
"scanType": "Patch",
"message": "No Patch scan package is assigned to the computer."
}Examples of conflict codes: ScanPackageNotAssigned, PackageNotAssigned, PackageNotInstalled, UninstallAlreadyPending, ProductScopeRequired. Evaluate the code in your integration rather than the message text.
Endpoint Overview
The API contains more than 150 operations. The following table summarizes the functional areas. See the OpenAPI specification for the complete list of parameters and response schemas.
| Area | Base path | Main capabilities |
|---|---|---|
| Auth | /api/auth |
Issue access tokens |
| Admin | /api/admin |
Local and Identity Provider principals, roles, features |
| Computer | /api/computer |
CRUD and search; full hardware and software inventory; health, security posture, reboot and patch status; software deployment, reinstall and uninstall; activation, rescan, reboot; variables; effective Agent Template, OS image SKU, PXE boot image and Language Packs |
| Computer issues | /api/computer/issues |
Fleet-wide sweeps: failed deployment, shared package failure, missing patch, pending reboot, stale agent, stale inventory, stale deployment, agent suspended, low disk, battery wear, BitLocker off, overview |
| Group | /api/group |
Deployment groups and membership; package, PXE, OS image SKU, Agent Template, Language Pack, Variable Configuration and Software Class assignments; distribution options; depot servers; variables; activation |
| Packages | /api/packages |
Package catalog and search, fleet deployment status, "Ready to Install" flag, import from PackageStore, hash generation |
| Patch | /api/patches |
Patch catalog search, patch and product lookup, patch and product approval |
| PM groups | /api/pmgroup |
Patch Management groups, their products and patches, tree assignments, emergency patching |
| OS deployment objects |
/api/operating-system-imports, /api/pxe-bootimages, /api/language-pack-imports, /api/agent-templates
|
Catalog, search and reverse lookup of assigned groups |
| Variables |
/api/variable-definitions, /api/variable-configurations
|
Variable catalog, children, inverse search of computers, groups and configurations using a variable |
| Software Classes | /api/softwareclasses |
Catalog and search |
| System | /api/system |
Version information, depot servers, depot sync jobs and heartbeat, trigger depot sync |
| Tasks and Queues |
/api/tasks, /api/queues
|
External task tracking, backend task queues |
PowerShell Examples
The following examples use two small helper functions that handle token acquisition, token renewal, the api-version header and JSON serialization. Save them in a file such as EmpirumApi.ps1 and dot-source it in your scripts.
All IDs, host names and GUIDs in the examples are placeholders. Replace them with values from your environment. Test all write operations in a test environment first.
Helper Functions
# EmpirumApi.ps1 - helper functions for the Empirum REST API
$script:EmpirumBaseUrl = 'https://empirum-api.contoso.local:5443'
$script:EmpirumToken = $null
$script:EmpirumTokenExp = [datetime]::MinValue
$script:EmpirumCred = $null
function Connect-Empirum {
param(
[Parameter(Mandatory)] [string] $BaseUrl,
[Parameter(Mandatory)] [pscredential] $Credential # UserName = client_id, Password = secret
)
$script:EmpirumBaseUrl = $BaseUrl.TrimEnd('/')
$script:EmpirumCred = $Credential
Get-EmpirumToken -Force | Out-Null
}
function Get-EmpirumToken {
param([switch] $Force)
# Renew the token 60 seconds before it expires
if (-not $Force -and $script:EmpirumToken -and (Get-Date) -lt $script:EmpirumTokenExp.AddSeconds(-60)) {
return $script:EmpirumToken
}
$body = @{
grant_type = 'client_credentials'
client_id = $script:EmpirumCred.UserName
client_secret = $script:EmpirumCred.GetNetworkCredential().Password
}
$response = Invoke-RestMethod -Method Post `
-Uri "$script:EmpirumBaseUrl/api/auth/token" `
-ContentType 'application/x-www-form-urlencoded' `
-Headers @{ 'api-version' = '1' } `
-Body $body
$script:EmpirumToken = $response.access_token
$script:EmpirumTokenExp = (Get-Date).AddSeconds([int]$response.expires_in)
return $script:EmpirumToken
}
function Invoke-EmpirumApi {
param(
[Parameter(Mandatory)] [string] $Path, # e.g. '/api/computer/4711'
[ValidateSet('GET','POST','PUT','PATCH','DELETE')] [string] $Method = 'GET',
[object] $Body,
[hashtable] $Query
)
$uri = "$script:EmpirumBaseUrl$Path"
if ($Query) {
$pairs = foreach ($k in $Query.Keys) {
'{0}={1}' -f $k, [uri]::EscapeDataString([string]$Query[$k])
}
$uri = $uri + '?' + ($pairs -join '&')
}
$params = @{
Method = $Method
Uri = $uri
Headers = @{
Authorization = "Bearer $(Get-EmpirumToken)"
'api-version' = '1'
}
}
if ($null -ne $Body) {
$params.ContentType = 'application/json'
$params.Body = $Body | ConvertTo-Json -Depth 10
}
try {
Invoke-RestMethod @params
}
catch {
$detail = $_.ErrorDetails.Message
throw "Empirum API $Method $Path failed: $($_.Exception.Message) $detail"
}
}
function Get-EmpirumPagedResult {
# Reads all pages of a paged GET endpoint
param(
[Parameter(Mandatory)] [string] $Path,
[hashtable] $Query = @{},
[int] $PageSize = 200
)
$skip = 0
do {
$q = $Query.Clone()
$q.skip = $skip
$q.top = $PageSize
$page = Invoke-EmpirumApi -Path $Path -Query $q
$page.items
$skip += $PageSize
} while ($page.hasMore)
}Connect once at the beginning of a script. The credential can come from the SecretManagement module, a vault or an interactive prompt:
. .\EmpirumApi.ps1
# Interactive: user name = client_id, password = client secret
$cred = Get-Credential -Message 'Empirum REST API client credentials'
# Unattended: read from a registered secret vault
# $cred = Get-Secret -Name 'EmpirumApiClient'
Connect-Empirum -BaseUrl 'https://empirum-api.contoso.local:5443' -Credential $cred
# Verify the connection
Invoke-EmpirumApi -Path '/api/system'If the REST API uses a certificate that is not trusted by the calling system, PowerShell 7 can bypass the check with -SkipCertificateCheck on Invoke-RestMethod. Use this only in test environments. In production, install the issuing CA certificate on the calling system.
Example 1: Find a Computer and Read Its Inventory
Required role: computer.read. Resolves a computer by hostname and reads the aggregated inventory (system info, BIOS, disks, network adapters, batteries, printers, video controllers, monitors, processors) in one call.
$result = Invoke-EmpirumApi -Method POST -Path '/api/computer/search' -Body @{ hostname = 'PC-SALES-042' }
if ($result.totalCount -eq 0) { throw 'Computer not found.' }
$computer = $result.items | Select-Object -First 1
"Found {0} (client_id {1}), last seen {2}" -f $computer.hostname, $computer.id, $computer.lastSeenUtc
$inventory = Invoke-EmpirumApi -Path "/api/computer/$($computer.id)/inventory"
$inventory | ConvertTo-Json -Depth 6
# Individual inventory areas are also available, for example:
Invoke-EmpirumApi -Path "/api/computer/$($computer.id)/inventory/disks"
Invoke-EmpirumApi -Path "/api/computer/$($computer.id)/inventory/installed-software"
Invoke-EmpirumApi -Path "/api/computer/$($computer.id)/security-posture"Example 2: Export All Computers to CSV
Required role: computer.read. Reads all computers page by page and exports them, for example for a CMDB import. The modifiedAfter filter enables delta synchronization.
# Full export
$computers = Get-EmpirumPagedResult -Path '/api/computer'
# Delta export: only computers modified in the last 24 hours
# $since = (Get-Date).ToUniversalTime().AddDays(-1).ToString('o')
# $computers = Get-EmpirumPagedResult -Path '/api/computer' -Query @{ modifiedAfter = $since }
$computers |
Select-Object id, hostname, domain, serialNumber, macAddress, uuid, ou, lastSeenUtc, inventoryDate |
Export-Csv -Path '.\empirum-computers.csv' -NoTypeInformation -Encoding UTF8
"Exported $($computers.Count) computers."Example 3: Fleet Health Report
Required role: computer.read. The issue endpoints return pre-evaluated fleet sweeps. This example lists devices with failed deployments that were online in the last 7 days, and packages that fail on several devices.
# Devices with failed software deployments, seen in the last 7 days
$failed = Get-EmpirumPagedResult -Path '/api/computer/issues/failed-deployment' -Query @{ lastSeenWithinDays = 7 }
$failed | ForEach-Object {
$c = $_
$c.failedPackages | ForEach-Object {
[pscustomobject]@{
Hostname = $c.hostname
ClientId = $c.id
Package = $_.packageName
LastFailedUtc = $_.lastFailedUtc
}
}
} | Sort-Object Package | Format-Table -AutoSize
# Packages failing on multiple devices (likely a package problem, not a device problem)
Invoke-EmpirumApi -Path '/api/computer/issues/shared-package-failure'
# Other sweeps with the same pattern
# /api/computer/issues/stale-agent
# /api/computer/issues/pending-reboot
# /api/computer/issues/low-disk
# /api/computer/issues/bitlocker-off
# /api/computer/issues/overview (all devices with at least one issue)Example 4: Roll Out Software to a Group
Required roles: package.read, group.read, group.write, activation.execute. Finds a package, creates a rollout group below an existing parent group, adds computers, assigns the package and activates the group.
# 1. Find the package
$pkg = (Invoke-EmpirumApi -Method POST -Path '/api/packages/search' -Body @{ name = '7-Zip'; version = '24' }).items |
Select-Object -First 1
if (-not $pkg.operational) { Write-Warning "Package $($pkg.name) is not 'Ready to Install'." }
# 2. Find the parent group and create the rollout group
$parent = (Invoke-EmpirumApi -Path '/api/group' -Query @{ nameContains = 'Software Rollouts' }).items |
Select-Object -First 1
$group = Invoke-EmpirumApi -Method POST -Path '/api/group' -Body @{
name = 'Rollout 7-Zip Wave 1'
type = 'AssignmentGroups'
parentId = $parent.id
description = 'Created by automation'
}
# 3. Add computers (client ids); each computer is processed independently
$add = Invoke-EmpirumApi -Method POST -Path "/api/group/$($group.id)/computers" -Body @{
computerIds = @(4711, 4712, 4713)
}
"Added: $($add.succeeded), failed: $($add.failed)"
# 4. Assign the package (an existing assignment is a no-op success)
Invoke-EmpirumApi -Method POST -Path "/api/group/$($group.id)/packages" -Body @{ packageId = $pkg.id }
# 5. Activate the group for software deployment (cascades over the subtree)
Invoke-EmpirumApi -Method POST -Path "/api/group/$($group.id)/activation" -Body @{
software = $true
pxe = $false
pull = $false
global = $true
}
# 6. Follow up on the deployment status
Invoke-EmpirumApi -Path "/api/packages/$($pkg.id)/status" -Query @{ groupId = $group.id }Changes to assignments and distribution options take effect for group members at their next activation. The API does not activate automatically; always call the activation endpoint when the change should be executed.
Example 5: Import a Package from the PackageStore
Required roles: package.write, package.read. Imports a package folder into Empirum and waits for the result. Hash generation is chained automatically by the backend.
# folderPath is relative to the PackageStore root; absolute, UNC and '..' paths are rejected
$import = Invoke-EmpirumApi -Method POST -Path '/api/packages/import' -Body @{
folderPath = 'Igor Pavlov\7-Zip\24.08'
overwrite = $false
}
"Import queued, tracking id $($import.trackingId)"
$timeout = (Get-Date).AddMinutes(15)
do {
Start-Sleep -Seconds 15
$status = Invoke-EmpirumApi -Path "/api/packages/import/$($import.trackingId)"
"{0:u} {1} {2}" -f (Get-Date), $status.status, $status.message
} while ($status.status -in 'Pending','Running' -and (Get-Date) -lt $timeout)
if ($status.status -ne 'Success') { throw "Package import did not succeed: $($status.status) $($status.message)" }Example 6: Reinstall Software on a Computer
Required roles: computer.read, reinstall.execute. Typical helpdesk automation: a ticket reports a broken application, the script triggers an enforced reinstall through the package's existing assignment.
$clientId = 4711
# Show assigned packages and their state
$deployments = Invoke-EmpirumApi -Path "/api/computer/$clientId/software-deployment"
$deployments | Select-Object name, version, status, installationState, desiredMode | Format-Table
# Pick the package and trigger the reinstall
$target = $deployments | Where-Object name -like '*Adobe Acrobat*' | Select-Object -First 1
$reinstall = Invoke-EmpirumApi -Method POST -Path "/api/computer/$clientId/software-reinstall" -Body @{
packageId = $target.softwareId
}
"Reinstall requested via group '$($reinstall.parentGroupName)' at $($reinstall.requestedAtUtc)"
# Pending reinstalls can be listed and cancelled
Invoke-EmpirumApi -Path "/api/computer/$clientId/software-reinstall"POST /api/computer/{id}/software-uninstall sets the distribution mode of the package's nearest assignment to Uninstall. This applies to the whole assignment group: every computer in that group uninstalls the package. Check the group membership with GET /api/computer/{id}/packages/{packageId}/groups before triggering an uninstall.
Example 7: Patch Rescan and Missing Patch Report
Required roles: computer.read, scan.execute. A patch rescan also triggers remediation: if the scan finds missing patches approved for the device's PM groups, the assigned Patch Management Fix package installs them at the next agent contact.
$clientId = 4711
# Force a patch scan (scanType: Inventory or Patch); idempotent if already pending
try {
Invoke-EmpirumApi -Method POST -Path "/api/computer/$clientId/rescan" -Body @{ scanType = 'Patch' }
}
catch {
if ($_ -match 'ScanPackageNotAssigned') { Write-Warning 'No patch scan package is assigned to this computer.' }
else { throw }
}
# Missing-patch summary for this computer
Invoke-EmpirumApi -Path "/api/computer/$clientId/patch-status"
# Fleet-wide: devices missing critical patches (CVSS 9 or higher), seen in the last 14 days
$critical = Get-EmpirumPagedResult -Path '/api/computer/issues/missing-patch' -Query @{
minCvss = 9
lastSeenWithinDays = 14
}
"$($critical.Count) devices are missing patches with CVSS 9 or higher."Example 8: Emergency Patching
Required roles: pm.read, pm.execute. Triggers emergency remediation of a PM group's patches on selected computers, for example after a zero-day vulnerability.
$pmGroup = (Invoke-EmpirumApi -Path '/api/pmgroup' -Query @{ nameContains = 'Emergency Browser' }).items |
Select-Object -First 1
Invoke-EmpirumApi -Method POST -Path "/api/pmgroup/$($pmGroup.id)/emergency-patching" -Body @{
computerIds = @(4711, 4712, 4713)
}
# When remediation is complete, remove the emergency assignment group again
# Invoke-EmpirumApi -Method DELETE -Path "/api/pmgroup/$($pmGroup.id)/emergency-patching"Example 9: Request a Reboot with Grace Period
Required roles: computer.read, reboot.execute. Flags computers with a pending reboot to restart at the next agent poll via Silent Reboot Logic. Logged-on users get 60 minutes, with a reminder every 15 minutes.
$pending = Get-EmpirumPagedResult -Path '/api/computer/issues/pending-reboot'
foreach ($c in $pending) {
Invoke-EmpirumApi -Method POST -Path "/api/computer/$($c.id)/reboot" -Body @{
timeoutMinutes = 60 # -1 forces the reboot immediately at the next poll
reminderMinutes = 15
} | Out-Null
"Reboot requested for $($c.hostname)"
}Example 10: Wake and Activate a Computer
Required role: activation.execute. Sends Wake-on-LAN immediately and activates the computer for software deployment. A Wake-on-LAN is always combined with an activation.
Invoke-EmpirumApi -Method POST -Path '/api/computer/4711/activation' -Body @{
software = $true
pxe = $false
pull = $false
wol = $null # or a UTC time to schedule the wake-up
wolNow = $true # mutually exclusive with wol
srl = $null
global = $true
}Best Practices
-
Least privilege: create one principal per integration and grant only the roles it needs. Set an expiry date with
expiresAtUtcand rotate secrets regularly. - Reuse tokens: cache the access token until shortly before it expires instead of requesting a token per call.
-
Page large result sets: use
skipandtopand evaluatehasMore. Use delta filters such asmodifiedAfterorlastSeenAfterfor synchronizations. - Resolve IDs first: search computers, groups and packages by name, then work with IDs. Do not rely on names being unique.
-
Evaluate conflict codes: handle
409responses by theircodefield. Many write operations are idempotent (for example an already assigned package or an already pending rescan) and return success. - Respect asynchronous execution: actions are executed by the agent at its next contact. Track results with the task, status and queue endpoints instead of assuming immediate completion.
- Test destructive operations: deleting groups, deleting computers, uninstalling software and setting distribution options to Uninstall affect many devices. Validate scope in a test environment.
- Log API calls: log method, path, principal and result of write operations in your integration for audit and troubleshooting.
DELETE /api/group/{id} deletes a deployment group. Setting the distribution option Uninstall with PUT /api/group/{id}/distribution-options makes every member computer of the group and its subgroups uninstall the affected packages at the next activation. Double-check the group ID and scope before running these operations in automation.
Troubleshooting
| Symptom | Possible cause and solution |
|---|---|
401 Unauthorized |
Token missing, expired or malformed. Request a new token and check the Authorization: Bearer header. Check whether the principal is revoked or expired. |
403 Forbidden |
The principal lacks the required role. Check the "Requires role" note of the operation and the principal's roles in the web-based principal management (/admin) or with GET /api/admin/local-principals/{id}. |
| TLS or certificate error | The calling system does not trust the server certificate. Install the issuing CA certificate on the calling system. |
409 ScanPackageNotAssigned |
No scan package of the requested type is assigned to the computer in its group tree. Assign the Inventory or Patch scan package first. |
409 PackageNotAssigned on reinstall or uninstall |
The package is not assigned to the computer anywhere in the tree. Assign it to a group the computer belongs to. |
Package import fails immediately with 400
|
folderPath is absolute, a UNC path or contains ... Use a path relative to the PackageStore root. |
Package import ends with Failed
|
A package with the same identity already exists. Set overwrite to true if the existing package should be replaced. |
Deployment stays Pending
|
The agent has not contacted the server yet, the group was not activated, or the package is the registry-gated Patch Management Fix package (expected behavior). Check GET /api/computer/{id}/health and GET /api/computer/issues/stale-deployment. |
| Backend jobs do not complete | Check GET /api/queues for queued or running jobs and GET /api/system/sync-jobs/depots for depot sync heartbeat. |
You are now ready to integrate Empirum into your processes. Start with read-only calls (/api/system, /api/computer, issue sweeps), then add write operations step by step with dedicated, least-privilege principals.