ScaleEngine APIVersion 0.8

This is the first publicly available version of the ScaleEngine API. It currently features commands for asynchronously Purging and Priming the ESC (Edge Side Cache), CDN (Content Distribution Network) and OWC (Origin Web Cluster) Caches. It also features a set of commands for controlling SE-VU (ScaleEngine Virtual Usher Movie Ticket System). While it is a versioned API, We highly recommend that you check back here regularly as we continue to iterate and improve the API and its functionality.

API Endpoint

https://www.scaleengine.com/cp/api/0.8/
You will need an API key to interface with the ScaleEngine API. If you do not already have one, please contact us via the support form in the customer control panel.

Read the full article to see example requests and responses, as well as sample PHP code.

Getting Viewer Countsvsn.viewercounts

The ScaleEngine VSN (Video Streaming Network) is capable of providing you up-to-date live and historical information on how many viewers are viewing you video streams.

By accessing the SE-VU API you can embed live viewer counts on your existing 'theatre' page (the page where your protected video content is embedded for the viewer to watch). Calling the SE-VU API, passing the video and backend name. In return the API sends the latest viewer count recorded by the application.

Read the full article for Response and Return messages, and Sample Code

Creating a SE-VU Ticketsevu.request

The ScaleEngine Virtual Usher Movie Ticket System or SE-VU for short (pronounced See View), allows you to maintain strict access control over your Live and On-Demand video content. It works as a drop-in API to your existing e-commerce, membership, subscription or pay-per-view system.

Implementation is quite simple, you augment your existing 'theatre' page (the page where your protected video content is embedded for the viewer to watch) such that the embed passes the users ticket and secret key to the video streaming server. Access to this theatre page should be restricted/controlled by your existing membership/subscription system. In the code for the 'theatre' page, you add a call to the SE-VU API, passing it the randomly generated password, the IP address of the viewer, the video they are authorized to view, how many times they are authorized to view it, and within which time frame they must start watching the video. In return the SE-VU API will pass you a ticket. Simple add this ticket number, and the randomly generated password to the embed URL for the video and your content is now secure. Only a valid ticket will allow the user to watch the video. Each ticket can only be used the specified number of times, and must be used withing the indicated time frame. There is also an API call to allow you to check the status of an existing ticket, as well as revoke it.

The full article includes example PHP code. Click the title to read the full article.

Managing a SE-VU Ticketsevu.status / sevu.search / sevu.revoke

The ScaleEngine Virtual Usher Movie Ticket System or SE-VU for short (pronounced See View), allows you to maintain strict access control over your Live and On-Demand video content. It works as a drop-in API to your existing e-commerce, membership, subscription or pay-per-view system.

After creating a SE-VU Ticket the API allow you to check the status of an existing ticket, as well as revoke it, or view all tickets associated to a specific key. To Search existing Tickets, you add a call to the SE-VU API passing one or more of the following the randomly generated password for the ticket, the IP address of the viewer, the video they are authorized to view. You can further limit search results by passing either the Created / Used / Expire date to view tickets with dates newer than what was specified. In Return the SE-VU API will return all Tickets that match the listed criteria.

To View the Status of a ticket, you add a call to the SE-VU API passing the key. In return the SE-VU API will return the ticket and its status.

To Revoke a Ticket, you can add a call to the SE-VU API passing the key, revoking all access to tickets using that key. In return the SE-VU API will return a status message on the success of the request.

Read the full article to see example requests and responses, as well as sample PHP code.

Viewing SE-VU Ticket Error Logssevu.errorlog

The ScaleEngine Virtual Usher Movie Ticket System or SE-VU for short (pronounced See View), provides you with the ability to search the error logs associated with your streams.

By accessing the SE-VU API you can view error logs by searching by one or more criteria including: Ticket, Original Generated Password, IP Address, Video Name, Application, or Success of the request, which in return will supply you with all requests that match those criteria. By specifying a Date time you may limit your search results to only logs newer than the date. To access the error logs, make a call to the SE-VU API supplying one or more of the criteria, an Offset and Max number of results to display. You will then be supplied with all ticket information regarding the attempt including: Date the attempt was made, Ticket Key, Original Generated Password, IP Address, Video Name, Application Name, Application Instance (live or VOD), The URL of the Page making the request, the URL of the Player making the request, the Success of the Attempt, and a Reason.

Read the full article for Response and Return messages, and Sample Code

SEVU Java implementation ExamplePosted On: 2012-05-16

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

public class SeVuService {

  private static final Log log = LogFactory.getLog(SeVuService.class);

  private static final String SE_VU_URL = "https://www.scaleengine.com/cp/api/0.8/";

  private static final String API_KEY = "your-key-here";

  private static final String API_SECRET = "your-secret-here";

  private static final String PASS = "your-pass-here";

  private static final String APPLICATION_NAME = "app-name";

  private static final Integer CDN = 1;//your cdn id here

  public JSONObject viewerCounts(String url) throws JSONException, IOException {
    final LinkedHashMap paramMap = getBaseMap("vsn.viewercount");
    paramMap.put("app", APPLICATION_NAME);
    paramMap.put("url", url);
    return createSignatureAndPost(paramMap);
  }

  //expire time should be 150-250% the length of the video
  //number of uses probably 10-20
  public JSONObject createTicket(String remoteAddress, String video, int secondsToExpire)
    throws JSONException, IOException {
    final LinkedHashMap paramMap = getBaseMap("sevu.request");
    paramMap.put("pass", PASS);
    paramMap.put("ip", remoteAddress);
    paramMap.put("video", video);
    paramMap.put("app", APPLICATION_NAME);
    paramMap.put("uses", 1);
    paramMap.put("expire", "+" + secondsToExpire + " seconds");
    
    return createSignatureAndPost(paramMap);
  }

  public JSONObject searchTickets(String video) throws JSONException, IOException {
    final LinkedHashMap paramMap = getBaseMap("sevu.search");
    paramMap.put("video", video);
    return createSignatureAndPost(paramMap);
  }

  public JSONObject ticketStatus(String ticketKey) throws JSONException, IOException {
    final LinkedHashMap paramMap = getBaseMap("sevu.status");
    paramMap.put("key", ticketKey);

    return createSignatureAndPost(paramMap);
  }

  public JSONObject revokeTicket(String ticketKey) throws JSONException, IOException {
    final LinkedHashMap paramMap = getBaseMap("sevu.revoke");
    paramMap.put("key", ticketKey);

    return createSignatureAndPost(paramMap);
  }

  public JSONObject errorLog(String ticketKey) throws JSONException, IOException {
    final LinkedHashMap paramMap = getBaseMap("sevu.errorlog");
    paramMap.put("key", ticketKey);
    //paramMap.put("pass", PASS);
    //paramMap.put("ip", remoteAddress);
    //paramMap.put("video", video);
    //paramMap.put("app", APPLICATION_NAME);
    //paramMap.put("success", 1);
    //paramMap.put("seek", 0);
    //paramMap.put("limit", 100);
    
    return createSignatureAndPost(paramMap);
  }
  
  private JSONObject createSignatureAndPost(final LinkedHashMap paramMap) 
    throws JSONException, IOException {
    paramMap.put("timestamp", new Date().getTime()/1000);
    String json = new JSONObject(paramMap).toString();
    //php encodes slashes in a non-standard way such that it needs
    //to be added AFTER json encoding
    json = json.replace("/", "/");
    paramMap.put("signature", generateSignature(json));
    
    final JSONObject responseJsonObject = postMethod(new JSONObject(paramMap));
    return responseJsonObject;
  }
  
  private LinkedHashMap getBaseMap(final String command) {
    final LinkedHashMap paramMap = new LinkedHashMap();
    paramMap.put("api_key", API_KEY);
    paramMap.put("cdn", CDN);
    paramMap.put("command", command);
    return paramMap;
  }

  private String generateSignature(String requestData) {
    String signature = null;
    try {
      Mac mac = Mac.getInstance("HmacSHA256");
      SecretKeySpec secret = new SecretKeySpec(API_SECRET.getBytes(), "HmacSHA256");
      mac.init(secret);
      signature = new String(Base64.encodeBase64(mac.doFinal(requestData.getBytes())));
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
    return signature;
  }

  private JSONObject postMethod(JSONObject jsonObject) throws JSONException, IOException {
    HttpClient httpClient = new HttpClient();
    PostMethod postMethod = new PostMethod(SE_VU_URL);
    final String json = jsonObject.toString().replace("/", "/");
    log.trace(json);
    postMethod.addParameter(new NameValuePair("json", json));
    httpClient.executeMethod(postMethod);

    String response = postMethod.getResponseBodyAsString();
    log.info("response from postMethod: " + response);

    return new JSONObject(new JSONTokener(new InputStreamReader(postMethod.getResponseBodyAsStream())));
  }
}