Post JSON data into another domain - Rest API - rest

I am trying to POST a data to receive an input using powershell but it's throwing error.
Url: https://www.example.com/api/login
JSON data = {"username": "emailid", "password": "password"}
Once the post is successful, i will receive an output in JSON format something like:
{"account": "some-guid", "Token": "xxx", "selflink": "https://www.example.com/api/me", "username": "emailid"}
When I am posting the JSON data, I'm getting syntax error.
I'm using the below code to invoke
$url = "https://somedomain.com/api/login"
$params = #{"username"="abcd#pqr.com";
"password"="123456";
}
$response = Invoke-WebRequest -Uri $url -Method POST -Body $params -ContentType "application/json"

I changed the $param to | ConvertTo-Json
$JSON = #{
"username" = "abcd#xyz.com"
"password" = "123456"
} | ConvertTo-Json
and it worked fine.

Related

Calling graph API using Powershell - Passing JSON as Body

I am able to call https://login.microsoftonline.com/$($TenID)/oauth2/v2.0/token using powershell by passing below parameters:
$requestBody = #{client_id=$CliID;client_secret=$CliSec;grant_type="password";username=$Username;password=$Password;scope=$Scope} | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$($TenID)/oauth2/v2.0/token" -Body $body
However, I unable to pass body as JSON and call the same API. I want it to be in JSON formatted to be used in Power Automate to call HTTP endpoint.
I used below as JSON and request:
$JSON = '{
"grant_type": "password",
"password": "pwd",
"client_id": "clieid-12345-32234",
"client_secret": "jewhfjkjlskw;fdslk;",
"username": "user#example.com",
"scope": "Directory.AccessAsUser.All"
}'
Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$($TenID)/oauth2/v2.0/token" -ContentType "application/json" -Body $JSON
I am always getting error as below while passing it as JSON:
Invoke-RestMethod : "error":"invalid_request","error_description":"AADSTS900144: The request body must contain the following parameter: 'grant_type'.
Can you please help?
I think that this will work for you.
$data = #{
grant_type = "client_credentials";
password = "pwd";
client_id = "clieid-12345-32234";
client_secret = "jewhfjkjlskw;fdslk;";
username = "user#example.com";
scope = "Directory.AccessAsUser.All";
};
$json = $data | ConvertTo-Json
$url = "https://login.microsoftonline.com/$($TenID)/oauth2/v2.0/token"
$contentType = "application/json; charset=utf-8"
Invoke-RestMethod -Method POST -Uri $url -ContentType $contentType -Body $json

Invoke-WebRequest -Method 'POST' with -ContentType 'application/json' Fails

When using:
$body = #{
Manager = "spmigrationuser#contoso.com" #$item.PMEmail
Name = "some name"
Number = "Some number"
Practice = "Some Practice"
}
$response = Invoke-RestMethod -Method Post -Uri $Url -Body $body -ContentType 'application/json' # -Headers $Headers
Or
$response = Invoke-WebRequest -Method 'POST' -Uri $Url -Body $body -ContentType 'application/json' # -Headers $Headers
Neither ContentType 'application/json'
Nor
$Headers = #{'Content-Type' = 'application/json' }
-Headers $Headers
Works
The error is always:
"Invoke-WebRequest : {"error":{"code":"InvalidRequestContent","message":"The request content is not valid and could not be deserialized: 'Error parsing NaN value. Path '', line 1, position 1.'."}}"
The same call works in Postman
I am using PS 5.1 and I must have -ContentType 'application/json' otherwise PS works but the service fails
What can be the issue?
I agree with NickSalacious. Your issue is that you are not sending JSON.
If you are using Postman and just starting to do API in PowerShell. Postman has a "Code" Link in the top right hand corner of the request. Just below and to the right of the Send button. In there you can select PowerShell. This will give you a good basis to see how the same request could be ran in PowerShell.
Postman would turn your body into this:
$body = "{`n `"Manager`": `"spmigrationuser#contoso.com`",`n `"Name`": `"some name`",`n `"Number`": `"Some number`",`n `"Practice`": `"Some Practice`"`n}"
This is not the easiest to work with and to read. Learning and using ConvertTo-Json is going to help a lot more in the long run.
*Edit: Also look at Invoke-RestMethod and Invoke-WebRequest. They behave differently and sometimes one will be better than the other.
*Edit2: Figured I would put an example of another way to do it.
$request = #{
Uri = 'http://YourURI.Here'
Headers = #{ 'Authorization' = $token
'AnotherHeader?' = 'Sure'}
Method = 'POST'
Body = '{
"Manager": $item.PMEmail,
"Name": "some name",
"Number": "Some number",
"Practice": "Some Practice"
}'
ContentType = 'application/json'
}
$response = Invoke-RestMethod #request
The API requires that the body be a JSON string. You can do a simple conversion (using ConvertTo-Json) in your Invoke-RestMethod command and set the content type accordingly.
Invoke-RestMethod -Method POST -Uri $uri -Header $header -Body ($body | ConvertTo-Json) -ContentType 'application/json'
Sorry I bothered all of you.
I tested on another computer and it works fine.

calling an API in PowerShell

need help here: I have this api which i run in Postman (https://dev.azure.com/abc/Abc/_apis/build/builds/24169/workitems?api-version=4.1), I get result as
{
"count": 50,
"value": [
{
"id": "21610",
"url": "https://dev.azure.com/abc/_apis/wit/workItems/21610"
},
{
"id": "21606",
"url": "https://dev.azure.com/abc/_apis/wit/workItems/21606"
}]}
I need to call this in Powershell, and get a list of all IDs. I am doing this way but I am not getting anything..what wrong am I doing?
Function GET-RELEASEWIT {
$AzureDevOpsPAT ='psgklxbjircg5g5fda'
$AzureDevOpsAuthenicationHeader = #{Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($AzureDevOpsPAT)")) }
$uriAcc = "https://dev.azure.com/abc/ABC/_apis/build/builds/24169/workitems?api-version=4.1"
write-host $uriAcc
$responseRelW = Invoke-RestMethod -Uri $uriAcc -Method get -Headers $AzureDevOpsAuthenicationHeader
write-host $responseRelW
$BID = #()
$BID += $responseRelW.value.id
write-host "********START****************"
write-host $BID
}
I've tried the below and it works. Only difference I can see is that I've used UTF8.GetBytes instead of ASCII.GetBytes when converting the PAT token to a base64 string, which shouldn't cause any difference since the character mappings are the same.
$uri = "https://dev.azure.com/abc/ABC/_apis/build/builds/24169/workitems?api-version=4.1"
$AzureDevOpsPAT ='psgklxbjircg5g5fda'
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$AzureDevOpsPAT"))
$headers = #{ Authorization = "Basic $B64Pat" }
Invoke-RestMethod -Uri $uri -Headers $headers
Note the URI and PAT token are obviously different when I tested this, but this should work for you.

Powershell Invoke-RestMethod POST has issues with json

I am trying to use a REST API to configure some alerts in RecoverPoint for Virtual Machines (RP4VM). I am trying to enter multiple filters at the same using json. The json file looks like this:
[
{
"JsonSubType": "SystemEventLogsFilter",
"level": "WARNING",
"scope": "NORMAL",
"eventsIDs": [],
"filterUID": {
"id": 1570417688566256135
},
"name": "RPA_issue",
"topic": "RPA",
"groupsToInclude": null
},
{
"JsonSubType": "SystemEventLogsFilter",
"level": "WARNING",
"scope": "ADVANCED",
"eventsIDs": [],
"filterUID": {
"id": -1728986321682574312
},
"name": "cluster_events",
"topic": "CLUSTER",
"groupsToInclude": null
}
]
When I try to run the script I get an error:
Unexpected token (START_ARRAY), expected START_OBJECT: need JSON Object to contain As.PROPERTY type information (for class com.emc.fapi.version5_2.commons.SystemEventLogsFilter)
at [Source: org.apache.catalina.connector.CoyoteInputStream#75b592c2; line: 1, column: 1]
If I remove the square brackets it does the first value but not the second. Is this an issue with my code or an issue with theirs?
The script:
$rp4vmcl = import-csv -Path .\test_clusters.csv
$credential = Get-Credential
$username = $credential.GetNetworkCredential().UserName
$password = $credential.GetNetworkCredential().password
$credPair = "$($username):$($password)"
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($credPair))
$headers = #{
Authorization = "Basic $encodedCredentials";
"Accept" = "application/json";
"Content-Type" = "application/json"
}
$comp = "/system/event_logs_filters"
$json = Get-Content .\event_log_filter.json -Raw
foreach ($s in $rp4vmcl) {
$cluster = $s.cluster_name
$uid = $s.cluster_uid
$curl = $s.cluster_url
$url = "$curl$comp"
$cluster
$results = Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body $json
}
If the recipient expect one Call per Json Object it will not be able to handle arrays. It's totally dependant from the implementation of the webservice. Btw, better change the body:
$results = Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($json))
Try this first, and if this is doesnt help, loop through the elemnts and call the webservice individual:
$jsonObject = $json | ConvertFrom-Json
$results = #()
$jsonObject | foreach {
$json = $_ | ConvertTo-Json -Depth 99
$results += Invoke-RestMethod -Method POST -uri $url -SkipCertificateCheck -Headers $headers -Body ([System.Text.Encoding]::UTF8.GetBytes($json))
}
Btw, the invoke-restmethod is buggy in powershell < 6 Version, so if youre will with the standard V5 Windows Version, check the response headers via invoke-webservice, and if the response header is:
"application/json"
and not
"application/json; charset=utf-8"
powershell will misinterpret this as a windows encoding. So if youree experiencing encoding issues, you have four options:
1.) if you can modify the webservice, change the response header
2.) switch to a newer powershell version (v7 is recommended)
3.) build your own webservice call directly via the .net cmdlets
4.) use the invoke-webservice, write the answer directly into a file with the OutFile Paramater
see also:
Powershell Invoke-RestMethod incorrect character

Error 400 bad request when creating a group calendar event in powershell with Microsoft Graph API

I'm trying to create an event in a calendar in an Office 365 group via powershell.
This is my first experience to do this type of programming so sorry if my question will be very basic :-)
First, I created a simple json file (calendar.json)
{
"start":
{
"dateTime":"2017-03-12T17:00:00.0000000",
"timeZone":"UTC"
},
"end":
{
"dateTime":"2017-03-12T17:30:00.0000000",
"timeZone":"UTC"
},
"responseStatus": {
"response": "None"
},
"iCalUId": "null",
"isReminderOn": false,
"subject": "Test Event created from API"
}
Then I create the event with these steps:
Use a tested powershell function that give me the token
Add header with this code:
$headers = #{}
$headers.Add('Authorization','Bearer ' + $token.AccessToken)
$headers.Add('Content-Type',"application/json")
Because I'm starting now, I convert the json file in an object and then the object in json (I know, it's quite stupid, but I've done so beacuse I have no knowledge of json and how convert without error in powershell code)
$json = ConvertFrom-Json -InputObject (Gc 'C:\Users\mmangiante\OneDrive - Interactive Media S.p.A\Office 365\calendar.json'-Raw)
$body = ConvertTo-Json $json
Call the Invoke-RestMethod
response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/groups/768afb0c-bafd-4272-b855-6b317a3a9953/calendar/events' -Method Post -Headers $headers -Body $json
What is returned is a 400 bad request.
It's the same error of Sending Microsoft Graph request events returns 400
Given the answer given to that question I modified my code to return the error:
try{$restp=Invoke-RestMethod 'https://graph.microsoft.com/v1.0/groups/768afb0c-bafd-4272-b855-6b317a3a9953/calendar/events' -Method Post -Headers $headers -Body $json
} catch {$err=$_}
$err
like suggested in How do I get the body of a web request that returned 400 Bad Request from Invoke-RestMethod but I found nothing of interest.
The only thing that I found is that, at the time of writing, the Invoke-RestMethod doesn't return the full response as in this https://github.com/PowerShell/PowerShell/issues/2193
I suppose my json is not "well formed", but I don't know why.
Does anyone have a suggestion?
This formatting has worked for me in the past. Let me know if this resolves your issues:
$headers = #{
"Authorization" = ("Bearer {0}" -f $token);
"Content-Type" = "application/json";
}
$body = #{
Name1 = 'Value1';
Name2 = 'Value2';
}
$bodyJSON = $body | ConvertTo-Json
Invoke-RestMethod -Method Post -Uri <API HERE> -Headers $headers -Body $bodyJSON -OutFile $output
Thanks Shawn,
I tried your suggestion but without luck; I have done other test with 2 other api and found discordant results.
The first test is to use the graph api related to contact, creating a contact as in https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/user_post_contacts
I created the powershell representation of the sample json:
$contactbody = #{
givenName = 'Ciccio';
surname = 'Patacca';
emailAddresses = #(
#{
address = 'cicciopatacca#cicciociccio.com'
name = 'Ciccio Patacca'
}
)
businessPhones = (
'+39 555 123 4567'
)
}
and then converted in json
$contactbody = $contactbody | ConvertTo-Json
I retrieved from Azure Portal the object ID related to my user in my company and so I call the rest method:
$response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/users/e37d2dbe-bdaf-4098-9bb0-03be8c653f7d/contact' -Method Post -Headers $headers -Body $contactbody
The final result is a 400 bad request error.
So, I tried another example and reused some code retrieved from a google search.
This time I copied the powershell json representation as in the sample and converted:
$body = #{"displayName"="ps-blog"; "mailEnabled"=$false; "groupTypes"=#("Unified"); "securityEnabled"=$false; "mailNickname"="ps1" } | ConvertTo-Json
and, as stated in https://graph.microsoft.io/en-us/docs/api-reference/v1.0/api/group_post_groups I called the rest method
$response = Invoke-RestMethod 'https://graph.microsoft.com/v1.0/groups' -Method Post -Headers $headers -Body $body
and this worked.
So I thought that the previously powershell representations of the sample with the error were not correctly formed (even if when I printed it they are equal to the samples on the graph api); for test, I rewritten the last powershell of the body as this:
$body = #{
displayName = 'TestGraphGroup';
mailEnabled = $true;
groupTypes = #('Unified')
securityEnabled = $false;
mailNickname = 'TestGraphGroup'
}
$body = $body | ConvertTo-Json
and invoked last method: it worked again.
So, where I'm doing wrong?
A new SDK was released that makes this easier.
Checkout instructions on how to use it here