Our latest API is a RESTful one, since REST calls are pretty straight forward.

A REST API basically works like a filesystem, where you might see the resources as directories and the data as files.
REST provides the following methods for access:

CleverReach® REST API Structure

Some of the most important resources of our REST API are the following.


While every resource is accessable on its own, some of these resources may be nested within each other because they can have multiple points of origin.

/receivers f.e. can be a standalone resource, returning you information about an email address.
/groups/{group_id}/receivers on the other hand returns only the receiver inside the group with {group_id} and way more data like subscription dates, group bound attributes events and more.

/attributes Returns a list of all global attributes (not bound to any group)
/groups/{group_id}/attributes returns all attributes bound to this group and
groups/{group_id}/receivers/{pool_id}/attributes returns all attributes assigned to this user, including their current values.
However, if you just use groups/{group_id}/receivers/{pool_id}, you will get the attributes of the user anyway embeded inside the returned structure.


To use the REST API, an access_token is required. Tokens always belong to a certain CleverReach® account.
Note: With an access_token you can control a certain CleverReach® account via REST API!

Therefore we obviously need the permission of the affected CleverReach® account owner.
That permission can be granted by the account owner using OAuth, which leads us to the next important point.

Authorization Code

Example code for pros

How to work with OAuth Code in CleverReach®:

  1. Go to Account > Extras > REST API and create an OAuth app inside of CleverReach®.
    Note the Client ID and the Client Secret the app contains!
  2. Create a callback page to be called after OAuth process has finished.
    Place that file on a server to be refereed to as the redirect_uri.
  3. Redirect the user to our OAuth service (see example code)
    The user will grant you access by logging in to CleverReach®.
    After the OAuth process finished, the redirect_uri is called.
  4. The redirect_uri - your callback page - is called with a code.
    Immediately trade this code in for an access token (see example code).
    Please note, that the code is valid only a few seconds!

This way, all your users can provide you with a token using one OAuth app.
It is really easy. Give it a try!

Example OAuth process

We will handle both, the callback page and the page to start from in one php file. Note the if to differ the output.
The example is well documented, though to try you do not need to read all the comments. Just fill the variables and go...

Download the example here

// This file contains both:
//   1. A simulation of your page/plugin/service to start the OAuth
//   2. The callback page to be called after OAuth finished
// Make sure to place this file freely accessible on a server!

// At first some very important variables:

// Values from your OAuth app. You create ONE for a page/plugin/service.
$clientid     = "#Place OAuth clientID here#";
$clientsecret = "#Place OAuth client secret here#";

// This is the url of your callback page, to be called after OAuth finished.
// In this case it is this file - wherever you put it on your server.
$redirect_uri = "#The URL of this file#";

// The official CleverReach URLs, no need to change those.
$auth_url  = "https://rest.cleverreach.com/oauth/authorize.php";
$token_url = "https://rest.cleverreach.com/oauth/token.php";

// As the callback page is called by our OAuth service with a code, we use that parameter to differ between the two pages.

if (!$_GET["code"]) {  // If there is no code, this page was propably opened in a browser normally

  // This is a simulation of YOUR page/plugin/service.
  echo "<h1>My fancy web service</h1>";
  echo "<h2>Please let me access your CleverReach® account, user!</h2>";

  // The link will redirect the user to our OAuth service.
  // As the redirect_uri is used as a url parameter, we have to encode it accordingly.
  $redir = urlencode($redirect_uri);
  echo "<a href=\"{$auth_url}?client_id={$clientid}&grant=basic&response_type=code&redirect_uri={$redir}\">OK, connect now!</a>";

} else {  // If there is a code, it must be a callback from OAuth

  // No time to loose! Quickly trade the code for a Token, before it gets invalid.
  // We need to send some data in a POST request for that.

  // Preparing post data:

  // your secret data to make sure, it is you
  $fields["client_id"] = $clientid;
  $fields["client_secret"] = $clientsecret;

  // This must be the same as the previous redirect uri
  $fields["redirect_uri"] = $redirect_uri;

  // This is the actual trade. We tell OAuth what we want and provide the code.
  $fields["grant_type"] = "authorization_code";
  $fields["code"] = $_GET["code"];

  // We use curl to make the request
  $curl = curl_init();
  curl_setopt($curl,CURLOPT_URL, $token_url);
  curl_setopt($curl,CURLOPT_POST, sizeof($fields));
  curl_setopt($curl,CURLOPT_POSTFIELDS, $fields);
  curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
  $result = curl_exec($curl);
  curl_close ($curl);

  echo "<h1>My fancy web service</h1>";
  echo "<h2>This is the result of the OAuth process:</h2>";

  // The final $result contains the access_token and some other information besides.
  // For you to see it, we dump it out here.

  // Make sure to store the access_token in order to control the users REST API!

OAuth token response

The final result of the OAuth process is the access token.
Here is the format of the reponse as an example.

  "access_token":  "7h4t1s50mek1nd0fab4t70ken",
  "expires_in":    31536000,
  "scope":         "batmobile batcycle batplane batcopter",

In case the access_token has expired, you get request a new one by using the refresh_token. The refresh_token therefore has a longer lifetime than the access_token.

Using the refresh token

In case the access_token is expired, you should take care to retrieve a new one using the refresh_token.

To accomplish that, you do a request to POST http://rest.cleverreach.com/oauth/token.php

// Values from your OAuth app.
$clientid     = "#Place OAuth clientID here#";
$clientsecret = "#Place OAuth client secret here#";

// No need to change anything from here.
$token_url = "https://rest.cleverreach.com/oauth/token.php";

$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, $token_url);
curl_setopt($curl,CURLOPT_POSTFIELDS, array(
  "grant_type" => "refresh_token",
  "refresh_token" => "m4keb4t70kenfr35h",
  "client_id" => $clientid,
  "client_secret" => $clientsecret

curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
curl_close ($curl);

// The final $result contains the new access_token and some other information.
// For you to see it, we dump it out here.

Client Credentials

In case you just want to retrieve a token for your account to work with, you can use this Method.
Please note, that this token only has access to the account that created the app!

Note: Store the token and reuse it. Request a new one, if it expires!

// Values from your OAuth app. You create ONE for a page/plugin/service.
$clientid     = "#Place OAuth clientID here#";
$clientsecret = "#Place OAuth client secret here#";

// The official CleverReach URL, no need to change this.
$token_url = "https://rest.cleverreach.com/oauth/token.php";

// We use curl to make the request
$curl = curl_init();
curl_setopt($curl,CURLOPT_URL, $token_url);
curl_setopt($curl,CURLOPT_USERPWD, $clientid . ":" . $clientsecret);
curl_setopt($curl,CURLOPT_POSTFIELDS, array("grant_type" => "client_credentials"));
curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
curl_close ($curl);

// The final $result contains the access_token and some other information besides.
// For you to see it, we dump it out here.
So how do you actually use the REST API? Here are some simple and advanced examples.
We wrote a PHP REST client which the examples here are based on. You can download our REST client here.


GET (retrieve)

To retrieve a resource, like all your available groups, simply run this:

$data = $rest->get("/groups");

Some resources have additional filters/options. /mailings for example has filters to specify what kind of mailings you want (all/finished/draft/waiting)

$data = $rest->get("/mailings", array("type"=>"draft") );

POST (create new and special functions)

Creating a new resource like f.e. a group, follows the same principle. All you need to do is adding the required parameters.

$data = $rest->post("/groups", array("name"=>"my new REST group") );

PUT (update)

Updating a resource requires you to know the resource ID, but follows the same style as a POST.

$data = $rest->put("/groups/1234", array("name"=>"my updated REST group") );


Deleting just requires the resource ID

$data = $rest->delete("/groups/1234");

Error handling

In case of errors, you will receive an http error code and the apropiate error description. In this example we tried to access a report which does not exist.

$data = $rest->get("/report/4321");

    "error": {
        "code": 404,
        "message": "Not Found"

Practical examples

Assuming you want to develop an integration of Cleverreach® in an other system, here are some practial calls to be made.

Initialization - Create what you need!

Once a Cleverreach® account owner authorized and left an access_token for you to access the according account, you should set up, what your plugin needs.
Its best to create an individual group (or let the user select it) and create attributes to be used later on.
We highly recommend using global attributes which are shared over all groups.
Note: only create attributes the user realy needs since the number of attributes are limited.

Imagine a User withe the Email "batman@gotham.com" with the firstname "Bruce". It should not matter what group (list) he is in, his name will always be "Bruce". Therefor creating a global attribute "Firstname" makes sense.

$rest->post("/attributes", array("name"=>"salutation", "type"=>"gender"));
$rest->post("/attributes", array("name"=>"firstname", "type"=>"text"));
$rest->post("/attributes", array("name"=>"lastname", "type"=>"text"));
$rest->post("/attributes", array("name"=>"address", "type"=>"text"));
$rest->post("/attributes", array("name"=>"city", "type"=>"text"));
$rest->post("/attributes", array("name"=>"zip", "type"=>"text"));
$rest->post("/attributes", array("name"=>"country", "type"=>"text"));
$rest->post("/attributes", array("name"=>"birthday", "type"=>"date"));

If you are writing software for f.e. Multishop solutions, you might want to switch to group bound attributes because the multiple firstnames might interfere with each other.

$rest->post("/groups/{$groupid}/attributes", array("name"=>"firstname", "type"=>"text"));
$rest->post("/groups/{$groupid}/attributes", array("name"=>"lastname", "type"=>"text"));

Synchronize/import receivers

After your setup process, its best to do an initial import. This should be done in stacks and not one by one. While you can import each user one by one, you shouldnt, because this way you will be dealing with way more overhead then necessary.

Here for example, we are passing to the REST API once a stack reaches 1000.

$receivers = array();
$rows = mysql_query("select id, email, firstname, lastname, gender, registration_date from user");

foreach ($rows as $row) {
    $orders = array();
    $order_rows = mysql_query("select * from orders where user_id={$row->id}");
    foreach ($order_rows as $order_row) {
        $orders[] = array(
            "order_id"   => $order_row->order_id,      //required
            "product_id" => $order_row->product_id,    //optional
            "product"    => $order_row->product_name,  //required
            "price"      => $order_row->single_price,  //optional
            "currency"   => "EUR",                     //optional
            "amount"     => $order_row->order_ammount, //optional
            "mailing_id" => $order_row->mailing_id,    //optional
            "source"     => "batman-shop.org"          //optional

    $receivers[] = array(
    "email"			=> $row->email,
    "registered"		=> strtotime($row->registration_date),
    "activated"		=> strtotime($row->registration_date),
    "source"		=> "Batcave Computer",
    "global_attributes"	=> array(
        "firstname" => $row->firstname,
        "lastname" =>  $row->lastname,
        "gender" =>    $row->gender
    "orders" => $orders


    if( count($receivers) > 1000) {
        $rest->post("/groups/{$target_group_id}/receivers", $receivers);
        $receivers = array();
$rest->post("/groups/{$target_group_id}/receivers", $receivers);

Order injection vs. import (post setup)

Since data still needs to be synchronized after the initial import, there are 2 methods you can use. You can either run the original import as a cronjob, or you can do a live order injection. We actualy prefer the live order injection which is basically nothing more like reduced version of the Import.
Please make sure that you are using some sort of try and catch methods, otherwhise you might break your shops order process if the API cant be reached and any other error occurs.

try {
    $receiver = array(
        "email"      => "bruce@wayne.com",
        "registered" => time(),	//current date
        "activated"  => time(),
        "source"     => "Batcave Computer",
        "global_attributes" => array(
            "firstname" => "Bruce",
            "lastname"  => "Wayne",
            "gender"    => "male"
        "orders" => array(
                "order_id" => "xyz12345",                //required
                "product_id" => "SN12345678",            //optional
                "product" => "Batman - The Movie (DVD)", //required
                "price" => 9.99,                         //optional
                "currency" => "EUR",                     //optional
                "amount" => 1,                           //optional
                "mailing_id" => "8765432",               //optional
                "source" => "Batshop"                    //optional
                "order_id" => "xyz12345",                //required
                "product" => "Batman - The Musical (CD)" //required
    $batman = $rest->post("/groups/{$gotham_group->id}/receivers", $receiver);
} catch (\Exception $e){
    system_log("error syncing order");


To send a DOI Email, you have to first create the customer. Please note the that the field "activated" is set to ZERO which means he will not be active and can't receive any newsletters until he is activated. After creation we will tell the REST API to sent him a specific form to activate his account.

$new_user = array(
    "email"      => "batman@gotham.com",
    "registered" => time(),  //current date
    "activated"  => 0,       //NOT active, will be set by DOI
    "source"     => "Batcave Computer",
    "attributes" => array(
        "firstname" => "Bruce",
        "lastname"  => "Wayne",
        "gender"    => "male"

if( $success = $rest->post("/groups/{$target_group_id}/receivers", $new_user) ) {
    $rest->post("/forms/{$form_id}/send/activate", array(
        "email"   => $new_user["email"],
        "doidata" => array(
            "user_ip"    => $_SERVER["REMOTE_ADDR"],
            "referer"    => $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"],
            "user_agent" => $_SERVER["HTTP_USER_AGENT"]
© 2018 Cleverreach® The code is provided as is. Free to use, at your own risk.