I have been challenged to get a response from an api with powershell.
I have little to no experience with powershell, but have at least been able to get a response from the API provider, but not a response i can use, so i hope someone can help me.
The photo is of the documentaion i have
Documentation
What i can't figure out is how i send the message that i want a response for.
The command is the specific api that i need to use, and it has some inputs as seen in the photo.
Input to API:
StreetName
BuildingIdentifier
Floor
Suite
DistrictCode
This is what i got so far.
$uri = 'SomeUrl.com'
$command = '/Ois/RealUnit/Address'
$token = 'SomeSecureToken'
$contentType = 'application/json'
$secureToken = ConvertTo-SecureString $token -AsPlainText -force
$webResult = Invoke-RestMethod -Method get -Uri $uri -ContentType $contentType -Token $secureToken
write-output $webResult
What i know but i don't know how to use or i it has to be used is as follows.
Request URL: https://SomeUrl.com/Ois/RealUnit/Address
Response body: is JSON and i only need the response for "unitUse"
Response Code: I also know that a good response gives the code 200
Curl: I also know that something called CURL looks a bit like this curl -X POST --header 'Content-Type: application/x-www-form-urlencoded' --header 'Accept: application/json' -d 'StreetName=STREET&BuildingIdentifier=123&Floor=12&Suite=th&DistrictCode=1234' 'https://SomeUrl.com/Ois/RealUnit/Address'
Reponse Header: Looks like this
{ "access-control-allow-headers": "Content-Type", "access-control-allow-methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS", "access-control-allow-origin": "*", "cache-control": "private", "content-length": "7604", "content-type": "application/json; charset=utf-8", "date": "Tue, 08 Mar 2022 13:21:27 GMT", "server": "Microsoft-IIS/8.5", "strict-transport-security": "max-age=31536000", "vary": "Accept", "x-aspnet-version": "4.0.30319", "x-powered-by": "ServiceStack/5.10 NET45 Win32NT/.NET, ASP.NET" }
$uri = 'https://SomeUrl.com/Ois/RealUnit/Address'
$token = 'SomeSecureToken'
$contentType = 'application/json'
$secureToken = ConvertTo-SecureString $token -AsPlainText -force
$Body = #{
StreetName = "STREET"
BuildingIdentifier = 123
Floor = 12
Suite = "th"
DistrictCode = 1234
}
$webResult = Invoke-RestMethod -Method POST -Uri $uri -ContentType $contentType -Token $secureToken -Body $Body
write-output $webResult
I can't really remember if you have to convert body to JSON data or if the 'Invoke-RestMethod' does it automatically. In any case: this is how you could do it:
$webResult = Invoke-RestMethod -Method POST -Uri $uri -ContentType $contentType -Token $secureToken -Body ($Body | ConvertTo-Json)
Related
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
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.
I'm sending a POST request with ID/password and I need to get back a respond token, how can I get it and save it for later use in the script?
$loginUrl = "https://some-ip"
$params = #{
"username"="$username"
"password"="$password"
}
Invoke-WebRequest -Uri $loginUrl -Method POST -Body ($params|ConvertTo-Json) -ContentType "application/json"
Following your input:
$url = "https://some-ip"
$params = #{
"username" = $username
"password" = $password
} | ConvertTo-Json
$apiReturn = Invoke-RestMethod -Uri $url -Method POST -Body $params -ContentType "application/json"
$apiReturn can then be used as response.
Furthermore, you can use the SessionVariable parameter of Invoke-RestMethod.
$apiReturn = Invoke-RestMethod -Uri $url -Method POST -Body $params -ContentType "application/json" -SessionVariable sessionToken
$sessionToken.Headers.Add('Authorization', $apiReturn)
$sessionToken.Headers.Add('Content-Type', 'application/json')
In this scenario, you add the response token to 'Authorization' and forward the whole token to your subsequent API calls. Like this you only need to add $sessionToken and Content-Type for example is already provided.
Invoke-RestMethod -Method Post -Uri $url -WebSession $sessionToken
You can add more parameters to your Header in case it is required.
Am Currently trying to query the authToken
$uri = 'http://xxx.centreon/api/index.php?action=authenticate'
$headers = #{
'username' = 'exemple'
'password' = 'exemple'
}
Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -ContentType application/x-www-form-urlencoded
But am having bad parameters
Via linux : curl -s -d "username=exemple&password=exemple" -H "Content-Type: application/x-www-form-urlencoded" -X POST http://xxx.centreon/api/index.php?action=authenticate
{"authToken":"NWU5OWM0YjRhMjIzMDYuMzg2NzYyMDY="}-
So this is a vague question but i do see how things might be wrong.
First the Username and Password are usually in the Body not the Header.
In your curl command I see its being passed as -d which would be the Body
$uri = 'http://xxx.centreon/api/index.php?action=authenticate'
$Body = #{
'username' = 'exemple'
'password' = 'exemple'
}
Invoke-RestMethod -Uri $uri -Method Post -body $Body -ContentType "application/x-www-form-urlencoded"
I'm trying to use the Invoke-RestMethod cmdlet in PowerShell 3 and 4, to upload a large binary file using a REST API's multipart/form-data upload. Here is a working cURL example on how to perform what I want to do in PowerShell:
curl -i -k -H "accept: application/json" -H "content-type: multipart/form-data" -H "accept-language: en-us" -H "auth: tokenid" -F file="#Z:\large_binary_file.bin" -X POST "https://server/rest/uri2"
I would love to see a working example on how to use Invoke-RestMethod to POST a multipart/form-data. I found a blog post from the PowerShell team showing how to use Invoke-RestMethod to upload to OneDrive (aka SkyDrive), but doesn't work well. I'd also like to avoid using System.Net.WebClient if at all possible. I also found another thread here on Stackoverflow, but it really didn't help much.
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
$server = "https://server"
uri = "/rest/uri1"
$headers = #{"accept" = "application/json"; "content-type" = "application/json";"accept-language" = "en-us"}
$body = #{"userName" = "administrator"; "password" = "password"}
$method = "POST"
#Get Session ID
$resp = Invoke-RestMethod -Method $method -Headers $headers -Uri ($server+$uri) -body (convertto-json $Body -depth 99)
$sessionID = $resp.sessionID
#Upload file
$uri = "/rest/uri2"
$headers = #{"accept" = "application/json";"content-type" = "multipart/form-data"; "accept- language" = "en-us"; "auth" = $sessionID}
$medthod = "POST"
$largeFile = "Z:\large_binary_file.bin"
I have tried both ways of using Invoke-RestMethod:
Invoke-RestMethod -Method $method -Headers $headers -Uri ($server+$uri) -InFile $largeFile
or
$body = "file=$(get-content $updateFile -Enc Byte -raw)"
Invoke-RestMethod -Method $method -Headers $headers -Uri ($server+$uri) -body $body
I notice couple of mistakes in your invoke statement. First, you need to use POST keyword instead of string value. Second, make sure that Content-Type is set to multipart/form-data. So this is my revised statement -
$uri = "http://blahblah.com"
$imagePath = "c:/justarandompic.jpg"
$upload= Invoke-RestMethod -Uri $uri -Method Post -InFile $imagePath -ContentType 'multipart/form-data'
You can check the response from the server by checking $upload.