Ironman Software Forums
Continue the conversion on the Ironman Software forums. Chat with over 1000 users about PowerShell, PowerShell Universal, and PowerShell Pro Tools.
Invoke-RestMethod
is an alternative to Invoke-WebRequest
that makes it easy to integrate PowerShell with HTTP REST API services. In this post, we’ll look at how to integrate with REST APIs with Invoke-RestMethod
.
In this post, we’ll use PowerShell Universal to produce web APIs. You can learn how to create REST APIs with PowerShell Universal here. You’ll find examples throughout this post as well.
HTTP provides numerous verbs that define how an API is intended to react including GET, POST, PUT and DELETE. You can specify the method by using the -Method
parameter of Invoke-RestMethod
.
GET is intended for retrieving data. GET methods should not change state in the REST API.
Let’s assume we have a basic API such as this.
New-PSUEndpoint -URL /user -Endpoint {
@(
[PSCustomObject]@{ UserName = "adam"; FirstName = "Adam"; LastName = "Driscoll" }
[PSCustomObject]@{ UserName = "bruce"; FirstName = "Bruce"; LastName = "Willis" }
[PSCustomObject]@{ UserName = "tom"; FirstName = "Tom"; LastName = "Hanks" }
)
}
To invoke this API method, you can invoke the following cmdlet call. Invoke-RestMethod
will inspect the Content-Type
header and deserialize the JSON data into a PSCustomObject that you can use.
$Objs = Invoke-RestMethod http://localhost:5000/user
$Objs.UserName
POST methods are intended for creating new entities with a REST API. POST methods typically accept a body and will return the result of the entity creation. You can POST data by passing objects to the -Body
parameter of Invoke-RestMethod
.
By default, the body will be an application/w-xxx-form-urlencoded
content type.
In this example, we can create an API that accepts a couple of parameters. Each form field will be mapped to the parameter in the endpoint.
New-PSUEndpoint -URL /user -Method POST -Endpoint {
param(
[Parameter(Mandatory)]
$UserName,
[Parameter(Mandatory)]
$FirstName,
[Parameter(Mandatory)]
$LastName
)
[PSCustomObject]@{
UserName = $UserName
FirstName = $FirstName
LastName = $LastName
}
}
To invoke this API, you can call Invoke-RestMethod
with a -Body
parameter that has a hashtable that includes values for each parameter.
Invoke-RestMethod http://localhost:5000/user -Method POST -Body @{
UserName = "adamdriscoll"
FirstName = "Adam"
LastName = "Driscoll"
}
The Invoke-RestMethod
call will return the object as a PSCustomObject.
The PUT method is typically used for updating entities in a REST API. Similar to the POST method, you will usually send a entity body of some kind.
In this example, we can create an API that accepts a couple of parameters. Each form field will be mapped to the parameter in the endpoint.
New-PSUEndpoint -URL /user -Method PUT -Endpoint {
param(
[Parameter(Mandatory)]
$UserName,
[Parameter(Mandatory)]
$FirstName,
[Parameter(Mandatory)]
$LastName
)
[PSCustomObject]@{
UserName = $UserName
FirstName = $FirstName
LastName = $LastName
}
}
Unlike the POST method, with PUT, you will need to specify the content type.
Invoke-RestMethod http://localhost:5000/user -Method PUT -Body @{
UserName = "adamdriscoll"
FirstName = "Adam"
LastName = "Driscoll"
} -ContentType 'application/x-www-form-urlencoded'
The DELETE method is used for deleting entities within a REST API. This example does not use a body but rather a route parameter to filter out the item we are deleting.
New-PSUEndpoint -URL /user/:id -Method DELETE -Endpoint {
@(
[PSCustomObject]@{ Id = 1; UserName = "adam"; FirstName = "Adam"; LastName = "Driscoll" }
[PSCustomObject]@{ Id = 2; UserName = "bruce"; FirstName = "Bruce"; LastName = "Willis" }
[PSCustomObject]@{ Id = 3; UserName = "tom"; FirstName = "Tom"; LastName = "Hanks" }
) | Where-Object Id -ne $Id
}
Invoking this request will return all objects except the deleted one.
Invoke-RestMethod http://localhost:5000/user/2 -Method DELETE
Headers are included with HTTP requests to provide additional information about the request. This can include content type, length, cookies, user-agent strings and more. You can define additional headers by passing a hashtable to the -Header
parameter of Invoke-RestMethod
.
Assume you have an API that reads a specific header and returns a result based on that. In this example, if the Credential header contains the SuperAdmin string, then the user will have success, otherwise a 401 unauthorized will be returned.
New-PSUEndpoint -URL /secure-user -Method POST -Endpoint {
if ($Headers['Credential'] -eq 'SuperAdmin')
{
"Success!"
return
}
New-PSUApiResponse -StatusCode 401
}
To invoke this API with Invoke-RestMethod
, you can do the following. The first call will succeed while the second will fail.
Invoke-RestMethod http://localhost:5000/secure-user -Method POST -Headers @{
Credential = "SuperAdmin"
}
Invoke-RestMethod http://localhost:5000/secure-user -Method POST
Query strings are included as part of the URL when making HTTP calls. They include additional information about the request and since they are part of the URL, can be stored and repeated. This can be a benefit rather than with headers which are not so easily included.
Assume we have an API that returns users based on the query string search string.
New-PSUEndpoint -URL /user -Endpoint {
@(
[PSCustomObject]@{ UserName = "adam"; FirstName = "Adam"; LastName = "Driscoll" }
[PSCustomObject]@{ UserName = "bruce"; FirstName = "Bruce"; LastName = "Willis" }
[PSCustomObject]@{ UserName = "tom"; FirstName = "Tom"; LastName = "Hanks" }
) | Where-Object { $_.UserName -match $UserName }
}
To invoke this API, we would modify the URL to include the query string with the value for username.
Invoke-RestMethod http://localhost:5000/user?username=ad
The Content-Type header of an HTTP request helps the server determine what is contained within the body of the request. Some common content types include application/x-www-form-urlencoded, application/json and text/plain
By default the Invoke-RestMethod
content type will be set to application/x-www-form-urlencoded
for POST methods. For all other methods, the content type is blank. This means when using the POST method for sending form data, you do not need to specify the content type.
You can specify a hashtable of values to the body of Invoke-RestMethod
and it will automatically encode the data as an HTTP form post.
For example, here is a hashtable we could post with the cmdlet.
@{
FirstName = "Adam"
LastName = "Driscoll"
}
The above hashtable will be encoded like this.
FirstName=Adam&LastName=Driscoll
PowerShell Universal endpoints automatically read form keys and values into parameters so you could create an endpoint such as this.
New-PSUEndpoint -URL /user -Method POST -Endpoint {
param(
[Parameter(Mandatory)]
$FirstName,
[Parameter(Mandatory)]
$LastName
)
[PSCustomObject]@{
FirstName = $FirstName
LastName = $LastName
}
}
Then, you can call Invoke-RestMethod
to call that endpoint.
Invoke-RestMethod http://localhost:5000/user -Method POST -Body @{
FirstName = "Adam"
LastName = "Driscoll"
}
Many REST APIs accept and produce JSON data. JavaScript Object Notation (JSON) is frequently used by front-end web technologies. You can send and consume JSON easily will Invoke-RestMethod
.
Let’s assume we have an endpoint that accepts and returns JSON like the one below. The endpoint will accept a JSON body, deserialize it, update a property and return the JSON back to the caller.
New-PSUEndpoint -Url /user -Method PUT -Endpoint {
# Body of the HTTP Request
$User = $Body | ConvertFrom-Json
$User.Updated = Get-Date
$User | ConvertTo-Json
}
To invoke this endpoint with Invoke-RestMethod
, you need to serialize a hashtable or PSCustomObject to JSON and specify the proper content type.
Invoke-RestMethod http://localhost:5000/user -Method PUT -Body (@{
FirstName = "Adam"
LastName = "Driscoll"
} | ConvertTo-Json) -ContentType 'application/json'
The web cmdlets support numerous ways to authenticate.
Default authentication is used for using your current user credentials and supplying them to systems that support Negotiate authentication. In the Windows world, this is use synonymous with Single-Sign On or Windows Authentication. It uses NTLM or Kerberos to provide a token that the server can use to verify the user’s identity.
With PowerShell Universal, you can enable Windows Authentication via IIS or through the Kestrel web server. Once enabled, you can enforce authentication by specifying the -Authentication
parameter.
The below endpoint will return the current user name of the caller of the endpoint. Unauthenticated calls will return a 401 status code.
New-PSUEndpoint -Url /me -Authentication -Endpoint {
$Identity
}
To call endpoints using Invoke-RestMethod
with default authentication, you can use -DefaultAuthentication
. You will need to include the -AllowUnencryptedAuthentication
parameter if you have not enabled HTTPS.
Invoke-RestMethod http://localhost:5000/me -UseDefaultCredentials -AllowUnencryptedAuthentication
Bearer authentication takes advantages of tokens such as JSON Web Tokens. Tokens are granted to identities like users and applications to provide authentication and authorization information to web APIs. Tokens are useful because they do not include user credentials, can contain roles, expire after a certain amount of time and can be revoked by the server.
Bearer authentication is enabled by default in PowerShell Universal and you can generate app tokens by navigating to Security \ Tokens in the admin console. Using the same endpoint as with default authentication, we can enforce authentication by the server.
New-PSUEndpoint -Url /me -Authentication -Endpoint {
$Identity
}
To call this endpoint with a bearer token, we can use the authorization header of Invoke-RestMethod
. Place the app token directly in the authorization header value with after the Bearer
string.
$AppToken = 'This Token Value'
Invoke-RestMethod http://localhost:5000/me -Headers @{ Authorization = "Bearer $AppToken" }
Many times HTTP services maintain a session between HTTP calls. This ensures that users do not need to reauthenticate with every call and session data can be retained to adjust how calls function. Create a web session can be accomplished with the -WebSession
and -SessionVariable
parameters of Invoke-RestMethod
.
As an example, we’ll use the cookie sign in functionality of PowerShell Universal.
First, we need to establish a session using -SessionVariable
. The following example calls PowerShell Universal’s login form.
Invoke-RestMethod http://localhost:5000/api/v1/signin -Body (@{
username = "admin"
password = "password"
} | ConvertTo-Json) -SessionVariable "PSUSession" -ContentType 'application/json' -Method POST
After running this command, you’ll establish a session that you can reuse for additional web requests. The $PSUSession
variable will be defined that contains the session data.
Now, we can call our authenticated endpoint to return our identity.
Invoke-RestMethod http://localhost:5000/me -WebSession $PSUSession
You will frequently run into errors when dealing with REST APIs. This may come in the form of non-200 status codes such as 401 or 403 or server error codes like 500. By default, non-200 status codes will result in an error thrown by Invoke-RestMethod
For example, we can call a nonexistent API in PowerShell Universal. You’ll see an error returned by Invoke-RestMethod
.
Invoke-RestMethod http://localhost:5000/notthere
Sometimes, servers will return additional information about what error has occurred.
For example, we may have an endpoint that throws an exception in PowerShell Universal.
New-PSUEndpoint -Url /throws -Endpoint {
throw "Oh, no!"
} -ErrorAction Stop
When invoke this endpoint in PowerShell 7 or later, you will see the error message.
Invoke-RestMethod http://localhost:5000/throws
This is not the case for Windows PowerShell so you will need to retrieve the exception and get the error message from it.
try
{
Invoke-RestMethod http://localhost:5000/throws
}
catch
{
[System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream()).ReadToEnd()
}
Find this useful? Please consider sharing this article. Have a question about PowerShell? Contact us and we'll write a post about it.
Continue the conversion on the Ironman Software forums. Chat with over 1000 users about PowerShell, PowerShell Universal, and PowerShell Pro Tools.
Receive once-a-month updates about Ironman Software. You'll learn about our product updates and blogs related to PowerShell.