How to Leverage Invoke-RestMethod for More Powerful Scripting – Part 1

invoke-restmethod

Invoke-RestMethod is an incredibly powerful Cmdlet in PowerShell. It is built into PowerShell so there are no additional modules needed, and it allows you to connect to any RESTful API out there. I want to spend some time digging in and really learning to leverage this tool for some truly powerful scripts. As someone who is not a developer, the idea of being able to interact with an API and leverage tools that normally are limited to developers is an awesome proposition. I’m always looking to automate processes and having REST API as another tool in the box is just what I needed.

DISCLAIMER

Please understand that the content herein is for informational purposes only. This existence and contents shall not create an obligation, liability or suggest a consultancy relationship. In further, such shall be considered as is without any express or implied warranties including, but not limited to express and implied warranties of merchantability, fitness for a particular purpose and non-infringement. There is no commitment about the content within the services that the specific functions of the services or its reliability, applicability or ability to meet your needs, whether unique or standard. Please be sure to test this process fully before deploying in ANY production capacity, and ensure you understand that you are doing so at your own risk.

Table of Contents

A few notes…
REST API Basics
Invoke-RestMethod
Conclusion

A few notes…

The truth is that this is newer to me, so I am far from an expert. I’ve been learning this out of necessity more than anything. In case you missed it, I wrote a previous article about How to use the Microsoft Graph PowerShell SDK. That is really where this journey started. The Microsoft Graph PowerShell SDK is a work in progress, and many things don’t exist yet. Plus the module is huge, and includes many different parts that need installed to leverage it. At this point, I’m a firm believer that the SDK is a great way to start interacting with MS Graph, and makes many scripts easier to write. Its powerful in its own right, and this post should not be taken as a statement against the SDK.

However, the more I learn, the more I have realized that including Invoke-RestMethod should also be included in this discussion. The PowerShell SDK for MS Graph doesn’t include things like getting a secret from a KeyVault to authenticate to an app registration. It doesn’t include a cmdlet for everything MS Graph can do. It doesn’t even have a cmdlet to remove all users from an Azure AD group. Leveraging Invoke-RestMethod will also allow our scripts to access more than just a single REST API in a single script, and potentially build integrations where none exist currently. Pretty cool huh? I think so…

Other resources

With all that said, here are some of my favorite resources for this stuff. These folks really know their stuff, and if something I say contradicts with them, go with them.


REST API Basics

First, it is helpful to understand a few things with a RESTful API before we get started. These will become foundational as we learn more, so it helps to get a few things out of the way now.

  • Not all REST API’s are the same, but they are pretty close. The idea behind having a standardized API is that it makes it easier for applications and interfaces to interact with each other. Developers can learn and maintain standard practices that don’t make their skills become too niche. This means that once you understand the basics of REST API, the main differences become nuances, not major learning curves.
    • For example, all RESTful API’s will have methods that are called to perform different functions. Examples of those include: (But aren’t limited to)
      • GET
      • POST
      • PUT
      • UPDATE
      • DELETE
  • REST API uses HTTP requests to perform all queries and commands. That means that each request will go to a URI that looks like an HTTP web address.
  • REST is a stateless connection, meaning there is no dedicated client-server relationship, and the connection is active only while the API call is running. This means that all information for the call is required on each call (meaning an access token or authorization details)
  • Query results, and changes being passed to an application are organized in standard formats like XML & JSON.
  • Documentation is KING. Since each REST API is a little different from the others, it is important to refer to the documentation from the developer of the API. Some may require a greater minimum of information to successfully complete a command than others.

Invoke-RestMethod

Invoke-RestMethod is the native cmdlet for PowerShell to pass along REST API commands. It is built into PowerShell, and doesn’t require any additional modules. This also means that PowerShell can collect REST query results and parse them to PowerShell objects automatically. This is helpful when trying to parse results of a JSON response that you need information from to continue further in a script.

REST API’s like Microsoft Graph often have their own content explorer that allows for testing and developing queries. Microsoft calls theirs the Graph Explorer, and it is useful when you are trying out new methods or new processes. However, there are also tools like Postman or the Thunder Client extension for VS code (my personal favorite), that allow for similar exploration of any given REST API. This is often the best place to start with a new API as you learn how it wants calls formatted and what information it returns.

Basic Structure

The basic structure of this cmdlet follows every other PowerShell command. After the cmdlet, the URI is the only default property that is required by PowerShell to run Invoke-RestMethod.

Invoke-RestMethod -uri https://blogs.msdn.microsoft.com/powershell/feed/

However, this doesn’t mean it is the minimum needed for every REST API. Each one is a little different, so you need to refer to the documentation to know for sure. For example, when working with some REST API’s, you need to include an authentication header and a method as well. For example, here we are including both an authorization header and method to be able to connect this this API

Invoke-RestMethod -uri https://graph.microsoft.com/v1.0/sites/ -Headers @{Authorization = "Bearer $($Token.access_token)"} -Method Get

The key takeaway here is that there is research and time spent in the documentation that is required for every REST API. Even if it is pretty standard, there are often nuances. Experience is probably the only way to cut down time in documentation, but even then you usually won’t know until you’ve read it.

Splatting for Readability

If you look at that last command, you might notice it is a little tricky to read, and is a very long one-liner. If you had this as a part of multiple lines of code, it might get difficult to find or edit. Add-in a BODY and other items in the header, and now it becomes unruly. One way of managing this, is to “Splatt” the information into Hashtables that can be read by Invoke-RestMethod as variables. For example, say that I needed to include a Content-Type in the header in addition to an authorization. It might look like this:

$apiUrl = "https://api.dropboxapi.com/2/team/members/list_v2"
$headers = @{
            "Authorization" = "Bearer $accessToken"
            "Content-Type" = "application/json"
        }
Invoke-RestMethod -Uri $apiURL -Headers $headers -Method POST

Suddenly, it becomes a little easier to read right? If I needed to change something, it would be much easier to do so now that I have it written this way. It is especially helpful when you have data for a body to pass along with the command. We’ll examine that after we talk about JSON.

Keep in mind, the hashtable is a standard format, so if you are having issues, it is probably formatting. (Although, isn’t that often the case). If you aren’t using VS Code for your scripting, I recommend checking it out, as it will help with formatting as you go.

Working with JSON

So more and more REST API’s are leveraging JSON, but you will still see some use XML or even other types of formatting for data being passed across the API. Essentially (from the brain of a non-developer over here), JSON is a standardized method of formatting strings and variables so that the API can read them easily both ways. PowerShell doesn’t normally store things in JSON, as it is not the standard for objects. However, the PowerShell developers were kind enough to give us a cmdlet that will convert it for us.

ConvertTo-JSON is a cmdlet that will take a single value or a hashtable of values and convert it to a JSON format that REST API can understand. Look at this example below:

$apiUrl = "https://api.dropboxapi.com/2/team/members/list_v2"
$headers = @{
            "Authorization" = "Bearer $accessToken"
            "Content-Type" = "application/json"
        }
$Data = @{
            "include_removed" = $false
            "limit" = 200
        }
$json = $data | ConvertTo-JSON
Invoke-RestMethod -Uri $apiURL -Headers $headers -Method POST -body $json

With this example, we are calling the API to provide a list of team members, using an authorization token, and we want to to return content in a JSON format. The body of the request includes filters that limit the results so that we don’t see more than we want. The information is then returned in a JSON format that PowerShell can recognize and convert to objects.

Working with Results

When I run the full version of that script above, I get results that look something like this:

api results from invoke-restmethod example API call

This script saves the results of the query into a variable $results, and will allow me to manipulate and extract what I need from them. Looking at these results do you notice anything significant about them? It looks like a bunch of hashtables right? Thanks PowerShell! Now we can run a command that looks like this:

($results.members).profile | Select-Object email,membership_type,status,joined_on

And that will give us information that looks like this:

results from invoke-restmethod query managed in a powershell way

At this point, we could easily recognize that it looks like normal PowerShell results, and could pass the email and joined_on results with no additional manipulation.

Now this is just one example, and isn’t guaranteed to match every REST API. I can’t say this enough, but you will have to consult the documentation to confirm that it will return results like this. In most cases you will just have to start playing with the API to see what you get back.


Conclusion

So there you have the basics to begin using Invoke-RestMethod in your scripting. This is a part one because that was hardly enough information to being making your scripts more powerful. However, it is important to understand the baseline of information needed to be successful with REST API. Keep in mind that it really is a programming interface, so there may be some challenges. Not to mention a lot of documentation will be written for developers, with code snippets in another language. You’ll have to spend some time in the documentation to really build out your knowledge about each API to get it right. But that is why we are here right?

Learning new things is one of my favorite hobbies, and I am really digging spending time learning this stuff. I hope you enjoy it too and that you stick around as we continue this journey. Leveraging RESTful API’s will help tremendously as the world becomes more connected and cloud based. You’ll be able to pull in more data, and make more intelligent scripts do the work that might otherwise take you significantly longer.

I love getting feedback, and look forward to hearing from you about this one. Be sure to come back for Part 2 where we will start looking at things like pagination and functions to formalize our scripting a bit more. As always, hit me up on Twitter @SeeSmittyIT to let me know what you thought of this post. Thanks for reading!

Smitty

Curtis Smith works in IT with a primary focus on Mobile Device Management, M365 Apps, and Azure AD. He has certifications from CompTIA and Microsoft, and writes as a hobby.

View all posts by Smitty →