Jira API POST and Invoke-RestMethod - json

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.

Related

Convert multi header and json input curl command in to powershell

I have the below curl command which i am trying to convert to powershell, but i am not sure on how to handle the multi header inputs and the JSON input
Any help is highly appreciated
curl --location --request POST 'https://anypoint.studio.com/cloudhub/api/v2/applications' \
--header 'X-ANYPNT-ENV-ID: 4a96abfd4f5237cf1b64' \
--header 'X-ANYPNT-ORG-ID: bc0d-3b9fd79234ad' \
--header 'Authorization: Bearer 3esede-a44b-29ab8841b508' \
--form 'file=#"/C:/Users/pgi/Downloads/eafdc-flow-proxy-v1.2.jar"' \
--form 'appInfoJson="{
\"domain\": \"testproxy-test\",
\"Version\": {
\"version\": \"4.4.0\"
},
\"properties\": {
\"platform.client_id\": \"8f95qw3sa4b679aaa699cf0f5c6b6\",
\"secure.key\": \"sYf%NJ7F^y&3lNRH*D$#\",
\"env\": \"dev\",
\"platform.client_secret\": \"acF0JHFUEFH8829a481D9c37EF364be7a\"
},
\"propertiesOptions\": {
\"secure.key\": {
\"secure\": true
},
\"anypoint.platform.client_secret\": {
\"secure\": true
}
},
\"region\": \"us-west-1\",
\"monitoringEnabled\": true,
\"monitoringAutoRestart\": true,
\"workers\": {
\"amount\": 1,
\"type\": {
\"name\": \"Micro\",
\"weight\": 0.1,
\"cpu\": \"0.1 vCores\",
\"memory\": \"500 MB memory\"
}
},
\"loggingNgEnabled\": true,
\"persistentQueues\": true
}"' \
--form 'autoStart="true"'
You can replace curl with Invoke-WebRequest and parse the JSON with ConvertFrom-Json.
$r = Invoke-WebRequest -Uri $uri -Method Post -Body $body
$j = ConvertFrom-Json $r.Content
I've left out setting the value of $uri and $body. I hope this is enough for you to get started with.
Update
First response was written too quickly. You probably need to pass header and body.
Like curl, Invoke-Webrequest is powerful and complex. You can find online documentation here:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.2&WT.mc_id=ps-gethelp
You'll need to use the Headers and Body Parameters:
-Headers <System.Collections.IDictionary>
Specifies the headers of the web request. Enter a hash table or dictionary.
To set UserAgent headers, use the UserAgent parameter. You can't use this parameter to specify User-Agent or cookie headers.
Content related headers, such as Content-Type is overridden when a MultipartFormDataContent object is supplied for Body .
-Body <System.Object>
Specifies the body of the request. The body is the content of the request that follows the headers. You can also pipe a body value to Invoke-WebRequest.
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.
The Body parameter may also accept a System.Net.Http.MultipartFormDataContent object. This facilitates multipart/form-data requests. When a MultipartFormDataContent object is supplied for Body , any Content related headers supplied to the ContentType , Headers , or WebSession parameters is overridden by the Content headers of the MultipartFormDataContent object. This feature was added in PowerShell 6.0.0.
Looks like you'll have to create a MultipartFormDataContent object. Note this was added in PowerShell Version 6, so you can't use the Windows built-in default version 5. If you haven't already, you'll probably need to install the latest version of Version 7. (I use version 7 and it's great.)
So for headers you'd create something like:
$headers = [ordered]#{
'X-ANYPNT-ENV-ID' = '4a96abfd4f5237cf1b64'
'X-ANYPNT-ORG-ID' = 'bc0d-3b9fd79234ad'
'Authorization' = 'Bearer 3esede-a44b-29ab8841b508'
}
Then make a call like:
$r = Invoke-WebRequest -Uri $uri -Method Post `
-Headers $headers -Body $myMultipartFormDataContent
I haven't used MultipartFormDataContent so I'll leave that up to you. I hope this provides you with a good starting point.

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

How do I fix a "cannot bind parameter 'uri'. Cannot convert the...." when converting json in powershell?

I am doing a Get-Weather project in powershell, where I pull data down from weatherapi.com . I am able to successfully connect to the website using an API key but, when I try to convert it from json in the script it doesn't work. The error I get is:
"Cannot bind parameter 'Uri'. Cannot convert the..."
I have tried so many different ways to write this:
$response = Invoke-RestMethod -uri $url -Method Get -ResponseHeadersVariable r -StatusCodeVariable s
$weatherobject = ConvertFrom-Json $url
The request for the website is:
$url = Invoke-WebRequest "http://api.weatherapi.com/v1/forecast.json?key=$key&q=$location&days=$Days"
Any help would be very much apperciated, thank you!
The input of the ConvertFrom-Json cmdlet is a JSON object. Look at the document below for more information
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-7.1#description
$url = "http://api.weatherapi.com/v1/forecast.json?key=$key&q=$location&days=$Days"
$response = Invoke-RestMethod -uri $url -Method Get -ResponseHeadersVariable r -StatusCodeVariable s
$weatherobject = ConvertFrom-Json $response

ADO: upload an attachment to Azure DevOps via HTTP REST request

We're using ADO Server 2019 and as part of a larger project I need to upload some emails to the ADO environment to attach to work items. I've already figured out that you first need to upload the attachment, pass over the attachment ID to the work item patch request and add the relationship from the work item end however what I can't for the life of me figure out is where to pick the actual email or any item up to upload.
The example that's given within the MS docs shows you how to post an upload but it uploads nothing, it just creates a blank page.
POST https://{instance}/fabrikam/_apis/wit/attachments?fileName=textAsFileAttachment.txt&api-version=5.0
A body for the request needs to be built to define where the attachment is from what I can gather however there isn't any kind of documentation around this for simply posting it via HTTP.
We're using Blue Prism so using C# is an option but not ideal.
Thanks in advance.
Please follow the steps below:
1.Upload a text file
POST https://{instance}/fabrikam/_apis/wit/attachments?fileName=textAsFileAttachment.txt&api-version=5.0
Request Body: "User text content to upload"
2.You will get a response like:
{
"id": "6b2266bf-a155-4582-a475-ca4da68193ef",
"url": "https://fabrikam:8080/tfs/_apis/wit/attachments/6b2266bf-a155-4582-a475-ca4da68193ef?fileName=textAsFileAttachment.txt"
}
Copy this url from the response.
3.Add an attachment to work items:
POST https://{instance}/fabrikam/_apis/wit/attachments?fileName=textAsFileAttachment.txt&api-version=5.0
Request body:
[
{
"op": "add",
"path": "/relations/-",
"value": {
"rel": "AttachedFile",
"url": "https://fabrikam:8080/tfs/_apis/wit/attachments/6b2266bf-a155-4582-a475-ca4da68193ef?fileName=textAsFileAttachment.txt",
"attributes": {
"comment": "Spec for the work"
}
}
}
]
Replace the url of the request body.
You have to pass a file content if you create a new attachment. Upload a binary file
POST
https://dev.azure.com/fabrikam/_apis/wit/attachments?fileName=imageAsFileAttachment.png&api-version=6.1-preview.3
"[BINARY FILE CONTENT]"
Here is an example through Powershell:
$user = ""
$token = "<personal access token>"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$org = "org_name"
$teamProject = "teamproject"
$wiId = "work item Id"
$folderPath = "c:/temp"
$fileName = "some_file.zip"
$createAttachmetUrlTemplate = "https://dev.azure.com/$org/$teamProject/_apis/wit/attachments?fileName={fileName}&api-version=5.0"
$updateWIUrlTemplate = "https://dev.azure.com/$org/_apis/wit/workitems/{id}?api-version=5.0"
$wiBodyTemplate = "[{`"op`": `"add`",`"path`": `"/relations/-`",`"value`": {`"rel`": `"AttachedFile`",`"url`": `"{attUrl}`", `"attributes`": {`"comment`": `"Spec for the work`"}}}]"
function InvokePostRequest ($PostUrl, $body)
{
return Invoke-RestMethod -Uri $PostUrl -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
function InvokePatchRequest ($PatchUrl, $body)
{
return Invoke-RestMethod -Uri $PatchUrl -Method Patch -ContentType "application/json-patch+json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
$bytes = [System.IO.File]::ReadAllBytes("$folderPath/$fileName")
$createAttachmetUrl = $createAttachmetUrlTemplate -replace "{filename}", $fileName
$resAtt = InvokePostRequest $createAttachmetUrl $bytes
$updateWIUrl = $updateWIUrlTemplate -replace "{id}", $wiId
$wiBody = $wiBodyTemplate -replace "{attUrl}", $resAtt.url
InvokePatchRequest $updateWIUrl $wiBody

How to POST in powershell to canvas LMS

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!