PowerShell + REST APIs to monitor the status of MS Flows

Translated from the Spanish original. Read in Spanish

In this guide, we’ll learn how to use PowerShell together with REST APIs and an Azure Service Principal to monitor the status of several Flows. This can be especially useful for managing and automating alerts on critical flows.

iStock AI Generator

Create a Service Principal in Azure

Before running the script, you’ll need to create a Service Principal in Azure. It acts as an application identity that lets you authenticate and perform operations through the Azure APIs.

Define the environment ID and the scope

The EnvironmentID is the Microsoft Automate environment where your flows live.

$environmentId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
$scope = "https://service.flow.microsoft.com//.default"

Set the Flows to monitor

Create a hashtable with the names of the Flows you want to monitor and their IDs.

$taskFlows = @{
    "Flow1" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    "Flow2" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    # Agrega más Flows si es necesario
}

Service Principal details

Provide your Service Principal’s details: Tenant ID, Application ID and Secret.

$tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
$appId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
$appSecret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Getting the Token for the Service Principal

Send a request to get an access token, which we’ll use to authenticate our API calls.

$body = @{  
    grant_type    = "client_credentials"  
    client_id     = $appId  
    client_secret = $appSecret  
    scope         = $scope
}  
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"  
$tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body  
$token = $tokenResponse.access_token

Setting up the headers for the API call

The headers include the access token and the accepted content type.

$headers = @{  
    Authorization = "Bearer $token"  
    'Content-Type' = 'application/json'  
}

Creating a Hashtable to store the failure status of the Flows

$flowFailureStatus = @{}

Loop through and process each Flow

Loop through each Flow, check its status and store the result in the hashtable.

foreach ($key in $taskFlows.Keys) {
    Write-Output "Processing: $key"
    Write-Output "FlowName: $($taskFlows[$key])"
    Write-Output "------------------"
    $taskFlowID = $($taskFlows[$key])
    $apiUrl = "https://api.flow.microsoft.com/providers/Microsoft.ProcessSimple/environments/$environmentId/flows/$taskFlowID/runs?api-version=2016-11-01&$top=50"

    try {
        $response = Invoke-RestMethod -Uri $apiUrl -Headers $headers -Method Get

        if ($key -eq "Flow1") {
            $runningCount = ($response.value | Where-Object { $_.properties.status -eq 'Running' }).Count
            if ($runningCount -eq 5) {
                Write-Output "Flow Alert: at least 5 jobs are still running in the Flow1 flow."
            }
        }

        $failedCount = ($response.value | Where-Object { $_.properties.status -eq 'Failed' }).Count

        if ($failedCount -gt 5) {
            Write-Output "The flow has failed more than 5 times."
            $flowFailureStatus[$key] = $true
        }
    } catch {
        Write-Output "Failed to retrieve flow run history for: $key"
        Write-Output $_.Exception.Message
        $flowFailureStatus[$key] = $null
    }
    Write-Output "------------------"
}

Complete code

Here is the complete PowerShell script to monitor the status of your Flows:

$environmentId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
$scope = "https://service.flow.microsoft.com//.default"

$taskFlows = @{
    "Flow1" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    "Flow2" = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    # ... (agrega tantos Flows como necesites)
}

$tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
$appId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
$appSecret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Acquire Token for Service Principal  
$body = @{  
    grant_type    = "client_credentials"  
    client_id     = $appId  
    client_secret = $appSecret  
    scope         = $scope
}  
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"  
$tokenResponse = Invoke-RestMethod -Uri $tokenUrl -Method Post -Body $body  
$token = $tokenResponse.access_token  

$headers = @{  
    Authorization = "Bearer $token"  
    'Content-Type' = 'application/json'  
}  

$flowFailureStatus = @{}

foreach ($key in $taskFlows.Keys) {
    Write-Output "Processing: $key"
    Write-Output "FlowName: $($taskFlows[$key])"
    Write-Output "------------------"
    $taskFlowID = $($taskFlows[$key])
    $apiUrl = "https://api.flow.microsoft.com/providers/Microsoft.ProcessSimple/environments/$environmentId/flows/$taskFlowID/runs?api-version=2016-11-01&$top=50"

    try {
        $response = Invoke-RestMethod -Uri $apiUrl -Headers $headers -Method Get

        if ($key -eq "Flow1") {
            $runningCount = ($response.value | Where-Object { $_.properties.status -eq 'Running' }).Count

            if ($runningCount -eq 5) {
                Write-Output "Flow Alert: at least 5 jobs are still running in the Flow1 flow."
            }
        }

        $failedCount = ($response.value | Where-Object { $_.properties.status -eq 'Failed' }).Count

        if ($failedCount -gt 5) {
            Write-Output "The flow has failed more than 5 times."
            $flowFailureStatus[$key] = $true
        }
    } catch {
        Write-Output "Failed to retrieve flow run history for: $key"
        Write-Output $_.Exception.Message
        $flowFailureStatus[$key] = $null
    }
    Write-Output "------------------"
}

if ($flowFailureStatus.Count -gt 0) {
    Write-Host "Flows that have failed the last 5 times:"
    foreach ($flow in $flowFailureStatus.GetEnumerator()) {
        if ($flow.Value -eq $true) {
            Write-Host "Flow: $($flow.Key) - Failed 5 times consecutively"
        }
    }
} else {
    Write-Host "No flows have failed the last 5 times."
}

Maximiliano Díaz Doglia

AI Platform Engineer & Full-Stack Developer
Building Enterprise Integrations & Automations