Invoke-WebRequest CloudFlare API Error 400


This returns server 400 but there’s no debug information. How can I get the debug information or what have I done wrong?

$ZoneID = "MyZoneId"
$recordID = "IDofARecord"
$URL = "" + $ZoneID+ "/dns_records/" + $recordID
$newIPAddress = Invoke-WebRequest -Uri http://somethingtogetmyip | Select-Object -ExpandProperty Content
$headers = @{
 "X-Auth-Email" = "mycloudflareemail";
 "X-Auth-Key" = "myapiauthkey";
 "Content-Type" = "application/json";
$body = @{
 "type" = "A";
 "name" = "therecordtoupdate";
 "content" = "$newIPAddress";
 "ttl" = "120"; 
 "proxied" = "false";
$body = $body | ConvertTo-Json

(Invoke-WebRequest -Uri $URL -Method PUT -Headers $headers -Body $body).Content

The output I get is:

Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
At C:\Users\Me\Documents\CloudFlareUpdater.ps1:20 char:13
+ $response = Invoke-RestMethod -Uri $URL -Method 'PUT' -Headers $heade ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Response is: 
PS C:\Users\Me>


I’m not familiar with the scripting language you’re using there, but I suspect the JSON you’re sending is malformed because you’re treating these values as strings:

 "ttl" = "120"; 
 "proxied" = "false";

The TTL should be a number, and the proxied value should be a boolean:

If you change your scripting so that those values are not quoted, this may ensure the JSON request is properly formatted. If you still have issues - the best thing to do is get the JSON encoded body of the request logged somewhere so you can see exactly how it is formatted.


Hi @simon thanks for the reply. I’ve looked at this a lot over the past two days and just a second ago found the problem. The URL needs to have a trailing slash. This is not documented in the API information and is possibly a quirk of using PowerShell as opposed to cURL.

In the hopes that someone else might find this useful, here’s a working example (fill in the examples as appropriate):

$ZoneID = "zoneid"
$recordID = "recordid"
$URL = "" + $ZoneID + "/dns_records/" + $recordID + "/"
$myIP = (Invoke-WebRequest -Uri http://ipservice).Content
$headers = @{
 "X-Auth-Email" = "email";
 "X-Auth-Key" = "apikey";
 "Content-Type" = "application/json";
$body = @{
 "type" = "A";
 "name" = "arecord";
 "content" = "$myIP";
$body = $body | ConvertTo-Json

Invoke-WebRequest -Uri $URL -Method PUT -Headers $headers -Body $body

“ttl” and “proxied” are optional so I omitted them to rule them out.


@simon PowersShell FTW :slight_smile:


Hopefully, this helps someone:

$body = @{
“type” = “A”;
“name” = “arecord”;
“content” = “$myIP”;
“ttl” = 120;
“proxied” = $false;