Month left to switch to the Graph API for fetching Service Health Dashboard data

In a message center post sent earlier today, Microsoft is again reminding customers to stop using the good old manage.office.com endpoint to fetch information pertaining to the Service Health Dashboard or the Message center. The cutoff date is December 17th, 2021. With only a month left, there is no news about any replacement for the Management activity API, which also uses the same (root) endpoint.

Anyway, after completing my duties for spreading the message, let’s also take a quick look at how the new ednpoints, now part of the Graph API, behave. First, a reminder on how things looked like. The example below shows a query for fetching the current status of all services, along with the output returned from the old Service Communications API endpoint:

$uri = "https://manage.office.com/api/v1.0/$tenantname/ServiceComms/CurrentStatus"
$result = (Invoke-RestMethod -Uri $uri –Headers $authHeader1 –Method Get –Verbose)
$result.value

FeatureStatus : {@{FeatureDisplayName=Backend Data Processing; FeatureName=Backend Data Processing; FeatureServiceStatus=ServiceOperational; FeatureServiceStatusDisplayName=Normal service}, @{FeatureDisplayName=Networking Issues; FeatureName=Networking Issues; FeatureServiceStatus=ServiceOperational; 
FeatureServiceStatusDisplayName=Normal service}, @{FeatureDisplayName=Sign-in; FeatureName=Signin; FeatureServiceStatus=ServiceOperational; FeatureServiceStatusDisplayName=Normal service}, @{FeatureDisplayName=E-Mail and calendar access; FeatureName=Access; FeatureServiceStatus=ServiceOperational; 
FeatureServiceStatusDisplayName=Normal service}...}
Id : Exchange
IncidentIds : {EX295761}
Status : ServiceDegradation
StatusDisplayName : Service degradation
StatusTime : 2021-11-04T00:31:52.803Z
Workload : Exchange
WorkloadDisplayName : Exchange Online

The full output will of course contain information about all the services, each returned as separate entry, but for our purposes looking only at the status of Exchange Online will do. The corresponding Graph API endpoint is /admin/serviceAnnouncement/healthOverviews and unfortunately is a bit lighter on the details. Compared to the information in the example above, that is.

$uri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews"
$result = (Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Get –Verbose)
$result.value

service status id 
------- ------ -- 
Exchange Online serviceDegradation Exchange 
Identity Service serviceOperational OrgLiveID 
Microsoft 365 suite restoringService OSDPPlatform 
Skype for Business serviceOperational Lync 
SharePoint Online serviceDegradation SharePoint 
Dynamics 365 Apps serviceOperational DynamicsCRM 
Azure Information Protection serviceOperational RMS 
Yammer Enterprise serviceOperational yammer 
Mobile Device Management for Office 365 serviceOperational MobileDeviceManagement 
Planner serviceOperational Planner 
Sway serviceOperational SwayEnterprise 
Power BI serviceOperational PowerBIcom 
Microsoft Intune serviceOperational Intune 
OneDrive for Business serviceOperational OneDriveForBusiness 
Microsoft Teams serviceOperational microsoftteams 
Microsoft StaffHub serviceOperational StaffHub 
Microsoft Kaizala serviceOperational kaizalamessagingservices
Microsoft Bookings serviceOperational Bookings 
Office for the web serviceOperational officeonline 
Microsoft 365 Apps serviceOperational O365Client 
Power Apps serviceOperational PowerApps 
Power Apps in Microsoft 365 serviceOperational PowerAppsM365 
Microsoft Power Automate serviceOperational MicrosoftFlow 
Microsoft Power Automate in Microsoft 365 serviceOperational MicrosoftFlowM365 
Microsoft Forms serviceOperational Forms 
Microsoft 365 Defender serviceOperational Microsoft365Defender 
Microsoft Stream serviceOperational Stream 
Privileged Access serviceOperational PAM 
Microsoft Viva serviceOperational Viva 
Cloud App Security serviceOperational cloudappsecurity

The data is all there, it just takes another query to get to all the details, namely a GET request against /admin/serviceAnnouncement/issues. As by default data for all recent incidents across all services is returned, you can use the $filter operator to get the details for particular event only (few examples included below).

$uri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues"
$uri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues?`$filter=service eq 'Exchange Online' and status eq 'serviceDegradation'"
$uri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues?`$filter=service eq 'Exchange Online' and endDateTime eq null"
$result = (Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Get –Verbose)
$result.value
#$result.value.posts | % {$_.description.content}

startDateTime : 2021-10-28T01:00:00Z
endDateTime :
lastModifiedDateTime : 2021-11-04T00:31:52.803Z
title : Admins may be unable to view or manage users in role groups
id : EX295761
impactDescription : Admins may be unable to view or manage users in role groups.
classification : advisory
origin : microsoft
status : serviceDegradation
service : Exchange Online
feature : Tenant Administration (Provisioning, Remote PowerShell)
featureGroup : Management and Provisioning
isResolved : False
highImpact :
details : {}
posts : {@{createdDateTime=2021-11-02T18:24:35.043Z; postType=regular; description=},...}

I’ve trimmed the output above for the sake of brevity, but overall you should be able to see the same level of detail as exposed within the Microsoft 365 Admin portal, including Post Incident review reports (via the /admin/serviceAnnouncement/issues/{serviceHealthIssueId}/incidentReport endpoint).

Apart from SHD data, the Service Communications API covers Message center post (via /admin/serviceAnnouncement/messages endpoint). The interesting part here is that apart from allowing you to list those posts, the Graph API allows you to also perform additional operations on them. Those include Mark as Read, Archive and Mark Favorite, matching the functionality we have in the M365 admin center. Only Delegate permissions are supported for such operations though, specifically you need the ServiceMessageViewpoint.Write scope.

Some examples below:

$uri = "https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/messages?`$top=1"
$result = (Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Get –Verbose)
$result.value

startDateTime : 2020-12-09T19:58:01Z
endDateTime : 2022-01-02T08:00:00Z
lastModifiedDateTime : 2020-12-10T18:10:27.953Z
title : Update to Microsoft 365 and Outlook for Windows connectivity
id : MC229143
category : planForChange
severity : normal
tags : {User impact, Admin impact}
isMajorChange : True
actionRequiredByDateTime : 2021-11-01T07:00:00Z
services : {Exchange Online, Microsoft 365 Apps}
expiryDateTime :
viewPoint :
details : {}
body : ...

where again some of the output has been trimmed. The body of the message center post can be saved locally and visualized as follows:

$result.value.body.content | Out-File "D:\MC229143.htm"
ii "D:\Downloads\MC229143.htm"

HTML body of a Service Health Dashboard postThat’s it, in a nutshell. Another service moves to using the Graph API and leaves its roots behind. All that’s left to see is when the Management Activity API will follow. Well, and Exchange Online 🙂

2 thoughts on “Month left to switch to the Graph API for fetching Service Health Dashboard data

  1. Shejal M says:

    I m getting this error :

    VERBOSE: GET https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/healthOverviews with 0-byte payload
    Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.
    At line:1 char:12
    + $result = (Invoke-RestMethod -Uri $uri -Headers $authHeader -Method G …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
    eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

    Reply
    1. Vasil Michev says:

      You need to pass a valid access token as part of the request, the examples above don’t cover that part. Just use your preferred method for obtaining a token and set the $authHeader variable accordingly.

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.