phpList 3.4.3 API

phpList 3.4.3
PHP 7.3

phpList “user” is a Super Admin user.

I want to receive mailing lists through API.
I get the following error:
string(89) “{“expiry”:“2019-06-20T06:14:37+00:00”,“key”:“c41e6707d76104cb6ec7b20afb6b0392”,“id”:1614}” string(34) “{“code”:403,“message”:“Forbidden”}”

<?php
	$api_path = 'https://domain.com/lists/api/v2/';
	$loginName = 'name';
	$loginPass = 'pass';
	
	// login
	
	$credentials = base64_encode($loginName . ':' . $loginPass);
	$curl = curl_init();
	curl_setopt_array($curl, array(
		CURLOPT_URL => $api_path . "sessions",
		CURLOPT_RETURNTRANSFER => true,
		CURLOPT_ENCODING => "",
		CURLOPT_MAXREDIRS => 10,
		CURLOPT_TIMEOUT => 0,
		CURLOPT_FOLLOWLOCATION => false,
		CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
		CURLOPT_CUSTOMREQUEST => "POST",
		CURLOPT_POSTFIELDS =>"{\n    \"login_name\": \"$loginName\",\n    \"password\": \"$loginPass\"\n}",
		CURLOPT_HTTPHEADER => array(
			"Content-Type: application/json",
			"Authorization: Basic $credentials"
		),
	));
	$response = curl_exec($curl);
	curl_close($curl);
	
        var_dump($response);	
        $response = json_decode($response);
	
	// call API
	
	$credentials = base64_encode($loginName . ':' . $response->key);
	$curl = curl_init();
	curl_setopt_array($curl, array(
		CURLOPT_URL => $api_path . "lists",
		//CURLOPT_URL => $api_path . "lists/1/members",
		CURLOPT_RETURNTRANSFER => true,
		CURLOPT_ENCODING => "",
		CURLOPT_MAXREDIRS => 10,
		CURLOPT_TIMEOUT => 0,
		CURLOPT_FOLLOWLOCATION => false,
		CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
		CURLOPT_CUSTOMREQUEST => "GET",
		CURLOPT_POSTFIELDS => '',//"{\n    \"loginName\": \"$loginName\",\n    \"password\": \"$loginPass\"\n}",
		CURLOPT_HTTPHEADER => array(
			"Content-Type: application/json",
			"Authorization: Basic $credentials"
		),
	));
	
	$response = curl_exec($curl);
	curl_close($curl);
	var_dump($response);
?>

I’m not sure your authentication code is correct in the second call. I think only the token is required for the basic authentication, not the login name as well. Might be wrong, check the example api client on GitHub.

I’ve checked the following example, and I believe that my code is correct:

//Use session key as password for basic auth
$credentials = base64_encode($loginname . ':' . $key);
// Get list info  where id=1
$listInfo = $client->get($base_uri . '/lists/1',
    [
        'headers' => [
            'Authorization' => 'Basic ' . $credentials,
            'Content-Type' => 'application/json',
        ],
    ]);

Should sessions be stored in the “lists/base/var/session” folder?
“lists/base/var/session” has only an empty “prod” directory in my case.

I created a new example. It has only “login” and “logout” calls. “logout” does not work. Why?

Result:

string(89) "{"expiry":"2019-06-24T15:29:15+00:00","key":"aa07ee7b3fdbfd626f0a1a7709e16f0d","id":1736}"
string(34) "{"code":404,"message":"Not Found"}"

Script:

    <?php
    	$api_path = 'http://domain.com/lists/api/v2/';
    	$loginName = 'name';
    	$loginPass = 'pass';
    	
    	// login
    	
    	$credentials = base64_encode($loginName . ':' . $loginPass);
    	$curl = curl_init();
    	curl_setopt_array($curl, array(
    		CURLOPT_URL => $api_path . "sessions",
    		CURLOPT_RETURNTRANSFER => true,
    		CURLOPT_ENCODING => "",
    		CURLOPT_MAXREDIRS => 10,
    		CURLOPT_TIMEOUT => 0,
    		CURLOPT_FOLLOWLOCATION => false,
    		CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    		CURLOPT_CUSTOMREQUEST => "POST",
    		CURLOPT_POSTFIELDS =>"{\n    \"login_name\": \"$loginName\",\n    \"password\": \"$loginPass\"\n}",
    		CURLOPT_HTTPHEADER => array(
    			"Content-Type: application/json",
    			"Authorization: Basic $credentials"
    		),
    	));
    	$response = curl_exec($curl);
    	curl_close($curl);
    	
    	var_dump($response);
    	$response = json_decode($response);		
    	
    	$key = $response->key;
    	$credentials = base64_encode($loginName . ':' . $key);
    	
    	// logout
    	
    	$url = $api_path . "sessions/" . $key;
    	//var_dump($url);
    	
    	$curl = curl_init();
    	curl_setopt_array($curl, array(
    		CURLOPT_URL => $url,
    		CURLOPT_RETURNTRANSFER => true,
    		CURLOPT_ENCODING => "",
    		CURLOPT_MAXREDIRS => 10,
    		CURLOPT_TIMEOUT => 0,
    		CURLOPT_FOLLOWLOCATION => false,
    		CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    		CURLOPT_CUSTOMREQUEST => "DELETE",
    		CURLOPT_POSTFIELDS => '',
    		CURLOPT_HTTPHEADER => array(
    			"Content-Type: application/json",
    			"Authorization: Basic $credentials"
    		),
    	));
    	$response = curl_exec($curl);
    	curl_close($curl);
    	var_dump($response);
    ?>

Unfortunately without running your code locally I cannot easily check this. I think you’ll need to continue debugging on your own unless someone else steps in to assist.

Hello All,
I have the same problem.
I have installed PHPList in Docker container based on CentOS 7, PHP 7.3.6, 5.5.60-MariaDB,
enabled PHP API following instruction on the page: manual/ch049_api-and-integrations.xhtml
Now I am trying API queries using curl.
I checked if API works trying to authenticate, and it works well:
curl --request POST --url http://localhost:8090/lists/api/v2/sessions --header ‘Content-Type: application/json’ --data ‘{“login_name”: “admin”,“password”: “password”}’{“expiry”:“2019-07-12T08:29:19+00:00”,“key”:“1cfd8597c325ba5c0c7a77bef20f7245”,“id”:79}

But any other query returns me {“code”:403,“message”:“Forbidden”}
For example:
curl --location --request GET “http://127.0.0.1:8090/lists/api/v2/lists/2” --header “Content-Type: application/json” --header “Authorization: Basic 1cfd8597c325ba5c0c7a77bef20f7245” --data “”
{“code”:403,“message”:“Forbidden”}

Appreciate any advice on how it can be further investigated!

Sorry to hear that; @xheni might have thoughts on this.

1 Like

The authorization token in the query looks wrong.
The generated login token (“key” value) is passed as basic auth password for requests that require authentication like this: base64_encode($login_name: $session_key)
In your example, the result would be base64_encode(admin:1cfd8597c325ba5c0c7a77bef20f7245) which returns YWRtaW46MWNmZDg1OTdjMzI1YmE1YzBjN2E3N2JlZjIwZjcyNDU= and this is the authorization token.
Make sure to generate a new token when you try this as session tokens expire :slight_smile:

1 Like

In the $url, please try using session ID instead of the key.

1 Like

Changed it as:
$url = $api_path . ‘sessions/’ . $response->id;
Now my script returns {“code”:403,“message”:“Forbidden”}

Thank you @samtuke @xheni for fast reply!
Looks like (not looks like, but it is really true) I do not know http protocol well. Just trying to compose the query using samples I took here: https://documenter.getpostman.com/view/3293511/phplist-4-rest-api-demo/RVftkC9t?version=latest

Following your advice I tried to rewrite my query. Now it returns something different (better?):

curl --location --request GET “http://127.0.0.1:8090/lists/api/v2/lists/82” --header “Content-Type: apication/json” --header “Authorization: Basic base64_encode(admin:c4c12ca836dc1113637ebc13111c16e9)” --data “”
{“code”:404,“message”:“Not Found”}

The result from previous query to open session was:
{“expiry”:“2019-07-12T12:43:40+00:00”,“key”:“c4c12ca836dc1113637ebc13111c16e9”,“id”:82}

What I want to achieve is to execute
GET get list info
sample working.

What I am not sure, is where to specify session ID?

Can I ask you for a favor to correct my curl request above to make it working, so that I have some firm starting point to further study the subject?

please do not hardcode this in the curl request, that’s an example for PHP. The idea is that you should encode the value using base64 or use --user as explained here https://ec.haxx.se/http-auth.html

1 Like

@xheni

did you mean this way?
curl --location --request GET “httpts/83” --header “Content-Type: apication/json” --user admin:password --data “”

But it still does not work…

curl --request POST --url http://localhost:8090/lists/api/v2/sessions --header ‘Content-Type: application/json’ --data ‘{“login_name”: “admin”,“password”: “password”}’
{“expiry”:“2019-07-14T08:15:14+00:00”,“key”:“22850e86e3ca0ebcd029f5c65989d756”,“id”:83}

curl --location --request GET “http://localhost:8090/lists/api/v2/lists/83” --header “Content-Type: apication/json” --user admin:22850e86e3ca0ebcd029f5c65989d756 --data “”
{“code”:404,“message”:“Not Found”}

Hi,
I have the same problem with a 403 response.
I can call the sessions api and get the key but calling the lists api returns 403 response.
I copied an extract of the sample posted in the api manual page.

<!DOCTYPE html>
<html>
<body>

<?php
require __DIR__ . '/vendor/autoload.php';

$client = new \GuzzleHttp\Client();

//Please replace the following values with yours.
$loginname = 'mvd';
$password = 'yyyy';
$base_uri = 'http://mydomain.com/phplist/api/v2';

try {
    $response = $client->request('POST', $base_uri . '/sessions', [
        'form_params' => [
            'login_name' => $loginname,
            'password' => $password,
        ],
    ]);
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
}

//get session key
if ($response->getBody()) {

    $obj = json_decode($response->getBody(), true);
    $key = $obj['key'];
    $id = $obj['id'];
    echo 'Session key is: ' . $key . ' id: ' . $id . '<br><br>';
}

//Use session key as password for basic auth
$credentials = base64_encode($loginname . ':' . $key);

echo 'Encoded credentials:' . $credentials . '<br><br>';


try {
$listInfo = $client->get($base_uri . '/lists/4',
    [
        'headers' => [
            'Authorization' => 'Basic ' . $credentials,
            'Content-Type' => 'application/json',
        ],
    ]);
if ($listInfo->getBody()) {
    $listInfoResponse = json_decode($listInfo->getBody(), true);
    echo 'List Info: <br><br>';
    foreach ($listInfoResponse as $key => $value) {
        echo "$key : $value<br>";
    }
    echo '<br>';
}
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}


?>

</body>
</html>

The output is:
Session key is: c54ada8fa215f41d0818d9b57a9d5def id: 1986

Encoded credentials:bXZkOmM1NGFkYThmYTIxNWY0MWQwODE4ZDliNTdhOWQ1ZGVm

Caught exception: Client error: GET http://lsqanet.info/phplist/api/v2/lists/4 resulted in a 403 Forbidden response: {“code”:403,“message”:“Forbidden”}

Thanks in advance.

Hi All,
back from vacation things look much easier. No problems any more :slight_smile:

Here is shell equivalent of sample php script RESTAPIphpListClient.php provided on GitHub:

#!/bin/bash

loginname=‘admin’
password=‘password’
base_uri=’ ’ # I had to remove my base uri, as far as site does not permits me to publish it

#Initialize session

echo “Itializing session…”

response=curl --request POST --url "${base_uri}/sessions" --header 'Content-Type: application/json' --data "{\"login_name\": \"$loginname\",\"password\": \"password\"}"

#$response=’{“expiry”:“2019-08-17T18:37:27+00:00”,“key”:“3de46ddd6930def96bf1ac63d38e1985”,“id”:94}’
echo $response

#Extract sesson key from response

key=echo $response | jq '.key' | sed -e 's/^"//' -e 's/"$//'
echo “Got session key: $key”

#Use session key as password for basic auth

credentials=echo -n "$loginname:$key" | base64
echo “Encoded credentials: $credentials”

#echo $credentials | base64 --decode

#Get list info where id=1 (pipe to jq. to make result more readable

echo “Get list info where id=1”
curl --location --request GET “${base_uri}/lists/1” --header “Content-Type: application/json” --header “Authorization: Basic $credentials” | jq .

#Get all subscribers where list id=1

echo “Get all subscribers where list id=1”
curl --location --request GET “${base_uri}/lists/1/members” --header “Content-Type: application/json” --header “Authorization: Basic $credentials” | jq .

#Add a new subscriber

echo “Add a new subscriber”

curl --location --request POST “${base_uri}/subscribers”
–header “Content-Type: application/json”
–header “Authorization: Basic $credentials”
–data “{“email”:“restapi7@example.com”,“confirmed”:true,“blacklisted”:false,“html_email”:true,“disabled”:false}” | jq .


And below is the script output:

Itializing session…
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 134 100 88 100 46 644 336 --:–:-- --:–:-- --:–:-- 647
{“expiry”:“2019-08-20T09:36:57+00:00”,“key”:“bb3bb3df05484aab008831853fe5e764”,“id”:174}
Got session key: bb3bb3df05484aab008831853fe5e764
Encoded credentials: YWRtaW46YmIzYmIzZGYwNTQ4NGFhYjAwODgzMTg1M2ZlNWU3NjQ=
Get list info where id=1
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 128 100 128 0 0 903 0 --:–:-- --:–:-- --:–:-- 907
{
“name”: “test”,
“description”: “List for testing”,
“creation_date”: “2019-07-02T11:29:16+00:00”,
“public”: false,
“category”: “”,
“id”: 1
}
Get all subscribers where list id=1
./CURL_Tests.bash: line 41: unexpected EOF while looking for matching `"’
./CURL_Tests.bash: line 43: syntax error: unexpected end of file
leonid@leonid-ThinkPad-T520:~/Projects/Allegro/HoneyPOT/20190627_PHPListCcontainer/REST_API$ ./CURL_Tests.bash
Itializing session…
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 134 100 88 100 46 655 342 --:–:-- --:–:-- --:–:-- 656
{“expiry”:“2019-08-20T09:38:09+00:00”,“key”:“68f2b04d9641f0a9df096d1a83a4727d”,“id”:175}
Got session key: 68f2b04d9641f0a9df096d1a83a4727d
Encoded credentials: YWRtaW46NjhmMmIwNGQ5NjQxZjBhOWRmMDk2ZDFhODNhNDcyN2Q=
Get list info where id=1
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 128 100 128 0 0 855 0 --:–:-- --:–:-- --:–:-- 853
{
“name”: “test”,
“description”: “List for testing”,
“creation_date”: “2019-07-02T11:29:16+00:00”,
“public”: false,
“category”: “”,
“id”: 1
}
Get all subscribers where list id=1
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 216 100 216 0 0 1468 0 --:–:-- --:–:-- --:–:-- 1479
[
{
“creation_date”: “2019-07-02T11:29:16+00:00”,
“email”: "leon@us.ibm.com",
“confirmed”: true,
“blacklisted”: false,
“bounce_count”: 0,
“unique_id”: “047355177e01fac11435bd3abda4b18f”,
“html_email”: true,
“disabled”: false,
“id”: 1
}
]
Add a new subscriber
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 339 100 235 100 104 1352 598 --:–:-- --:–:-- --:–:-- 1358
{
“creation_date”: “2019-08-20T08:38:09+00:00”,
“email”: "restapi7@example.com",
“confirmed”: true,
“blacklisted”: false,
“bounce_count”: 0,
“unique_id”: “7108f6352dec2c1d1d3bd6720fd8981f”,
“html_email”: true,
“disabled”: false,
“extra_data”: “”,
“id”: 9
}

}

2 Likes

@ltepl That’s fantastic - thanks for sharing! Happy it’s working for you, and that you enjoyed a good vacation.