---
title: "Working with REST APIs and PowerShell’s Invoke-RestMethod"
description: "Learn how to work with REST APIs using PowerShell’s Invoke-RestMethod cmdlet in this extensive tutorial!"
canonical: "https://adamtheautomator.com/invoke-restmethod/"
---

# Working with REST APIs and PowerShell’s Invoke-RestMethod

> Learn how to work with REST APIs using PowerShell’s Invoke-RestMethod cmdlet in this extensive tutorial!

Source: https://adamtheautomator.com/invoke-restmethod/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Working with REST APIs and PowerShell’s Invoke-RestMethod](https://adamtheautomator.com/wp-content/uploads/2021/06/How-to-Work-with-REST-APIs-and-PowerShells-Invoke-RestMethod.jpg)

# Working with REST APIs and PowerShell’s Invoke-RestMethod

[![](https://secure.gravatar.com/avatar/7d72048d0ab477855cc517014bf312a028d43de5905de92f66959463e53badde?s=192&d=mm&r=g)Ryan Kowalewski](https://adamtheautomator.com/author/ryan-kowalewski/)18 June 202116 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell Language](/tag/powershell-language/)

Table of Contents

*   [Invoke-RestMethod in a Nutshell](#h-invoke-restmethod-in-a-nutshell)
*   [Prerequisites](#h-prerequisites)
*   [Retrieving Data via a Simple GET request](#h-retrieving-data-via-a-simple-get-request)
*   [Authenticating to an API](#h-authenticating-to-an-api)
*   [Using a Username and Password with Basic Authentication](#h-using-a-username-and-password-with-basic-authentication)
*   [Using an API/OAuth Token with Bearer Authentication](#h-using-an-api-oauth-token-with-bearer-authentication)
*   [Retrieving Data with Using Query Parameters](#h-retrieving-data-with-using-query-parameters)
*   [Sending Data to an API with the POST HTTP Method](#h-sending-data-to-an-api-with-the-post-http-method)
*   [Sending JSON Data in a POST Request](#h-sending-json-data-in-a-post-request)
*   [Sending Form Data with Invoke-RestMethod](#h-sending-form-data-with-invoke-restmethod)
*   [Following Relation Links](#h-following-relation-links)
*   [Maintaining Session Information](#h-maintaining-session-information)
*   [Overriding Session Values](#h-overriding-session-values)
*   [Saving the Response Body to a File](#h-saving-the-response-body-to-a-file)
*   [Working with SSL and Certificates](#h-working-with-ssl-and-certificates)
*   [Skipping Certificate Validation](#h-skipping-certificate-validation)
*   [Specifying a Client Certificate for a Request](#h-specifying-a-client-certificate-for-a-request)
*   [Restricting SSL/TLS Protocols](#h-restricting-ssl-tls-protocols)
*   [Other Interesting Features](#h-other-interesting-features)
*   [Using a Proxy Server](#h-using-a-proxy-server)
*   [Skipping Checks and Validation](#h-skipping-checks-and-validation)
*   [Disabling Keep Alive](#h-disabling-keep-alive)
*   [Changing the Encoding Type](#h-changing-the-encoding-type)
*   [Conclusion](#h-conclusion)

Do you often access [application programming interfaces](https://www.redhat.com/en/topics/api/what-are-application-programming-interfaces) (APIs) using PowerShell? Maybe you want to but don’t know where to start? Whether you’re a PowerShell pro or just starting, this tutorial has you covered with a built-in PowerShell cmdlet that interacts with APIs called [`Invoke-RestMethod`](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7.1#parameters).

Not a reader? Watch this related video tutorial!

**_Not seeing the video? Make sure your ad blocker is disabled._**

In this article, you’ll learn many different ways to work with [representational state transfer](https://www.redhat.com/en/topics/api/what-is-a-rest-api) (REST) APIs from using GET and POST requests, covering authentication, how to download files, and more!

## Invoke-RestMethod in a Nutshell

When you need to retrieve or send data to a REST API, you need a client. In the PowerShell world, that client is the `Invoke-RestMethod` cmdlet. This cmdlet sends HTTP requests using various [HTTP methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) to REST API endpoints.

HTTP methods then instruct REST APIs to carry out various actions to be performed on a resource.

> _The official HTTP methods are GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, and PATCH, although some APIs may implement custom methods._

The `Invoke-RestMethod` cmdlet supports all HTTP methods, including authentication, sending different HTTP headers, HTTP bodies, and also automatically translates JSON and XML responses to PowerShell objects. The `Invoke-RestMethod` cmdlet is _the_ PowerShell cmdlet to interact with REST APIs!

## **Prerequisites**

If you’d like to follow along with the many demos in this tutorial, be sure that you have:

*   [PowerShell](https://github.com/PowerShell/PowerShell/releases) 7.0 or later installed. This tutorial uses a Windows 10 machine and PowerShell 7.1.

Without further ado, open your PowerShell console and/or code editor and let’s get started!

## Retrieving Data via a Simple GET request

Let’s start things off with the simplest example out there; querying a REST API with a GET request. `Invoke-RestMethod` can do a lot, but you need to understand the basics first.

To send a simple GET request to a REST API endpoint, you’ll only need one parameter, `Uri`. The `Uri` parameter is what tells `Invoke-RestMethod` where the endpoint is.

For example, run the command below. This command queries the [JSONPlaceholder](http://jsonplaceholder.typicode.com) APIs `posts` endpoint and returns a list of `post` resources.

> _The JSONPlaceholder site offers a free fake API for testing, which is used to demonstrate real examples of queries with the `Invoke-RestMethod` command._

```powershell
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts"
```

![Partial output from JSONPlaceholder API posts endpoint.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T105227.919.png)

Partial output from JSONPlaceholder API posts endpoint.

When the REST endpoint https://jsonplaceholder.typicode.com/posts returns data, it doesn’t return it in nice PowerShell objects, as you see above. Instead, it returns data in JSON. `Invoke-RestMethod` automatically converted the JSON to PowerShell objects for you.

You can see below that PowerShell converted the output to the [`PSCustomObject` type](https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.1) by looking at a single item in the PowerShell array and running the `GetType()` method on it.

Related:[Build Better Scripts with PowerShell ArrayLists and Arrays](https://adamtheautomator.com/powershell-array/)

```powershell
# Store the API GET response in a variable ($Posts).
$Posts = Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts"

# Run the GetType() method against the first item in the array, identified by its index of 0.
$Posts[0].GetType()
```

![Output showing the automatic conversion of the JSON response to PowerShell's PSCustomObject type.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T105347.482-1024x125.png)

Output showing the automatic conversion of the JSON response to PowerShell’s PSCustomObject type.

## **Authenticating to an API**

In the previous section, you queried a public REST API using the GET method. The API didn’t require any authentication. Much of the time, though, you must authenticate to a REST API somehow.

Two of the most common ways to authenticate to a REST API is using [Basic](https://swagger.io/docs/specification/authentication/basic-authentication/) (username/password) or [Bearer](https://swagger.io/docs/specification/authentication/bearer-authentication/) (token) authentication. To differentiate between these two wildly different authentication schemes requires using an [Authorization HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) when sending the request.

Let’s now cover how you can use `Invoke-RestMethod` to send HTTP headers (especially the Authorization HTTP header) to REST endpoints.

> _The `Invoke-RestMethod` abstracts away a lot of the tedium to sending HTTP requests. Even though you must provide an Authorization header in an HTTP request, you’ll see no references to “headers” in this example. Abstracting away concepts like this is common with the `Invoke-RestMethod` cmdlet._

### Using a Username and Password with Basic Authentication

The simplest way to authenticate to a REST endpoint is using a username and password. To capture that username and password, you must pass a PSCredential object to the endpoint that contains the username and password.

Related:[Using the PowerShell Get-Credential Cmdlet and all things credentials](https://adamtheautomator.com/powershell-get-credential/)

First, create the PSCredential object containing the username and password.

```bash
# This will prompt for credentials and store them in a PSCredential object.
$Cred = Get-Credential
```

Once you have a PSCredential object stored in a variable, pass the required URI to the command but this time add the `Authentication` and `Credential` parameter.

Setting the `Authentication` parameter sends an authorization HTTP header containing the word `Basic`, followed by a `base64` encoded `username:password` string like `Authorization: Basic ZGVtbzpwQDU1dzByZA==`.

The `Credential` parameter accepts the PSCredential you created earlier.

> _The below example and many more in this tutorial use a concept called PowerShell splatting that allows you to define parameters in a [hashtable](https://docs.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.1) and then pass to the command. Learn more about splatting in the [ATA post PowerShell Splatting: What is it and how does it work?](https://adamtheautomator.com/powershell-splatting/)_

```powershell
# Send a GET request including Basic authentication.
$Params = @{
	Uri = "https://jsonplaceholder.typicode.com/posts"
	Authentication = "Basic"
	Credential = $Cred
}

Invoke-RestMethod @Params
```

![Partial output from JSONPlaceholder API posts endpoint using basic authentication.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T105824.858.png)

Partial output from JSONPlaceholder API posts endpoint using basic authentication.

> _If you use the `Credential` or `Authentication` parameter option with a `Uri` that does not begin with https://, `Invoke-RestMethod` will return an error for security reasons. The override this default behavior, use the `AllowUnencryptedAuthentication` parameter [at your own risk.](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#security_of_basic_authentication)_

### Using an API/OAuth Token with Bearer Authentication

Basic username and password authentication are OK, but it’s not great. Credentials are simply encoded as base64 (not encrypted) which opens up security issues. To address this, APIs usually implement a token authentication system or Bearer/OAuth authentication.

To authenticate to a REST API with an OAuth token:

1\. Obtain the OAuth token from your API. How this token is obtained will depend on your API provider.

2\. Next, convert your token string into a secure string with the [`ConvertTo-SecureString` cmdlet](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwi7z6mcpZfxAhUBQ80KHTxGAA4QFnoECAMQAA&url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fpowershell%2Fmodule%2Fmicrosoft.powershell.security%2Fconvertto-securestring&usg=AOvVaw3MyW7TLfzu992jWHD6WHe0), as shown below. The `Invoke-RestMethod` requires the token to be a secure string.

```powershell
$Token = "123h1v23yt2egv1e1e1b2ei1ube2iu12be" | ConvertTo-SecureString -AsPlainText -Force
```

3\. Finally, define and pass the `Uri`, `Authentication` type, and `Token` to the `Invoke-RestMethod` cmdlet. `Invoke-RestMethod` will then call the URI provided and add the token to the Authorization HTTP header.

> _The `Authentication` parameter argument `OAuth` is an alias for `Bearer`. You can use both of these parameter values interchangeably._

```powershell
# Send a GET request including bearer authentication.
 $Params = @{
     Uri = "https://jsonplaceholder.typicode.com/posts"
     Authentication = "Bearer"
     Token = $Token
 }
 Invoke-RestMethod @Params
```

![Partial output from JSONPlaceholder API posts endpoint using bearer token authentication.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T110216.698.png)

Partial output from JSONPlaceholder API posts endpoint using bearer token authentication.

## Retrieving Data with Using Query Parameters

Typically, sending a GET request to a REST API is more involved than just a simple, generic request to an endpoint. Instead, you need to pass parameters to specify exactly what you need from the API; you need to pass HTTP query parameters.

To send query parameters with `Invoke-RestMethod`, you have two options. You can either directly append the parameters to the URI, as shown below, which passes a `userId` of `1` and an `id` of `8`.

```powershell
https://jsonplaceholder.typicode.com/posts?userId=1&id=8
```

Or, you could define the parameters in the HTTP body using the `Body` parameter as a hashtable. Let’s cover how to pass parameters to an endpoint using the `Body` parameter.

Create a hashtable containing the query parameter key/value pairs, as follows.

```powershell
$Body = @{
    userId = 1
    id = 8
}
```

Finally, provide the `$Body` variable to the `Body` parameter, as shown below.

> _You can specify the `Method` parameter using a value of `GET` or exclude the `Method` parameter or `Invoke-RestMethod` to default to the value._

```powershell
$Params = @{
	Method = "Get"
	Uri = "https://jsonplaceholder.typicode.com/posts"
	Body = $Body
}

Invoke-RestMethod @Params
```

You can now see below that the endpoint only returns the post item you’re looking for.

![Querying API with HTTP query parameters with Invoke-RestMethod](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T110342.571.png)

Querying API with HTTP query parameters with Invoke-RestMethod

## Sending Data to an API with the POST HTTP Method

In the previous examples, you were querying data from a REST API or using HTTP GET requests. You were _reading_ the data it sent back, but reading is only half the story with many REST APIs. REST APIs must support a full [CRUD model](https://www.codecademy.com/articles/what-is-crud) so you can interact with the service.

When you need to make changes to a service providing an API, you won’t use a GET HTTP request; you’ll use a “writable” request like POST.

> _You’ll also typically need to pass an HTTP body with requests when using any “writable” HTTP method like PUT or PATCH._

### Sending JSON Data in a POST Request

Using the previous REST API endpoint, let’s now _create_ a new post item rather than just reading them.

1\. First, create a hashtable including all of the attributes for the posts API endpoint. You’ll see below that the tutorial’s specific endpoint allows you to create a new post item with a `title`, `body` and `userId`.

```powershell
$Body = @{
     title = "foo"
     body = "bar"
     userId = 1
 }
```

2\. Next, convert the hashtable represented in the `$Body` variable to a JSON string storing it in a new variable `$JsonBody`.

> _REST endpoints don’t know what a PowerShell hashtable is, and you must convert the object into a language that the REST API understands. Creating a hashtable first is optional. You could type up the JSON directly and skip this step if you wanted to._

```powershell
$JsonBody = $Body | ConvertTo-Json
```

3\. Finally, craft the required parameters and run `Invoke-RestMethod`. Notice below that you must now use the `Method` parameter with a value of `Post`. Without using the `Method` parameter, `Invoke-RestMethod` defaults to sending a GET request.

Also, many REST APIs require you to specify the `ContentType` indicating the [HTTP Content-Type header](https://www.geeksforgeeks.org/http-headers-content-type/) the `Body` is stored in. In this example, you must use `application/json`.

```powershell
# The ContentType will automatically be set to application/x-www-form-urlencoded for
# all POST requests, unless specified otherwise.
 $Params = @{
     Method = "Post"
     Uri = "https://jsonplaceholder.typicode.com/posts"
     Body = $JsonBody
     ContentType = "application/json"
 }
 Invoke-RestMethod @Params
```

Notice below that the API returns a post item along with an `id` for that new post.

![Sending a JSON POST with Invoke-RestMethod](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T110620.275.png)

Sending a JSON POST with Invoke-RestMethod

### Sending Form Data with `Invoke-RestMethod`

Some REST API endpoints may require you to submit data via the [`multipart/form-data`](https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2) HTTP content type. To send a different content type with `Invoke-RestMethod` is a bit easier than using JSON. Since PowerShell 6.1.0, you can now use the `Form` parameter.

The `Form` parameter provides a convenient way to add `multipart/form-data` objects to a request without the need to use the .NET [`System.Net.Http.MultipartFormDataContent`](https://docs.microsoft.com/en-us/dotnet/api/system.net.http.multipartformdatacontent?view=net-5.0) class directly.

To send form data with `Invoke-RestMethod`, first, create a hashtable with each item as before.

```powershell
$Form = @{
    title = "foo"
    body = "bar"
    userId = 1
}
```

> _Notice using the `Form` parameter; you don’t need to use the `Body` parameter. Also, if you attempt to specify the `ContentType` and the `Form` parameter together, `Invoke-RestMethod` will ignore the `ContentType` parameter._

Finally, simply pass the hashtable to the `Form` parameter, as shown below.

```powershell
$Params = @{
	Method = "Post"
	Uri = "https://jsonplaceholder.typicode.com/posts"
	Form = $Form
}

Invoke-RestMethod @Params
```

![Submitting Form Content type using the Invoke-RestMethod cmdlet](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T110948.672.png)

Submitting Form Content type using the Invoke-RestMethod cmdlet

## **Following Relation Links**

Rather than returning massive datasets in one go, APIs often return “pages” of data. For example, the GitHub Issues API returns 30 issues per page by default. Some APIs include links to the next (or previous, last, etc.) page of data the response to help navigate the dataset known as [relation links](https://datatracker.ietf.org/doc/html/rfc5988#page-6).

To find relation links an API returns, you must inspect the HTTP response headers. One easy way to do that is to use the `ResponseHeadersVariable` parameter. This parameter automatically creates a variable and stores the headers in a hashtable.

Let’s use the PowerShell GitHub repo’s issues as an example.

1\. Make a GET request to the PowerShell GitHub repo’s issues endpoint, as shown below. Be sure to use the `ResponseHeadersVariable` to create a variable. The below example uses the `$Headers` variable.

```powershell
# Issue GET request to GitHub issues API for the PowerShell project repo and store
# the response headers in a variable ($Headers).
 Invoke-RestMethod -Uri "https://api.github.com/repos/powershell/powershell/issues" -ResponseHeadersVariable "Headers"
# Print the $Headers variable to the console.
 $Headers
```

Notice below that the hashtable inside of the `$Headers` variable has a key called `Links`. This key contains the relation links for the response that indicates the data set is bigger than just this one response.

![Response headers from request to GitHub issues API showing relation links.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled_2.png)

Response headers from request to GitHub issues API showing relation links.

2\. Next, follow the relation links using the `FollowRelLink` parameter. This parameter automatically reads each of the relation links and issues a GET request for each of them.

The below code snippet is following each relation link up to three. In this example, the `Invoke-RestMethod` cmdlet will stop querying for issues once it hits 90 (30 items per request) using the

```powershell
$Params = @{
   Uri = "https://api.github.com/repos/powershell/powershell/issues"
     FollowRelLink = $true
     MaximumFollowRelLink = 3
 }
 Invoke-RestMethod @Params
```

When using the `FollowRelLink` parameter, `Invoke-RestMethod` returns an array of objects (`Object[]`). Each item in the array contains the response from one of the relation links, which could be another array of objects itself!

![Partial output from request to GitHub issues API using FollowRelLink parameter.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T111525.982.png)

Partial output from request to GitHub issues API using FollowRelLink parameter.

3\. Re-run the previous example but this time check on the returned results from the initial query. You’ll see a count of only `3`, meaning three “pages.” But you’ll see that the first page of items (`$Results[0]`) contains 30 items.

```powershell
$Params = @{
   Uri = "https://api.github.com/repos/powershell/powershell/issues"
     FollowRelLink = $true
     MaximumFollowRelLink = 3
 }
 # Store the three pages of results in the $Results variable.
 $Results = Invoke-RestMethod @Params
 # Check that $Results contains three items (pages of issues from the GitHub issues API).
 $Results.Count
 # Check that the first item in the $Results array contains the first page of thirty issues.
 $Results[0].Count
```

![Output showing the nested arrays returned by the FollowRelLink parameter.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T111641.958.png)

Output showing the nested arrays returned by the FollowRelLink parameter.

4\. Finally, iterate over each item in the `$Results` variable using a `foreach` loop. You’ll see below you’ll have to iterate over each page with a `foreach` loop. Then, for each page, iterate over all of the items in that page requiring a nested loop.

Related:[Back to Basics: The PowerShell ForEach Loop](https://adamtheautomator.com/powershell-foreach/)

```powershell
# This might be different depending on the data structure of the API you are using.
# 1) $Results.ForEach({}) - this loops through each page in the $Results array.
# 2) $_.ForEach({}) - this loops through each item in the current page.
# 3) $_ - this simply returns each item to the pipeline.
 $AllResults = @( $Results.ForEach({ $_.ForEach({ $_ }) }) )
# Check that the $AllResults variable contains all ninety items.
 $AllResults.Count
```

![Output showing all ninety GitHub issues in a single array ($AllResults).](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T111819.362.png)

Output showing all ninety GitHub issues in a single array (`$AllResults`).

## **Maintaining Session Information**

When working with APIs, it’s often useful to store information related to a previous request such as headers, credentials, proxy details, and cookies, to re-use in subsequent requests. All of this information is stored in a session.

The `Invoke-RestMethod` can leverage sessions by storing the session using the `SessionVariable` parameter and then referencing that session using the `WebSession` parameter.

To demonstrate, call the _posts_ endpoint again and this time use the `SessionVariable` parameter, as shown below. In this example, `Invoke-RestMethod` will create a variable called `MySession`.

> _Remember, the session object isn’t a persistent connection. A session is simply an object that contains information about the request._

```powershell
# Invoke the request storing the session as MySession.
# The SessionVariable value shouldn't include a dollar sign ($).
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -SessionVariable "MySession"

# Print the session object to the console.
$MySession
```

![Output showing the session object properties.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T111930.719.png)

Output showing the session object properties.

Now, re-use the session information by calling `Invoke-RestMethod` with the `WebSession` parameter. As you can see in the following example, all previous session values are passed via the `$MySession` variable in the new request.

```powershell
# Invoke the request using the session information stored in the $MySession variable.
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -WebSession $MySession
```

![Partial output showing the re-use of a stored session ($MySession).](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T112009.089.png)

Partial output showing the re-use of a stored session ($MySession).

### Overriding Session Values

A session contains various information about the request. If you want to re-use the session but change a value, you can override it.

Perhaps, you’d like to re-use the session previously created but now authenticate with a username and password. Let’s first see what the before situation looks like.

Notice below that the `$MySession` object does not contain any value for the `Credentials` property. But, after invoking `Invoke-RestMethod` again using the `Credential` parameter, the REST endpoint receives the credential even though it wasn’t in the session.

```powershell
# Print the $MySession variable to the console to demonstrate that the Credentials
# property is empty.
$MySession

# Override the session value by specifying the Credential parameter.
# In this example you will be prompted for the username and password.
$Params = @{
	Uri = "https://jsonplaceholder.typicode.com/posts"
	WebSession = $MySession
	Credential = (Get-Credential)
}

Invoke-RestMethod @Params
```

> _The property in the saved session is named `Credentials`, but the parameter name is `Credential`. The names will not always match._

![Overriding Credentials value in session variable ($MySession) by specifying the Credential parameter.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T112057.462.png)

Overriding Credentials value in session variable ($MySession) by specifying the Credential parameter.

## **Saving the Response Body to a File**

Sometimes it will be necessary to save the response from a request to a file. To do that, use the `OutFile` parameter.

Run `Invoke-RestMethod` again to query the tutorial’s testing endpoint but this time use the `OutFile` parameter and provide a file path.

You’ll see below that `Invoke-RestMethod` queries the endpoint, returns the response in JSON format, and then saves the raw JSON into the _.\\my-posts.json_ file.

> _You can also use the `PassThru` parameter to return the response to the console and save a file with the response at once._

```powershell
# Save post items to my-posts.json in the current directory.
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -OutFile "my-posts.json"

# Print the contents of the JSON file to the console.
# ".\" in this command refers to the current working directory in your terminal session.
Get-Content -Path ".\my-posts.json"
```

![Partial output of the contents of my-posts.json.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T112159.969.png)

Partial output of the contents of my-posts.json.

Once you have the response saved as JSON in a file, you can parse it for information as you’d like. Below you’ll find a good example of finding a post with a specific ID.

```powershell
# Save the response to "my-posts.json" and also in the $Posts variable using PassThru.
$Posts = Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -OutFile "my-posts.json" -PassThru

# Filter posts with 1 as the userId into a new variable ($User1Posts).
$User1Posts = $Posts.Where({$_.userId -eq 1})

# Import all posts from the "my-posts.json" file and store them in the $AllUserPosts variable.
$AllUserPosts = Get-Content -Path ".\my-posts.json" | ConvertFrom-Json

# Print the count of both variables to the console to demonstrate that they are different.
$User1Posts.Count
$AllUserPosts.Count
```

![Output showing how to use PassThru to store results in a variable and a file in the same command.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T112256.130.png)

Output showing how to use PassThru to store results in a variable and a file in the same command.

## Working with SSL and Certificates

Throughout this tutorial, you’ve only been working with HTTP. HTTPS and SSL haven’t come into the picture. But that doesn’t mean `Invoke-RestMethod` won’t work with SSL. In fact, it can manage just about anything you need.

### Skipping Certificate Validation

By default, `Invoke-RestMethod` validates any SSL site’s certificate to ensure it’s not expired, revoked, or the trust chain is intact. Although this behavior is a security feature you _should_ leave on, there are times, like when testing, you need to disable it.

Related:[New-SelfSignedCertificate: Creating Certificates with PowerShell](https://adamtheautomator.com/new-selfsignedcertificate/)

To skip certificate validation, use the `SkipCertificateCheck` parameter. This parameter removes all certificate validation `Invoke-RestMethod` typically runs.

### Specifying a Client Certificate for a Request

If you need to specify a client certificate for a particular request, use `Invoke-RestMethod`‘s `Certificate` parameter. This parameter takes an [`X509Certificate`](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate?view=net-5.0) object as its value which you can retrieve using the `Get-PfxCertificate` command or the `Get-ChildItem` command from within the `Cert:` [PSDrive](https://docs.microsoft.com/en-us/powershell/scripting/samples/managing-windows-powershell-drives?view=powershell-7.1).

For example, the following command uses a certificate from the `Cert:` drive to make a request to the JSONPlaceholder APIs `posts` endpoint.

```powershell
# Change location into your personal certificate store.
Set-Location "Cert:\CurrentUser\My\"

# Store the certificate with the thumbprint DDE2EC6DBFF56EE9C375A6073C97188ABAA4F5E4 in a variable ($Cert).
$Cert = Get-ChildItem | Where-Object {$_.Thumbprint -eq "DDE2EC6DBFF56EE9C375A6073C97188ABAA4F5E4"}

# Invoke the command using the client certificate.
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -Certificate $Cert
```

![Using a client certificate when making a GET request.](https://adamtheautomator.com/wp-content/uploads/2021/06/Untitled-2021-06-17T112441.423.png)

Using a client certificate when making a GET request.

### Restricting SSL/TLS Protocols

By default, all SSL/TLS protocols supported by your system are allowed. But, if you need to restrict a request to a specific protocol version(s), use the `SslProtocol` parameter.

Using the `SslProtocol`, you can specifically call a URI with a [version of TLS](https://docs.microsoft.com/en-us/dotnet/api/microsoft.powershell.commands.websslprotocol?view=powershellsdk-7.0.0) from v1, 1.1, 1.2 and 1.3 as an array.

```powershell
# Restrict the request to only allow SSL/TLS 1.2 and 1.3 protocol versions.
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -SslProtocol @("Tls12", "Tls13")
```

> _On non-Windows platforms, you may not have `Tls` or `Tls12` as an option. Support for `Tls13` is not available on all operating systems and will need to be verified on a per operating system basis. `Tls13` is only available in PowerShell 7.1+._

## Other Interesting Features

To wrap up this tutorial, let’s finish off with some useful parameters but don’t necessarily need an instruction section.

## Using a Proxy Server

Corporate environments often use proxy servers to manage internet access. To force `Invoke-RestMethod` to proxy its request through a proxy, use the `Proxy` parameter.

If you need to authenticate to the proxy, either supply a `PSCredential` object to the `ProxyCredential` parameter or use the switch parameter `ProxyUseDefaultCredentials` to use the currently logged-on user’s credentials.

```powershell
# Invoke request using proxy server <http://10.0.10.1:8080> and the current user's credentials.
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -Proxy "http://10.0.10.1:8080" -ProxyUseDefaultCredentials
```

## Skipping Checks and Validation

> _Using these parameters can expose you to potential security risks. You’ve been warned!_

The `Invoke-RestMethod` cmdlet has many different checks it does under the hood. If you’d prefer to disable these checks for some reason, you can do with with a few parameters.

*   **SkipHeaderValidation** – Disable validation for values passed to the `ContentType`, `Headers`, and `UserAgent` parameters.
*   **SkipHttpErrorCheck** – Any errors will be ignored. The error will be written to the pipeline before processing continues.
*   **StatusCodeVariable** – When using `SkipHttpErrorCheck`, you might need to check the HTTP response status code to identify success or failure messages. The `StatusCodeVariable` parameter will assign the status code integer value to a variable for this purpose.

### Disabling Keep Alive

[TCP Keep Alive](https://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html) is a handy network-level feature that allows you to create a persistent connection to a remote server (if the server supports it). By default, `Invoke-RestMethod` does not use Keep Alive.

If you’d like to use Keep Alive, potentially reducing the CPU and memory usage of the remote server, set the `DisableKeepAlive` parameter to `$false`.

```powershell
Invoke-RestMethod -Uri "https://jsonplaceholder.typicode.com/posts" -DisableKeepAlive $false
```

### Changing the Encoding Type

Whenever `Invoke-RestMethod` sends a request to a remote endpoint, it encodes the request using a [transfer-encoding header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding). By default, `Invoke-RestMethod` and the server negotiate this encoding method, but you can explicitly define an encoding type with the `TransferEncoding` parameter.

If you’d like to change the encoding type, you may do using:

*   Chunked
*   Compress
*   Deflate
*   GZip
*   Identity

## Conclusion

In this tutorial, you’ve learned how `Invoke-RestMethod` makes interacting with REST APIs much easier than with standard web requests. You’ve looked at parameters for authentication, sending data in the body of a request, maintaining session state, downloading files, and much more.

Now that you’re up to speed on `Invoke-RestMethod` and working with REST APIs, what REST API will you try this handy cmdlet on?

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Finvoke-restmethod%2F&text=Working%20with%20REST%20APIs%20and%20PowerShell%E2%80%99s%20Invoke-RestMethod)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Finvoke-restmethod%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Finvoke-restmethod%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2023/08/powershell-approved-verbs.jpg)

### [Your Getting Started Guide to PowerShell Approved Verbs](/powershell-approved-verbs/)

Discover how to get started with PowerShell Approved Verbs to make sure your scripts and code is top-notch in this ATA Learning tutorial!

![](https://adamtheautomator.com/wp-content/uploads/2023/07/powershell-sort-object.jpg)

### [Learning PowerShell Sort-Object with Examples](/powershell-sort-object/)

Learn all of the ins-and-outs of the PowerShell Sort-Object cmdlet in this example driven tutorial by ATA Learning!

![](https://adamtheautomator.com/wp-content/uploads/2023/03/powershell-change-directory.jpg)

### [PowerShell Change Directory: Navigating Your File System](/powershell-change-directory/)

Learn how to use the PowerShell change directory command to navigate your file system with ease. Master the basics of PowerShell file navigation today.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
