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:
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.
Our OAuth implementation follows the 2.0 Specification. For a detailed OAuth explanation please have a look at this introduction to OAuth.
The main approach of OAuth is to get a REST API Token in order to be able to control the users account by using the REST API.
There are multiple ways to retrieve a token. Described here are:
How to work with OAuth Code in CleverReach®:
This way, all your users can provide you with a token using one OAuth app.
It is really easy. Give it a try!
<?php // 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. var_dump($result); // Make sure to store the access_token in order to control the users REST API! }
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", "refresh_token": "m4keb4t70kenfr35h" }
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.
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. var_dump($result);
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. var_dump($result);
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") );
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") );
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");
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" } }
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"));
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);
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( 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 ), array( "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"] ) ); }