What to do when an API has no documentation - rest

I'm currently trying to use a REST API to insert data from Powershell into a Jira custom field made by a certain plugin (Easy links for JIRA). Unfortunately there's no documentation on the required syntax. Does anyone who's run into this plugin know the commands/syntax I'll need to use the REST API (It's quite a small plugin so I'll be surprised if anyone else has seen it)? Failing that, does anyone have any advice on discovering how to use APIs with no/bad documentation i.e. some standard method of making an API return a list of commands and syntax (preferably by using powershell)?
I've tried contacting the developer but haven't heard back from them.
The code I'm using is here, if that's helpful:
function Test-Upload(){
Param()
Process{
$data=#"
{
"fields":
{
"project":
{
"key": "CCWASSET"
},
"summary": "Testing Linked Field",
"issuetype":
{
"name": "Asset"
},
"description" : "Testing Linked Field"
},
"update":{
"customfield_10500":[
{
"set":{
"type":{
"name":"Asset PO",
"inward":"Asset",
"outward":"Purchase Order"
},
"outwardIssue":{
"key":""
}
}
}
]
}
}
"#
return Jira-WebRequest -data $data
}
}
function Jira-WebRequest(){
Param(
[Parameter(mandatory=$false)]$data,
[Parameter(mandatory=$false)]$requesttype="issue",
[Parameter(mandatory=$false)]$method="POST",
[Parameter(mandatory=$false)]$ContentType='application/json'
)
Process{
$path = $("/rest/api/2/$requesttype/")
$Uri = ""
[URI]::TryCreate([URI]::new($Settings.Jira.URL),"$path",$([ref]$Uri))
$Params = #{
ContentType = $ContentType
Body = $data #$(#{"vlan_id"=$vlanID;"port_id"="$portID";"port_mode"="$portMode"} | ConvertTo-JSON)
Method = $method
URI = $uri.AbsoluteUri
Headers = $JiraHeaders
#WebSession = $Session
}
try{
$result = Invoke-RestMethod #Params -Verbose
return $result
} Catch [System.Net.WebException] {
$exception = $_.Exception
$respstream = $exception.Response.GetResponseStream()
$sr = new-object System.IO.StreamReader $respstream
$ErrorResult = $sr.ReadToEnd()
return $ErrorResult
}
}
}

It doesn't matter if the custom field made by a plugin or by you. At the end it's custom field so since the plugin doesn't have a good documentation, I would recommend you to stay with Atlassian Documentation and update / edit your issues base on official REST API. You can see Atlassian examples with Custom Fields here
What you need to do is you just need to figure out what's the custom field ID and that would be easy by going towards admin panel and clicking on the custom field and check it from URL if you don't want to go to database.
I know it's pain to see API without documents but at least you can workaround it this way.

Managed to get it working for this particular plugin. Had to include the ID field as well as the Key of the issue that I want to link to. I'd still be interested to hear if anyone has some tips for working with API's that have no/bad documentation.
"update":{
"customfield_10500":[
{
"set":{
"type":{
"name":"Asset PO",
"inward":"Asset",
"outward":"Purchase Order"
},
"outwardIssue":{
"key":""
"ID":""
}
}
}
]
}
}

Related

Use Graph API and PowerShell to add item to SharePoint list to 'Person or Group' with multiple values

I'm having hard time trying to accomplish adding new entries to SharePoint list which one of fields type it's 'People or Group' with multiple selection allowed. I'm able to add entry without People field filled, but when I'm trying to somehow compose JSON having people included, I get error 'invalid request' or just field with people is not filled. I know that I have to use some SharePoint ID for user but somehow I'm unable to add it anyway...
Code I'm using:
$apiUrl = "$($resource)/v1.0/sites/$SharepointSiteId/lists/$SharepointListId/items"
$paramsItemToAdd = #{
fields = #{
Title = "Test"
field_1 = "1111"
Field2= "Some Text"
Name = "Name"
Type = "22222"
Date = (get-date).ToString("yyyy-MM-dd")
Ownership = #(
,#{
lookupid=25;
lookupvalue="User2ndName, Name";
email="Name.User2ndName#company.com"
}
)
}
}
$payload = ConvertTo-Json $paramsItemToAdd -Depth 5
$Data = Invoke-RestMethod -Headers #{Authorization = "Bearer $($TokenResponse.access_token)"} -ContentType "application/json" -Uri $apiUrl -Method Post -Body $payload
My JSON looks like this:
{
"fields": {
"Title": "Test",
"Field2": "Some Text",
"Type ": "22222",
"Name": "Name",
"Ownership": [
{
"email": "Name.User2ndName#company.com",
"lookupvalue": "User2ndName, Name",
"lookupid": 25
}
],
"field_1": "11111",
"Date": "2022-11-25"
}
}
I added few people to one of the field and done GET method to see how they are defined when they are added manually:
Ownership : {#{LookupId=43; LookupValue=U1_2ndName, U1_Name; Email=U1_Name.U1_2ndName#company.com},
#{LookupId=25; LookupValue=U2_2ndName, U2_Name; Email=U2_Name.U2_2ndName#company.com}}
But this really doesn't gives me any idea how should I change my code to get working one eventually. Tried many different combinations of above like with just LookupId as value, or removing email and lookupvalue from field - still nothing. I spent so much time trying to achieve this, I saw many different articles but I'm still unable to see what I'm doing wrong. Maybe I'm missing something obvious...
Just want to highlight - I know that it must be something wrong with way how I'm defining 'Ownership' field, because when I removed that completely from JSON, I'm able to add entries to SharePoint list without errors. So it must be something around how 'Ownership' field should be defined.

Powershell - Invoke-RestMethod - POST nested JSON

I'm trying to interact with an API to POST some data to a service we use, in order to add some email addresses to a policy. This will eventually take a list of email addresses and loop through it for each one, but for now I'm just trying to get it to work with a single address.
I'm using Powershell 7, I would say I'm intermediate with powershell, but this is my first foray into interacting with an API, using JSON, and using the Invoke-RESTMethod commandlet. The API reference for the service shows lots of code examples in other languages, just not PS!
Here's the problem I'm running in to. I'm trying to formulate a -Body statement that looks to be 3 elements instead of two. Here is what that example statement looks like in CURL:
{
"custodians": [
{
"emailId": "john.doe#someorg.com"
}
],
"action": "add"
}
The Action:Add part is fine, easy peasy. I'm trying to figure out how to correctly format the custodians part. I cant figure out how to do 3 elements instead of two. I've tried different combinations of {} [] and () to no avail:
"custodians" = ({"emailId" = "emailaddress#place.com"})
gives me an "The assignment expression is not valid" error
"custodians" = [{"emailId" = "emailaddress#place.com"}]
and
"custodians" = [#{"emailId" = "emailaddress#place.com"}]
give me an "Missing type name after '['." error.
These, as well as a few other combinations I've typed out, all showed formatting errors in VSCode so I already knew they wouldn't work, I'm just not sure why. I'm sure I just haven't cracked the right combination of #, {}, [] or () but I cant seem to find any info online (probably because I'm not using the right vocabulary or phrasing in my searches) that shows how to format with three elements.
If its relevant or helpful, here is a larger code sample of the whole query Im working on. Assume the Auth headers are fine (I can request my auth tokens and do GETs without issue so far):
$headers = #{
"Authorization" = $bearerAuthValue
"Accept" = "application/json"
"Content Type" = "application/json"
}
$body = #{
"custodians" = #(emailId = "emailaddress#place.com"),
"Action" = "add"
}
$uri = "https://thisisanaddress.com"
Invoke-RestMethod -Method 'POST' -Uri $uri -Headers $headers -Body $body
You are looking at having multiple emailids in custodians?
$body = #{
custodians = #(
#{emailId = 'emailaddress#place.com' }
#{emailId = 'emailaddress#place.com' }
#{emailId = 'emailaddress#place.com' }
)
Action = 'add'
}
Output:
$body | ConvertTo-Json
{
"Action": "add",
"custodians": [
{
"emailId": "emailaddress#place.com"
},
{
"emailId": "emailaddress#place.com"
},
{
"emailId": "emailaddress#place.com"
}
]
}

Corrupt Documents in new DocuSign envelope

I'm doing a POC to demonstrate DocuSign programmatically creating and routing an envelope containing a simple document. I'm using PowerShell and the JSON API. Login and the Create Envelope work without complaint, but the resulting Word doc routed to me for signature contains gibberish. I believe I have the base64 encoding and headers right. Any thoughts about what I'm doing wrong?
The entire POC is pasted below. I've just removed the ID, Password, Integrator Key, etc. Thanks!
function boundry {
[System.Guid]::NewGuid().ToString()
}
###this is the corrected code###
function encodeFile {
param ([string]$fileName)
[System.Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path $fileName).ProviderPath))
}
function logonParams {
[string] $userName = 'DocuSign user name'
[string] $password = 'DocuSign password'
[string] $integratorKey = 'DocuSign Integrator Key'
#"
{
"Username" : "$userName",
"Password" : "$password",
"IntegratorKey" : "$integratorKey"
}
"#
}
function logon {
[string] $loginURL = 'https://demo.docusign.net/restapi/v2/login_information'
$headers =
#{
"X-DocuSign-Authentication"=$(logonParams);
"accept"="application/json";
"content-type"="application/json";
}
$r = Invoke-WebRequest -uri $loginURL -headers $headers -method GET
$responseInfo = $r.content | ConvertFrom-Json
$baseURL = $responseInfo.loginAccounts.baseURL
#return the base URL for the next call
$baseURL
}
function createEnvelope {
param ([string]$file1,
[string]$baseURL
)
[string]$boundry = boundry
$headers =
#{
"X-DocuSign-Authentication"=$(logonParams);
"accept"="application/json";
"content-type"="multipart/form-data; boundary=$boundry";
}
[string]$formData = #"
--$boundry
Content-Type: application/json
{
"status":"sent",
"emailBlurb":"Please sign.",
"emailSubject": "Contract $(date)",
"documents": [{
"name": "$file1",
"documentId":"1",
"order":"1"
}],
"recipients": {
"signers" : [{
"email": "recipient#somecompany.com",
"name": "Recipient Name",
"recipientId":"1",
}]
}
}
--$boundry
Content-Type: application/msword
Content-Transfer-Encoding: base64
Content-Disposition: file; filename="$file1";documentid=1
$(encodeFile $file1)
--$boundry--
"#
$envelopeURL = "$baseURL/envelopes"
Invoke-WebRequest -uri $envelopeURL -headers $headers -body $formData -method POST
}
$baseURL = logon
createEnvelope "test.doc" $baseURL
Try changing your Content-Type header value. I'm not sure if application/msword works here, I think the proper mime-type for .docx is
application/vnd.openxmlformats-officedocument.wordprocessingml.document
See this previous SO post for a more complete list of mime-types:
What is a correct mime type for docx, pptx etc?
I solved it with assistance from the DocuSign support team. You can enable server side logging in DocuSign which is very helpful. From the old UI (not available in new UI as of June '15) choose Preferences from the dropdown next to your ID/photo. Then select Permissions under Member Options on the left. Check "Enable API Request Logging." After you run your test, the Download API Request Logs button becomes active.
It was pretty clear from the logs that my encoding was wrong. Here's the correct version:
function encodeFile {
param ([string]$fileName)
[System.Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path $fileName).ProviderPath))
}
I've updated this in the original code with the question so feel free to use it.

Powershell - Inexplicable timeout for HttpRequests

I have a powershell script that monitors several pages on a handful of servers. It gives the HTTP status code from each to determine the server's health.
This has been working perfectly for a number of weeks but today, without making any changes to the script, I started receiving timeout errors ("The operation has timed out"). A telnet on port 80 to the server let me through instantly and I could connect happily via every other mechanism I could think of.
Finally I updated the script by changing the timeout period from 1000ms to 2000ms and the script worked again, instantly. And it still worked after I changed it back to 1000ms.
This is the second time something like this has happened with the same resolution. What is happening and how can I avoid it?
This script may help, it may be a bit overkill for your situation.
function HTTP-Get() {
param
(
[string] $target
)
try
{
$webRequest = [System.Net.WebRequest]::Create($target)
$webRequest.Method = "GET"
[System.Net.WebResponse] $resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs;
[string] $results = $sr.ReadToEnd();
}
catch [System.Net.WebException]
{
Write-Warning $_
if ($_.response)
{
$_.response.Close();
}
}
finally
{
if ($sr)
{
$sr.close();
$sr.dispose();
}
if ($resp)
{
$resp.close();
}
}
return $results;
}
As I mentioned in the comments: I had this issue with powershell and none of the .NET http tricks worked (httprequest, webclient). The site I used worked fine with postman and other http helpers.
It seemed like the issue is related to the .NET version, sp, etc. I changed my code to use COM instead of .NET and now it works fine.
......
$HTTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0
$Http = new-object -com "WinHttp.WinHttpRequest.5.1"
$Http.open("GET", "http://....", $false)
$Http.SetCredentials($userName, $password, $HttpREQUEST_SETCREDENTIALS_FOR_SERVER)
$Http.send()
$status = [int]$Http.Status
$responseText = $Http.responseText
.....
I hope it helps :)

Facebook: extracting user information from access token

i used the user's valid access token to identify the user...
with this:
https://graph.facebook.com/me?fields=id&access_token=VALID_ACCESS_TOKEN
it returns:
{
"id": "100000004811603"
}
it's obvious that i only want to extract the user's id... that's the only one thing i need to do everything for the user/
can someone teach me how to parse this?
it's weird for me seeing this type of result without the Data: key
Based on how you described your problem I'll try to answer.
$response = // get facebook response as you do
$data = json_decode($response);
$id_that_you_need = $data['id']
Maybe I'm getting you all wrong.
Use this function
function objectToArray( $object )
{
if( !is_object( $object ) && !is_array( $object ) )
{
return $object;
}
if( is_object( $object ) )
{
$object = get_object_vars( $object );
}
return array_map( 'objectToArray', $object );
}
pass the output from https://graph.facebook.com/me? to this function. this function will return array. and you can use values easily.
like this
$Array = objectToArray($Data);
print_r($Array);
$facebook_token = <VALID_ACCESS_TOKEN>;
$user_information = curl_init("https://graph.facebook.com/me?access_token=$facebook_token");
curl_setopt($user_information,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($user_information,CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt($user_information,CURLOPT_RETURNTRANSFER,true);
$reps= curl_exec($user_information);
curl_close($user_information);
echo($reps);`
`