This site uses cookies and by using the site you are consenting to this. We utilize cookies to optimize our brand’s web presence and website experience. To learn more about cookies, click here to read our privacy statement.

Test your RESTful API using PowerShell

Before I get into the “how” on this topic, I want to start by addressing the “why” and “when”, as in “Why / When the heck would I want to do this?” Here are some situations I’ve run into or thought of where having a functional test script was (or could be) rather handy:

  1. You have unit tests for your API, but also want some “client-facing” tests as well.
  2. You want to make sure when a new build is posted, the routes operate as they did before.
  3. You inherited an API that you need to maintain, but there are no unit tests.
  4. You need to provide some kind of automated test for your application, but do not have time / budget to write a full suite of unit tests.
  5. You do not like writing unit tests, but still need some kind of test coverage solution.
  6. You REALLY like automated tests; can’t get enough of them :).

So now with some (mostly) real-world uses in mind, let’s take a look at how this can be accomplished with PowerShell. A link to my code is posted at the bottom of this column in the last paragraph; take a minute to read through it, then come back to the next paragraph. I want to point out a few nuances that will make more sense within the context of the code sample.

Finished? Cool – let’s dig into the nitty-gritty:

Invoke-RestMethod vs. Invoke-WebRequest

If you read the code carefully, you probably noticed that I’ve used two different PowerShell functions to call the API – Invoke-RestMethod and Invoke-WebRequest. Gah? Why not just use one or the other? Well, I ran into a known issue while writing a test script for an API I built recently, and this was the recommended workaround. Essentially, if you’re going to make multiple subsequent PUT or DELETE requests from a PowerShell script (which you’ll probably want to do at some point), Invoke-WebRequest is the method to use for those HTTP verbs.


Each of my RunRoute functions in the script has a $SecondsAllowed parameter. This allows you to do strict performance testing of your routes (should you choose to do so) by specifying the number of seconds until the route times out when you call each function using the -TimeoutSec parameter. If you don’t want to set a timeout for certain tests, just pass a zero.


I include this parameter on every request. According to the documentation, this tells PowerShell to “[establish] a persistent connection to the server to facilitate subsequent requests.” That seems harmless, but in a production setting, we have no clue IF there will be subsequent requests by the caller. I’ve noticed test scripts will run slightly faster without this parameter, which can disrupt the timing of the -TimeoutSec check discussed in the previous paragraph, and potentially cause you to get a false sense of “real-world” performance.


Invoke-RestMethod allows for a -Headers parameter, but I’m not using it in the code sample. The test API is very basic, and doesn’t require me to provide any headers to interact with it. However, I want to mention it here because you’ll likely need to add this to tests for a production API, since this is usually where you would exchange security information with the server. The param expects a hash object like so:

$RequestHeader = @{};
$RequestHeader.Add("Key", $Value);
Invoke-RestMethod ... -Headers $RequestHeader;

You can put as many custom headers into this collection as needed. Check the documentation for further details.


I don’t specify where to create the log file; it should default to – C:Users{your-name}. Simply update this variable to change the output location. The log will contain an entry for each RunRoute call you make, indicating PASS or FAIL of the executed route, as well as total run time for all of the routes in your script.

Here’s my script –  it’s available as a Gist on GitHub.

The API which I wrote the tests against (jsonplaceholder) is publicly accessible, so you should be able to just download the code and start running it. I’m hoping once you’ve done that and stepped through it a few times, it will be fairly clear how you can modify the structure I’ve provided to fit your specific API.