Close Menu
Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Facebook X (Twitter) Instagram
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    • Home
    • Intune
    • Windows
      • Modern Workplace
    • macOS
    • Android
    • iOS
    • Automation
      • Logic Apps
      • Intune Monitoring
      • GitHub
    • Security
      • Passwordless
      • Security
    • Speaking
    • About me
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Home»Automation»MEM Monitoring: Get your Windows Autopilot deployment events in a Teams channel with Logic Apps – Part 1
    Automation

    MEM Monitoring: Get your Windows Autopilot deployment events in a Teams channel with Logic Apps – Part 1

    Peter KlapwijkBy Peter KlapwijkApril 16, 2021Updated:February 14, 2025148 Mins Read

    Update 2021-08-06: To filter out events with an inProgress status I changed the first HTTP URI and added a Condition to the flow.

    At my current employee, we are still imaging most of our devices with Configuration Manager. When such a task sequence to apply an image is finished (successfully or failed), a message is placed in a Teams channel with some data about the device and deployment. This triggered me to create such a solution, but for Windows Autopilot deployments.

    For a couple of months, we have Windows Deployments available in the Microsoft Endpoint Management admin center. I thought these deployment reports would be a good start to get this solution in place as these events hold the information about our Windows Autopilot deployments we need for this solution. As most data for Intune is available via Microsoft Graph, I thought about creating a flow in Logic Apps, to pull this data out of the cloud. If we can pull this data via Graph into our Flow, we should be able to process this data and create a Teams message in a channel for every Autopilot enrollment job.

    This blog post is part of the MEM (Intune) Monitoring series. An article with a short explanation of every MEM Monitoring flow I shared and links to the related articles can be found here.

    The solution in short

    Compared to the previous Logic App flows, this one is pretty simple. At least, the basics which I describe here.

    I expanded the flow a little with extra steps, which can be found in part 2 of this post.

    The flow starts with a Recurrence trigger. For now, it runs every hour.
    Every hour Microsoft Graph is queried for the Autopilot Events, by using an HTTP action. At that moment it retrieves all Autopilot events from the previous hour. When this data is received, it’s parsed so we can further process the data and its variables.
    After this step, for every retrieved Autopilot event, a message is posted in a Teams channel by using an Incoming Webhook.
    As an optional action, I used a Get User action. From the Graph, we only receive the user ID. If you want to add the User (by Name or UPN), we can use that ID to retrieve some information about the user.
    And to secure the HTTP action I use Azure Key Vault.

    The complete flow can also be downloaded as an ARM Template from my GitHub repository.

    Requirements

    We have some requirements for this flow.

    First of all, we need to have the appropriate permissions to run the Graph query. The HTTP action we use in the flow uses an Azure App Registration to authenticate to MS Graph. On this App Registration, we set the required permission we need for our Graph queries.
    The minimum permissions are DeviceManagementManagedDevices.Read.All.

    In this previous blog post, I described in detail how to create an App Registration.

    To secure the HTTP actions I use an Azure Key Vault, which is described in this previous post.

    To post a message to a Teams channel, I first used a Post Teams message action, but that requires a Teams license and you need to add the member to the Teams channel. We can also use an Incoming Webhook to get the job done. So make sure to add a webhook to your Teams channel and save the webhook URL, to use it in one of the actions in our flow.

    And optional, when you want to use the Azure AD Get User action, we need rights to read the user properties. For this, an Enterprise Application is created when the first user in the tenant signs in to an Azure AD action in Logic Apps.

    Setup the Logic Apps

    Sign in to the Azure portal and open the Logic Apps service. Here create a new, blank Logic App.

    In the search box for connections and triggers search for Schedule. Select Schedule and select Recurrence which functions as our flow trigger.

    I choose to run this Logic Apps flow every hour.

    The first action we add is an Azure Key Vault action to retrieve the secret for authentication of the upcoming HTTP action. Search for Azure Key Vault and select Get secret.

    Enter at least the Vault name and click sign-in.

    Enter the name of the secret.

    Add an HTTP action.
    In the URI we already use a filter with a date and time to get the events from the last hour, filtered on the deploymentEndDateTime.

    As Method select GET.
    As URI enter:

    https://graph.microsoft.com/beta/deviceManagement/autopilotEvents?$filter=microsoft.graph.DeviceManagementAutopilotEvent/deploymentEndDateTime%20ge%20

    Behind this URI we enter an expression. This expression enters the current time (in UTC), -1 hour, to the URI and sets the date and time in the right context.
    Make sure the cursor is located at the end of the URI, on the right click expression.
    Enter this expression and click OK.

    formatDateTime(addHours(utcNow(),-1),'yyyy-MM-ddTHH:mm:ssZ')

    If you’d like to run the flow once a day and want to retrieve all the Autopilot events from the previous day, use this expression.

    formatDateTime(addDays(utcNow(),-1),'yyyy-MM-ddTHH:mm:ssZ')

    Check Authentication and choose Active Directory OAuth as Authentication type. Enter the Tenant, Client ID (from the app registration) and Audience.
    And make sure to select the Key Vault secret value from the Key Vault action.

    This is how our HTTP action looks like.

    Next, add a Parse JSON action.
    As input, we use the Body (selected as Dynamic content) from the previous HTTP action.

    We can fill the Schema, by using an example payload. This example payload is generated by running this flow or by running the same Graph query as from our HTTP action using Graph Explorer.
    Copy the response in Graph Explorer, click Use sample payload to generate the schema, and paste the response in the text box.

    Next, we’re adding a Condition to the flow, which is a Control action.
    As even events which have a status of inProgress already get a deploymentEndDateTime (which is later changed to the real end date/ time), we need to filter these out so we only get notified of events with a real end state.
    To do this we use the value deploymentState (on the left), choose is not equal to, and enter inProgress as the value on the right.

    When an event deploymentState is not equal to inProgress, the result is true. Under true we place the next action. When the result is false, nothing is done and the flow stops running.

    To post a message in a Teams channel, I use a webhook. We can post messages via the webhook by using an HTTP action.
    Add an HTTP action under True.
    As Method select POST.
    As URI enter the webhook URL.
    As Headers enter Content-Type – application/json

    In the body, we add the text and title in JSON format. Below is the JSON format we need to use for this, without our variables:

    {
     "text": "WRITE YOUR MESSAGE TEXT HERE",
      "title": "WRITE YOUR TITLE HERE"
    }

    We can use dynamic content (variables) from the previous PARSE JSON action and enter our own text.
    Use \n\n in the text to create new lines in the text message, otherwise, the message consists of one long line of text.
    And I used ** to get some text in bold.

    This is the JSON from my above example:

    {
      "text": "**Device name:** @{items('For_each')?['managedDeviceName']}\n\n **Device serial nr:** @{items('For_each')?['deviceSerialNumber']}\n\n **OS Version:** @{items('For_each')?['osVersion']}\n\n **Autopilot Deployment profile:** @{items('For_each')?['windowsAutopilotDeploymentProfileDisplayName']}\n\n **Deployment Status:** @{items('For_each')?['deploymentState']}\n\n **Deployment start time:** @{items('For_each')?['deploymentStartDateTime']}\n\n **Deployment end time:** @{items('For_each')?['deploymentEndDateTime']}\n\n **Deployment duration:** @{items('For_each')?['deploymentDuration']}",
      "title": "Windows Autopilot deployment finished for @{items('For_each')?['managedDeviceName']} with status @{items('For_each')?['deploymentState']}"
    }

    Optional, we can add a Get user action to our flow before the HTTP Post action. The Graph GET query only returns the user ID, but with the user ID we can retrieve for example the User Principal Name of the user who enrolled the device. Use the userPrincipalName from the Parse JSON action as input for the Get user action.

    If you are the first one who uses an Azure AD action in Logic Apps, an Enterprise Application is created in Azure to grant permissions to Logic apps to run the actions. It depends on your tenant design how this permission flow runs, but the end result is a new Enterprise Application with these permissions.

    If you use the Get user action, you can use the output from that action, in your HTTP Post action.

    And this is our flow.

    The end result

    For the end result, I can be short. All the Windows Autopilot deployment events are automatically added to the Teams channel.

    Thanks for reading! And if you have questions or suggestions, leave a comment!

    Autopilot Flow Graph Graph API Intune Intune Monitoring Logic Apps MEM MEMMonitoring Microsoft Endpoint Manager Power Automate PowerApps Windows 10 Windows Autopilot
    Share. Facebook Twitter LinkedIn Email WhatsApp
    Peter Klapwijk
    • Website
    • X (Twitter)
    • LinkedIn

    Peter is a Security (Intune) MVP since 2020 and is working as Modern Workplace Engineer at Wortell in The Netherlands. He has more than 15 years of experience in IT, with a strong focus on Microsoft technologies like Microsoft Intune, Windows, and (low-code) automation.

    Related Posts

    MEM Monitoring: Monitor Security baselines in Endpoint Security

    August 16, 2022

    Getting started with Android Enterprise dedicated devices with AAD shared mode

    May 15, 2021

    Export Endpoint Analytics Proactive remediation data with Logic Apps

    April 19, 2021
    View 14 Comments

    14 Comments

    1. Alec Beckett on April 30, 2021 00:05

      This is really great, unfortunately i just cannot get any data back when running this. Would be really handy as rolling out Autopilot to a 1k+ devices

      Reply
      • Alec Beckett on April 30, 2021 00:11

        Body in the HTTP output just has no values even using the one looking over the previous day but i know for a fact there are have been quite a few autopilot deployments. If you have an idea or can assist me in the right direction that would be great!

        Reply
        • Peter Klapwijk on April 30, 2021 13:52

          What do you get when you use https://graph.microsoft.com/beta/deviceManagement/autopilotEvents?$top=100
          This should return the last 100 AutopilotEvents

          And what if you use this expression instead the one from the article (both expressions work fine for me):
          addhours(utcNow(‘yyyy-MM-ddTHH:mm:ssZ’),-1)

          Reply
          • Michaël Van den Steen on June 17, 2021 15:18

            For some reason this gives me an invalid filter clause error.

            Whenever I try to run the query in graph explorer graph explorer crashes..
            Bit stuck here aLSO the top=00 doesn’t give me any results.

            Reply
            • Michaël Van den Steen on June 17, 2021 15:22

              To add to this: just querying https://graph.microsoft.com/beta/deviceManagement/autopilotEvents
              Gives me an empty array. Is that expected behaviour?

              Bedankt!

            • Peter Klapwijk on June 17, 2021 19:06

              https://graph.microsoft.com/beta/deviceManagement/autopilotEvents should give the events which you also see in the MEM admin center via https://endpoint.microsoft.com/#blade/Microsoft_Intune_DeviceSettings/DevicesMonitorMenu/autopilotDeployments

              Do you see Autopilot events in de MEM Admin center?
              No permission errors when using Graph Explorer?

            • Michaël Van den Steen on June 22, 2021 10:40

              Okay, I was finally able to make it work.
              Bit of rookie mistake I suppose but I tried to query in graph explorer using the formatedatetime expression. That always gave me an “wrong filter clause” error. It did work in the HTTP request though.
              I came to this solution by simplifying my query and just querying for https://graph.microsoft.com/beta/deviceManagement/autopilotEvents?$filter=enrollmentStartDateTime ge 2021-06-01 in graph explorer.

              Hope this helps anyone.

    2. Alex Ledger on May 5, 2021 12:53

      The following query worked for mw with the ‘formatDateTime’ expression. I think this is perfect for our needs. Love having the Team notifications

      https://graph.microsoft.com/beta/deviceManagement/AutoPilotEvents?$filter=enrollmentStartDateTime%20ge%20

      Reply
    3. Kamil Zelazny on October 11, 2021 14:38

      Hello,

      here you can find the proper query (put filter arguments under the brackets):

      https://graph.microsoft.com/beta/deviceManagement/autopilotEvents?$filter=(microsoft.graph.DeviceManagementAutopilotEvent/deploymentEndDateTime%20ge%20@{formatDateTime(addHours(utcNow(),-1),’yyyy-MM-ddTHH:mm:ssZ’)
      })

      Reply
      • Alex on December 8, 2021 16:22

        That doesn’t seem to work either. With the first one from the guide only get Unknown Error. Your query cant even be added.

        Reply
    4. Josh on May 17, 2022 15:48

      I implemented the version 2 using managed identity, everything appears to be working but I am not getting user information back – anyone else having this problem? If I query the graph for autopilotEvents or windowsAutopilotDeviceIdentities, userPrincipalName is blank there, however the MEM AutoPilot report under monitoring shows user information properly.

      Reply
    5. Kevin Pequeneza on August 22, 2022 18:01

      My results on the posted webhook always show the device name as the azure ad device ID. Any idea why that is?

      Reply
      • Peter Klapwijk on August 24, 2022 16:52

        Same for me, most of the time. This has been fine for a while, but unfortunately the last few months more often the device name isn’t reported back via Graph.

        Reply
    6. Rich Wells on March 22, 2023 15:21

      The following URI seem to work for me

      https://graph.microsoft.com/beta/deviceManagement/autopilotEvents?’$filter=microsoft.graph.DeviceManagementAutopilotEvent/deploymentEndDateTime%20ge%20′

      Reply
    Leave A Reply Cancel Reply

    Peter Klapwijk

    Hi! Welcome to my blog post.
    I hope you enjoy reading my articles.

    Hit the About Me button to get in contact with me or leave a comment.

    Awards
    Sponsor
    Latest Posts

    Update Windows Defender during Windows Autopilot enrollments

    May 16, 2025

    Hide the “Turn on an ad privacy feature” pop-up in Chrome with Microsoft Intune

    April 19, 2025

    How to set Google as default search provider with Microsoft Intune

    April 18, 2025

    Using Windows Autopilot device preparation with Windows 365 Frontline shared cloud PCs

    April 13, 2025
    follow me
    • Twitter 4.8K
    • LinkedIn 6.1K
    • YouTube
    • Bluesky 1.5K
    Tags
    Administrative Templates Android Automation Autopilot Azure Azure AD Browser Conditional Access Edge EMS Exchange Online Feitian FIDO2 Flow Google Chrome Graph Graph API Identity Management Intune Intune Monitoring iOS KIOSK Logic Apps macOS MEM MEMMonitoring Microsoft 365 Microsoft Edge Microsoft Endpoint Manager Modern Workplace Office 365 OneDrive for Business Outlook Passwordless PowerApps Power Automate Security SharePoint Online Teams Windows Windows 10 Windows10 Windows 11 Windows Autopilot Windows Update
    Copy right

    This information is provided “AS IS” with no warranties, confers no rights and is not supported by the authors, or In The Cloud 24-7.

     

    Copyright © 2025 by In The Cloud 24-7/ Peter Klapwijk. All rights reserved, No part of the information on this web site may be reproduced or posted in any form or by any means without the prior written permission of the publisher.

    Shorthand; Don’t pass off my work as yours, it’s not nice.

    Recent Comments
    • Adam on Get notified on expiring Azure App Registration client secrets
    • Peter Klapwijk on Update Windows Defender during Windows Autopilot enrollments
    • Rob van de Ven on Add a certificate to the Trusted Publishers with Intune without reporting errors
    • Carl on Update Windows Defender during Windows Autopilot enrollments
    • Peter Klapwijk on The next step in a passwordless Windows experience
    most popular

    Application installation issues; Download pending

    October 1, 2024

    Restrict which users can logon into a Windows 10 device with Microsoft Intune

    April 11, 2020

    How to change the Windows 11 language with Intune

    November 11, 2022

    Update Microsoft Edge during Windows Autopilot enrollments

    July 9, 2024
    Peter Klapwijk – In The Cloud 24-7
    X (Twitter) LinkedIn YouTube RSS Bluesky
    © 2025 ThemeSphere. Designed by ThemeSphere.

    Type above and press Enter to search. Press Esc to cancel.

    Manage Cookie Consent
    To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
    Functional Always active
    The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
    Preferences
    The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
    Statistics
    The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
    Marketing
    The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
    Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
    View preferences
    {title} {title} {title}