Cloudonaut.

Getting started (JS)

This step is easy. Sign up here and choose the authentication provider you like to sign up with Cloudonaut.

Applications

An app is your basic starting point to use Cloudonaut. Each app has its cloud data, leaderboards, players, characters, etc...
Cloudonaut does not limit the number of apps you can have. Even in the free tier, you can have as many apps as you want.
Just remember that you have 1000 free calls each month shared between apps.

Create an application

After you logged in to your Cloudonaut dashboard, in the left side menu you see a + icon next to Your applications.
To create a new app click on that + sign.
Give your app a name and click on create.
The app will be created and you will see the applications name in the left side menu.

The app ID

To get your app ID you can click on the application name and then settings in the left side menu.
The number next to "Your appID:" is your application ID.
You will need this ID to identify your app later on.

The app secret

The app secret is auto-generated. To reveal your app secret follow these steps:
Click on the application name and then settings in the left side menu.
Click on the text: *** Click to reveal your app secret ***

Read about App security in the next section for more info.

App security

For compiled games, you can use the app secret key.
The backend API will check the combination of appID with the app secret to identify every call you make.
For web games, we strongly suggest you whitelist your URL for your app and do not use the app secret key.
As an alternative, you can set up a backend script as a router. This router script can use the app secret key.

Whitelist a URL

To whitelist an URL follow the following steps:
Click on the application name and then settings in the left side menu.
Type your domain name in the Url list field and press the update button.
You do not need to specify subdomains. Just use something like "example.com".
To add multiple domains you can an "," to separate domains.

Using a Router script

A router will make it possible to manipulate calls on your backend before passing them on to the Cloudonaut API.
A simple example is adding the app secret to the call instead of whitelisting URLs in your app.
Another example could be to create your anti-cheating mechanisms and check a score before submitting it.

Here is a very basic example router written in PHP.

$rawData = file_get_contents("php://input");
$request = json_decode(urldecode($rawData));
$request->appSecret = <your app secret>;

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://api01.cloudonaut.com',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => json_encode($request),
  CURLOPT_HTTPHEADER => array(
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

Facebook integration

If you want to integrate Facebook to authenticate your players you need to provide us the Facebook App ID and the Facebook App Secret. To get these you need a Facebook developer account and create a Facebook app first. To do this you can find their documentation here.

To enter the facebook app ID and Secret follow the following steps:
Click on the application name and then settings in the left side menu.
Fill in the Facebook App ID and Facebook App Secret and click on the update button.

Firebase integration

Firebase can be used to authenticate using lots of auth providers. Including Facebook, Gmail, Microsoft, Apple, etc... You can use Firebase auth to identify your players. To do that, you need to provide us a service account. You can do that in the project settings of your Firebase project. When you generate a new key you will be able to download a JSON file. Copy the complete contents of this JSON.

To store this json contents go to your Cloudonaut dashboard.
Click on the application name and then settings in the left side menu.
Paste the contents in the field Firebase Service Account and click the update button.

Cloud Data

Cloud data is a key-value store to store player, character, and even app data.

For player data, the player can write and read to his data by default and can be read by other players of the same app.
You can change this behavior with the privacy field.
Each player can also create specific character data. So you can store character abilities or levels for each character as an example.

App data are key values that can be read by all players and characters.
You can use this to store texts or game settings that need to be synchronized to all players without republishing your game.
We strongly advise using the Cloudonaut dashboard to fill-in app data and only retrieve the app data with the API in your game/app or website. In this case, the default privacy setting is set to read-only for players. Using the API to write app data means you are writing data as a player. The privacy setting will be set as read and writable for all players.
We do not recommend this. Use it with care if you have an edge case for this.

Privacy

The privacy field for player/character data can be 0,1 or 2.
0 = Everybody can read and write to this data of the player. (not recommended)
1 = Everybody can read the data but only the logged-in player can write. (default)
2 = Only the logged-in player can read and write to this data.

Notice that when you set privacy to 0. Other players could write to your data. There is no API call for the other player to do that at this moment but there might be one in the future. So take care of the player's data and set the privacy to 1 or 2 to be future proof.

For application data, you can set the privacy to 0,1 or 2.
0 = Everybody can read and write this data. (Not recommended, only for edge cases)
1 = Everybody can read this data but the data can only be set through the Cloudonaut dashboard. (Maybe a back-end API in the future)
2 = Only readable and writeable through the Cloudonaut dashboard.

When a player tries to write to app data that does not have privacy of 0, the following will be returned.

{
  "success":false,
  "error":"Wrong permission to write to this data.",
  "errorId":2
}

All other cases with permission problems will return the following object:

{
  "success":false
}

Write-lock

If 2 users get the same read and writable key what happens when they both save a change?
Without write locks the last one to press save will win. His value will overwrite the other user's value.
If you want to prevent this you can use write locks. Again, when 2 users get the same key they now get the same write lock.
But you can only save data if you have the write lock that matches the write lock value on the server.
In this case, user A saves first. The write lock on the server will be incremented.
If user B saves his data now, it will fail because he used an old write lock.

For app data, the write-lock is always enabled.
For player data, it is disabled by default. As long as you do not set the value of the write-lock it won't be used. If you want to use it for player data, set the write lock to 1 or above. From that moment the write lock is used and can't be undone.

Response after writing with the wrong write lock:

{
  "success":false,
  "error":"Wrong writelock provided",
  "errorId":1
}

Create App data

To create application level key value pairs you will need login to the Cloudonaut dashboard.
On the left side menu click on your app and choose App data.
Click on the Add key button.
Fill in the Key wich has to be unique for this app. (If you try to create a duplicate key you will be prompted that there is a failed API call.)
Set the privacy. Default it is Everybody can read.
Last but not least, fill in a value for the key. This can be any string. Even Json is possible.
Click on Create.

Modify App data

To modify a key follow these steps:
On the left side menu click on your app and choose App data. Click on the Edit button of the key you want to modify.
You can change the value, privacy and the writeLock.
The writeLock should be kept as is. Only in some special occasion you can change it here. Remember that it needs to be a higher number than before.

Quickstart

Lets create a game!

Javascript SDK

Installation

Option 1: CDN

To add the Javascript SDK you can use the CDN from the nice people of Jsdelivr.

<script src="https://cdn.jsdelivr.net/npm/@cloudonaut/[email protected]/dist/cloudonaut.min.js"></script>

At the time we were writing this document the version is 1.1.5 make sure to change it to the latest one.

Option 2: Download from GitHub

Download the latest version from GitHub. The build and minified version cloudonaut.min.js, can be found in the dist folder.

Option 3: npm

[TODO] We need to test this :(

The basics

The SDK is basicly a class that can be instantiated.

var api = new cloudonaut.API(<app ID>, <Optional: app secret>);

As mentioned before we suggest filling in app ID only and do not pass the app secret. Whitelist your URL or use a router back-end script.

The variable API now holds the entire ecosystem of Cloudonaut and is connected with your app ID.

The API object has a few properties.
api.appID is the app ID you provided.
api.appSecret should be blank or contains the value you provided.
api.url contains the API entry point URL. You can change this to the URL of your router script. All calls made by this SDK will post data to this URL.
api.player is an object containing the logged-in player. This object should be empty as long as you do not log in. Once a player is logged in this object will be used in calls made by this SDK that needs player info.
api.character will contain a selected player character. After you log in with a player you can select one of his characters. The selected character will be used in calls made by this SDK that uses character info.

To use the power of Cloudonaut, the API holds lots of services.
Auth() for authentication.
Friend() for managing friends.
Leaderboard() for the leaderboard and scoring service and many more.
We will go through all services in this document.

To use a service you can instantiate one using the API.
This example will create an authentication service.

var auth = api.Auth();

Services have methods that call the Cloudonaut backend. All these methods return a promise. So you can use them with then() and catch(). In this example we login with an anonymous user.

var auth = api.Auth();
auth.Anonymous(<device ID, GUID, Custom unique ID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

You can skip the creation of an instance and just call a specific method of the service. In this example we use a Cloudonaut helper function from our CF() service to generate a GUID.

api.CF().GetGUID().then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});

Paging objects

In some methods, you can use paging. API calls that return a list of something like characters, scores, friends are limited to a maximum of 100 results in one call. But you can use paging to get the next results. A paging object looks like this:

{
  "limit":<int>,
  "page":<int>
}

Every service that contains a list method like ListCharacters, ListScores, ListFriends has a default page object. You can modify this object on the service level itself. To set a default limit of 25 for example.

Let's do exactly that with an example. We will call the get scores API and limit the scores to 25.

var leaderboard = api.Leaderboard();
// set the default limit to 25
leaderboard.paging.limit = 25;
//From now on each call you make with this leaderboard service will include the 25 limit.
// The folowing results in the top 25 scores
leaderboard.ListScores().then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});
// This one will result in the top 25 scores of friends
leaderboard.ListScoresOfFriends().then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});

To get the next 25 entries you can increment the page attribute of the paging. This can be done the same way.

var leaderboard = api.Leaderboard();
leaderboard.paging.page = 2;

Every call to a List will now return the second page of the dataset.

If you want to manage a paging object yourself, or overrule the default paging object for a certain API call, then you can create a paging object. This paging object can be passed as a parameter to a call.

var paging = new cloudonaut.Paging();
paging.limit = 25;
paging.page = 1;
api.Leaderboard().ListScores(paging).then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});

Go on and explore our services!

Authentication

For user authentication, you can use our anonymous system or use an existing authentication provider. We integrate with Firebase and Facebook. We did not develop our own email/username/password system because there are already so many providers and security is a huge thing. That is why we recommend using Firebase or Facebook to allow players to play on different devices. Firebase can be used to login with lots of different providers (Game Center, Play games, Google, Apple, ...) and has a free tier.

The API service for authentication is called Auth().

api.Auth()

Anonymous

Anonymous authentication uses a single unique string to identify the player. We call this the provider UID. For Facebook and Firebase, the provider UID will be the UID of that platform. For anonymous authentication, we recommend using the device ID. If you are using a browser application or a platform without a device ID you can generate a unique ID with the Cloudonaut Function Get GUID or Get Random String. Store that string in a browser cookie or local storage to remember the device/player and use it as the provider UID.

Remember that once the provider UID is lost by the player he can't recover his account anymore. (Apple devices have a unique ID for each app. If the player uninstalls the app and reinstalls it again the unique ID will not be the same.) If you need users to have more secured accounts use Firebase or Facebook instead.

However, you should use anonymous authentication to start with. So a player can use all features of your game or app. Including leaderboards and cloud data. If a user logs in with Firebase or Facebook, you can merge the current anonymous user with the social user.

The anonymous authentication function requires one parameter called provider UID. This can be generated or given. If you pass this unique ID to the function it will create a player for your app or, if the unique ID already exists in your app, returns the existing player. The provider UID has to be unique in combination with the App ID. So you can use the same provider UID in a different app.

var api = new cloudonaut.API(<app ID>);
api.Auth().Anonymous(<unique ID>).then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});

The data object looks like this:

{
  "success":<bool>,
  "player":
  {
    "playerID":<int>,
    "playerSecret":<string>,
    "displayName":<string>,
    "displayNameExtra":<string>,
    "providerUID":<string>
  }
}

The SDK will now auto-fill the api.player object with the player ID, player secret, display name, display name Extra, and provider UID.

Let us create a more realistic example. In this example, we build a complete anonymous authentication flow. We will create a GUID as the unique ID and store it in localStorage. Of course, you can create your own unique ID and store it wherever you like. (cookie, database, human memory, ...).

// A global var to hold the Cloudonaut API.
var api;

// Let us wrap the authentication in a function so we can use it from multiple places.
function auth(providerUID)
{
  // Just call the service with the provider UID as a parameter.
  api.Auth().Anonymous(providerUID)
    .then((data) => {
      console.log(data);
      //The user is logged-in. Call the function you want to run after login. startGame() for example :)
    }).catch((error) => {
      console.log(error);
    });
}

// As a best practice, we wait for the DOM to be ready.
document.onreadystatechange = function () {
    // Check the value - if it's 'interactive' then the DOM has loaded
    if (document.readyState === "interactive") {
        //Create the API service instance and connect it to your app ID.
        api = new cloudonaut.API(<your app ID>);

        // We store the unique ID in local storage.
        // You can also use a cookie or ask the player to remember his uid and let him enter it in a textbox.
        // Check if there is a provider UID in local storage.
        if (localStorage.getItem("providerUID") === null) {
          // In this example, we use GetGuid to create a unique ID for the player.
          // You can also use GetRandomString() or create your own if you want.
          api.CF().GetGUID()
            .then((data) => {
              //Save the GUID to local storage
              localStorage["providerUID"] = data.GUID;
              // Call the auth function
              auth(localStorage["providerUID"]);
            }).catch((error) => {
              console.log(error);
            });
        }
        else {
          // If there is already a unique provider UID so call the auth function
          auth(localStorage["providerUID"]);
        }
    }
}

Authenticate with Facebook

To use Facebook authentication you need to create a Facebook app on their developer site.
Once you have created an app get the app ID and Facebook app secret.
In the Cloudonaut App Dashboard, you can edit your Cloudonaut app and fill in the Facebook app ID and app secret.
Now your app can connect with Facebook.

var api = new cloudonaut.API(<app ID>);
api.Auth().WithFacebook(<Facebook token>).then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});

The data object looks like this:

{
  "success":<bool>,
  "player":
  {
    "playerID":<int>,
    "playerSecret":<string>,
    "displayName":<string>,
    "displayNameExtra":<string>,
    "providerUID":<string>,
    "merged":<bool>
  }
}

The SDK will now auto-fill the api.player object with the player ID, player secret, display name, display name extra, and provider UID. If an anonymous user is already authenticated the SDK will try to merge the accounts. This will only happen if the social use did not used your app before. The merged field in the response is an indicator if the current anonymous user was merged into the social user (true) or not (false). If the user is merged you should remove the generated ID (GUID, Unique ID, ...) from local storage, the cookie, or wherever you stored it.

Assume we stored the anonymous provider UID in localStorage:

var api = new cloudonaut.API(<app ID>);
api.Auth().WithFacebook(<Facebook token>).then((data)=>{
  if (data.player.merged)
  {
    localStorage.removeItem("providerUID");
  }
}).catch((error)=>{
  console.log(error);
});

We created a full Facebook integration example for you. Here we use the default code from Facebook to create a Facebook login page and pass the token to Cloudonaut.

<!DOCTYPE html>
<html>
<head>
<title>Facebook Login JavaScript Example</title>
<meta charset="UTF-8">
</head>
<body>
  <!-- The JS SDK Login Button -->
  <!--
  We will ask for permissions gaming_profile, gaming_user_picture, email and user_friends
  gaming_user_picture and email is not required for Cloudonaut but we recommend them.
  user_friends can be used to get your friends from facebook and sync them with the friends on Cloudonaut.
  It is not required to do this. Remember that asking for the user_friends permission you need to pass you app to facebook review.
  //-->
  <fb:login-button scope="gaming_profile,gaming_user_picture,email,user_friends" onlogin="checkLoginState();">
  </fb:login-button>
  <div id="status">
  </div>
  <!-- Load the JS SDK asynchronously -->
  <script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@cloudonaut/[email protected]/dist/cloudonaut.min.js"></script>
<script>
// a global var to hold the cloudonaut api.
var api;

// Lets wrap the authentication in a function so we can use it from multiple places.
function auth(token)
{
  //Create the api service instance and connect it to your app ID.
  api = new cloudonaut.API(<Cloudonaut App ID>);
  // Just call the service with the Facebook token as parameter.
  api.Auth().WithFacebook(token)
    .then((data) => {
      console.log(data);
      //User is logged-in. Call the function you want to run after loggin. startGame() for example :)
    }).catch((error) => {
      console.log(error);
    });
}

function statusChangeCallback(response) {  // Called with the results from FB.getLoginStatus().
  console.log('statusChangeCallback');
  console.log(response);                   // The current login status of the person.
  if (response.status === 'connected') {   // Logged into your webpage and Facebook.
    auth(response.authResponse.accessToken);
  } else {                                 // Not logged into your webpage or we are unable to tell.
    document.getElementById('status').innerHTML = 'Please log into this webpage.';
  }
}

function checkLoginState() {               // Called when a person is finished with the Login Button.
  FB.getLoginStatus(function(response) {   // See the onlogin handler
    statusChangeCallback(response);
  });
}

window.fbAsyncInit = function() {
  FB.init({
    appId      : <Your Facebook App ID>, //Fill in the app ID of you Facebook app.
    cookie     : true,                     // Enable cookies to allow the server to access the session.
    xfbml      : true,                     // Parse social plugins on this webpage.
    version    : 'v10.0'           // Use this Graph API version for this call.
  });
  FB.getLoginStatus(function(response) {   // Called after the JS SDK has been initialized.
    statusChangeCallback(response);        // Returns the login status.
  });
};
</script>
</body>
</html>

Authenticate with Firebase

Firebase contains a huge amount of authentication providers. From Gmail to Apple Game center and Android Play games. Currently, we did not implement these auth providers on our own. But you can use them through Firebase. (Why reinvent the wheel?)

If you do not have a Firebase application yet you should create one. (Follow their instructions) In the Firebase console, you can generate a service account. It will generate a JSON file. You need this to connect Cloudonaut to Firebase. In the Cloudonaut app dashboard, edit the app you want to use firebase authentication with. Paste the Contents of the JSON file into the Firebase Service Account field.

Now we can connect with Firebase.

var api = new cloudonaut.API(<app ID>);
api.Auth().WithFirebase(<Firebase token>).then((data)=>{
  console.log(data);
}).catch((error)=>{
  console.log(error);
});

The data object looks like this:

{
  "success":<bool>,
  "player":
  {
    "playerID":<int>,
    "playerSecret":<string>,
    "displayName":<string>,
    "displayNameExtra":<string>,
    "providerUID":<string>,
    "merged":<bool>
  }
}

The SDK will now auto-fill the api.player object with the player ID, player secret, display name, display name extra, and provider UID. If an anonymous user is already authenticated the SDK will try to merge the accounts. This will only happen if the social use did not used your app before. The merged field in the response is an indicator if the current anonymous user was merged into the social user (true) or not (false). If the user is merged you should remove the generated ID (GUID, Unique ID, ...) from local storage, the cookie, or wherever you stored it.

Assume we stored the anonymous provider UID in localStorage:

var api = new cloudonaut.API(<app ID>);
api.Auth().WithFirebase(<Firebase token>).then((data)=>{
  if (data.player.merged)
  {
    localStorage.removeItem("providerUID");
  }
}).catch((error)=>{
  console.log(error);
});

Cloudonaut Functions

Cloudonaut Functions are a set of helper functions to make your life easier. The API service for Cloudonaut Functions is called CF().

api.CF()

Get Distance

Get the distance between 2 geo points in km, miles, or nautical miles. You can send the longitude-latitude points as a decimal or in the degree, minute, and second format.

To define these geo points we created an object GeoPoint.
You can choose which unit of measurement you want to use.
km = kilometer
mi = miles
nmi or nm = nautical miles

var api = new cloudonaut.API(<app ID>);
// Add the decimal coordinates of Antwerp, Belgium to g1
var g1 = new cloudonaut.GeoPoint({ long: "4.4024643", lat: "51.2194475" });
// Add the degree coordinates of Brussels, Belgium to g2
var g2 = new cloudonaut.GeoPoint({ long: "4°21'6.156\"", lat: "50°51'1.224\""});
// We pass "km" if we want the distance measure to be kilometer.
// You can use km for kilometer, mi for miles, nmi or nm for nautical miles
api.CF().GetDistance(g1, g2, "km").then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The data object looks like this:

{
  "success":<bool>,
  "latitude1": "51.2194475",
  "latitude2": "50.85034",
  "longitude1": "4.4024643",
  "longitude2": "4.35171",
  "distance":"41.19405040417068",
  "unit":"km"
}

Get Random String

Generate a unique string.

var api = new cloudonaut.API(<app ID>);
api.CF().GetRandomString().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": true,
    "randomString": "196069d18d8aea4CRS6069d18d8aea64.49739688"
}

Get GUID

Generate a version 4 GUID.

var api = new cloudonaut.API(<app ID>);
api.CF().GetGUID().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": true,
    "GUID": "eb3a4d22-1df8-469a-ab6f-353f6d912152",
    "GUIDVersion": 4
}

Characters

Each player can have multiple characters. Characters will have a character ID.
If you want your game our app to make use of this possibility you can pass this character ID along with the player ID to most of our API functions.
Examples are leaderboards. Add a score for a player. Or for a player character combination.
Cloud data can be stored for a player but also a player character combination.
It is not necessary to use characters if you do not need multiple characters per player. The API service for characters is called Character().

api.Character();

The character object

There is a character object available.
The API object itself has an instance of the character object. This will store the currently selected character.
When we talk about the currently selected character, we refer to this object.

api.character.characterID; // Stores the character Id
api.character.characterName; // Stores the character name
api.character.characterNameExtra; // Stores an additional part of name (can be used freely)
api.character.characterAvatar; // Stores a string to use as a ref to an Avatar.

The character avatar can be anything you want. It can hold an URL to the picture or you can hold a keyword that defines the avatar in your code.
For example, you use a shared resource of avatar pictures in your game. You can hold the reference to that picture instead of the full URL.

You can create a new character object with the following code:

var character = new cloudonaut.Character({
              characterName: "Character name",
              characterNameExtra: "Extra part of the character name",
              characterAvatar: "A link to the character avatar"
            });

or

var character = new cloudonaut.Character();
character.characterName = "Character name";

Add Character

Creates a character for the currently logged-in player.

var api = new cloudonaut.API(<app ID>);
var character = new cloudonaut.Character({
              characterName: "Character name",
              characterNameExtra: "Extra part of the character name",
              characterAvatar: "A link to the character avatar"
            });
api.Character().AddCharacter(character).then((data) => {
  // You can store the auto-generated Id in the characterID field.
  character.characterID = data.characterID;
  console.log(data);
}).catch((error) => {
  console.log(error);
});

Warning! The character ID will be auto-generated by the back-end. If you filled in an Id in character object and pass that to the AddCharacter function it will be ignored.

The response object looks like this:

{
    "success": <bool>,
    "characterID": "<int>"
}

Update Character

This function can be used to update your selected character or a specific character of the player by providing a character object.
You can update the character name, character name extra, and the character avatar.

In the following example, we update a character of a player. We assume we already got this character from a previous API call.

var api = new cloudonaut.API(<app ID>);
var character = new cloudonaut.Character();
// Let us assume we know that this player has a character with Id 5.
// In a real-world application you probably get a list of the player's character first
// and fill this character object using one entry of that list.
character.characterID = 5;
character.characterName = "Character Five";

api.Character().UpdateCharacter(character).then((data) => {
  // We have changed the name of the character to Character Five.
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>
}

Most of the time a player selects a character to play with. This selected character is kept in the API object.
If you now want to let the player change his selected character you do not need to provide a character object.
Let us update the currently selected character.

var api = new cloudonaut.API(<app ID>);
//Modify the name of the currently selected character
api.character.characterName = "My Favorite";

// If we do not pass a character object the SDK will pass the api.character object to the back-end.
api.Character().UpdateCharacter().then((data) => {
  // We have changed the name of the currently selected character to "My Favorite"
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>
}

Get Character

If you know the character Id, you can get the full character profile of a character.

var api = new cloudonaut.API(<app ID>);
api.Character().GetCharacter(<character ID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "character": {
        "characterID": "<int>",
        "playerID": "<int>",
        "characterAvatar": "<string>",
        "characterName": "<string>",
        "characterNameExtra": "<string>",
        "created": "<datetime>"
    }
}

This function searches the character Id in the list of characters of the current logged-in player. To get a character from another player you can use:

GetCharacterOfPlayer(<playerID>,<characterId>);

Example use case:
You could store the current selected character ID in local storage for example. And when the player logs back into the game, you get that character ID from local storage and get that character's profile. Now you can show the player a message that asks him to continue to use this character?
If he continues, you can set the api.character to this character.

Set Character

Get a character profile by a character Id and set this character as the default character in the API.
The character must be owned by the currently authenticated player.

var api = new cloudonaut.API(<app ID>);
api.Character().SetCharacter(<character ID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "character": {
        "characterID": "<int>",
        "playerID": "<int>",
        "characterAvatar": "<string>",
        "characterName": "<string>",
        "characterNameExtra": "<string>",
        "created": "<datetime>"
    }
}

It is a shortcut to get a character profile and fill in the api.character object for you.

List Characters

List all the characters of the logged-in player. You can use the default paging of the Character service but the function can accept a custom paging object if you need it.

var api = new cloudonaut.API(<app ID>);
api.Character().ListCharacters(<optional: Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "characterList": [
        {
            "characterID": "<int>",
            "playerID": "<int>",
            "characterAvatar": "<string>",
            "characterName": "<string>",
            "characterNameExtra": "<string>",
            "created": "<datetime>"
        },
        ...
    ]
}

See paging for more information about the paging parameter.

Count Characters

Gets the number of characters the player owns.

var api = new cloudonaut.API(<app ID>);
api.Character().CountCharacters().then((data) => {
 console.log(data);
}).catch((error) => {
 console.log(error);
});

The response object looks like this:

{
    "success": true,
    "listCount": "<int>"
}

Based on the paging limit and the result of this function you can calculate how many pages there are in the recordset.

Get character of another player

Provide a player Id and character Id to get that specific character profile of that specific player.

var api = new cloudonaut.API(<app ID>);
api.Character().GetCharacterOfPlayer(<playerID>,<characterId>).then((data) => {
 console.log(data);
}).catch((error) => {
 console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "character": {
        "characterID": "<int>",
        "playerID": "<int>",
        "characterAvatar": "<string>",
        "characterName": "<string>",
        "characterNameExtra": "<string>",
        "created": "<datetime>"
    }
}

List characters of another player

List all the characters of a certain player.

var api = new cloudonaut.API(<app ID>);
api.Character().ListCharactersOfPlayer(<playerID>, <optional: Paging>).then((data) => {
 console.log(data);
}).catch((error) => {
 console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "characterList": [
        {
            "characterID": "<int>",
            "playerID": "<int>",
            "characterAvatar": "<string>",
            "characterName": "<string>",
            "characterNameExtra": "<string>",
            "created": "<datetime>"
        },
        ...
    ]
}

See paging for more information about the paging parameter.

Count characters of another player

Get the number of characters owned by a certain player.

var api = new cloudonaut.API(<app ID>);
api.Character().CountCharactersOfPlayer(<playerID>).then((data) => {
 console.log(data);
}).catch((error) => {
 console.log(error);
});

The response object looks like this:

{
    "success": true,
    "listCount": "<int>"
}

Based on the Paging limit and the result of this function you can calculate how many pages there are in the recordset.

Cloud Data

Cloud data is a key-value store to store player, character, and even app data.

For player data, the player can write and read to his data by default and can be read by other players of the same app.
You can change this behavior with the privacy field.
Each player can also create specific character data. So you can store character abilities or levels for each character as an example.

App data are key values that can be read by all players and characters.
You can use this to store texts or game settings that need to be synchronized to all players without republishing your game.
We strongly advise using the Cloudonaut dashboard to fill-in app data and only retrieve the app data with the API in your game/app or website. In this case, the default privacy setting is set to read-only for players. Using the API to write app data means you are writing data as a player. The privacy setting will be set as read and writable for all players.
We do not recommend this. Use it with care if you have an edge case for this.

The API service for cloud data is called CloudData().

api.CloudData();

Set application data

This will modify an existing key that can be read or written to by all players.
Normally you will not use this function because this will modify a key-value pair on the application level.
But if you have an edge case, please continue.

To create application key's you need to use the cloudonaut dashboard! We will not allow the creation of application level data from this SDK.

var api = new cloudonaut.API(<app ID>);
api.CloudData().SetAppData(<dataKey>, <optional: value>, <optional: writeLock>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>
}

The data key is a unique string stored in the application context. The default value will be an empty string.
More information about the use of the write-lock can be found here.

Get application data

Get the value of a certain app data key.

var api = new cloudonaut.API(<app ID>);
api.CloudData().GetAppData(<dataKey>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "cloudData": {
        "dataKey": "<string>",
        "value": "<string>",
        "writeLock": "<int>",
        "created": "<datetime>",
        "modified": "<datetime>"
    }
}

Set data

Set data for the currently logged-in player.
If there is a character selected. It will set the data for this character of the player and not the player itself.
If there is no character selected it will set the data for the logged-in player.

var api = new cloudonaut.API(<app ID>);
api.CloudData().SetData(<dataKey>, <Optional: value>, <Optional: writeLock>, <Optional: privacy>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The default value will be an empty string.
More information about the use of the write-lock can be found here.
More information about the use of privacy can be found here.

The response object looks like this:

{
    "success":<bool>,
    "inserted":<bool>
}

If inserted is true, it means that the key did not exist and is inserted.

Set player data

Set data for the currently logged-in player.
Use this instead of SetData, if you want to set player data when there is character selected.

var api = new cloudonaut.API(<app ID>);
api.CloudData().SetPlayerData(<dataKey>, <Optional: value>, <Optional: writeLock>, <Optional: privacy>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The default value will be an empty string.
More information about the use of the write-lock can be found here.
More information about the use of privacy can be found here.

The response object looks like this:

{
    "success":<bool>,
    "inserted":<bool>
}

If inserted is true, it means that the key did not exist and is inserted.

Set character data

Provide a charachter ID to set data for a specified character of the currently logged-in player.

var api = new cloudonaut.API(<app ID>);
api.CloudData().SetCharacterData(<dataKey>, <Optional: characterID>, <Optional: value>, <Optional: writeLock>, <Optional: privacy>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The default value of characterID will be zero and the key value will be assigned to the player instead of a character.
The default value will be an empty string.
More information about the use of the write-lock can be found here.
More information about the use of privacy can be found here.

The response object looks like this:

{
    "success":<bool>,
    "inserted":<bool>
}

If inserted is true, it means that the key did not exist and is inserted.

Get data

Gets the data of the logged-in player and the currently selected character.
If no character is selected it will try to get the data from the player itself.

var api = new cloudonaut.API(<app ID>);
api.CloudData().GetData(<dataKey>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "cloudData": {
        "playerID": "<int>",
        "characterID": "<int>",
        "dataKey": "<string>",
        "value": "<string>",
        "writeLock": "<int>",
        "created": "<datetime>",
        "modified": "<datetime>"
    }
}

Get player data

Get the data of the logged-in player. Even if there is a selected character.

var api = new cloudonaut.API(<app ID>);
api.CloudData().GetPlayerData(<dataKey>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "cloudData": {
        "playerID": "<int>",
        "characterID": "<int>",
        "dataKey": "<string>",
        "value": "<string>",
        "writeLock": "<int>",
        "created": "<datetime>",
        "modified": "<datetime>"
    }
}

Get character data

Get the data of a specific character of the logged-in player.

var api = new cloudonaut.API(<app ID>);
api.CloudData().GetCharacterData(<dataKey>, <Optional: characterID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The default value of characterID will be zero and the key value returned will be from the player instead of a character.

The response object looks like this:

{
    "success": <bool>,
    "cloudData": {
        "playerID": "<int>",
        "characterID": "<int>",
        "dataKey": "<string>",
        "value": "<string>",
        "writeLock": "<int>",
        "created": "<datetime>",
        "modified": "<datetime>"
    }
}

Get player data of a specific player

If the data is not blocked by privacy you can get the value of the key of another player.

var api = new cloudonaut.API(<app ID>);
api.CloudData().GetPlayerDataOfPlayer(<dataKey>, <playerID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success": <bool>,
    "cloudData": {
        "playerID": "<int>",
        "characterID": "<int>",
        "dataKey": "<string>",
        "value": "<string>",
        "writeLock": "<int>",
        "created": "<datetime>",
        "modified": "<datetime>"
    }
}

Get character data of a specific player

If the data is not blocked by privacy you can get the value of the key of a specific character of another player.

var api = new cloudonaut.API(<app ID>);
api.CloudData().GetCharacterDataOfPlayer(<dataKey>, <playerID>, <Optional: characterID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The default value of characterID will be zero and the key value returned will be from the player instead of a character.

The response object looks like this:

{
    "success": <bool>,
    "cloudData": {
        "playerID": "<int>",
        "characterID": "<int>",
        "dataKey": "<string>",
        "value": "<string>",
        "writeLock": "<int>",
        "created": "<datetime>",
        "modified": "<datetime>"
    }
}

Friends

Players can add each other as friends.
We do not prevent users from becoming friends. Becoming friends is never 2 ways.
Each player can add his friends. So if player A adds player B as a friend. Player A can see player B's score on the friend's leaderboard. Player A on the other hand does not see player B. Player A needs to add player B as a friend.
This way we do not use friend requests and approves because we do not share private data between players.The friends API service called Friend().

api.Friend();

Add friend

Add a friend to the logged-in players friend list.

var api = new cloudonaut.API(<app ID>);
api.Friend().AddFriend(<friendID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The parameter friendID is a player ID of another player.

The response object looks like this:

{
    "success":<bool>
}

Remove friend

Remove a friend from the players friend list.

var api = new cloudonaut.API(<app ID>);
api.Friend().RemoveFriend(<friendID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The parameter friendID is a player ID of one of your friends.

The response object looks like this:

{
    "success":<bool>
}

Add friends from facebook

Provide a list containing the facebook UID of the facebook friends of the logged-in player.
This only works if the player is authenticated with Facebook or Firebases Facebook implementation.
You can get this list with the Facebook API if you ask for the friends permission.
Facebook needs to review your app before you can use the friends permission.

var api = new cloudonaut.API(<app ID>);
api.Friend().AddFriendsFromFacebook(<Array: friendList>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>
}

List friends

Get a list of all the friends of the logged-in player.

var api = new cloudonaut.API(<app ID>);
api.Friend().ListFriends(<Optional: paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

See paging for more information about the paging parameter.

The response object looks like this:

{
    "success":<bool>,
    "friendList": [
        "<friends player ID>",
          ...
    ]
}

Count friends

Returns the number of friends of the logged-in player.

var api = new cloudonaut.API(<app ID>);
api.Friend().CountFriends().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "listCount":<int>
}

Player Profile

Each player has a player profile. Scores, characters, Cloud data and friends are linked to a player profile.
You can see the player profile as character number zero. If a player only has a single profile in your game then you do not need to use characters.

The Player Profile API service called PlayerProfile().

api.PlayerProfile();

The player object

The API object contains the player object of the logged in player.
You can use this object after you have authenticated the player as follows:

api.player.playerID; // Contains the playerID of the player
api.player.providerUID; // Contains the unique ID of the authentication provider.
api.player.playerSecret; // Contains the token to access the api as this player. Never store this somewhere else.
api.player.displayName; // Contains the player name
api.player.displayNameExtra; // Contains an additional part of the name (can be used freely)
api.player.avatar; // Stores a string to use as a ref to an Avatar.

The avatar can be anything you want. It can hold an URL to the picture or you can hold a keyword that defines the avatar in your code. For example, you use a shared resource of avatar pictures in your game. You can hold the reference to that picture instead of the full URL.

Update Profile

You can update the displayName, displayNameExtra and the avatar field using the following function:

var api = new cloudonaut.API(<app ID>);
  //Change one of the players properties.
api.player.displayName = "new name";
api.player.displayNameExtra = "new addiational part";
api.player.avatar = "https://www.gravatar.com/avatar/"
api.PlayerProfile().UpdateProfile().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>
}

Get Profile

Gets the profile of the logged-in player how it is stored on the server.

var api = new cloudonaut.API(<app ID>);
api.PlayerProfile().GetProfile().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "playerProfile": {
        "playerID": "<int>",
        "displayName": "<string>",
        "displayNameExtra": "<string>",
        "avatar": "<string>"
    }
}

Get Profile Of Player

Gets the profile of another player using the player ID.

var api = new cloudonaut.API(<app ID>);
api.PlayerProfile().GetProfileOfPlayer(<playerID>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "playerProfile": {
        "playerID": "<int>",
        "displayName": "<string>",
        "displayNameExtra": "<string>",
        "avatar": "<string>"
    }
}

List Profiles Of Players

Gets all the player profiles of a array of playerID's.
As a second parameter you can send a paging object. Or use the default paging object of the PlayerProfile service.
Remember that you can modify the default pagina object to.
See paging for more information about the paging parameter.

var api = new cloudonaut.API(<app ID>);
var playerList = new Array(<ID1>, <ID2>, ..., <IDn>);
api.PlayerProfile().ListProfilesOfPlayers(playerList, <optional:Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "playerProfileList": [
      {
        "playerID": "<int>",
        "displayName": "<string>",
        "displayNameExtra": "<string>",
        "avatar": "<string>"
      },
      ...
    ]
}

Search players

You can search for players using parts of their displayName, displayNameExtra and playerID. As a second parameter you can send a paging object. Or use the default paging object of the PlayerProfile service.
Remember that you can modify the default pagina object to.
See paging for more information about the paging parameter.

var api = new cloudonaut.API(<app ID>);
api.PlayerProfile().SearchProfiles(<search string>, <optional:Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

If the search string is empty it will return all players and limits them using the paging object.

The response object looks like this:

{
    "success":<bool>,
    "playerProfileList": [
      {
        "playerID": "<int>",
        "displayName": "<string>",
        "displayNameExtra": "<string>",
        "avatar": "<string>"
      },
      ...
    ]
}

Score / Leaderboard

The leaderboard and scores service manage a huge list of posted scores to the backend per App.
We have build a verry flexible way on how to get this leaderboard back from the server.
This way you can build daily boards, monthly boards, high scores, lowest score first etc...

Each app can also contain multiple leaderboards and multiple levels.
A leaderboard conntains an ID and a level parameter so that each app can contain multiple leaderboards (Different game modes is a great example for using multiple leaderboard ID's) and multiple levels (The same leanderboard ID is used but for every level you increase the level proprery).

Ranking

You can configure a function and a sort order on how to calculate which score is the best score.
The default function and sort order are MAX and DESC. (Higher is better)

Here are some common use scenarios.

Function Sort Description Extra
MAX DESC Gets the highest score and ranks from high to low If the function is MAX the sort will default to DESC
MIN ASC Gets the lowest score and ranks from low to hight If the function is MIN the sort will default to ASC
AVG DESC Gets the avarage score and ranks from high to low For AVG the default sort is DESC

There are 2 more functions that can be used:

Function Description Use case example
COUNT Counts the number of scores the player / character has submitted Most effort in the game/app
SUM Sums up the scores of each player / character Most effort combined with high scores.

For each function you can swap the sort order. So if you want the avarage score of each player but sorted lowest first you can do:

Function Sort
AVG ASC

Periodicity

All scores are timestampt in the background. That makes it posible to get scores using time frames.
You can do this by using a start and end date or a Periodicity parameter.

Please not that you can't combine start, end date with the periodicity parameter. The periodicity parameter will win over the start, end date.

When using this time frame the function and sort will be applied to all scores in this time range. This way you can create daily boards for example.

The start and end date should be in YYYY-mm-dd hh:mm:ss (24 hour) format.
Example:
2021-01-05 13:30:00
For the fifth of januari 2021 at half past one in the afternoon. (This is always server time).

To make things easier for more common use cases you can use the periodicity parameter.

Value Description
DAILY All the scores of past 24 hours
WEEKLY All the scores of the past 7 days
MONTHLY All the scores of the past month

The API service for score and leaderboards is called Leaderboard().

api.Leaderboard();

The leaderboard object

The leaderboard service has a default leaderboard object to store the leaderboard settings as leaderboardID, level, startDate, endDate, periodicity, function and sort.
Most of the time the default settings will be good enough.

var api = new cloudonaut.API(<app ID>);
  // get a leaderboard service
var leaderboard = api.Leaderboard();
leaderboard.settings.leaderboardID; // Default 0
leaderboard.settings.level; // Default 0
leaderboard.settings.startDate; // Default ""
leaderboard.settings.endDate; // Default ""
leaderboard.settings.periodicity; // Default ""
leaderboard.settings.function; // Default "MAX"
leaderboard.settings.sort; // Default "". If kept empty it will default to DESC
// except when you use the function MIN. Then it will be ASC

So without any changes you have a all time leaderboard that keeps scores ranked by highest score is better.

To change settings you can do the following:

var api = new cloudonaut.API(<app ID>);
  // get a leaderboard service
var leaderboard = api.Leaderboard();
leaderboard.settings.leaderboardID = 1; // sets the leaderboard ID to 1
leaderboard.settings.level = 8; // Sets the level to 8
leaderboard.settings.startDate = "2021-01-05 00:00:00"; // sets a start date
leaderboard.settings.endDate = "2021-01-10 00:00:00"; // sets an end date
leaderboard.settings.periodicity = "MONTHLY"; // Overwrites start date to today - 1 month and the end day to today.
leaderboard.settings.function = "AVG"; // Sets the leaderboard to Avarage scores
leaderboard.settings.sort = "ASC"; // force the leaderboard into ascending ranks.

List Scores

To get a list of all scores based on the settings you can call this function.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.ListScores(<optional:Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

See paging for more information about the paging parameter.

The response object looks like this:

{
    "success":<bool>,
    "limit": <int>,
    "leaderboard": [
        {
            "playerID": "<int>",
            "displayName": "<string>",
            "displayNameExtra": "<string>",
            "avatar": "<string>",
            "providerUID": "<string>",
            "provider": "<int>",
            "characterID": "<int>",
            "characterName": "<string>",
            "characterNameExtra": "<string>",
            "characterAvatar": "<string>",
            "score": "<double>",
            "rank": "<int>",
            "rowNumber": "<int>"
        },
      ...
    ]
}

The difference between rank and rowNumber is that when 2 users have the same score. They share the same rank but have a different rowNumber.
The providerUID will be empty for anonymous users.

List Scores Arround Me

If the player is not a top listed player then you probably want to list scores arround the the currently logged-in player (and his selected character).

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.ListScoresAroundMe(<optional:Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

See paging for more information about the paging parameter.

The response object looks like this:

{
    "success":<bool>,
    "limit": <int>,
    "leaderboard": [
        {
            "playerID": "<int>",
            "displayName": "<string>",
            "displayNameExtra": "<string>",
            "avatar": "<string>",
            "providerUID": "<string>",
            "provider": "<int>",
            "characterID": "<int>",
            "characterName": "<string>",
            "characterNameExtra": "<string>",
            "characterAvatar": "<string>",
            "score": "<double>",
            "rank": "<int>",
            "rowNumber": "<int>"
        },
      ...
    ]
}

The difference between rank and rowNumber is that when 2 users have the same score. They share the same rank but have a different rowNumber.
The providerUID will be empty for anonymous users.

List Scores Arround Player

You can also get a leaderboard arround a specific player / character.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.ListScoresAroundPlayer(<playerID>, <Optional: characterID default to 0>, <optional:Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

See paging for more information about the paging parameter.

The response object looks like this:

{
    "success":<bool>,
    "limit": <int>,
    "leaderboard": [
        {
            "playerID": "<int>",
            "displayName": "<string>",
            "displayNameExtra": "<string>",
            "avatar": "<string>",
            "providerUID": "<string>",
            "provider": "<int>",
            "characterID": "<int>",
            "characterName": "<string>",
            "characterNameExtra": "<string>",
            "characterAvatar": "<string>",
            "score": "<double>",
            "rank": "<int>",
            "rowNumber": "<int>"
        },
      ...
    ]
}

The difference between rank and rowNumber is that when 2 users have the same score. They share the same rank but have a different rowNumber.
The providerUID will be empty for anonymous users.

Count Scores

Gets the number of scores in the leaderboard so you can calculate how many pages there are in the recordset.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.CountScores().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "listCount":<int>
}

List Scores Of Friends

To get a friends leaderboard. Only friends and the player /character of the logged in player are shown.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.ListScoresOfFriends(<optional:Paging>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

See paging for more information about the paging parameter.

The response object looks like this:

{
    "success":<bool>,
    "limit": <int>,
    "leaderboard": [
        {
            "playerID": "<int>",
            "displayName": "<string>",
            "displayNameExtra": "<string>",
            "avatar": "<string>",
            "providerUID": "<string>",
            "provider": "<int>",
            "characterID": "<int>",
            "characterName": "<string>",
            "characterNameExtra": "<string>",
            "characterAvatar": "<string>",
            "score": "<double>",
            "rank": "<int>",
            "rowNumber": "<int>"
        },
      ...
    ]
}

The difference between rank and rowNumber is that when 2 users have the same score. They share the same rank but have a different rowNumber.
The providerUID will be empty for anonymous users.

Count Scores Of Friends

Gets the number of scores in the friends leaderboard so you can calculate how many pages there are in the recordset.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.CountScoresOfFriends().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "listCount":<int>
}

Get Score

Gets the current highscore / rank of the logged-in player / character.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.GetScore().then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "score": "<double>",
    "rank": "<int>"
}

Get Score Of Player

Gets the current highscore / rank of a specific player / character.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.GetScoreOfPlayer(<playerID>, <Optional: characterID default to 0>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>,
    "score": "<double>",
    "rank": "<int>"
}

Add Score

Sends a score of the currently logged in player / character to the specific leaderboard.

var api = new cloudonaut.API(<app ID>);
var leaderboard = api.Leaderboard();
leaderboard.AddScore(<score>).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

The response object looks like this:

{
    "success":<bool>
}