PowerShell (Invoke-RestMethod) - ERROR "team ids must be a array"

rest-api
powershell

(Brandon Humphrey) #1

I’m trying to query a list of users by team_ids using PowerShell’s Invoke-RestMethod. Unfortunately, the body, which declares team_ids = is returning an error:

{“error”:{“message”:“Invalid Input Provided”,“code”:2001,“errors”:[“Team ids must be a Array.”]}}

Here’s the code:

<#------------USERS------------#>
$apiRoot = “https://api.pagerduty.com/users
$headers = New-Object “System.Collections.Generic.Dictionary[[String],[String]]”
$headers.Add(“Accept”, ‘application/vnd.pagerduty+json;version=2’)
$headers.Add(“Authorization”, ‘Token token=InsertTokenHere’)
$body = @{
‘limit’ = ‘100’
‘team_ids’= @(‘PZYAW28’)
}
$contentType = “application/json”
$users = Invoke-RestMethod -Uri $apiRoot -ContentType “application/json” -Method Get -Header $headers -Body $body
$userArray = @()
Foreach ($user in $users.users){
$psObject = New-Object -TypeName PSObject
$psObject | Add-Member -MemberType NoteProperty -Name userName -Value $user.name
$psObject | Add-Member -MemberType NoteProperty -Name userEmail -Value $user.email
$psObject | Add-Member -MemberType NoteProperty -Name userTimeZone -Value $user.time_zone
$psObject | Add-Member -MemberType NoteProperty -Name userRole -Value $user.role
$psObject | Add-Member -MemberType NoteProperty -Name userID -Value $user.id
$userArray += $psObject
}

$userArray | Sort userName | Format-Table

When I run this without the team_ids specified in the body, I get results. I also tried:

$body = @{
‘limit’ = ‘100’
‘team_ids’= @(‘PZYAW28’)
} | ConvertTo-Json

Which stores the following in the $body variable:

{
“limit”: “100”,
“team_ids”: [
“PZYAW28”
]
}

But I get this error from PowerShell:

Invoke-RestMethod : Cannot send a content-body with this verb-type.

I appreciate any help!


(Demitri Morgan) #2

Hi Brandon,

The meaning of the “team IDs must be an array” error is that you need to append square brackets to the name.

The “parameters” in the API Reference refer to URL query string parameters, i.e. in the case of your goal here the URL should end up coming out as:

https://api.pagerduty.com/users?limit=100&team_ids%5B%5D=PZYAW28

Note how team_ids[] in the above is url-encoded as team_ids%5B%5D.

The meaning of the second error is that when making a HTTP GET request, there should be no body.

However, per the PowerShell 6 documentation on Invoke-Restmethod, one should be able to do this in an automated fashion versus manually writing out all the parameters into the URL::

The -Body parameter can be used to specify a list of query parameters or specify the content of the response.

When the input is a GET request, and the body is an IDictionary (typically, a hash table), the body is added to the URI as query parameters. For other request types (such as POST), the body is set as the value of the request body in the standard name=value format.

In light of this, I’m not entirely sure why you’re getting the error message, but the body should be an “IDictionary” object.

Thus, in summary: there are a few things I recommend trying, as they may be leading to Invoke-Restmethod sending the request in not the manner that is desired:

  • Append square brackets to the team_ids parameter, i.e. name it team_ids[]; it is an array-type parameter and so requires them.
  • Don’t perform ConvertTo-Json in the declaration of the $body variable; let it be a hash/dict. I believe ConvertTo-Json might be serializing it into a string. Per the documentation, it needs to be a dict for it to be converted into query string parameters in GET requests.
  • Don’t include the -ContentType option (which sets the Content-Type header in the request); it is not necessary for GET requests. Rather, it is used to specify the type of content when transmitting data to a remote host, i.e. via POST/PUT.

Please give that a try, and let us know if it helps!


(Brandon Humphrey) #3

Hello Demitri,

First, thank you for the detailed and technically sound response (as most of us know, that’s frequently not the common experience in forums). Your time and expertise is greatly appreciated!

You were correct. I was able to make the following changes and receive results:

  • Remove the -ContentType parameter from the Invoke-RestMethod cmdlet

  • Use the square brackets in the body for team_ids[] (though I did need to surround them in apostrophes to avoid syntax issues

The working code is as follows:

<#------------USERS------------#>
$apiRoot = “https://api.pagerduty.com/users
$headers = New-Object “System.Collections.Generic.Dictionary[[String],[String]]”
$headers.Add(“Accept”, ‘application/vnd.pagerduty+json;version=2’)
$headers.Add(“Authorization”, ‘Token token=InsertTokenHere’)
$body = @{
‘limit’ = ‘100’
‘team_ids[]’ = “PZYAW28”
}
$users = Invoke-RestMethod -Uri $apiRoot -Header $headers -Body $body -Method Get
$userArray = @()
Foreach ($user in $users.users){
$psObject = New-Object -TypeName PSObject
$psObject | Add-Member -MemberType NoteProperty -Name userName -Value $user.name
$psObject | Add-Member -MemberType NoteProperty -Name userEmail -Value $user.email
$psObject | Add-Member -MemberType NoteProperty -Name userTimeZone -Value $user.time_zone
$psObject | Add-Member -MemberType NoteProperty -Name userRole -Value $user.role
$psObject | Add-Member -MemberType NoteProperty -Name userID -Value $user.id
$userArray += $psObject
}
$userArray | Sort userName | Format-Table

Best Regards,
Brandon


(Demitri Morgan) #4

Hi Brandon,

I’m really glad that helped, and thank you for sharing the working solution for comparison and edification!

Sorry to hear your experience in the forums has been less than stellar. If you feel that any answer you’ve received is inadequate or is wanting more in detail, please feel free to @-mention support-team for further assistance.


(system) #5