Skip to content

Custom API Requests

Custom API Requests with Invoke-LMAPIRequest

Section titled “Custom API Requests with Invoke-LMAPIRequest”

The Invoke-LMAPIRequest cmdlet provides direct access to any LogicMonitor API endpoint while leveraging the module’s authentication, retry logic, and error handling infrastructure.

Terminal window
Invoke-LMAPIRequest -ResourcePath "/endpoint/path" -Method <GET|POST|PATCH|PUT|DELETE> [-Data <hashtable>] [-QueryParams <hashtable>]
Terminal window
# Get all devices
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method GET
# Get a specific device by ID
Invoke-LMAPIRequest -ResourcePath "/device/devices/1234" -Method GET
# Get devices with query parameters
$queryParams = @{
size = 500
offset = 0
filter = 'displayName~"prod*"'
fields = "id,name,displayName,currentCollectorId"
sort = "+displayName"
}
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method GET -QueryParams $queryParams
# Get alert rules
Invoke-LMAPIRequest -ResourcePath "/setting/alert/rules" -Method GET
# Get escalation chains
Invoke-LMAPIRequest -ResourcePath "/setting/alert/chains" -Method GET
Terminal window
# Create a new device (matches New-LMDevice)
$data = @{
name = "server01.example.com"
displayName = "Production Web Server 01"
description = "Primary web server"
preferredCollectorId = 5
hostGroupIds = "2,15,23" # Comma-separated string
disableAlerting = $false
customProperties = @(
@{ name = "environment"; value = "production" }
@{ name = "owner"; value = "ops-team" }
@{ name = "cost.center"; value = "engineering" }
)
}
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method POST -Data $data
# Create a recipient group (matches New-LMRecipientGroup)
$data = @{
groupName = "Operations Team"
description = "Primary ops team notifications"
recipients = @(
@{ type = "ADMIN"; method = "email"; addr = "ops@example.com" }
@{ type = "ADMIN"; method = "sms"; addr = "+15551234567" }
@{ type = "ARBITRARY"; method = "email"; addr = "external@partner.com" }
)
}
Invoke-LMAPIRequest -ResourcePath "/setting/recipientgroups" -Method POST -Data $data
Terminal window
# Update device properties (matches Set-LMDevice)
$updates = @{
displayName = "Production Web Server 01 - Updated"
description = "Primary web server - migrated to new datacenter"
disableAlerting = $false
customProperties = @(
@{ name = "environment"; value = "production" }
@{ name = "datacenter"; value = "us-west-2" }
)
}
Invoke-LMAPIRequest -ResourcePath "/device/devices/1234" -Method PATCH -Data $updates
# Update alert rule
$updates = @{
name = "Critical CPU Alert - Updated"
priority = 100
escalatingChainId = 5
}
Invoke-LMAPIRequest -ResourcePath "/setting/alert/rules/789" -Method PATCH -Data $updates
Terminal window
# Delete a device (will prompt for confirmation)
Invoke-LMAPIRequest -ResourcePath "/device/devices/1234" -Method DELETE
# Delete without confirmation
Invoke-LMAPIRequest -ResourcePath "/device/devices/1234" -Method DELETE -Confirm:$false
# Delete an alert rule
Invoke-LMAPIRequest -ResourcePath "/setting/alert/rules/789" -Method DELETE
# Delete a recipient group
Invoke-LMAPIRequest -ResourcePath "/setting/recipientgroups/456" -Method DELETE

Some newer endpoints require different API versions (check Swagger docs for version requirements):

Terminal window
# Most endpoints use version 3 (default)
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method GET -Version 3
# Some newer endpoints may require version 4
Invoke-LMAPIRequest -ResourcePath "/setting/integrations" -Method GET -Version 4

For cases where you need exact control over JSON formatting:

Terminal window
# Useful when you need to preserve null values or specific formatting
$rawJson = @"
{
"name": "test-device",
"displayName": "Test Device",
"preferredCollectorId": 5,
"description": null,
"customProperties": []
}
"@
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method POST -RawBody $rawJson
Terminal window
# Download a report (see /report/reports/{id}/download in Swagger)
Invoke-LMAPIRequest -ResourcePath "/report/reports/123/download" -Method GET -OutFile "C:\Reports\monthly-availability.pdf"
# Download device config backup
Invoke-LMAPIRequest -ResourcePath "/device/devices/1234/config/configBackup" -Method GET -OutFile "C:\Backups\device-config.txt"

Leverage existing format definitions for clean table output:

Terminal window
# Apply LogicMonitor.Device formatting
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method GET -TypeName "LogicMonitor.Device"

For large datasets, implement manual pagination:

Terminal window
$offset = 0
$size = 1000
$allResults = @()
do {
$response = Invoke-LMAPIRequest `
-ResourcePath "/device/devices" `
-Method GET `
-QueryParams @{ size = $size; offset = $offset; sort = "+id" }
$allResults += $response
$offset += $size
Write-Progress -Activity "Fetching devices" -Status "$($allResults.Count) retrieved"
} while ($response.Count -eq $size)
Write-Progress -Activity "Fetching devices" -Completed

By default, Invoke-LMAPIRequest returns raw objects. Control formatting as needed:

Terminal window
# Pipe to Format-Table with specific properties
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method GET |
Format-Table id, name, displayName, status -AutoSize

Use the -Debug parameter to see detailed request information:

Terminal window
Invoke-LMAPIRequest -ResourcePath "/device/devices" -Method POST -Data $data -Debug

Debug output includes:

  • HTTP method and timestamp
  • Parameters used
  • Full endpoint URL
  • Request headers (sensitive data redacted)
  • Complete JSON payload being sent
Terminal window
try {
$result = Invoke-LMAPIRequest `
-ResourcePath "/custom/endpoint" `
-Method POST `
-Data $data `
-ErrorAction Stop
Write-Host "Success: Created resource with ID $($result.id)"
}
catch {
Write-Error "API request failed: $($_.Exception.Message)"
# Implement fallback logic
}

Create reusable wrapper functions for frequently used endpoints:

Terminal window
function Get-LMDeviceByProperty {
<#
.SYNOPSIS
Get devices filtered by a custom property
#>
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$PropertyName,
[Parameter(Mandatory)]
[string]$PropertyValue,
[int]$Size = 1000
)
$queryParams = @{
size = $Size
filter = "customProperties.name:`"$PropertyName`",customProperties.value:`"$PropertyValue`""
fields = "id,name,displayName,currentCollectorId"
}
Invoke-LMAPIRequest `
-ResourcePath "/device/devices" `
-Method GET `
-QueryParams $queryParams |
Format-Table id, name, displayName, currentCollectorId -AutoSize
}
# Usage
Get-LMDeviceByProperty -PropertyName "environment" -PropertyValue "production"
Terminal window
# Bulk update device descriptions
$deviceIds = @(1234, 1235, 1236, 1237)
foreach ($id in $deviceIds) {
$updates = @{
description = "Bulk updated on $(Get-Date -Format 'yyyy-MM-dd')"
customProperties = @(
@{ name = "last.update"; value = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') }
)
}
try {
Invoke-LMAPIRequest `
-ResourcePath "/device/devices/$id" `
-Method PATCH `
-Data $updates `
-Confirm:$false
Write-Host "✓ Updated device $id" -ForegroundColor Green
}
catch {
Write-Warning "Failed to update device $id: $_"
}
Start-Sleep -Milliseconds 100 # Rate limiting
}
Terminal window
function New-LMDeviceWithGroups {
<#
.SYNOPSIS
Create a device and add it to multiple groups
#>
param(
[string]$Name,
[string]$DisplayName,
[int]$CollectorId,
[string[]]$GroupNames
)
# Step 1: Get group IDs from names
$groupIds = @()
foreach ($groupName in $GroupNames) {
$group = Invoke-LMAPIRequest `
-ResourcePath "/device/groups" `
-Method GET `
-QueryParams @{ filter = "name:`"$groupName`""; size = 1 }
if ($group) {
$groupIds += $group[0].id
}
}
# Step 2: Create the device
$deviceData = @{
name = $Name
displayName = $DisplayName
preferredCollectorId = $CollectorId
hostGroupIds = ($groupIds -join ",")
customProperties = @(
@{ name = "created.by"; value = "automation" }
@{ name = "created.date"; value = (Get-Date -Format 'yyyy-MM-dd') }
)
}
$device = Invoke-LMAPIRequest `
-ResourcePath "/device/devices" `
-Method POST `
-Data $deviceData
Write-Host "✓ Created device: $($device.displayName) (ID: $($device.id))"
return $device
}
# Usage
New-LMDeviceWithGroups `
-Name "server01.example.com" `
-DisplayName "Production Server 01" `
-CollectorId 5 `
-GroupNames @("Production", "Web Servers", "US-West")

This usually means your data structure doesn’t match the API’s expected format.

Solution: Compare with a working dedicated cmdlet using -Debug:

Terminal window
# Run the equivalent cmdlet with -Debug to see the correct payload format
New-LMDevice `
-Name "test.example.com" `
-DisplayName "Test Device" `
-PreferredCollectorId 5 `
-Properties @{ environment = "test"; owner = "ops" } `
-Debug
# The debug output will show:
# DEBUG: Request Payload:
# DEBUG: {
# DEBUG: "name": "test.example.com",
# DEBUG: "displayName": "Test Device",
# DEBUG: "preferredCollectorId": 5,
# DEBUG: "customProperties": [
# DEBUG: {
# DEBUG: "name": "environment",
# DEBUG: "value": "test"
# DEBUG: },
# DEBUG: {
# DEBUG: "name": "owner",
# DEBUG: "value": "ops"
# DEBUG: }
# DEBUG: ],
# DEBUG: "deviceType": 0
# DEBUG: }
# Now you can replicate this structure in Invoke-LMAPIRequest

You can also check the Swagger API Documentation for the exact schema requirements.

Terminal window
# Increase retry attempts
Invoke-LMAPIRequest -ResourcePath "/endpoint" -Method GET -MaxRetries 10
# Or add manual delays in loops
foreach ($item in $items) {
Invoke-LMAPIRequest -ResourcePath "/endpoint/$item" -Method GET
Start-Sleep -Milliseconds 500
}
Terminal window
# Verify you're connected
if (-not $Script:LMAuth.Valid) {
Connect-LMAccount -AccessId $id -AccessKey $key -AccountName "company"
}

✅ DO

  • Use dedicated cmdlets when available
  • Validate input locally before sending
  • Use -WhatIf for testing destructive operations
  • Implement proper error handling
  • Add rate limiting for bulk operations

❌ DON'T

  • Don’t skip input validation
  • Don’t ignore API documentation
  • Don’t hardcode sensitive data
  • Don’t forget to handle pagination
  • Don’t disable retries without good reason

📖 LogicMonitor Swagger API

The official API documentation is your best resource for:

  • Complete endpoint listings
  • Request/response schemas
  • Required vs optional fields
  • API version requirements
  • Authentication details

View Swagger Documentation →

💡 Pro Tip

When building custom requests:

  1. Check Swagger for the endpoint schema
  2. Run a similar dedicated cmdlet with -Debug
  3. Compare the payload formats
  4. Replicate the structure in your request

This approach ensures your requests match the API’s expectations!

If you find yourself frequently using Invoke-LMAPIRequest for a specific endpoint:

  1. Open a GitHub issue requesting a dedicated cmdlet
  2. Contribute a PR with the new cmdlet implementation
  3. Share your use case to help prioritize development

The module is community-driven, and your feedback helps improve it for everyone!