I'm converting a curl request to PowerShell's Invoke-RestMethod for an API endpoint that expects a JSON array of objects. The curl request sends an array like [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}]. I first created a here-string containing one JSON object and then piped it through ConvertTo-Json before passing it as the request body, but the API returned an invalid_json error. What is the correct way to construct and send this body, especially when submitting only one object?
3 Answers
The request body should look like this for two entries: $body = @'
[
{ "key1": "value1", "key2": "value2" },
{ "key1": "value3", "key2": "value4" }
]
'@. A single-quoted here-string is convenient because the JSON double quotes don’t need escaping. The important parts are not double-converting an already valid JSON string and including the array brackets required by the endpoint.
A more maintainable approach is to create PowerShell hashtables and convert the resulting array to JSON. Be careful to preserve the array shape when there is only one item: $body = ConvertTo-Json -InputObject @(@{ key1 = 'value1'; key2 = 'value2' }) -Depth 3. For multiple items: $body = @(@{ key1 = 'value1'; key2 = 'value2' }, @{ key1 = 'value3'; key2 = 'value4' }) | ConvertTo-Json -Depth 3. Then use Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -ContentType 'application/json' -Body $body.
The here-string already contains JSON, so don’t pipe it through ConvertTo-Json again. Also, the curl example sends an array, not a single object. Even with one item, the API may require the surrounding square brackets: $body = @'
[
{
"key1": "value1",
"key2": "value1"
}
]
'@. Then send it with Invoke-RestMethod and set ContentType to application/json.
That was the key issue in my case: the endpoint required [{...}] even when there was only one object. Using a literal JSON array fixed the request.

PowerShell can enumerate a one-element array through the pipeline, which can turn it into a JSON object instead of a JSON array. Supplying it with -InputObject helps retain the outer array.