Using the Cubepoints plugin API

Since writing this, development of the CubePoints plugin has slowed to a halt. So I’ve created my own points plugin, WordPoints. Please give it a try!

 

I searched the web, but I couldn’t find any documentation on how to use the built-in API for the WordPress CubePoints plugin. So I took a close look at the code (in the cp_api.php plugin file), and was able to figure it out. It’s actually really simple. Its a shame that there isn’t any documentation of it. The following is based on the latest version of CubePoints as of this writing (3.2.1) and I will try to update it in future if anything changes.

Step 1: Getting Your API Key #

Using the API, you can get, update, or reset the points for any user. But in order to use the API, you first have to get your cp_api_key (AKA cp_auth_key). Without it, you can’t access the API. You already have a unique API key, that was generated when you installed the plugin. If you are planning to be using the API inside of the WordPress loop, such as in a custom plugin, you can get the key by simply calling for it in your PHP code, something like this:

<?php
$api_key = get_option('cp_auth_key');
?>

The PHP variable $api_key will now hold your API key. But this will only work if you are calling the script within WordPress. If what you are trying to achieve requires you to have the API key outside of the WordPress loop, then you can use get it using the CubePoints module below. Create a file called ‘api_key.php’ (or whatever you like) in the ‘/wp-content/cubepoints/modules/‘ folder. Copy and paste this code into it:

<?php
/** API Key Module */

cp_module_register(__('API Key', 'cp') , 'authkey' , '1.0', 'J.D. Grimes',
   'http://www.efieldguide.com', 'http://efieldguide.com/using-the-cubepoints-plugin-api/' ,
   __('This module displays your API key on the "Configure" page.', 'cp'), 1);

if(cp_module_activated('authkey')){

function cp_module_authkey_config(){
?>
<br />
<h3><?php _e('API Key','cp'); ?></h3>
<table>
<tr valign="top">
<th scope="row"><label for="cp_authkey"><?php _e('Your API key:', 'cp'); ?>:</label></th>
<td valign="middle"><?php echo get_option('cp_auth_key'); ?></td>
</tr>
</table>
<?php
}
add_action('cp_config_form','cp_module_authkey_config');
}
?>

Once you have saved the file, go to your WordPress dashboard, navigate to the CubePoints->Modules page, and activate the “API Key” module (the one that just created with the code above). Then you can visit the CubePoints->Configuration page, and you will see your API key displayed near the bottom, to the right of where it says “API Key”. Once you have your API key saved in a safe place, you can go back and deactivate the module, if you like.

Be very careful how you use the API key! Using it on the front end of your site will reveal it to your users, and anyone who knows how could change your user’s points any way that they want. Not only that, they can easily get lots of other info about your users, including their encrypted passwords. If you are thinking of integrating CubePoints with something on the front end, it would be much better, safer, and in the long run easier to use use a CubePoints module instead of doing it through the API. (See below).

 Step 2: Constructing the cp_api Parameter #

Now that you have your API key, you can start accessing the API. But first you need to understand the second parameter, and how it works.

To use the API, you pass two parameters (your API key, and another string which we will explain in a moment) to your site like this:

http://www.your-site.com/?cp_api_key=Your_API_Key&cp_api=API_Action

(You can send these by either GET or POST method, but I’ll assume you will be using GET, since it is the usual method used with AJAX.) The 'cp_api_key' is your API key. The 'cp_api' is a second parameter that tells the CubePoints plugin what to do. This second parameter is actually up to 9 different parameters strung together, which the API script converts to an array. The delimiter used is the forward slash ‘/’. So this parameter looks something like this: 'cp_api=parameter1/parameter2/parameter3/parameter4/parameter5/...'

Here is an explanation of each (sub-)parameter:

Parameter 1 #

The first parameter is very easy, because there is only one possible value for it: 'user'. You might be thinking to yourself, “Why even have it if it is the only option? Isn’t that unnecessary?” Well, at first I thought that too, but I guess the developers of the CubePoints plugin where leaving room for the API to expand in the future. It’s possible that  in later versions there will be other options. But for now, your 'cp_api' will always start 'cp_api=user/'. This tells the API what sort of information we are dealing with: information regarding a particular user.

Parameter 2 #

We know from the first parameter, that we will be dealing with information regarding a particular user. What the API needs to know next, is what user we are dealing with. There are two different ways that you can tell the API this; 1) by passing the user’s id, or 2) by passing the user’s username (or “login”). But the API needs to know which you are using, and that is what this second parameter tells us. Its value is either 'id' or 'login', depending on whether you are using the user’s id or username. So the first two parameters of 'cp_api' will look like this:

cp_api=user/id/

Or this:

cp_api=user/login/

Which you use will depend on which of the two is more readily available. In my case, I will be using the userIDs.

Parameter 3 #

As might be deduced from parameter 2, the third parameter is the user’s id or username. If you were working with a user with id ‘5’ and username ‘billy’, the cp_api parameter would look like this:

cp_api=user/id/5/

Or this:

cp_api=user/login/billy/

Parameter 4 #

The fourth parameter tells the API what aspect of the user we are interested in. The expected value is 'points'. If this value is left blank, then the API will just return an array of the user’s information. But I assume the reason you are interested in the API is to manipulate the user’s points, so its safe to say that you will be passing this parameter most of the time. Your cp_api parameter would look something like this:

cp_api=user/id/5/points/

Parameter 5 #

Now that we’ve told the API what we are interested in (the points of a user with a specific id or username), we need to tell it what we want to do. There are three different actions that you can take: 'get', 'set', or 'add'. This is fairly straightforward. You either want to 'get' the number of points that the user has, or you want to 'set' the user’s points to a certain amount, or you just want to 'add' a certain number of points to what the user already has. If you don’t set this parameter, the API will assume that you want to 'get' the number of points that the user has (the other two possibilities require more parameters). Here’s what cp_api would look like:

To find out how many points billy has:

cp_api=user/login/billy/points/get/ (or cp_api=user/id/5/points/get/)

Parameter 6 #

Now we know how to tell the API what we want to do, but if we want to 'set' or 'add', we need to tell the API how many points to set the user’s points to, or how many points to add to the user’s points. That is what the sixth parameter does. (Note that you don’t need to pass this parameter if you are just 'get'ting.) Say we want to set billy’s points to 500. We would do this:

cp_api=user/login/billy/points/set/500 (or cp_api=user/id/5/points/set/500)

Now billy will have exactly 500 points. But what if we don’t want to reset billy’s points? What if we just want to give him 500 more points in addition to those he already has? We just use 'add' instead of 'set', like this:

cp_api=user/login/billly/points/add/500 (or cp_api=user/id/5/points/add/500)

If billy had 3105 points to start with, he will now have 3605. If we want to take 500 points away from billy, we can do that too:

cp_api=user/login/billy/points/add/-500

Now billy will have 3105 points again. (Note the minus sign.)

Parameter 7 #

CubePoints keeps logs of points transactions. Whenever someone’s points change, it gets logged in the database. The rest of the parameters tell the API how to log an 'add' transaction. If you don’t want your adjustment to be logged, then don’t pass the rest of the parameters. If you do want the transaction logged, then just pass the seventh parameter ('log'):

cp_api=user/id/5/points/add/500/log

 This will add the transaction to the logs, but it won’t tell the user anything about the transaction. For that, we need to use the next two parameters.

Parameters 8 and 9 #

The eighth parameter, when used, tells the API what type of description we want to log. (We tell it what the description should be with the ninth parameter.) There are many different options for the log 'type' built into CubePoints (see cp_hooks.php in /wp-content/plugins/cubepoints/), although others may be defined in any modules that you are using, and you can also create your own with a custom CubePoints module. What type you specify will depend on what sort of description you want for the transaction. Here is a list of the log transaction description types that come built-in, and how they handle the description data:

  • 'misc' – The description data is not processed.
  • 'addpoints' – The description data is not processed.
  •  'comment' – The description data will be a delimited string of different information about the comment, which is processed when the transaction is displayed in the log.
  • 'comment_remove' – Regardless of the description data, ‘Comment Deletion’ is displayed as the description.
  • 'post' – The description data will be a delimited string of different information about the post, which is processed when the transaction is displayed in the log.
  • 'register' – ‘Registration’ will be displayed.
  • 'admin' – ‘Points adjusted by “some_user”‘ (‘some_user’ will be the username of the user whose id is passed as the description data.)
  • 'remote' – ‘Points earned from “some_site”‘ (‘some_site’ will be a link created from the description data, ‘some_site^url’, where ‘url’ is the location of the link.)
  • 'custom' – The description data will not be processed.

As you can see, if you set parameter 8 to 'misc', 'addpoints' or 'custom', whatever you passed as the ninth parameter (the description data) will not be processed when the transaction logs are displayed to the user. It will be displayed ‘as is’. If you had a points donate button and wanted to give the description “Thank you for donating!”, you could do this:

cp_api=user/id/5/points/add/-500/log/custom/Thank+you+for+donating!

Depending on how you plan to use the API, you probably wont be using 'comment', 'comment_remove', 'post', or 'register'. I won’t be using them, and since I don’t think many others will, I wont take the time to explain them here. But some of you might be using the 'remote' or 'admin' transaction types, so I will explain how those work.

The 'admin' transaction type is used by CubePoints when the administrator arbitrarily adjusts someone’s points. It will show the transaction description ‘Points adjusted by “[an administrators username here]”‘. When using this description type, the description data is the adjuster’s userID (the username will not work here, only the userID). When the transaction is displayed in the logs, CubePoints will take the userID and get that user’s username. If it doesn’t find a user with that id, it will just show ‘Points adjusted by “”‘.

The 'remote' transaction type is apparently used when the user earns points from visiting a remote website. As with the ‘admin’ transaction type,  when this type is used, CubePoints processes the description data when it displays the transaction in the logs. But it is a little more complex. It has two parameters, joined by a ‘^’, like this ‘param1^param2’. The first parameter, is the name of the site. It will be used as the text for a link. The second parameter is the location of the link. So you might do something like this:

cp_api=user/id/5/points/add/500/log/remote/My+Site^http://www.mysite.com/

The log description for that transaction will be ‘Points earned from “My Site“‘.

In some situations, like mine, it is simplest to just use the 'custom' (or 'addpoints' or 'misc') type. But in some cases the other types might be useful. Note: If CubePoints doesn’t recognize the transaction type, then no transaction description will be displayed.

In some cases it may be necessary and/or easier to process the description data in some way (as is done in the ‘remote’ transaction type above). If you think that might be the case, you may want to create your own transaction type, and data processing methods. You can do that with your own CubePoints module, but that is currently beyond the scope of this tutorial.

 

Here is a list of the 9 parameters of cp_api, for your reference. Exact values are in quotes. A * means that the value is variable. A short explanation of each parameter is given in parentheses.

 

  1. 'user' (The type of data we are concerned with.)
  2. 'id', 'login' (The way we are passing the identity of the user we are interested in.)
  3. * (The user’s id or login name.)
  4. ”, 'points' (The type of information about the user we are interested in.)
  5. ”, 'get', 'set', 'add' (What action we want to take.)
  6. * (The number of points.)
  7. 'log' (We want to log this transaction.)
  8. * (The log type.)
  9. * (The log data.)

 

 Step 3: Understanding the API’s Returns #

You now know how to construct a query to use the API. It might look something like this:

http://www.your-site.com/?cp_api_key=abc123&cp_api=user/login/billy/points/add/25/log/custom/Happy+Birthday!

But now you need to understand the API’s returns. Before I start on this explanation let me say that the CubePoints API, like many, returns JSON encoded objects and arrays, which can be handled with AJAX. The rest of this tutorial will assume that you have a working understanding of JavaScript, and JSON and AJAX in particular. If you don’t, then I suggest you visit W3Schools’ JSON and AJAX tutorials.

The API may return one or more of three different variables. These are 'error', 'points' and 'message'. If there is an error, for example, it will return the ‘error’ variable. It may have any one of the following values, depending on what the error was:

  • ‘Invalid API key’
  • ‘Method not implemented’
  • ‘Invalid user’
  • ‘Points must be integers’
  • ‘Log item must not be empty’

These are fairly straightforward, except perhaps for ‘Method not implemented’. That is returned if you have passed an unknown value for parameters 1, 2, 4, 5 or 7.

When the API doesn’t have an error, then the ‘points’ parameter is returned. Its value is the number of points that the user now has (calculated after any transaction has taken place). If the fifth parameter is 'set' or 'add', the 'message' will also be returned. At present, it has only one value: ‘Points updated’.

For the sake of completeness, an example of what a JavaScript function to add 10 points to a certain user when a button is clicked is seen below. The HTML behind it might look something like this:

<a onclick="addPoints('billy', '10')">Give billy 10 points</a>

The JavaScript function addPoints() might look something like this:

function addPoints(user,points,logData)
{
 // Generating the query...
 var url = '/?cp_api_key=abc123&amp;cp_api=user/id/'+userID+'/points/add/'+points+'/log/custom/'+logData;

 // Calling my_ajax() function (below) to perform the AJAX request.
 my_ajax(url, function(){
  // If the AJAX result is ready and the status is 200 (OK).
  if (xmlhttp.readyState==4 &amp;&amp; xmlhttp.status==200)
   {
      // We want to get the response...   
      var responseTxt = xmlhttp.responseText;
      // And convert the JSON objects to JavaScript objects.
      response = JSON.parse(responseTxt);
      // If there was an error...
      if (response.error){
         // We let ourselves know with an alert popup.
         alert('Error message: '+response.error);
      } else if (response.points) {
         // But if the query was successful, we give an alert popup with the 'message'.
         alert(response.message);
      } else {
         // Otherwise we got some unexpected response, and we give an alert popup like this:
         alert('Unknown server response: "'+responseTxt+'"');
      }
   } else if (xmlhttp.readyState==4) {
     // But if the AJAX is ready and the page didn't load OK...
     alert("Failed to connect to server.");
   }
 });
}

// This function will handle the AJAX call.
function my_ajax(URL, callback, async)
{
 if (window.XMLHttpRequest)
 {// code for IE7+, Firefox, Chrome, Opera, Safari
   xmlhttp=new XMLHttpRequest();
 } else {// code for IE6, IE5
   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
 }

 xmlhttp.onreadystatechange=callback;

 if (async !== false){
   async = true;
 }
 xmlhttp.open("GET",URL,async);
 xmlhttp.send();
}

 

As you can see, when the button is clicked, the addPoints() function is executed. It builds the query from the variables passed to it, and then uses the my_ajax() function to submit the query via AJAX. It passes the generated URL and a callback function to my_ajax(). After the query has been executed, the function gives a JavaScript alert (like this), which either notifies you of the error, or gives you the success message. Of course, exactly how you handle the different returns will depend on your project.

Conclusion #

Now you know how the CubePoints API works. The only question now is how will you use it? In my case, I had some forms that a user could submit. Then I review the submissions in the Dashboard, via a custom plugin. I needed some buttons that would let me accept or reject the submission, and adjust the user’s points based on that. The CubePoints API came to the rescue, and meant that I could do this easily through AJAX, without having to write my own PHP scripts to access the database and update the user’s points, create a log entry, etc. If what you want to achieve is similar to this, then the API will be very helpful for you. But if you are planing on using the API from the front end of your site, you probably should look into creating your own CubePoints module instead. Why? Because like I said above, the using the API on the front end will in most cases require you to use your API key somewhere in your code that would be visible to someone with the knowledge to look for it. And that is a very bad idea; its almost like revealing your password. Although there would be roundabout ways to avoid this, if you were going to go through all the trouble to implement them, you might as well have just created your own CubePoints module.

If you find this helpful let me know. Remember, I am NOT one of CubePoints’ developers, so I don’t know everything about the API. All you see here is the result of an hour of looking at the code behind the CubePoints plugin. If you learn anything in addition to what I’ve shared here, please leave a comment below. If I get time I may write a tutorial on building your own CubePoints module too, since that seems to be in need as well.

12 thoughts on “Using the Cubepoints plugin API

  1. Peter

    Thank you endlessly for writing this. I would be one of many to request that you write a tutorial for building a CubePoints module.

    Reply
    1. J.D. Grimes Post author

      Hi, Peter. Glad you find it helpful. I will get to work on writing a tutorial on CubePoints modules. I just published a tutorial on how to display the CubePoints logs on the front end. That shows a little about how to create a module, but there are lots of different things you can do with them. If you know a little about PHP and WordPress’s code, you could take a look at some of the modules included with CubePoints, and get an idea of how they work.

      As I study it more for my own purposes, I will keep sharing what I find. Hopefully before long I will find time to do a full tutorial on CubePoints modules.

      Reply
  2. BB

    Best documentation I have seen regarding CP, period. I wish more mod developers would share their knowledge (with us newbies) as generously as JD.

    Thanks so much for taking the time to explain this.

    BB

    Reply
  3. Dan

    Hey.. I have a problem here..maybe you can help me out if you feel like it and if you have the time of course. I’m asking you because I’ve seen that you arleady disected this plugin. So im using different paths to my plugin directory and I think this is what messing with my modules(they don’t show in my admin panel at cp->modules). Ive installed the plug on a clean version and they show up. So either the modules are created to show up on the standard path wp-content-themes-theme-plugin-cube-points-modules or there is something I am missing. The standard properties like points system is working and showing up where I need them. Only the modules are a bit off. Thank you!

    Reply
    1. J.D. Grimes Post author

      Hi Dan.

      This is probably due to CubePoints odd way of deciphering paths. In core.php change ABSPATH.PLUGINDIR.'/'.dirname(plugin_basename(__FILE__)) on lines 178 and 181 to plugin_dir_path( __FILE__ ). If that doesn’t work, let me know.

      Reply
          1. Dan

            features/cubepoints/cp_core.php:191 – Invalid argument supplied for foreach()
            this is what poppep up.

          2. J.D. Grimes Post author

            Try replacing the cp_modules_include() function in cp_core.php on line 177 with this:
            /** Function to include all modules in the modules folder */
            function cp_modules_include(){
            foreach (glob( CP_PATH."/modules/*.php") as $filename){
            require_once($filename);
            }
            foreach (glob(CP_PATH."/modules/*/*.php") as $filename){
            require_once($filename);
            }
            }

            If that doesn’t work then just replace ‘CP_PATH’ with hard-coded full path to the modules folder.

          3. Dan

            function cp_modules_include(){
            foreach (glob(ABSPATH. ‘/features/cubepoints/modules/*.php’) as $filename){
            require_once($filename);
            }
            foreach (glob(ABSPATH. ‘/features/cubepoints/modules/*.php’) as $filename){
            require_once($filename);
            }
            }
            This did the trick ! Thanks. Big time!!

Leave a Reply to J.D. Grimes Cancel reply

Your email address will not be published. Required fields are marked *