"Just the Fact's M'am"

Roll Your Own API

Machines are really picky about reading. They like normalized and structured sets of data. Machines don’t generally want to look at the pictures on your website or read the paragraphs of hand-crafted copy you’ve spent hours writing. Machines don’t care about the usability of your navigation or that you’re using the latest responsive design with metro tiles, flat icons and giant fonts. They just want your data.

So what do you do when a portion of your website visitors aren’t people? If your content is public and fairly static, you might employ a XML document, perhaps even an RSS feed. However, if you have a larger set of constantly changing data that needs to be queried and you have a valuable enough audience of robot consumers, you might want to provide an API.

An API, or application programming interface, is really just a simpler way for machines to interact with your website without the bells and whistles that you provide your regular users. If your site is database-driven, setting up a simple API is actually pretty easy. Instead of outputting the content of each page into an HTML view, you could echo the relevant information as structured XML or JSON.

There’s one more layer of complexity that you might need to address: What if you want to control which robots can access your API? If you’re picking and choosing who can access your data, you can give each user a unique API Key and require they submit it with each request.

Just as your website users log in with a public and private set of credentials (e.g., a username or e-mail address and a secret password) so should the API users. Give your API users a pseudo-public “APP Key” and a private “APP Secret” that must be provided with each request. Of course, if your user just sent along their secret as plain text, it could be intercepted and used to make malicious requests so you’ll want to only accept signed requests.

A signed request is simply a way of hashing the user’s password alongside the payload of their request so that it can be validated by your site. If the user were to only hash the password itself, that value would remain the same with each request which is no better than sending it in plain text. By salting the secret with the other information being sent, a unique hash value is created each time. Like all good processes, this technique has its own acronym: HMAC, or hashed message authentication code. As of version 5.2.1, there’s even a PHP hash_hmac() function available to make it even easier.

$request = array("request"=>"Show me some data","app_key"=>"my_unique_key");
$app_secret = "1234567890"; // shhh, don't tell anyone.
$json = json_encode($request); // convert to string
$signed_request = hash_hmac('sha256', $json, $app_secret, $raw=true);
// this is what the user sends to your API
$payload =array("request_package"=>$request,"signature"=>$signed_request);

Once the user has sent you the signed request payload you just need to rehash the package yourself. If your value matches the signature they sent, then you can trust their content!

function = lookup_app_secret( $app_key)
  // your function to lookup the user's app_key_secret from the database
$users_secret = lookup_app_secret( $_POST['app_key']);
$checksum = hash_hmac('sha256', $_POST['request_package'],$users_secret, $raw=true);
if($checksum === $_POST['signature'])
  $request = json_decode($_POST['request_package']);
  // process the $request array here!
  exit("ERROR: could not verify request. Invalid signature");

It’s important to note that the hashed signature is sent along-side the plain text requests which is not encrypted. If your data is secret in nature, you’ll want to use SSL. If you are sharing sensitive information through your API, remember that the user’s you have approved will be able to disseminate that data however they see fit.

For a fully flushed out example, checkout this simple API framework and corresponding SDK (software developer kit) code I’ve written GitHub.

Or if you’d like help building out your own API, please contact me and let me know how I can help.