Having recently been through a similar problem, and learning to solve it, I thought I'd share my learning experience.
As we learned, anybody can request a post with status=publish
. If you get errors like the following or similar, then you should start thinking in terms of problems with authentication or permissions:
stdClass Object
(
[code] => rest_invalid_param
[message] => Invalid parameter(s): status
[data] => stdClass Object
(
[status] => 400
[params] => stdClass Object
(
[status] => Status is forbidden.
)
[details] => stdClass Object
(
[status] => stdClass Object
(
[code] => rest_forbidden_status
[message] => Status is forbidden.
[data] => stdClass Object
(
[status] => 401
)
)
)
)
)
...or...
stdClass Object
(
[code] => jwt_auth_invalid_token
[message] => Wrong number of segments
[data] => stdClass Object
(
[status] => 403
)
)
...If you are logged in as an admin, then you should have permission to see draft posts. Therefore, it is likely your API calls are not authenticating for some reason.
The first thing I tested was the token. I happen to be using the JWT Authentication for WP-API plugin, which is actually pretty easy to implement. After installing/activating JWT Auth, go to the user you want to assign to use your API calls, and at the bottom of the user profile you will see :
![Application Account name](https://i.stack.imgur.com/Es3ar.png)
Give your application a name, Add New, and then a new application password will pop up. It will look like this:
![Application password](https://i.stack.imgur.com/Y0rF4.png)
Copy the whole password, keeping the spaces is fine.
I'm using PHP and cURL, so my get token code looks like this:
private function getAuthHeader(){
$JWTtoken = json_decode($this->getJWTToken());
$token = $JWTtoken->token;
$header = array(
"Content-type: application/json",
"Authorization: Bearer " . $token
);
return $header;
}
public function getJWTToken(){
/*
Request: POST http://basic/wp-json/api/v1/token
Body:
username = <wordpress username>
password = <wordpress password>
*/
$url = $this->baseurl . "jwt-auth/v1/token";
$params = array(
'requesttype' => 'POST',
'url' => $url,
'post' => array('username' => 'admin', 'password' => 'esmA UJom vxAG LFKU q8oN DSGK')
);
$ch = curl_init();
CURL_SETOPT($ch, CURLOPT_RETURNTRANSFER, 1);
CURL_SETOPT($ch, CURLOPT_URL, $params['url']);
CURL_SETOPT($ch, CURLOPT_POST, TRUE);
CURL_SETOPT($ch, CURLOPT_POSTFIELDS, http_build_query($params['post']));
CURL_SETOPT($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
...You will see way down in $params where I set the username/password. The username is "admin", because that's the user I set the new application password for, and the password is esmA UJom vxAG LFKU q8oN DSGK
. Notice I'm NOT using the admin's WordPress password.
Your header becomes an array, and it should look something like this, which includes a loooong token string:
Array ( [0] => Content-type: application/json [1] => Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9iYXNpYyIsImlhdCI6MTYyMzI2NjUyNSwibmJmIjoxNjIzMjY2NTI1LCJleHAiOjE2MjM4NzEzMjUsImRhdGEiOnsidXNlciI6eyJpZCI6IjEifX19.YX1UvJ5nlbG2MIlheI2NzTTzaQKBZ8I9WQOr70CE1Tk )
Finally, the function that makes the request using cURL looks like this:
public function getResponse($params){
$auth_header = $this->getAuthHeader();
$ch = curl_init();
CURL_SETOPT($ch, CURLOPT_RETURNTRANSFER, 1);
CURL_SETOPT($ch, CURLOPT_URL, $params['url']);
if( isset($params['requesttype']) && $params['requesttype'] == "POST" ){ //additional code to detect whether I'm making a GET, POST, or PUT request.
CURL_SETOPT($ch, CURLOPT_POST, TRUE);
}
else if( isset($params['requesttype']) && $params['requesttype'] == "PUT"){
CURL_SETOPT($ch, CURLOPT_CUSTOMREQUEST, "PUT");
}
if(isset($params['post'])){
CURL_SETOPT($ch, CURLOPT_POSTFIELDS, http_build_query($params['post']));
}
CURL_SETOPT($ch, CURLOPT_SSL_VERIFYPEER, false);
CURL_SETOPT($ch, CURLOPT_HTTPHEADER, $auth_header);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
Notice that before executing the cURL, I want to get my header, with the new token, by calling the getAuthHeader function:
$auth_header = $this->getAuthHeader();
and notice that I have to pass that header, which contains the new token, to the web service:
CURL_SETOPT($ch, CURLOPT_HTTPHEADER, $auth_header);
Barring any typos, which is always my problem, this should return posts with status=draft:
public function getPosts($params){
// I passed $params['status'] = "draft";
$url = $this->baseurl . "wp/v2/posts/?status=" . $params['status'] . "";
$data = array(
'requesttype' => 'GET',
'url' => $url
);
return $this->getResponse($data);
}