API Returning 400 Bad Request

Hi,

I am trying to setup a simple Cloudflare API request and I am having trouble getting the right key configurations. Can you please help?

For reference, there are 3 variables that I will be referencing:

TOKEN = generated through user profile - tokens page
Bearer = generated through user profile - tokens page
TOKEN2 = generated when viewing https://api.cloudflare.com/client/v4/user/tokens/verify with TOKEN

When I go to my user profile - Tokens and generate a New User TOKEN and an example of code below with a Bearer header request.

When I take those examples as through the documentation and visit the Tokens Verify page using the Bearer header, I receive a valid response. Example:

Invoke-RestMethod -URI ā€˜https://api.cloudflare.com/client/v4/user/tokens/verifyā€™ -Method ā€˜GETā€™ -ContentType ā€˜application/jsonā€™ -Headers @{ā€˜Authorizationā€™=ā€˜Bearer SECRETā€™;ā€˜Content-Typeā€™=ā€˜application/jsonā€™}

I receive ā€˜@{id=TOKEN2; status=active} True {} {@{code=10000; message=This API Token is validā€™

Giving me TOKEN from the user profile I generated and TOKEN2 from viewing my user tokens using the Bearer request.

I am now taking TOKEN and TOKEN2 that was just generated and attempting to purge the cache for a zone. I receive the error: {ā€œsuccessā€:false,ā€œerrorsā€:[{ā€œcodeā€:10000,ā€œmessageā€:ā€œAuthentication errorā€}]}

Iā€™ve tried using the following:

Invoke-RestMethod -URI ā€˜https://api.cloudflare.com/client/v4/zones/mywebsitezone/purge_cacheā€™ -Method ā€˜POSTā€™ -ContentType ā€˜application/jsonā€™ -Headers @{ā€˜X-Auth-Emailā€™=ā€˜[email protected]ā€™;ā€˜X-Auth-Keyā€™=ā€˜MYTOKEN AND MYTOKEN2ā€™;ā€˜Content-Typeā€™=ā€˜application/jsonā€™} -Body ā€˜{ā€œfilesā€:ā€œtestpage.htmlā€}ā€™

The permissions for my new TOKEN have Zone + Cache Purge Permissions set.

What am I doing wrong?

You donā€™t need TOKEN2. The verify endpoint just tells you the token is valid, it doesnā€™t give you another token.

It should look something like
Invoke-RestMethod -URI ā€˜https://api.cloudflare.com/client/v4/zones/mywebsitezone/purge_cacheā€™ -Method ā€˜POSTā€™ -ContentType ā€˜application/jsonā€™ -Headers @{ā€˜Authorizationā€™=ā€˜Bearer SECRETā€™;ā€˜Content-Typeā€™=ā€˜application/jsonā€™} -Body ā€˜{ā€œfilesā€:ā€œtestpage.htmlā€}ā€™

Is it possible there is a bug or something? Basically when I create a TOKEN, there is an example that says:

ā€™ Test this token

To confirm your token is working correctly, copy and paste the below CURL command in a terminal shell to test.ā€™

It has the -H "Authorization: Bearer string inside of itā€¦

I take that exact header and put it inside of my request, and it still fails with {ā€œsuccessā€:false,ā€œerrorsā€:[{ā€œcodeā€:10000,ā€œmessageā€:ā€œAuthentication errorā€}]}

Here is exactly what Iā€™m sending

Invoke-RestMethod -URI ā€˜https://api.cloudflare.com/client/v4/zones/MY ZONE/purge_cacheā€™ -Method ā€˜POSTā€™ -ContentType ā€˜application/jsonā€™ -Headers @{ā€˜Authorizationā€™=ā€˜THE DATA FROM THE USER PROFILE PAGE I JUST CREATEDā€™} -Body ā€˜{ā€œfilesā€:ā€œ/testing/testā€}ā€™

Which failsā€¦ but if I send the example request using the exact same Authorization header - it works.

Invoke-RestMethod -URI ā€˜https://api.cloudflare.com/client/v4/user/tokens/verifyā€™ -Method ā€˜GETā€™ -ContentType ā€˜application/jsonā€™ -Headers @{ā€˜Authorizationā€™=ā€˜Bearer THE DATA FROM THE USER PROFILE PAGE I JUST CREATEDā€™}

I am having the exact same issue with CURL through PHP and Powershell (examples given).

This is missing the Bearer part.

It could also be some weird conversation from curl to the PowerShell version of it.

Haha, I wish! I just removed that from one of the examples and not the otherā€¦

I literlyā€¦ have the code workingā€¦ and then I replace the ā€˜GETā€™ with POST and the URLā€¦

I already have this field set in CURL:

ā€˜curl_setopt($curl, CURLOPT_POSTFIELDS, ā€˜{ā€œfilesā€: ā€œ/testing/test/ā€}ā€™);ā€™

Which I actually just leaveā€¦ because when itā€™s on the GET request it skips thatā€¦

So basically my examples work, then I change the request from GET to POST and change the URL. Then I have an authentication error.

I have done this with both versionsā€¦ I get the same errorā€¦

Here is a screen shot of my API user account rules:

Can you share your code? I donā€™t know PHP that well, but I can take a quick clean look to see if I see anything obvious with it.

Here is example code in PHP using CURL. Set the $myzone variable to initiate a POST request an example purge of /testing/test/ which should throw some error or succeed

//set the $myzone variable to initiate the POST request to purge the cached

$token='Bearer ';		//leave Bearer in the string
$myzone='';		//example: 'c05d7c833333333fe24a01111bee1111'

if(!$myzone){
	$url='https://api.cloudflare.com/client/v4/user/tokens/verify';

}else{
	$url='https://api.cloudflare.com/client/v4/zones/'.$myzone.'/purge_cache';
}

$http_data=array();

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);

//curl_setopt($curl, CURLOPT_HTTPHEADER, array("X-Auth-Email: ", "X-Auth-Key: ", "Content-Type: application/json"));
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: $token", "Content-Type: application/json"));

if(!$myzone){
	curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');

}else{
	curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
	curl_setopt($curl, CURLOPT_POST, 1);
	curl_setopt($curl, CURLOPT_POSTFIELDS, '{"files": "/testing/test/"}');
}

$http_data['html'] = curl_exec($curl);
$http_data['http_code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);

$http_data['headers']=substr($http_data['html'], 0, strpos($http_data['html'], "\r\n\r\n"));
$http_data['html']=substr($http_data['html'], strpos($http_data['html'], "\r\n\r\n") + 4);


print_r($http_data);

Can you try having your files section be '{"files": "/testing/test/test.html"}'?

Iā€™m wondering if it is an issue with plans, as the URL prefix purge is only available on enterprise plans.

Hi, That doesnā€™t work either. I tried using an exact URL that is live and still receive

{ā€œsuccessā€:false,ā€œerrorsā€:[{ā€œcodeā€:10000,ā€œmessageā€:ā€œAuthentication errorā€}]}

Thank you for helping! Do you have purge code that works on your end? Like I gave you my API key, could you test it or something? I donā€™t think thereā€™s a way for me to contact Cloudflare. It should be so simple yet it seems broken lol.

Are you sure the X-Auth-Email and X-Auth-Key arenā€™t for the purge request? Neither work for me

I have a GitHub Action which handles purging of cache: GitHub - Cyb3r-Jak3/action-cloudflare-cache: Github Action to purge Cloudflare cache that you could try.

Thank you! Thatā€™s a good idea to maybe try a 3rd party service to see how it works.

It looks to me like your code uses the ā€˜Global APIā€™ token, not to be confused with the ā€˜Origin CAā€™ token which are different from the token you can generate and then it also uses the email hader field. Say that 5 times fast.

    zone: ${{ secrets.CLOUDFLARE_ZONE }}

    # Using API Token
    api_token: ${{ secrets.CLOUDFLARE_TOKEN }}

    # Using Global Token
    email: ${{ secrets.CLOUDFLARE_EMAIL }}
    global_token: ${{ secrets.CLOUDFLARE_KEY }}

But thank you! I will try to take a look because I really need to get the purge going for Comments

It supports both. You can either use the Global Token which is the X-Auth-Email and X-Auth-Key or the API token which is the Authorization header.

1 Like

Ok the solution is this:

The ZONE id must be retrieved through the API to get the correct Zone ID. The Zone ID through the web interface is different.

Here is the call to find the Zone ID for the purge call:

https://api.cloudflare.com/client/v4/zones?name=DOMAIN NAME&status=active&page=1&per_page=5&order=status&direction=desc&match=all

Switching the API zone ID with the Web Zone ID fixes it right up. Thank you!!

Where are you getting the Zone ID from the dashboard? Is it following Find zone and account IDs Ā· Cloudflare Fundamentals docs

1 Like

Sorryā€¦ I donā€™t know ;x I def need a break, hereā€™s to that soon! Ty for your help!

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.