There are a handful of SCOM REST API script examples floating around the interwebs. The problem is that quite a few of them are incorrect; the CSRFToken and WebSession parameters aren’t demonstrated correctly.
Here’s a decent example to help you on your way. Notice the CSRFToken is retrieved from the $WebSession and added to the $SCOMHeaders after authentication has been performed. The $WebSession and $SCOMHeaders should be used on all subsequent requests.
<#
Script: Get-SCOMAlerts.ps1
Author: Tyson Paul (https://monitoringguys.com/)
Version History:
2025.06.18.1326 - v1
#>
# Set the main SCOM Web Console Server URI
# My server uses SSL
$WebserverURI = 'https://Web21.contoso.com'
# The SCOM REST API authentication URL
$WebserverURIAuth = "$($WebserverURI)/OperationsManager/authenticate"
# Set SCOM Headers and Body
$SCOMHeaders = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$SCOMHeaders.Add('Content-Type', 'application/json; charset=utf-8')
$BodyPlaintext = "Windows"
$Bytes = [System.Text.Encoding]::UTF8.GetBytes($BodyPlaintext)
$EncodedText = [Convert]::ToBase64String($Bytes)
$JSONBody = $EncodedText | ConvertTo-Json
# Authenticate: Make the initial request with current user context and store the session in 'WebSession'
$Authentication = Invoke-RestMethod -Method Post -Uri $WebserverURIAuth -Headers $SCOMHeaders -Body $JSONBody -UseDefaultCredentials -SessionVariable WebSession
# After authentication, get the CSRF Token from session cookies
$CSRFtoken = $WebSession.Cookies.GetCookies($WebserverURIAuth) | Where-Object { $_.Name -eq 'SCOM-CSRF-TOKEN' }
# Add CSRF token to headers if it exists
if ($CSRFtoken) {
$SCOMHeaders.Add('SCOM-CSRF-TOKEN', [System.Web.HttpUtility]::UrlDecode($CSRFtoken.Value))
}
# Use $SCOMHeaders and $WebSession for subsequent REST API calls
$Query = @(
@{
classId = "" # Empty class ID means all classes
# classId = "8def7ccc-ca28-c7ef-796f-644160e0b22a" # Example class ID for MSSQL on Windows: DB Engine
# criteria = "((Severity = '2') AND (ResolutionState = '0'))"
# criteria = "((Severity = '2') AND (ResolutionState = '0') AND (MonitoringObjectDisplayName LIKE '%SQL%'))"
criteria = "((ResolutionState = '0'))"
displayColumns = @(
"name",
"severity",
"priority",
"timeraised",
"timeadded",
"timeresolved",
"age",
"resolutionstate",
"monitoringobjectdisplayname",
"monitoringobjectpath",
"monitoringobjectinmaintenancemode",
"monitoringobjectid",
"repeatcount",
"owner",
"context",
"customfield1",
"customfield2",
"customfield3",
"customfield4",
"customfield5",
"customfield6",
"customfield7",
"customfield8",
"customfield9",
"customfield10",
"description"
)
}
)
$JSONQuery = $Query | ConvertTo-Json
$Response = Invoke-RestMethod -Uri "$($WebserverURI)/OperationsManager/data/alert" -Method Post -Body $JSONQuery -WebSession $WebSession -Headers $SCOMHeaders
$Alerts = $Response.Rows
Write-Host "Building $($Alerts.Count) alert objects..."
[system.collections.arraylist]$arrRichAlerts = @()
$Counter = 0
ForEach ($Alert in $Alerts) {
$Counter++
Write-Progress -Activity "Processing SCOM Alerts" -Status "Processing alert $Counter of $($Alerts.Count)" -PercentComplete (($Counter / $Alerts.Count) * 100)
$CustomObj = $null
# Simple way to create a deep copy of [PSCustomObject], not just a reference assignment
$CustomObj = $Alert | ConvertTo-Json -Depth 10 | ConvertFrom-Json
# https://learn.microsoft.com/en-us/rest/api/operationsmanager/data/retrieve-alert-details?tabs=HTTP
$URI = "$($WebserverURI)/OperationsManager/data/alertdetails/$($Alert.Id)"
$AlertDetails = Invoke-RestMethod -Uri $URI -WebSession $WebSession -Headers $SCOMHeaders
# Add extra alert properties to custom object
$CustomObj | Add-Member -MemberType NoteProperty -Name 'source' -Value ($AlertDetails.source)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'sourceId' -Value ($AlertDetails.sourceId)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'ruleName' -Value ($AlertDetails.ruleName)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'monitorName' -Value ($AlertDetails.monitorName)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'typeSourceId' -Value ($AlertDetails.typeSourceId)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'ticketId' -Value ($AlertDetails.ticketId)
# https://learn.microsoft.com/en-us/rest/api/operationsmanager/data/retrieve-alert-properties?tabs=HTTP
$URI = "$($WebserverURI)/OperationsManager/data/alertInformation/$($Alert.Id)"
$AlertProperties = Invoke-RestMethod -Uri $URI -WebSession $WebSession -Headers $SCOMHeaders
# Add extra alert properties to custom object
$CustomObj | Add-Member -MemberType NoteProperty -Name 'alertHistoryResponses' -Value ($AlertProperties.alertHistoryResponses)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'ruleId' -Value ($AlertProperties.ruleId)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'monitorId' -Value ($AlertProperties.monitorId)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'isMonitorAlert' -Value ($AlertProperties.isMonitorAlert)
# Basic class info for source object
# https://learn.microsoft.com/en-us/rest/api/operationsmanager/data/retrieve-classes-for-object?tabs=HTTP
$URI = "$($WebserverURI)/OperationsManager/data/classesForObject/$($CustomObj.sourceId)"
$AlertSourceClass = Invoke-RestMethod -Uri $URI -WebSession $WebSession -Headers $SCOMHeaders
$CustomObj | Add-Member -MemberType NoteProperty -Name 'sourceClassId' -Value ($AlertSourceClass.rows.Id)
$CustomObj | Add-Member -MemberType NoteProperty -Name 'sourceClassDisplayName' -Value ($AlertSourceClass.rows.displayname)
[void]$arrRichAlerts.Add($CustomObj)
}
Write-Progress -Activity "Processing SCOM Alerts" -Completed
# Output the array of rich alert objects
$arrRichAlerts | Select-Object -First 5

Now the array of objects is yours to use as you wish
$arrRichAlerts