KScript allows you to use Kumulos to encapsulate business logic in custom server-side jobs, written in JavaScript. It will be deployed and accessed in the same way as your existing API methods but offers you much greater flexibility and control over what happens on the server-side of Kumulos.

Getting Started

Enabling KScript

KScript is not enabled by default as the majority of use cases can be satisfied via API Methods. If you wish to add server-side jobs, please email [email protected] who will be happy to enable KScripts for you.

Once you receive an email confirming that KScript has been enabled for your app, you can then create KScript methods from the API tab of your application in Kumulos. Underneath the "Create API" button, there will now be a "Create Some KScript" button once its enabled on your app.

Although used by numerous apps in production, our KScript feature is still under ongoing development and as such may change in future. However, we will contact you in advance of any significant changes.

The KScript Editor

The familiar three steplets are carried over from the existing API creator. Firstly you define a method title, and you tell kumulos whether you'll be returning objects (database records for example), or a number.

Next you can add typed input parameters to the method. Each parameter should have a name and a type set for it. These parameters will be available to use from your KScript code.

Finally there is a code entry box and toolbar. The toolbar provides the ability to insert the aliases of tables or other API methods (which can be hard to remember) and some buttons to save, run, and view the code in full screen.

The Esc key will toggle full screen editing when the code editor has focus.

Press Ctrl + Space to see the auto-complete for any function.

Function Reference

KScript has access to the parameters posted to the script, and a library of useful functions which can be used whilst writing your scripts. These methods are all exposed through the global variable K.


K.params will give you access to the parameters posted to your script. For example, a parameter called userID would be referenced as: K.params.userID.

K.params.has(key) will tell you if there is a non-empty value passed for the given key.


It is possible to log information to a debugging console during development of your KScripts. This can be useful for seeing what's going on at runtime. To log information to the debugging console, call K.log with any value you want to log out. It will accept a variable number of arguments and will show them as an array in the debug log.


This function is designed to log any arguments passed to it and also log a stack trace. It will also print the function that called the .error() method.This can be useful for tracing errors in KScripts.


This class replaces the standard Javascript JSON parser and is recommended for use in KScript methods. All of the usual methods included in the standard Javascript JSON parser are incuded such as K.JSON.parse(...) and K.JSON.stringify(...) etc.


Calling this method will output a stack trace of function names and line numbers called up to this point.

K.callAPIMethod(title, paramsObject)

This method allows you to call existing API methods from inside the KScript, and then operate on the results. For example:

var results = K.callAPIMethod('getUserByID', {userID, K.params.userID});
// Do stuff with the results


This is how a KScript returns data to the API endpoint. You can pass objects, arrays of objects, or numbers to this method. For example:

var users = K.select('users').run();

This method does not halt execution of the script, so you should plan to generate a result object and set it as the response at the end of execution.

If you plan to return binary data (for example: from base64 encoded data fields), then you must use the K.setResponseTypeMap() method to tell the API servers which fields in the result set contain binary data.


This function can be used to check for failure of any database operations. It returns true or false depending on if the call failed or not.


You can include other KScript files at runtime with the include function. Any functions or global variables inside the included KScript file will be loaded into the current scope. For example:

// In _init_ KScript method
function init() {

// In doSomething KScript method


If you want to halt execution on an error, you can throw an exception:

var results = false;
if (failed(results)) {
  throw "Results failed!";

Database Functions

Note that when querying tables using any of the following methods, you must use the table alias rather than the table name.

K.query(sql, parameters)

This function allows you to run custom queries on your database. Queries should be written in the MySQL syntax and should use placeholders where you wish to use a value passed as a parameter. For example, if you wanted to retrieve a digest of all new or edited posts (using the timeCreated and timeUpdated magic fields) after a given UNIX timestamp:

// Check we have an integer for our timestamp...
var timeUpdated=parseInt(K.params.timeUpdated, 10);
if ( isNaN(timeUpdated) ) {
  throw("Invalid timeUpdated argument");

// Execute the query...
var results = K.query(
  FROM 1234_1234_posts
  WHERE ((timeCreated >= FROM_UNIXTIME(?)) OR (timeUpdated >= FROM_UNIXTIME(?)))",

 if (failed(results)) {
     // See what the SQL error was

// Return the results...

Parameters will be bound in order, and the second argument must be an array. If you don't use any placeholders in your query then you should pass an empty array, like so: [].

Date/Time fields

In the above example, you can see that when querying the timeCreated and timeUpdated magic fields you must to use the FROM_UNIXTIME() function in your SQL query (as these fields are timestamps).

Date/Time fields on the other hand are signed integers that are intended to store dates and times as seconds relative to (i.e. before or after) the Unix epoch. You do not need to use FROM_UNIXTIME() when querying these fields.

However, please note that the getTime() method of the Javascript Date object will return timestamps in milliseconds and so you will need to divide this by 1000 before using in a query. For example, to get all events that have not yet started:

var seconds = Math.round(new Date().getTime() / 1000);
var results = K.query(
  FROM 1234_1234_events
  WHERE start >= ?",


K.select will return a select action object that can be used to query tables in the database. For example:

var select = K.select('1234_1234_users').filter('userID', K.params.userID);
var results = select.run();

Alternatively you can chain the .run() call:

var results = K.select('1234_1234_users').filter('userID', K.params.userID).run();


It is possible to use the .filter() method on select, update and delete action objects to filter the data each action will operate on.

Multiple filters can be chained together (in logical AND) by chaining calls, like: .filter('userID', K.params.userID).filter(...)

The filter method returns the original select object so you can chain on a call to run() if you want.


With the select action, it's possible to sort the records with a call to .sort(field, direction). field must be the lowerCamelCase name of a field in the table, and direction must be one of 'ASC' for ascending or 'DESC' for descending.

Result Handling

The K.query and K.select methods return array-like objects that can be iterated over and/or looped through and returned as responses. The following properties and methods are supported:

  • .length
  • .itemAtIndex(i)
  • .first()
  • .last()
  • .next()
  • .hasNext()
  • .push(object)

You can iterate through the returned rows like so:

var users = K.select('1234_1234_users').run();
var user;
while(users.hasNext()) {
  // Do something with user object e.g. set an additional property?
  user.expireCache = Date.now() + 3600;
// All user objects in users returned to the client now have an expiry time of one hour from now appended (i.e. we have advised the client they can cache the results of this query locally for one hour)

The .next() method increments the iteration pointer (so the result set can only be iterated through once).

If you wish to loop through the result set multiple times within the same Kscript method, without re-running the query, then you can use the .length property and .itemAtIndex() as follows:

var users = K.select('1234_1234_users').run();
for (var i=0; i < users.length; i++) {
  K.log( users.itemAtIndex(i).name );

Data fields

If the table you are selecting from contains data fields (for example base64 encoded images), then we need to tell our API servers to treat these fuelds as binary and base64 encode them rather than JSON encode them. This is done with the K.setResponseTypeMap() method, which is used to set strict types for fields in a result set.

The available constants that you can use to set strict types are:

  • K.Types.BOOL
  • K.Types.DATA
  • K.Types.DATE_TIME
  • K.Types.FLOAT
  • K.Types.INT
  • K.Types.STRING
  • K.Types.TEXT

In theory you could set the strict type for every field in the result set. However, it is only necessary to do this for data fields to tell the API servers to treat these fields as binary and base64 encode rather than JSON encode). This is explicitly done for drag and drop API methods, but you have to manually do this for KScript methods, for example:

var users = K.select('1234_1234_users').run();

K.insert(table_alias, object)

This method creates a record in the database and returns the ID of the newly created record. For example:

var userID = K.insert('1234_1234_users', {username: K.params.username});

K.update(table_alias, object)

To update records, use this method. It can have filters chained on to it just as K.select. If you're updating, do remember to define filters. An example to update a user:

var result = K.update('1234_1234_users',
  {username: K.params.username}).filter('userID', K.params.userID).run();

The result is the number of updated records, not the number of matching records. So if you call an update and there's nothing to change, it will return 0.


This method allows you to delete records from a table. If you call it with no filters, it will not run unless you also call .forceDeleteAll(). For example:

// Will run...
var deleteUser =
  K.delete('1234_1234_users').filter('userID', K.params.userID).run();
// Will throw an exception to the log...
var deleteAllUsers = K.delete('1234_1234_users').run();
// Will also run...
var deleteAllUsers = K.delete('1234_1234_users').forceDeleteAll().run();

This method returns the number of records deleted.

Security Functions


KScript has md5() and sha1() available as global functions. These should be faster than JavaScript implementations of these functions.


For storing passwords, bcrypt hashing functions are available. To store a password, use the K.sec.passwordHash() function:

var hashedPassword = K.sec.passwordHash(K.params.password);

var userID = K.insert('1234_1234_users', {name: K.params.name, email: K.params.email, password: hashedPassword});


To verify a password, use the K.sec.passwordVerify() function as follows:


var users = K.select('1234_1234_users').filter('email', K.params.email).run();

if ( users.length === 0) {
    K.log( "Unknown email address!");
else {
    if ( K.sec.passwordVerify(K.params.password, users.first().password) ){
    else {
        K.log("Incorrect password!");

While providing different error messages for unknown email address and incorrect password is a good user experience for your users, it does mean that a potential hacker could mine your users' email addresses. Therefore, you may wish to just provide a generic 'login failed' error.


Kumulos offers symmetric encryption using AES. These functions are suitable for protecting secrets.

The following example shows how to encrypt some plaintext, and then decrypt it again.

var PASSWORD = 'secret';

var ciphertext = K.sec.aesEncrypt('Plans to take over the world!', PASSWORD);

var plaintext = K.sec.aesDecrypt(ciphertext, PASSWORD);

if (failed(plaintext)) {
    // Decryption wasn't possible for some reason (wrong password/corrupted ciphertext)


Due to the increased length of ciphertext versus plaintext, we recommend storing encrypted strings in a Text field rather than a String field to avoid any possible truncation.

JSON Web Tokens (JWT)

Parsing a JWT

In order to integrate with a 3rd party user authentication service, such as Auth0, it is possible to verify JSON Web Tokens with KScript.

The following example will show how to create a reusable include to authenticate your KScript APIs.

First, create a script to parse & verify the JWT (_Jwt_Auth_):

// Create a parser using the given signature algorithm & secret
var parser = K.jwt.createParser(K.jwt.Signature.HS256, 'secret');
// Assume the JWT string is passed in a parameter called 'jwt'
var token = parser.parseAndVerify(K.params.jwt);

if (failed(token)) {
    throw 'Unauthorized!';

// Unpack any global variables you want from the token
var CURRENT_USER_ID = token.getClaim('uid', null);

Next, in any KScript you want to authenticate with a JWT, you can do:


if (CURRENT_USER_ID !== K.params.userId) {
    throw 'Unauthorized';

// Continue to use the passed parameters knowing they belong to the authenticated user

It is also possible to validate the issuer, subject, audience, or id claims in the token as they are being parsed:

var token = parser.parseAndVerify(K.params.jwt, {
    issuer: 'your-issuer',
    subject: 'user-123',
    audience: 'kumulos-app',
    id: 'your-expected-id'

All tokens are checked for expiry at time of parsing. All additional validation claims are optional.

Generating a JWT

To hand out authentication tokens for your app, it is possible to generate signed JSON Web Tokens with Kumulos.

The following example shows how to use the JWT builder interface to create a token for your app.

// Create a token builder using the given signing algorithm & secret
var builder = K.jwt.createBuilder(K.jwt.Signature.HS256, 'secret');

// Set some common claims
    .setIssuedAt(Date.now() / 1000)
    .setExpiry((Date.now() / 1000) + 3600) // Expire in 1hr

// Add some custom claims
builder.addClaim('roleIds', [1,2,3]);

// Get the signed token as a string
var tokenStr = builder.getToken();

CSV File Handling

KScript makes it possible to work with CSV files. You can read & write CSV files from a temporary filesystem available to your script context.

Reading CSV Files

The following example shows retrieving a CSV file from an API and parsing records from it in a loop:

var httpClient = K.http.createClient('https://your.api');

var response = httpClient.get('/game-scores.csv');

if (failed(response) || response.isError()) {
    throw 'Failed to fetch file';

var file = K.fs.createTmpFile(response.getBody());

if (failed(file)) {
    throw 'Failed to create temp file with content';

var reader = K.csv.createReader(file, {
    // Assumes the CSV has 3 columns in the order specified
    // These fields will then be used to map objects from the columns in each row of the CSV file
    recordFieldNames: ['homeTeamName', 'awayTeamName', 'score']

if (failed(reader)) {
    throw 'Failed to create a CSV reader';

var row;
while ((row = reader.readRecord())) {
    // Process the row object which will have the shape {homeTeamName, awayTeamName, score}


The K.csv.createReader(file, options) method takes an optional configuration object:

    delimiter: ',',
    enclosure: '"',
    escape: '\\',
    // Array of columns in CSV file, will be used as object keys by the reader.readRecord() method
    recordFieldNames: []

Writing CSV Files

The following example shows writing lines to a temporary CSV file. This file can then be passed to other routines such as the FTP functions.

var file = K.fs.createTmpFile();

if (failed(file)) {
    throw 'Failed to create temp file';

var writer = K.csv.createWriter(file);

if (failed(writer)) {
    throw 'Failed to create CSV writer';

// Write a header row
writer.writeRow(['date', 'weather', 'rainfallMm']);

// Write a data row
writer.writeRow(['2017-01-01', 'Sunny', 0]);

// Upload the file somewhere?


The K.csv.createWriter(file, options) method takes an optional configuration object:

    delimiter: ',',
    enclosure: '"',
    escape: '\\'

FTP Functions

KScript offers the ability to work with text files stored on remote FTP servers. The FTP functions can interoperate with the file handling functions already defined in KScript.

The following example shows the available FTP operations.

var client = K.ftp.createFtpClient('ftp.yourhost.com', 'yourUsername', 'yourPassword');

if (failed(client)) {
    throw 'Failed to connect to the FTP server';

// List the files on the remote

// Download a file from the remote and open as a temporary file
var file = client.getFile('orders.csv');

if (failed(file)) {
    throw 'Failed to download & open the file';

// Maybe process the file

// Upload the file back with a different name
var uploaded = client.putFile(file, 'orders-new.csv');

if (failed(uploaded)) {
    throw 'Failed to upload the file';

// Delete the original file
var deleted = client.deleteFile('orders.csv');

if (failed(deleted)) {
    throw 'Failed to delete remote file';

Session Support

KScript introduces persistent sessions to Kumulos and allows you to use them in your apps. KScript sessions are in-memory key-value stores which are designed to be fast and simple to use.


This method returns true if the session has a non-empty value for the given key.


If you need to unset a session variable, you can use this method. Subsequent accesses to the session key after removing it will return null.


All session values stored for the user's session will be deleted.

By default, session values will persist for one hour after the session was last accessed.


To access and set values in the session, you can use this object. It behaves like the K.params object, but it allows setting values too. For example:

var response = 0;
if (!K.session.has('userID')) {
  var results = K.select('1234_1234_users').filter({
    username: K.params.username,
    passwordHash: K.params.hashedPassword

  if (!failed(results) && results.length == 1) {
    K.session.userID = results.itemAtIndex(0).userID;
    response = 1;
  else {
    response = 0;
else {
  // Already logged in
  response = 1;

Push Notifications

You can use the Kumulos Push service from KScript to trigger targeted push notifications programmatically.

K.push.sendContentBroadcast(title, message, data)

This method can be used to send a push notification to all subscribed installations of your app. It has no targeting or filtering.

The optional data parameter allows you to pass custom meta-data to the client application as part of the push notification. For example:

K.push.sendContentBroadcast('New offer available', 'Buy one get two free!', {
  productId: 10

K.push.sendContentToInstallIds(installIds, title, message, data)

This method allows sending push notifications targeted to specific app installations.

Each Kumulos app installation is assigned a unique identifier. by retrieving this ID from the SDK and storing it in your users table in Kumulos, you can later target specific users by their install ID. For example:

var user = K.select('1_1_users').filter('userID', 10).get().first();

var data = {
  fromUserId: user.userID

K.push.sendContentToInstallIds([user.installId], 'New message from Dan', 'When's lunch?', data);

See the relevant integration guide for your chosen platforms to see how to access the unique installation ID

Targeted Push

You can also use the push notification builder to construct a notification, add content and target installs, audience segments or channels.



To add content to the push notification, you can use one of the following methods.

.inBackground(inBackground = true)
.withContent(title, message)


To send a broadcast notification or to target specific installs, segments or channels, use one of the following methods.

.broadcast(broadcast = true)


Finally, to send the notification, use the send() method, for example:

K.push.newMessage().broadcast().withContent('the title', 'the message').send();

Facebook SDK

It is possible to use the Facebook SDK through KScript if you want to add Facebook Login to your apps for example. In order to use the SDK in KScript you need to initialize it.

K.initFB(appID, appSecret, userAccessToken, graphVersion)

This initialization method sets up the Facebook SDK for use in your KScript. You need to pass in your facebook app details along with a valid user access token. This access token can be retrieved from a logged in user by using one of Facebook's various SDKs. With those items, you can initialize KScript's Facebook SDK like so:

var FB_APP_ID = '';
var FB_APP_SECRET = '';
K.initFB(FB_APP_ID, FB_APP_SECRET, K.params.fbAccessToken);

We recommend storing the access token in the KScript session after a successful login action.

It also makes sense to store this initialization in a KScript you can include whenever you need access to the Facebook SDK.

K.FB.api(path, method, data)

After initialization, the api() method can be used to query the Facebook graph API as the currently logged in user, in accordance with the permissions the user has granted your app. The results it returns are dependent on the query you issue.

This method can return an error which can be checked with the failed() function.

You can learn more about the Graph API in the Graph API Reference.

An example that retrieves the user's profile information is shown:

// In setFacebookAccessToken
K.session.fbAccessToken = K.params.fbAccessToken;

// In _facebook_
var FB_APP_ID = '';
var FB_APP_SECRET = '';
// Assume session storage of access token set by setFacebookAccessToken
K.initFB(FB_APP_ID, FB_APP_SECRET, K.session.fbAccessToken);

// In getFacebookProfile

var userProfile = K.FB.api('/me?fields=id,name,gender');

if (failed(userProfile)) {
  // Handle as needed


Convenience functions are also provided for each HTTP method:

  • K.FB.get(path)
  • K.FB.post(path, data)
  • K.FB.put(path, data)
  • K.FB.delete(path)


This method returns the currently logged in user's FBUID. The logged in user is determined by the currently initialized access token passed to K.initFB().

HTTP Client

Kumulos includes an HTTP client so you can make web requests to any web accessible API (such as Mailgun or Mandrill).

Creating an instance of a HTTP Client

You can create an instance of a blocking HTTP client by calling the K.http.createClient() method and passing in the baseURI.

var client = K.http.createClient( 'https://api.external-service.com' );

Similarly, you can create a streaming HTTP client by calling K.http.createStreamingClient() and passing in the baseURI.

Making a request

The HTTP client has methods for head, get, post, put and delete requests to a URI relative to the baseURI with given headers and parameters. For example, to perform a post request to an API using BASIC authentication.

Remember you can press Ctrl + space to see the auto-complete for any function.

var client = K.http.createClient( 'https://api.external-service.com' );

var username = 'username for external API service';
var password = 'password for external API service';
var auth = base64_encode( username + ':' + password );

var headers =
  'Authorization': 'Basic:' + auth,

var params =
  'param1': 'Hello',
  'param2': 'World'

var response = client.post('api/v1/endpoint', params, headers);

If the API expects JSON then use K.JSON.stringify(params) to encode the parameters.

Parsing Results

The HTTP client will return a response object with the following methods:

  • isSuccess()
  • isError()
  • getStatusCode()
  • getHeader(header)
  • getHeaders()
  • getBody()

The isSuccess() method will return true if the response had a status code in the range 200 - 299. The isError() method will return true if the status code is outside of this range.

If the API you are calling returns JSON, you can parse the results of the getBody() method using JSON.parse(). For example, if you want to allow users to login using their Google Identity, you could do something like:

var client = K.http.createClient('https://www.googleapis.com');

var response = client.get('oauth2/v1/userinfo?alt=json&access_token=' + K.params.userAccessToken);

// Handle errors
if (failed(response)) {
else {
    var data = JSON.parse(response.getBody());

Scheduled KScripts

Kumulos includes a robust scheduling engine that can be used to run KScript methods every minute, hour or day. While the UI for managing schedules remains in development, if you wish to schedule a recurring KScript, then please email [email protected] who will be happy to schedule it for you.

Known Issues

Reporting Bugs

If you experience any issues using KScript other than those listed above, please send an email to [email protected] and include as much information as possible about how to reproduce the error.