Exporting Powershell REST API results as CSV - powershell

I'm currently use the following Powershell script as an API call using REST to retrieve table data from a vendor, which appears to be in JSON format:
$uri = "https://www.SomeWebsite.com/api/orders"
$headers = #{
'Content-Type' = 'application/json'
'Authorization' = 'Bearer <MyTokenID>'
'Accept'= 'application/json'
}
Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -Body $body
The script works, and output as such in Powershell:
data
----
{#{type=appointments; id=1234; attributes=; links=; relationships=}, #{type=appointments; id=1235; attributes=; links=; relationships=}, #{type=appointments; i...
I need the ability to export this as a CSV file.
How can I incorporate anexport-CSV CMDLET (something like below) to have it work with the above syntax? (Preferably ALL Columns/Headers)
Select ID, Status | Export-Csv -Path "filename.csv" -NoTypeInformation

Your Invoke-RestMethod outputs an object with a data property. The data property contains the objects you want to reference. So you must expand that property first.
Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -Body $body |
Select-Object -ExpandProperty data |
Select-Object id,status |
Export-Csv filename.csv -NoTypeInformation

Related

Running query in Pipeline in Azure-DevOps

I want to add an Azure-DevOps query to a pipeline,
Is there an option to put a query in a yaml file?
If yes, how?
Thanks in advance.
I suppose that you could run a rest api for query via powershell script or something like that in a pipeline task to do it.
GET https://dev.azure.com/{organization}/{project}/_apis/wit/queries/{query}?api-version=7.0
Powershell Script
# Define organization base url, PAT and API version variables
$orgUrl = "https://dev.azure.com/{org}/{project}"
$pat = "{pat}"
$queryString = "api-version=7.0"
# Create header with PAT
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($pat)"))
$header = #{authorization = "Basic $token"}
# Get the list of all projects in the organization
$projectsUrl = "$orgUrl/_apis/wit/queries/{query}?$queryString"
$result = Invoke-RestMethod -Uri $projectsUrl -Method Get -ContentType "application/json" -Headers $header | ConvertTo-Json | ConvertFrom-Json
write-host $result
If you are going to echo the specific element from the query result, you could modify the $result line with below
$result = Invoke-RestMethod -Uri $projectsUrl -Method Get -ContentType "application/json" -Headers $header | ConvertTo-Json | ConvertFrom-Json | Select-Object -ExpandProperty {your element}
write-host $result
You could also create a query with rest api, and with the similar powershell script to put into pipeline.
POST https://dev.azure.com/{organization}/{project}/_apis/wit/queries/{query}?api-version=7.0

Issue with for each loop with Invoke-RestMethod

I am currently having issues creating a powershell script that taks to an api with Invoke-RestMethod and a loop, I have spent all day trying to figure out where i am going wrong but i have not managed to come up with something.
Here is the code that i am trying to make
$url = "/api/Rest/v1"
$Body = #{
Username = ""
Password = ""
Privatekey = ""
}
$apikey = Invoke-RestMethod -Method 'Post' -Uri $url/Authenticate -Body $body
$headers = #{
'Authorization' = $apikey
}
$allusers = Invoke-RestMethod -Uri $url/Users -Method Get -Headers $headers | ft -HideTableHeaders Id
foreach ($userid in $allusers)
{
echo $userid
Invoke-RestMethod -Uri $url/Users/$userid -Method Get -Headers $headers
echo "test"
}
I am not having issues with the veriables $apikey and $allusers as they seem to output what i need but i think my issue is to do with the outbut being in format table but i have tried other methods for the for each and i have no clue where i am going wrong
So i have tested the Invoke-RestMethod commands on there own and they work as exspected but when i try the script above i get the following.
Invoke-RestMethod : {"Message":"User with specified id was not found."}
the output of $allusers displays something like the following for the user ID
dce502ed-e4b6-4b5e-a047-0bf3b34e98c6
dc1e60c1-99a7-479a-a7d6-0dc618c8dd5e
1bd98bb0-a9ee-46b5-8e2e-0e3146aab6b3
AKA the following work with no issues and outputs what i need
Invoke-RestMethod -Uri $url/Users/1bd98bb0-a9ee-46b5-8e2e-0e3146aab6b3 -Method Get -Headers $headers
I would really appreciate some kind of guidance on this.
The standard advice applies:
Format-* cmdlets (such as Format-Table, whose built-in alias is ft) emit output objects whose sole purpose is to provide formatting instructions to PowerShell's for-display output-formatting system.
In short: only ever use Format-* cmdlets to format data for display, never for subsequent programmatic processing - see this answer for more information.
Therefore, remove the | ft -HideTableHeaders Id pipeline segment and use member-access enumeration to extract all .Id property values as data.
$allusers = (Invoke-RestMethod -Uri $url/Users -Method Get -Headers $headers).Id

Bypass Record limit in REST API Call

I currently have a Powershell script to fetch orders through a REST API Call.
The script (1) Uses the INVOKE-ResetMethod for the API call, then (2) uses the Export-CSV cmdlet to save the results in a CSV file, which works fine:
$uri = "https://api.SomeWebisite.com/api/orders?limit=1000"
$headers = #{
'Content-Type' = 'application/json'
'Authorization' = 'Bearer SomeTokenKey'
'Accept'= 'application/json'
}
Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -Body $body | select -expand data | select * | export-csv c:\extracts\orders.csv -notype -Force
The problem is, the provider has a 1000 record return limit, which doesn't work for us, as we need all orders in the dataset.
What would be the most efficient/appropriate way to retrieve the full recordset & and have all orders reside in a single CSV file?

Insert document on CosmosDB through Powershell

I am using Invoke-RestMethod to make a post request to create a new document in CosmosDB. So far I followed theses links: Invoking Rest API using PowerShell - CosmosDb
, Add a Document to CosmosDB via the REST API using PowerShell and the official documentation.
My script retrieves an object like this from external service:
{
"ObjectId": "bd33f6b5-a066-4f0f-8d1b-291a6a2b90ba",
"Date": "\/Date(1589379850000)\/",
"Data": "{\"CreationTime\":\"2019-06-13T13:21:55\",\"Id\":\"e985f142-9359-4ebf-a319-7fa30b6c9987\", \"Fields\":[{\"Name\":\"foo\",\"Value\":\"bar\"}]}"
}
My objective is to post the field Data into cosmos. To this I extract this field using: $payload | Select-Object -expand Data. (I have the above json as PowerShell object). Since this extracted object is a string, I passed it to Invoke-RestMethod:
Invoke-RestMethod -Method $Verb -Uri $queryUri -Headers $headers -Body $payload
But I keeping getting a Bad Request status. I've also tried the following:
Invoke-RestMethod -Method $Verb -Uri $queryUri -Headers $headers -Body ($payload | ConvertTo-Json -Depth 100)
Invoke-RestMethod -Method $Verb -Uri $queryUri -Headers $headers -Body ($payload | ConvertFrom-Json | ConvertTo-Json -Depth 100)
Note: I was able to deserialize this string in C# using newtonsoft (I made a function to receive the PowerShell request). I also was able to insert this document via Postman. Looks like the issue is in the body of the request, since using the PowerShell code generated by Postman worked for me.
Edit: I am passing the content type ("application/json") in header of the request. It also fails when pass it I directly to the Invoke-RestMethod
Can someone give a light? To me it should work fine.
Your payload is missing the required id attribute:
Remember that the REST API is for the Core SQL API operations. Your payload seems to be for a Mongo document?
Make sure you are also passing the partition key. Reference: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/PowerShellRestApi/PowerShellScripts/CreateItem.ps1
The data seems to be double converted, to extract it you can use this:
$json = '{"ObjectId": "bd33f6b5-a066-4f0f-8d1b-291a6a2b90ba", "Date": "\/Date(1589379850000)\/", "Data": "{\"CreationTime\":\"2019-06-13T13:21:55\",\"Id\":\"e985f142-9359-4ebf-a319-7fa30b6c9987\", \"Fields\":[{\"Name\":\"foo\",\"Value\":\"bar\"}]}"}'
$data = $json | ConvertFrom-Json | Select-Object -ExpandProperty "Data" | ConvertFrom-Json
$body = $data | ConvertTo-Json -Depth 10
So now $body is a proper JSON object which can be send by the Invoke-RestMethod:
Invoke-RestMethod -Method $verb -Uri $queryUri -Headers $headers -Body $payload -ContentType "application/json"

How to call Invoke-RestMethod in powershell for each JSON entry

$person = #{
"Username"="Test3";
"Password"="Test3";
}
$json = $person | ConvertTo-Json
Invoke-RestMethod -Method POST -Header $Header -ContentType "application/json" -uri "http://testa.katest.com/CreateUsers/api/v1.0/Users" -Body $json
Above powershell script works perfect and also creates the username Test3 in the system:
But If I would like to call this Invoke-RestMethod for creating multiple users at the same time - What command should I use?
Since I can only assume information about your API, I can offer two potential ways to do this.
If the POST supports a JSON array, you can do the following:
$persons = #{
"Username"="Test3";
"Password"="Test3";
},#{
"Username"="Test4";
"Password"="Test4";
}
$json = $persons | ConvertTo-Json
Invoke-RestMethod -Method POST -Header $Header -ContentType "application/json" -uri "http://testa.katest.com/CreateUsers/api/v1.0/Users" -Body $json
If POST only supports one json with one user, you can do the following:
$persons = #{
"Username"="Test3";
"Password"="Test3";
},#{
"Username"="Test4";
"Password"="Test4";
}
foreach ($person in $persons) {
$json = $person | ConvertTo-Json
Invoke-RestMethod -Method POST -Header $Header -ContentType "application/json" -uri "http://testa.katest.com/CreateUsers/api/v1.0/Users" -Body $json
}
Each method centers around creating an array of hash tables. Each hash table has a key-value pair for Username and Password. Then you can choose to either iterate or not before converting to JSON.