v1.0
Recommender API v1.0
This document describes the version 1.0 of the Sannsyn Recommender REST API.
If you like, you can try the new 1.1-beta version.

Getting Started

Communication with the recommender system mostly consists of two very basic interactions: Both of these are accessible through HTTP POST requests where you need to supply a JSON payload. The requests are accessible both from the serverside and from browsers populating their DOM trees dynamically. Here is the most basic way to use them:
  1. Send an Update
    Here's a tip
    If you want curl to be more expressive, use the -v option.
    curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/update' --data '{ "service": "serviceid", "updates": [ { "customer": "customerid", "entityIDs": [ "product ID" ], "what": "PURCHASE", "where": "app" } ] }'
  2. Get Recommendations
    curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/recommend' --data '{ "service": "serviceid", "externalIds": [ "someothercustomerid" ], "recommender": "ProductForCustomerRecommender" }'
  1. Send an Update
    <script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; var data = '{ "service": "serviceid", "updates": [ { "customer": "customerid", "entityIDs": [ "productid" ], "what": "PURCHASE", "where": "web" } ] }'; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/update'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); xmlhttp.send(data); </script>
  2. Get Recommendations
    <script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; var data = '{ "service": "serviceid", "recommender": "ProductForCustomerRecommender", "externalIds": [ "someothercustomerid" ], "num": numberofrecs }'; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/recommend'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == XMLHttpRequest.DONE) { if (xmlhttp.status == 200 || xmlhttp.status == 304) { // do whatever you want with xmlhttp.responseText here. You could for instance send it off to a callback method: callback(xmlhttp.responseText); } } } xmlhttp.send(data); </script>

Implementing the Sannsyn Recommender

In the Browser

Websites can have the client browser fetch recommendations directly. There are only three types of requests to implement: a customer recognition script to be included in all web pages, and two others, sending updates and/or fetching recommendations, anywhere needed.

Customer Recognition

The javascript that permits the Sannsyn Recommender System to recognize the client, assures that the subsequent updates and recommendation requests work. The script is included like this:
<html> <head> <script type="application/javascript" async="true" src="https://recommender.sannsyn.com/ajaxrecapi/1.0/crec?service=serviceid&euid=customerid"></script> ... </head> ...
The customer ID is here given in the euid parameter. If the customer's ID is unknown when the crec script URL is constructed, it may be omitted (although this will leave the customer recognition to the crec script exclusively, and may lead to less accurate recommendations if the user has disabled cookies in the browser).

Adding and Updating Information

Visits to web shops' product pages is to be logged by the recommender. When users enter a product page, an update must be sent. It looks like this:
<script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; var data = '{ "service": "serviceid", "updates": [ { "customer": "customerid", "entityIDs": [ "productid" ], "what": "BROWSE" } ] }'; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/update'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); xmlhttp.send(data); </script>
Refer to the update requests json fields table if necessary.

The update URLs do not return any information. If you need a confirmation that the request is OK, inspect the status code by using an XMLHttpRequest object and supply an onreadystatechange callback. As an example, if a user's visit to an online newspaper should be marked with both a page ID and a category ID, the update could look something like this (we call the newspaper «The Daily Overseas» and use the shortened form «thedo» as a name for the service):

<script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/update'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); var data = '{ "service": "thedo", "updates": [ { "customer": "subscriber472", "entityIDs": [ "article78", "international" ], "what": "BROWSE" } ] }'; xmlhttp.onreadystatechange = function() { console.log("HTTP status returned for the category call is " + xmlhttp.readyState); } xmlhttp.send(data); </script>
The returned HTTP code will then be printed to the javascript console.

Retrieving Recommendations

When a browser is to fetch recommendations, a POST request should be issued like this:
<script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/recommend'); var data = '{ "service": "serviceid", "recommender": "recommendername", "externalIds": [ "customerid" ], "num": numberofrecs }'; xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); xmlhttp.onreadystatechange = function() { // do whatever you want with xmlhttp.responseText here. } xmlhttp.send(data); </script>

Our overseas newspaper could have this call on a page to retrieve recommendations for a reader:
<!-- Retrieve 5 recommended articles --> <script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/recommend'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); var data = '{ "service": "thedo", "recommender": "ArticleForSubscriberRecommender", "externalIds": [ "subscriber36" ], "num": 5 }'; xmlhttp.onreadystatechange = function() { // send the results off to the javascript method // in charge of filling in the correct slot on the page: fillInRecommendations(xmlhttp.responseText); } xmlhttp.send(data); </script>
In response to this request, the Sannsyn Recommender could send a JSON object with three articles about politics, one about sports, and a fifth from the literature section, like this:
{ "result": [ "Politics-45", "Politics-392", "Politics-460", "Sports-78", "Books-177" ], "origin":"ArticleForSubscriberRecommender" }

Tracking Exposure and Interaction

For statistics and for enhancement of recommendations and algorithms, exposure of recommendations and clicks thereon must be reported back to the Recommender System. The customer recognition script is constructed to handle this for you, but it needs two data attributes to be placed in the recommendations' DOM-tree elements:

Using the result example above to embed recommendations in our HTML, we could construct something like this:

<html> <head> <script type="application/javascript" async="true" src="https://recommender.sannsyn.com/ajaxrecapi/1.0/crec?service=thedo&euid=subscriber36"> </head> <body> <h1>Recommended for you</h1> <ul> <li data-sannsyn-recommendation="Politics-45" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender"> <a href="clickOnPolitics45">Politics-45</a> </li> <li data-sannsyn-recommendation="Politics-392" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender"> <a href="clickOnPolitics392">Politics-392</a> </li> <li data-sannsyn-recommendation="Politics-460" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender"> <a href="clickOnPolitics460">Politics-460</a> </li> <li data-sannsyn-recommendation="Sports-78" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender"> <a href="clickOnSports78">Sports-78</a> </li> <li data-sannsyn-recommendation="Books-177" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender"> <a href="clickOnBooks177">Books-177</a> </li> </ul> ...
The customer recognition script will detect the recommendations becoming visible on screen. If any of them is being clicked on, that too is registered. Both of these events are automatically reported back to the recommender as the user leaves the webpage.

Serverside

The serverside API is for use in cases where it is impossible to fetch recommendations from the browser. Good examples of this is when recommendations are embedded in telephone apps or inside custom applications on desktop computers. Using the serverside API for recommendations that are to be exposed in an ordinary browser, is strongly discouraged.

Authentication

Authentication is handled with basic HTTP authentication. Using curl, it looks like this:
curl --user username:password 'https://recommender.sannsyn.com/recapi/1.0/ ... '
Failing to authenticate will give a 401 Unauthorized response.

Adding and Updating Information

(For initial uploads of a complete dataset, look at the Loading a Complete Dataset section below.
Sending updates from the server is just like sending them from the browser. Here's an example of reporting that a user has bought a pair of shoes:
curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/update' --data '{ "service": "shoeshop", "updates": [ { "customer": "12345", "entityIDs": [ "DrMartens-90"], "what": "PURCHASE" } ] }'
The parameters should be filled in like specified in the update requests json fields table. The above example payload gives this information to the recommender system:
  • The update is targeted for a service named shoeshop
  • Customer 12345 has purchased an item («entity») with ID DrMartens-90
Do not expect a lengthy response. The server will reply very concisely: {"text":"Message transmitted","statusOK":true}.

New Customers and New Products

Suppose we want to submit information about a new customer or a new product to the recommender system. Neither the customer nor the prouct need to be explicitly created in the system; they will be added as part of the update process. So to submit information about a customer that is new to the system, simply follow the process for customers that are already registered:
curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/update' --data '{ "service": "serviceid", "updates": [ { "customer": "newcustomerid", "entityIDs": [ "newproductid" ], "what": "PURCHASE" } ] }'
Granted that newcustomerid does not already exist, your new customer is registered; otherwise, the existing one is updated, and the same goes for newproductid. All IDs in the system are treated as unique identifier strings. Submitting an ID that is already in use, will tie the given information to this already-in-use ID.

Retrieving Recommendations

We saw in the Getting Started section how easy it is to fetch recommendations. Here is a more elaborate example:
curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/recommend' --data '{ "service": "shoeshop", "recommender": "ItemToItemRecommender", "externalIds": [ "Adidas-102" ], "tags": [ "userid:someothercustomerid" ], "num": 4 }'
The parameters are specified in the recommendation request json fields table. This example payload transports the following information to the recommender system:
  • The request is for the shoeshop service
  • Four recommendations should be generetad from a recommender named ItemToItemRecommender
  • Basis for the recommendations is Adidas-102
  • The tag gives information about the customer in this case, since the recommender is an item-to-item recommender. The intended consumer of these recommendations is the user someothercustomerid
The recommendation response will have the same structure as in the client side example above.

Some recommendations rely on more than one ID. They could e.g be calculated from the user's ID and at the same time be made to be similar to some other product (ID). How multiple IDs are handled is defined individually in each recommender, but submitting them is uniformly done with the externalIds array. Here is an example of retrieving recommendations to fit the contents of a shopping basket with six items in it:
curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/recommend' --data '{ "service": "service", "recommender": "ShoppingBasketRecommender", "externalIds": [ "item-1", "item-2", "item-3", "item-4", "item-5", "item-6" ], "num": number }'

Tracking Exposure and Interaction

For statistics and for enhancement of recommendations and algorithms, exposure of recommendations and clicks thereon must be reported back to the Recommender System. On a web page, this is automated by the provided javascript, and therefore fairly simple, but when using the recommender system from a server or in telephone or tablet apps, you need to send the reports yourself.

These reports really are just another sort of updates, however, so you can use your update implementation if you pay special attention to the what and the origin fields in your payload. The what field is to describe the event: it should be RECCLICK or RECEXPOSURE. The origin field is to contain the id (name) of the recommender instance that produced the recommendation in question. This is not always the same as the id (name) of the recommender that you requested, so copy into the origin field of your payload the value received in the recommendation JSON (in a field equally named origin, see the result example above if you need an example).

Here is what you could send e.g. from a telephone app:
curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/update' --data '{ "service": "serviceid", "updates": [ { "customer": "customerid", "entityIDs": [ "product-1" ], "what": "RECEXPOSURE", "where": "app", "origin": "ItemForCustomerRecommender" }, { "customer": "customerid", "entityIDs": [ "product-3" ], "what": "RECEXPOSURE", "where": "app", "origin": "ItemForCustomerRecommender" }, { "customer": "customerid", "entityIDs": [ "product-3" ], "what": "RECCLICK", "where": "app", "origin": "ItemForCustomerRecommender" }, ] }'
This tells the recommender system that product-1 and product-3 have been recommended to customerid, and that customerid has clicked on the recommendation of product-3. It also says that the recommendations were produced by a recommender named ItemForCustomerRecommender, and that the exposure took place in an app.

Loading a Complete Dataset

A newly started service has no data and will therefore not produce good recommendations. Initially, one should load a set of historical data into the service to avoid this. These data are not sent as individual updates through the REST interface, but as separate files. Dataset files must obey the xml format described in our xsd schema description.

Resources

Comments

We welcome comments, questions and improvement requests. Please send your remarks to Sannsyn support.