The Invoke-MgGraphRequest is a versatile cmdlet which allows you to make almost any call to the Microsoft Graph API without the need for additional cmdlets or Microsoft Graph modules. This is useful as you may not want to be reliant on other Microsoft Graph PowerShell modules but still want to make use of the Authentication module for simplicity.
In this tutorial, I am going to show you how to use the Invoke-MgGraphRequest cmdlet in the Microsoft Graph PowerShell SDK to make REST API requests to Microsoft Graph so you can view, edit and create resources in Microsoft 365 and Azure.
Page Contents
- How Invoke-MgGraphRequest works
- What is a REST URI?
- How to find your required REST URI
- How to create a request Body
- Testing our URI and Payload
- How to find the necessary permissions using Graph Explorer
- Building our script using the Invoke-MgGraphRequest cmdlet
- How to use the different methods; GET, POST, PUT, PATCH, DELETE
How Invoke-MgGraphRequest works
The Invoke-MgGraphRequest cmdlet works by making REST API requests to Microsoft Graph, which you can do by specifying the REST URI path, request body and request method parameters in your command.
Ideally, when working with Microsoft Graph PowerShell, you may have better control and can apply better logic when using the equivalent cmdlets to create, delete and update resources. However, not every task has a relevant cmdlet yet, so using the Invoke-MgGraphRequest cmdlet is especially useful to create resources which do not have supported cmdlets.
A full breakdown of parameters you can use with Invoke-MgGraphRequest is below:
Invoke-MgGraphRequest [[-Method] {GET | POST | PUT | PATCH | DELETE}]
[-Uri] <uri>
[[-Body] <Object>]
[[-Headers] <IDictionary>]
[[-OutputFilePath] <string>]
[[-InferOutputFileName]]
[[-InputFilePath] <string>]
[[-PassThru]] [[-Token] <securestring>]
[[-SkipHeaderValidation]]
[[-ContentType] <string>]
[[-Authentication] {Default | UserProvidedToken}]
[[-SessionVariable] <string>]
[[-ResponseHeadersVariable] <string>]
[[-StatusCodeVariable] <string>]
[[-SkipHttpErrorCheck]]
[[-GraphRequestSession] <GraphRequestSession>]
[[-UserAgent] <string>]
[[-OutputType] {HashTable | PSObject | HttpResponseMessage | Json}]
[-Break] [<CommonParameters>]
What is a REST URI?
The first piece off information you need to specify in your command when using the Invoke-MgGraphRequest cmdlet is the REST URI path. The URI (or Universal Resource Identifier) identifies where a specific resource can be found, in our case, in the Microsoft Graph API.
Let’s examine how a REST URI path is made up. For example, the rest URI path for a specific device registered to Microsoft Entra ID would be https://graph.microsoft.com/v1.0/devices/{id}. To break that down:
https://graph.microsoft.com/v1.0/devices/{id}
https://graph.microsoft.com – This is the hostname (or endpoint) of the Microsoft Graph service.
v1.0/ – This is the Microsoft Graph profile version.
devices/ – the is the path to the resource.
{id} – This is the unique resource id.
How to find your required REST URI
Whenever you make a request to Microsoft Graph you need to specify the URI path. With that, you of course need to know the path to the resource that you want to change. This is one of the added complexities when you don’t use one of the dedicated cmdlets.
There are various methods you can use to identify the path to the specific resource you need.
Option 1 is to use the Microsoft Graph Explorer site. You can access the Graph Explorer at: https://developer.microsoft.com/en-us/graph/graph-explorer
Start by searching for your desired resource under the resource heading, then select your resource from the list. You will see the URI appear in the text box highlighted below.
Option 2 is my preferred method. You can use developer tools (or the ‘Inspect’ feature) in your web browser to view the request header when creating a resource. So let’s say you want to change the category of a device in Intune. Start by opening up the device properties, then change the information you need. But before you click save, right-click the page and click Inspect.
Now select the Network tab like I have highlighted below:
Once you have the network tab selected, you can return and click Save on the device properties page. On the network tab, you will now see requests appear under the Name heading.
Select the request from the list which matches the action you have taken, the names will often be more meaningful than the below:
You can now see the full URI path that matches the action you want to take on the headers tabs to the right. Although you have already performed the action in the portal, you can utilise this new information to programmatically apply this change in the future or to multiple devices at once. The full output of the above, is below:
https://graph.microsoft.com/beta/deviceManagement/managedDevices('956a2c3b-bd8d-4339-9f26-3d1b034748f6')/deviceCategory/$ref
Also, take note of the request method (in this case, PUT) as we will use this later when constructing our request.
How to create a request Body
The request body, also known as the payload is the data that is sent back to Microsoft Graph (the API endpoint) that contains all the information about the request. The body of the request is sent to Microsoft Graph in JSON format, this format is extensively used by API clients and will usually contain information to create or update an existing resource.
Let’s have a look at an example body from our example above in option 2. Above we changed the category of a device in Intune and analysed the request headers using the inspect tool in our browser. To get the request body, we are going to do the same thing.
Follow the same process as above in option 2 to view the request, however, this time select the Payload tab, then view source.
You will now see the request payload in its raw JSON format:
We can then paste this code into the Microsoft Graph Explorer or an IDE of your choice to format it correctly. There are various online tools available that will automatically format your JSON code to improve its readability.
{
"@odata.id":"https://graph.microsoft.com/beta/deviceManagement/deviceCategories/3725a237-e0e4-4b0b-aab0-3868e12c8ba9"
}
Testing our URI and Payload
Before we begin any script development, it would be a good idea to test our URI and Payload to ensure it works as expected. I recommend you do this using the Microsoft Graph Explorer web tool provided by Microsoft.
Follow the below steps to test: (I will use the example URI and Payload we have used above)
2. Once logged in, paste the URI into the URL text box (to the left of ‘Run query’ button) and then paste the Payload into the Request body, as follows:
3. Before you run your query, make sure you head back into the portal to revert the change you originally made to gather the required information. Once we run the request in the Graph Explorer tool we can check it has been updated again in the portal to confirm the request works.
4. Lastly, change the request method to PUT and click Run query. In the case of this request, it was successful, however, the response was blank. But if we check the device properties from the Intune portal, they were updated as expected.
How to find the necessary permissions using Graph Explorer
One thing you cannot gather from extracting the request header and payload for your request using the inspect tool is the necessary permissions to perform the action you want.
There are a couple of convenient ways to identify what permissions are required…
The simplest option is to use the Microsoft Graph Explorer Modify Permissions tab which will tell you exactly which permissions are required to run your query. In the case of my test payload, you can see below which permissions were required.
Another option is to use the Find-MgGraphPermission cmdlet which will list all available permissions for Microsoft Graph.
Running the cmdlet alone will produce a lot of information and to understand each permission, you will need to read the description. To narrow this down, you can filter your results.
Find-MgGraphPermission | Where-Object {$_.Name -match "Device"}
Your results will look like the below:
Building our script using the Invoke-MgGraphRequest cmdlet
If you have followed the previous steps you should now have (or know how to get) all the information we need to build our PowerShell script so we can programmatically deploy or modify our resources. Again I will use the same example that we tested above in the Graph Explorer.
Here is our full example script: (keep scrolling for the breakdown).
#Connect to Microsoft Graph
Connect-MgGraph -Scopes DeviceManagementManagedDevices.ReadWrite.All
#Define the URI
$uri = @'
https://graph.microsoft.com/beta/deviceManagement/managedDevices('956a2c3b-bd8d-4339-9f26-3d1b034748f6')/deviceCategory/$ref
'@
#Define policy parameters
$json = @'
{
"@odata.id":"https://graph.microsoft.com/beta/deviceManagement/deviceCategories/3725a237-e0e4-4b0b-aab0-3868e12c8ba9"
}
'@
#Create policy
Invoke-MgGraphRequest -Uri $uri -Body $json -Method PUT -ContentType "application/json"
To break down the script so it is understood, I will trying to explain each section.
Firstly, I am going to connect to Microsoft Graph using the least amount of permissions needed to run our tasks.
Connect-MgGraph -Scopes DeviceManagementManagedDevices.ReadWrite.All
Here I am storing the URI path into the $uri variable. Notice how I am using the @’ and ‘@ surrounding my URI, these are called ‘Here Strings’. Here Strings are used to ensure the text between them is taken literally. Without the ‘Here Strings’, the $ref at the end of the URI would be taken as an empty variable.
$uri = @'
https://graph.microsoft.com/beta/deviceManagement/managedDevices('956a2c3b-bd8d-4339-9f26-3d1b034748f6')/deviceCategory/$ref
'@
We have done a similar thing to that above with our JSON payload:
$json = @'
{
"@odata.id":"https://graph.microsoft.com/beta/deviceManagement/deviceCategories/3725a237-e0e4-4b0b-aab0-3868e12c8ba9"
}
'@
Lastly, we are going to execute our command and make the change:
Invoke-MgGraphRequest -Uri $uri -Body $json -Method PUT -ContentType "application/json"
How to use the different methods; GET, POST, PUT, PATCH, DELETE
There are 5 different methods for retrieving and sending data to Microsoft Graph, I will break down what each of them means below.
The GET method
Using GET will retrieve data from the server about specific or multiple resources depending on the URI you specify. There is little risk in using the GET method as no changes are being made. For example, if we want to view all Conditional Access policies in our tenant, we can use the following:
#Define the URI
$uri = "https://graph.microsoft.com/beta/policies/conditionalAccessPolicies"
#Create policy
$policies = Invoke-MgGraphRequest -Uri $uri -Method GET
#Expand values
$policies.Values.values
The POST method
POST requests are used to create new resources, for example, if you want to create a new compliance policy in Microsoft Intune, you can use the below example:
$uri = "https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies"
$json = @'
{
"id":"00000000-0000-0000-0000-000000000000",
"displayName":"Temp1",
"roleScopeTagIds":["0"],
"@odata.type":"#microsoft.graph.windows10CompliancePolicy",
"scheduledActionsForRule":[
{
"ruleName":"PasswordRequired",
"scheduledActionConfigurations":[
{
"actionType":"block",
"gracePeriodHours":0,
"notificationTemplateId":"",
"notificationMessageCCList":[]
}]
}],
"deviceThreatProtectionRequiredSecurityLevel":"unavailable",
"passwordRequiredType":"deviceDefault",
"bitLockerEnabled":true,
"deviceThreatProtectionEnabled":false
}
'@
Invoke-MgGraphRequest -uri $uri -body $json -method POST -ContentType "application/json"
The PUT method
PUT requests are for updating resources, for example, if you want to change a property on a device in Intune, you would use a PUT request. Scroll up to review the example I gave when building our script using Invoke-MgGraphRequest.
The PATCH method
The PATCH method is similar to PUT but it will only apply specific updates to resources. For example, if we want to update the compliance policies we created with the POST method, we can use the following script:
$uri = "https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies/f048f8f0-5370-4ea6-979b-5dabc4f5329c"
$json = @'
{
"id":"f048f8f0-5370-4ea6-979b-5dabc4f5329c",
"displayName":"Temp1",
"description":null,
"roleScopeTagIds":["0"],
"@odata.type":"#microsoft.graph.windows10CompliancePolicy",
"bitLockerEnabled":true,
"codeIntegrityEnabled":true,
"tpmRequired":false,"validOperatingSystemBuildRanges":[],
"[email protected]":"https://graph.microsoft.com/beta/$metadata#deviceManagement/deviceCompliancePolicies('f048f8f0-5370-4ea6-979b-5dabc4f5329c')/microsoft.graph.windows10CompliancePolicy/assignments",
"[email protected]":"https://graph.microsoft.com/beta/$metadata#deviceManagement/deviceCompliancePolicies('f048f8f0-5370-4ea6-979b-5dabc4f5329c')/microsoft.graph.windows10CompliancePolicy/scheduledActionsForRule(scheduledActionConfigurations())"
}
'@
Invoke-MgGraphRequest -uri $uri -body $json -method PATCH -ContentType "application/json"
The DELETE method
The DELETE method as you may have guessed, allows you to delete specific resources. For example, we can use the below commands to delete the compliance policy we created and modified above:
$uri = "https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies/a7be0c3d-dd89-49c7-a464-f371e72b30d7"
Invoke-MgGraphRequest -uri $uri -method DELETE