How to POST in powershell to canvas LMS - json

I am currently making an API for an university. The purpose of this project to to look at every course and check if it contains a certain module and if not, add one in. Seems fairly simple enough, but the thing that is making the project complicated is on learning the syntax on to actually do it! I am writing this code in powershell and I have tried to use curl and invoke web request. I tried following canvas' documentation, but I cannot get it. Here are two instances I have, can you please show me how to properly format this.
######this is the first way I tried it and the error I get Invoke-WebRequest : {"message":"missing module parameter"}
$temp2=($mainURL+$course.ID+"/modules"+$securityToken)
$reply = curl -Uri $temp2 -Method Post -Body '{"module[name]"="Getting started","module[position]"="1"}'
#######
#########This is the second way I've tried and the error I get Invoke-WebRequest : The remote server returned an error: (422) Unprocessable Entity.
$url="https://University.instructure.com/api/v1/courses/1371/modules?access_token=abc123"
$body= "{'module[name]'='Getting started,'module[position]'=1}"
Invoke-WebRequest -Uri $url -ContentType "application/json" -Method Post -Body $body
#########
Documentation from the website https://canvas.instructure.com/doc/api/index.html
UPDATE 5-26-2016
I have figured out how to properly format the body for the message. Now I am getting the error message
$header = #{"Authorization"="Bearer "+ $security_token}
$body= '{"module[name]":"Getting started","module[position]":"1"}'
$curlly=Invoke-WebRequest -Headers $header -Body $body -Method Post -ContentType "application/json" -Uri ($url_main+"courses/1371/modules")
$module = ConvertFrom-Json $curlly.Content
curl : Invalid URI: The hostname could not be parsed.
At line:1 char:1
+ curl
+ ~~~~
+ CategoryInfo : NotSpecified: (:) [Invoke-WebRequest], UriFormatException
+ FullyQualifiedErrorId : System.UriFormatException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
I really do not know what to do at this point any guidance will be appreciated at this point.

After a week of fiddling around with the actual JSON format, I took out the content type on the Invoke-WebRequest to see if the server would be able to just guess the format. It worked!

Related

Powershell/PowerCLI, Horizon REST-API, invoke-restmethod returns "BAD_REQUEST The input request cannot be parsed"

I'm trying to copy Horizon application pools that exist on a source Horizon connection server (HCS) to another one. In my homelab that works perfectly, in another environment on "invoke-restmethod" I run into the error above.
First I get an auth token and the applications on the source HCS:
$horizonApps_source = Invoke-RestMethod -Method Get -uri "$RESTurl_source/rest/inventory/v2/application-pools" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken_source)`
Then I loop through them and create the copies on the target HCS (also exporting a .json-File for every app and removing unique values that the POST "inventory/v2/application-pools" will not accept):
If ($horizonApps_source -ne $null) {
ForEach ($item in $horizonApps_source) {
$jsonFile = $fileLoc + $item.Display_Name + ".json"
$item = $item | Select-Object * -ExcludeProperty Id, access_group_id, icon_ids, customized_icon_ids
$item.farm_id = $farmID_target
$item | ConvertTo-Json -Depth 100 | Out-File $jsonFile
$appJson = $item | ConvertTo-Json -Depth 100
$app_target = Invoke-RestMethod -Method Post -uri "$RESTurl_target/rest/inventory/v2/application-pools" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken_target) -body $appJson -SkipCertificateCheck
}
}
In one environment everything works, in another no chance...this is the error I get, .json-files are written and look okay, but no apps are created on the target HCS:
Line |
8 | … pp_target = Invoke-RestMethod -Method Post -uri "$RESTurl_target/rest …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"status":"BAD_REQUEST","timestamp":1670869477302,"error_message":"The input request cannot be parsed."}
Powershell 7.3.0, PowerCLI 13, Horizon 2111 everywhere. Any ideas? Any suggestion how I could catch the error in more detail to find the issue's source?
Tried to google problems with invoke-restmethod using a json-body. Sadly I'm not a Powershell pro...
Solved with help of a great colleague!
In my test enwironment I used two Horizon installations on Windows Server 2022 in an ENGLISH install. The other environment uses a source Horizon installation on a GERMAN server OS, but the target Horizon connection server runs on an ENGLISH OS. on the German based source install the admins made use of German special characters "äÄöÖüÜ".
In result the character set hast to be fixed to UTF-8 for the REST invocation:
$app_target = Invoke-RestMethod -Method Post -uri "$RESTurl_target/rest/inventory/v2/application-pools" -ContentType "application/json; charset=utf-8" -Headers (Get-HRHeader -accessToken $accessToken_target) -body $appJson
The part "application/json" has to become "application/json; charset=utf-8".
And that's it.

SurveyMonkey creating a collector in Powershell returning "The body provided was not a proper JSON string

I'm using Powershell to automate a survey creation, adding a collector, and sending the survey invitation - a pretty common use case. I was able to create a survey but I'm running into an issue in creating the collector. I created a collector via Postman but I get the error "1001 - The body provided was not a property JSON string" when using Powershell. I've tried everything I can think of but continue to get the error no matter how I create the JSON. Here is the code I'm using:
$SurveyCollector = [PSCustomObject]#{ type = 'email' }
$BodyText = $SurveyCollector | Select-Object -Property type |ConvertTo-Json -Depth 100 -Compress
$Results = Invoke-RestMethod -Uri $uri -StatusCodeVariable "ExtIDscv" -SkipHttpErrorChe -Method
Post -ContentType "application/json" -Authentication Bearer -Token $SecureToken -body -$BodyText
I'm sure I'm missing something simple. I'd appreciate any help.
The answer was more simple than what tripleee suggested. I had introduced a -$BodyText into the call and didn't catch it. I removed it and it works just fine.
$Results = Invoke-RestMethod -Uri $uri -StatusCodeVariable "ExtIDscv" -SkipHttpErrorChe -Method
Post -ContentType "application/json" -Authentication Bearer -Token $SecureToken -body -$BodyText

Convert Curl to Invoke-RestMethod

Problem
I am having a hard time converting a curl call into a Powershell Invoke-RestMethod call as Powershell doesn't really thow the most informative error messages (if any).
Curl call (Ubuntu)
token = "djsakldsakldjaslda"
host = "https://lalala.azuredatabricks.net/"
curl -X POST -H "Authorization: Bearer $(token)" $(host)/api/2.0/clusters/create -d $(cat my_file.json)
Invoke-RestMethod call (Powershell)
$token= "djsakldsakldjaslda"
$host = "https://lalala.azuredatabricks.net/"
Invoke-RestMethod -Method Post -Uri $host/api/2.0/clusters/create -Headers #{"Authorization" = "Bearer " + $token} -Body $(get-content my_file.json -raw | ConvertFrom-Json)
I have various formats for the body, but no matter what I send, I just get some HTML back for a login page. On Ubuntu with Curl everything works perfectly.
NOTE:
The problem seemed to be that PowerShell cannot handle double-"/" as in "https://lalala.azuredatabricks.net//api/2.0/clusters/create".
The strange part is that Invoke-RestMethod gets to the login page, but fails from there.
Use -InFile to upload a file. Don't forget to set the content type.
Wrapped for legibility (escaping the EOL works as line continuation in PowerShell, it looks funny because StackOverflow syntax highlighting cannot handle it):
Invoke-RestMethod `
-Method Post `
-Uri "$host/api/2.0/clusters/create"
-Headers #{
Authorization = "Bearer $token"
} `
-Infile my_file.json
-ContentType "application/json"
The body is expected to be JSON format, when you take the file and add the | ConvertFrom-Json the content becomes a PowerShell object.
So, you can remove the | ConvertFrom-Json and it should work :)

Post to json rest API from powershell

Hi can someone tell me where i'm going wrong here, i get the following error executing an API call from powershell. I have tried to format the body i many ways but cannot get it to work.
Invoke-RestMEthod : Cannot send a content-body with this verb-type.
At line:7 char:20
+ ... sponseKan = Invoke-RestMEthod -Uri $kanboardserver -ContentType "app ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Invoke-RestMethod], ProtocolViolationException
+ FullyQualifiedErrorId : System.Net.ProtocolViolationException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
My Code;
$headersKan = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" -ErrorAction Stop
$headersKan.Add("X-API-Auth", "jsonrpc:$kanboardtoken")
$bodyKan = #{jsonrpc = "2.0"
id = "1"
method = "getAllProjects"
} | ConvertTo-Json
$responseKan = Invoke-RestMEthod -Uri $kanboardserver -ContentType "application/json" -Headers $headersKan -Body $bodyKan -ErrorAction Stop
Write-Host $responseKan
The default http verb is GET which does not allow a body/payload. Pass POST as method argument and do not json-serialize the body yourself.

Jira API POST and Invoke-RestMethod

Using Jira API 2 and PowerShell 5 Invoke-RestMethod I can successfully execute GET, but I keep getting a (400) Bad Request when attempting POST method to create an issue in my project.
$user = [System.Text.Encoding]::UTF8.GetBytes("me:mypassword")
$headers = #{Authorization = "Basic " + [System.Convert]::ToBase64String($user)}
$data = Get-Content D:\scripts\powershell\issue.txt
Invoke-RestMethod -Uri "https://agile.mycompany.com/rest/api/2/issue/" -Method POST -Headers $headers -ContentType "application/json" -Body $data
$data variable is well-formed JSON for Jira:
{
"fields":
{
"project":{"Key": "ITS"},
"summary":"Rest Test 1",
"issuetype":{"name": "Task"},
"assignee":{"key": "myusername"},
"priority":{"id": "3"},
"description":
"||Host Name||IP Address||Comments||
|some-pc|192.168.1.1| |",
"duedate": "2016-09-11"
}
}
I am the project owner, so this isn't a permissions issue.
Get-content is tricky, because it will actually result in a array of strings, where each line in your text file is an object in that array. The best way to get around that is probably using .Net's file read methods instead:
$data = [System.IO.File]::ReadAllText("D:\scripts\powershell\issue.txt")
btw, you can use a regular ps credential object instead of manually building your request header.
On a side note, it's always a good idea to test your api out using a tool such as postman. That will let you verify that you're posting valid json while not having to worry about your code doing strange things.
Problem solved. The issue was that I was CAPITALIZING the first letter of the field names. Apparently, Jira is very sensitive to CASE. Trondh - thank you for the recommendation to use postman. The errors that were getting generated by postman from the failed API calls were very concise.