Welcome to XServer!

This guide covers the major aspects about installation of the Mobile, Unity and Web SDKs, the necessary requirements and some tip to get started with your first backend.

Unzip the package you've downloaded ans this is what you'll get:


The whole API (Web, Unity and Mobile SDKs) uses the following third-party libraries:

Requirements

The requirements to install and get XServer API to work are the following:
  • A VPS Server, minimum 2GB RAM, 1 vCPUs, 60GB Disk Storage - Amazon AWS Lightsail with Ubuntu is the best choice in terms of speed, reliability and price.
  • SSL certficate installed an active on your server (optional, but recommended).
  • Sublime Text (recommended), or any other HTML/text editor of your choice.
  • An FTP account confgured in FileZilla, needed to upload/edit files
  • Chrome Web Browser (recommended), and/or Safari or Firefox
For the iOS SDK:
  • The latest official version of Xcode – Beta versions of an IDE usually never work properly, and the code of this SDK has been written using the latest official version of Xcode. You can download it from the Mac App Store. Please avoid Betas.
  • An Apple Mac computer, updated to its latest OS version
  • An Apple Developer Account with an active iOS Development Program – This is needed for you to publish apps on the iTunes App Store.
  • Knowledge of Xcode and Swift programming
  • A real device to test the app - The Simulator may fail during tests, they are not reliable like a real device is
For the Android SDK:
  • The latest official version of Android Studio – Beta versions of an IDE usually never work properly, and the code of this SDK has been written using the latest official version of Android Studio. Please avoid Betas.
  • An Apple Mac or Windows computer, updated to its latest OS version.
  • A Google Play Developer Account – This is needed for you to publish apps on the Play Store.
  • Knowledge of Android Studio and Java/XML programming.
  • A real device to test the app before submitting it to the Play Store – Emulators may fail during tests, they are not reliable like a real device is
For the Unity SDK:
  • The latest official version of Unity 3D – Beta versions of an IDE usually never work properly, and the code of this SDK has been written using the latest official version of Unity. Please avoid Betas.
  • An Apple Mac or Windows computer, updated to its latest OS version.
  • Knowledge of Unity editor and C# programming.

Installation

Option 1:
With FileZilla (recommended), upload the xserver folder into the root of your server - the /var/www/html/ directory on AWS Lightsail with Ubuntu 18.04).

Option 2:
You may also protect your API by renaming the xserver folder into some random characters - something like as45DfR6y9S, or whatever you want - then upload that folder into the root of your server.

In any case, take note of the name of the API folder in order to propely configure the SDKs.

How to install XServer on Amazon AWS Lightsail

Watch this video to learn how to configure an AWS Lightsail instance and upload the XServerAPI's files in you Ubuntu server:

Configurations


On FileZilla you can right-click on a file and select the View/Edit option. That will open the selected file in your favorite text editor - I recommend you to configure Sublime Text as custom editor in the FileZilla's Settings panel -> File editing option.



• Protect JSON data files from being viewed by Web clients
If you installed XServer in an Ubuntu instance, you must open the apache2.conf file - it's into the /etc/apache2/ directory and you can access it with Filezilla - and add the following lines on the bottom that file:
 <Directory /var/www/html/>
    <Files "*.json">
      Order allow,deny
      Deny from all
    </Files>
 </Directory>
In this way, nobody will ever see any .json file of your database from a browser, not even you, and your data are safe.

• XServer Databse path
Open the _config.php file and edit the Database Path:
 $DATABASE_PATH = "https://mydomain.com/xserver/";
You must change that string into the URL of your server, where you've uploaded the xserver folder into - even if you've renamed it.

Example: Let's pretend your domain name is mydomain.net and you kept the xserver folder's name. You should set the $DATABASE_PATH variable as it follows:
 $DATABASE_PATH = "https://mydomain.com/xserver/";
Instead, if you've renamed the xserver folder into something like as45DfR6y9S:
 $DATABASE_PATH = "https://mydomain.com/as45DfR6y9S/";

• App name
Since XServer is mainly made to build mobile applications, you need to set the name of your app in this variable:
 $APP_NAME = "XServer";

• Admin login credentials
In order to set the username and password credentials to access the XServer admin dashboard, you must set those strings here:
 $ADMIN_USERNAME = "admin";
 $ADMIN_PASSWORD = "admin";

• Admin email address
You may need to provide an email address to users to get in touch with you, so set it in this variable:
 $ADMIN_EMAIL = "myemail@address.com";

• Google Sign In [Web OAuth Key]
In order to sing in with Google on a Login web page, you must provide your own OAuth key.
Create it on your own Google Cloud Platform and set it in this variable:
 $GOOGLE_SIGNIN_KEY = '';

• Apple Sign In and iOS Push Notifications
In order to make your iOS app send and receive Push Notifications and Sign In with Apple, you must perform the following actions:
  • Register your app's Bundle Identifier (the App ID) on your Apple Developer Account -> Certificates, Identifiers & Profiles -> Identifiers section
  • Click the Keys option from the left menu, then the (+) blue button to add a new Key.
  • Type a key name, enable the Apple Push Notifications service (APNs) and Sign In with Apple options in the Register a New Key section.
  • Click the Configure button next to the Sign In with Apple option and select your Bundle Identifier from the Primary App ID dropdown menu. Lastly, click the Save button.
  • Download the AuthKey.p8 file on your computer - pay attention, you'll be able to download it only once, so save it in a safe place.
  • On the Configure key page, click the Continue and then the Save button.
  • Delete the existing AuthKey_2NDC475ZK3.p8 file from the _Push folder and upload your own one inside it.
When you're done, replace the following variables in the _config.php file with your own data:
$AUTH_KEY_FILE = 'AuthKey_ABC123DEF4.p8'; // Your p8 Key file name
$APN_KEY_ID = 'ABC123DEF4';    // Your Apple Push Notification Key ID
$TEAM_ID = 'ZABC345QWE67';   // Your Team ID (see Apple Developer Portal -> Membership)
$BUNDLE_ID = 'com.myname.appname';    // Your iOS App's Bundle Identifier, the one you've set in Xcode
$APN_URL = 'https://api.development.push.apple.com';  // OR: http://api.push.apple.com  [for Production environment]
You can leave the $APN_URL variable as it is, since Push Notifications will still work even if you publish your app on the App Store without setting it into Production environment. It's just your choice.

• Android Push Notifications
If you don't have' a Firebase project on your Firebase Console, create one and enter the Project Overview -> Cloud Messaging section, copy the Server key from the Project credentials box and replace the existing string of this variable with your copied one:
 $FCM_SERVER_KEY = 'AAAALIIuEYQ:APA91bFzOf-yDRyp7Idb1AcweD6DQUVLr5zrbWVnB-uVTy0w6dt0UUXKDXthiHzqm...';
Remember to also download the google-services.json file and replace the one in the app folder of the Android Studio project's folder, that file will set the values of your project to send/receive Push Notifications in your Android app.


• Email Verification
If you want to send an email verification link to new users who sign up for the first time in your apps/website, just set the following variable into true:
 $IS_EMAIL_VERIFICATION = false;
NOTE: If you want to edit the message and other details of the Verification email, open the m-signup.php file from the xserver/_Tables folder, scroll down and check code inside the if ($IS_EMAIL_VERIFICATION) { ... } statement.
Do not change or remove the $APP_NAME and $DATABASE_PATH variables, you may change the message strings and "From" email address.


Using PEAR Mail.php (Ubuntu on AWS Lightsail)
If you open the m-signup.php and forgot-password-php files, you may notice 2 different mail functions.
The uncommented code is the default sendmail function that is supported by many hosting providers, such as GoDaddy.
In case you've hosted this API on an Ubuntu AWS Lightsail VPS server and want to use the PEAR Mail.php function, then comment the sendmail code and uncomment the code below:
 /* Pear Mail.php function
Then add your SMTP host name, email address and password in the following lines:
  host' => 'your_smtp_host',	// <-- YOUR SMTP HOST
 'username' => 'your@email.com', // <-- YOUR EMAIL ADDRESS
 'password' => 'your_password' 	// <-- YOUR PASSWORD
You can get the SMTP host of your email address by checking your email settings on your hosting provider.

In case you want to use a Gmail adress, edit the lines above like this:
  'host' => 'ssl://smtp.gmail.com',
  'port' => '465',
  'auth' => true,
  'username' => 'youremail@gmail.com',
  'password' => 'your_gmail_password' 
IMPORTANT: You must also turn the "Less Secure App" option ON on your Gmail settings here.
Be aware that a Gmail SMTP server sends max 99 emails/day, and the From input gets ignored, so the emails you'll receive will show your gmail address in the form field.



• Utility Functions
The _config.php file contains some utility functions and variables that make the entire system work.
DO NOT EDIT anything below the following comment:
// UTILITY FUNCTIONS AND GLOBAL VARIABLES
Otherwise the API will not work properly.

The XServer Dashboard

The Dashboard is the admin panel where you can see your database data, add/delete columns, edit/delete/add rows and sort objects, as well as send Push Notifications to mobile devices.
Here's how the Dashnoard looks like:


• Understanding Data Tables in XServer
The XServer backend is based on JSON files, they are your Tables which host all data.
In the xserver/_Tables folder of the package you can find 2 files with some demo data in order to get you started: the Users.json and Posts.json files.
You're free to rename the Posts.json file, or add new Tables with the [Add Table] button, but please follow these important directions:
  • You MUST NOT delete or rename the Users.json file.
  • Use the [Add Table] button on the Dashboard to create JSON files in the _Tables folder
  • When you create a Table, the next thing to do is to add its necessary columns, otherwise data cannot be properly saved.
  • Your Tables must at least have 1 row to keep their column names, so if you use the Dashboard to delete rows, XServer will create an empty default row that won't be visible in the Dashboard, but if you manually delete all data in a JSON Table file, you will lose all columns and will have to add them again.
  • You may manually edit a JSON file on your HTML editor, just be careful to keep the correct syntax and data
  • Make a backup of your work frequently, as you may mess something up or lose important data for your database


• Top Navigation Buttons
On the top navigation bar you can find 3 buttons:
  • Tools
  • Refresh
  • Logout
By clicking the [Tools] button you can find all the buttons that allow you to manage the database, such as [Add Table], [Add Column], etc.
The Options buttons are described below.


• Add a Table
You can create a Table by clicking the [Add Table] button and typing the desired name.
IMPORTANT:
  • If you want to manually edit a Table's data, you must open its JSON file on your favorite HTML editor from your server's _Tables folder.
  • If you want to delete a Table, delete its JSON file form your server.
  • If you want to change a Table name, simply rename its JSON files.
  • Spaces and special characters are not allowed while naming a Table, so:
    MyTable
    My Table
    @My Talbe
    $myTable



• Import Tables
You can upload JSON files (as Tables) into your own Database with FileZilla by uoploading those files into the _Tables folder, but you can also use the [Import Tables] button and choose one or more JSON files (just make sure they are compatible with the XServer's syntax for Tables).
Please note that Tables with the same name of the choosen one will be overwitten.



• Add a Column
Click the [Add Column] button and select the Type of data you want to set between the following ones:
String
Number
Array
File
Boolean
GPS
Pointer
Date

Type a name for your column and click the [Add column] button to create it.
You'll see that your new column gets created, along with 3 default other ones, which are:
ID_id
DT_createdAt
DT_updatedAt


IMPORTANT, FOR THE "Users" TABLE!
When you add a column in the empty Users table with the Dashboard, XServer adds a few default columns that are needed for the Web and Mobile SDKs to work properly, as well as for the whole API:
ID_id
DT_createdAt
DT_updatedAt
ST_username
ST_password
ST_email
ST_iosDeviceToken
ST_androidDeviceToken
NU_badge
BL_emailVerified
ST_signInWith

Although the Dashboard doesn't allow you to delete those columns, it's still good to know that you MUST NOT manually delete them from the Users.json file, neither change their names.



• Column Types
There are 9 types of columns for your data, it's important to know their sytax and meaning, so you'll be able to wisely choose them while creating new columns for your database.

  • ID | composed by ID_ prefix and id suffix
    This is the object Identifier of each row of the Table. It cannot be created manually, it gets automatically created by the API and its key is always ID_id. It also cannot be edited, but it can be copied by a double-click on its cell.

  • String | composed by ST_ prefix | the suffix will be the name you assigned to it
    This is a String to host and display text

  • Number | composed by NU_ prefix | the suffix will be the name you assigned to it
    It supports integer and decimal numbers. PLEASE NOTE that decimal numbers must have the dot (.) as separator, not the comma (,).
    Example: 123.45

  • Array | composed by AR_ prefix | the suffix will be the name you assigned to it
    This type is usually used to store arrays of Strings like object IDs or other text.
    It's comma-separated, so be careful while storing an array, put commas where they are needed and do not use the array [""] brackets, just type values separated by commas in the array's input field.
    Example: lorem,ipsum,dolor,sit

  • File | composed by FL_ prefix | the suffix will be the name you assigned to it
    This type hosts the URL of an uploaded file. Physical files get stored inside the uploads folder

  • Boolean | composed by BL_ prefix | the suffix will be the name you assigned to it
    It's either true or false, as per standard JSON syntax.
    Just keep in mind that if you use an input text field instead of a Checkbox or Switch button, the values you must pass are either "0" or "1" (True or False)

  • GPS | composed by GPS_ prefix | the suffix will be the name you assigned to it
    This type is an array of 2 decimal numbers, the latitude and longitude coordinates, usually used for location purposes.
    Like the Number data type, the decimal separator of the coordinates must be a dot (.), and the separator of the 2 coordinates must be a comma (,)
    Example: 12.236548,-45.845987

  • Pointer | composed by PO_ prefix | the suffix will be the name you assigned to it
    This type hosts the ID of an object taken from another Table. For instance, a user's ID from the Users table.
    It's clickable in the Dashboard, it opens the selected object's row

  • Date | composed by DT_ prefix | the suffix will be the name you assigned to it
    The Date format is YYYY-MM-DDTHH:mm:ss and it's a String

It's important to first plan what tables and columns you need to display and edit in your app or website, then create the proper JSON files into the _Tables folder and add the necessary columns in your Dashboard.



• Rename a Table
From the Tools menu, click che [Rename a Table] button, select the Table you want to rename, type a new name for it and hit [Rename Table].

As mentioned before, you're not allowed to use special characters or spaces to rename a Table.



• Delete a Table
Click che [Delete a Table] button, select the Table you want to delete and hit [Delete Table].



• Add a row
When you want to add data to a Table, click the [Add Row] button to add it:



• Edit cells data
Double-click on a cell to view and edit its data.



• Delete rows
You can select one or more rows - or even all rows (with the checkbox in the table's header) - then click the [Delete Row(s)] button to remove them.



• Rename a column
Click the [Rename Column] button, select the column you want to rename, type a new name and hit [Rename Column].



• Delete a column
Click the [Delete a Column] button, select the column you wish to remove, then hit [Delete column].
The column names will be the full ones, which means that you'll see prefix and suffix together. Example: ST_text



• Search filters
You can search for data in your Dashboard by clicking the [Search filters] button, select the column you wish to search data for, then choose the condition of your query and type the desired data.
Lastly, click the [Apply filters] button:



• Sort data
You can order data in your table by ascending or descending by clicking the [Sort Data] button, select a column and the desired sorting condition. Then click [Order data]:



• Order Columns
You can reorder columns in your database by clicking the [ Order Columns] button.
Drag the columns up or down basedon the order you need, then click [ Apply]:



• Send Push Notifications
You can send push notification texts to all those users who have allowed their devices to receive Push Notifications and are using an app based on this backend.
Click the [Send Push Notification] button in the left sidebar, select an audience, and type your message.
Hit the [Send Push Notification] button to send your push:

You can also type a string in the Push Type (optional) field, in case you want to add a specific type for your push message.



• Background Jobs
The custom.js file can host useful Javascript or jQuery functions that will be used as Background Jobs, here's an example:
$(function () {
 //------------------------------------------------
 // BACKGROUND JOB - DELETE ROWS WITH PASSED DATE
 //------------------------------------------------
 setInterval(function() {
   // Search Date in Posts.json
   $.getJSON("Posts.json", function(Posts){
     for (var i=0; i < Posts.length; i++) {
       var obj = Posts[i];
       var aDate = new Date(obj['DT_aDate']);
       var now = new Date();
       if (aDate <= now) {
         var rowID = obj['ID_id']; 
         var tableName = 'Posts';

         // Delete row with passed Date
         $.ajax({
           url:"delete-row.php?tableName=Posts&rowID=" + rowID,
           success:function(data) {
             console.log('row deleted!');
           }
         });
        }// ./ If
	}// ./ For
  });// ./ getJSON
 }, 5 *1000); // execute every 5 seconds
});// ./ on page load

This is just an example to show you how to create a Background Job, a function that runs in a loop every X seconds and performs an action in the database.
In this case, the code checks for dates in the Posts table -> DT_aDate column, and if it finds some dates that are older than the current Date, it deletes the found rows.

You can create your own Jobs by using the jQuery setInterval(function() { ... }, SECONDS *1000); function and perform actions in background (where "SECONDS" must be a number).
Please note that the Dashboard must be opened on your computer, like a server.
In case you must shut it down, a good trick may be to open the Dashboard on your smartphone's browser (Safari, Chrome, etc.) and leave it in background (do not kill the browser app), and of course, keep your smartphone on :)

[Web SDK]

The Web folder contained in the package includes the XServerSDK.php file that hosts the necessary functions to make the API work.
You must upload it in the same location of your website's file.
The SDK code is mainly written in Javascript, with the aid of jQuery, so you would need to use the $('#yourDivID').append() to display data in your webpage.
Check the sample PHP files included in the Web folder. I strongly recommend you to use those PHP files as a starter project template to build your own website, it'll be easier for you to edit code and design.

• Configurations
Open it and paste the path (URL) to your database folder:
 $DATABASE_PATH = 'https://yourdomain.com/xserver/';
Example: If you've left the xserver folder name as it is, and uploaded your website files and the XServerSDK.php file in the root of your server (usually the public_html directory), set the variable as it follows:
 $DATABASE_PATH = 'https://yourdomain.com/xserver/';
Otherwise, if you've renamed the xserver folder, let's say into as45DfR6y9S, set it as follows:
 $DATABASE_PATH = 'https://yourdomain.com/as45DfR6y9S/';
It's always better to host a website in the root of your server - the public_html folder - so the first options should be the right ones for you.

• Current User - XSCurrentUser
You can get the Current logged in User by calling the XSCurrentUser function.
Here's an example (check the header.php and index.php files):
 <script>
 var currentUser = XSCurrentUser();
 if (currentUser != null) {
   console.log(currentUser['ID_id']);
   console.log(currentUser['ST_username']);
   console.log(currentUser['ST_email']);
 // currentuser IS NOT LOGGED IN...
 } else {
   console.log('currentUser is not logged in...');
   // You may redirect the browser to the Login page:
   window.location.replace("login.php");
 }
 </script>

• Sign In - XSSignIn
To sign in as an existing user you have to call the XSSignIn() function and pass the usename and password parameters, usually via HTML inputs with id and name tags set as 'username' and 'password'.
Here's an example (check the user-login.php file):
 <!-- Sing in form -->
 <input id="username" name="username" type="text" placeholder="Username">
 <input id="password" name="password" type="password" placeholder="Password">
 <!-- Sign In Button -->
 <button id="loginButton" onclick="signIn()">Sign In</button>
 <script>
   function signIn() { 
     XSSignIn();
   });
 </script>

• Sign Up - XSSignUp
To sign up as a new user you have to call the XSSignUp() function and pass usename, password and email parameters, usually via HTML inputs with id and name tags set as 'usename', 'password', 'email'.
For additional parameters - for example, fullname, file, etc. - you must add them into the XSSignUp() function in the XServerSDK.php file, like this example:
var p2 = { 'tableName': 'Users' };
p2['ID_id'] = cuArr[0];

// Additional data (optional)
p2['BL_bool'] = '0';
p2['ST_fullname'] = $('#fullName').val();
p2['FL_file'] = 'https://yourserver.com/assets/img/profilepic.png';

XSObject(p2);
As you can see by the code above, the function's parameters needs to get the Users table, the ID of the signed up User and then the additional data (the extra columns you may have added to the Users table).
Here's an example of form and Sign Up execution (check the user-signup.php file):
 <!-- Inputs to pass data -->
 <input id="username" name="username" type="text">
 <input id="password" name="password" type="password">
 <input id="email" name="email" type="email">
 <input id="fullName" name="fullName" type="text">
 
 <!-- Sign up button -->
 <button id="signUpButton"><i class="fas fa-arrow-circle-right"></i></button>
 <script>
   // Sign Up
   $(function () { $("#signUpButton").click(function () {
     if ($('#username').val() == '' 
         || $('#password').val() == ''
         || $('#email').val() == ''
         || $('#fullName').val() == ''
     ){ console.log('Please fill all the fields.');

     } else {
       var params = { 'signInWith': '' };
       params['ST_username'] = $('#username').val();
       params['ST_password'] = $('#password').val();
       params['ST_email'] = $('#email').val();
       params['ST_iosDeviceToken'] = '';
       params['ST_androidDeviceToken'] = '';
       XSSignUp(params);
     }// ./ If
 }); });
 </script>

• Reset Password - XSForgotPassword
The user-login.php page has a button called Forgot Password to reset the password stored after signing up for the first time - or even if it has already been changed.
The XSForgotPassword() function in the XServerSDK.php file fires an alert with a text input where you have to type your valid email address and click the [Reset Password] button:
Here's how you call that function:
 <a class="btn btn-warning" href="#" onclick="XSForgotPassword()">Forgot password</a>
Check the XSForgotPassword() function in the XServerSDK.php file to edit the alert messages as you wish.


• Query Objects - XSQuery
You can query objects by calling the XSQuery function and passing it the tableName, columnName and orderBy parameters. Then, inside a for loop based on the length of a JSON objects' array, set an IF statement to filter your query by the desired keys (columns) and values.
Here's an example - check the index.php file:
 <script>
 function queryObjects() {
   var objects = XSQuery(
     'tableName=' + 'Posts'  // Set the Table name
     + '&columnName=' + 'DT_createdAt'  // Get the createdAt Date column
     + '&orderBy=' + 'descending'  // OR 'ascending' 
   );
 // array of objects
 var objectsArray = [];
 for (var i = 0; i < objects.length; i++) {
   // JSON Obj
   var obj = objects[i];

   // Query filters
   if(
     obj['ST_category'] == 'Fun'
     || obj['NU_likes'] == 1234
   ){ objectsArray.push(obj); }

   // Finalize array of objects by removing duplicates (if any)
   if (i == objects.length-1) { 
     objectsArray = XSRemoveDuplicatesFromArray(objectsArray);
     showData(objectsArray);
   } //./ If
 } // ./ For
}

// Show Data
function showData(objectsArray) {
  for(var i = 0; i < objectsArray.length; i++){
    // JSON object
    var obj = objectsArray[i];

    console.log(obj['ID_id']);
    console.log(obj['ST_text']);
    ...
  }
}
 </script>
As you may notice at the end of the FOR loop, we check when the loop ends and call a very important function called XSRemoveDuplicatesFromArray. That's because the IF statements may find the same object(s) more than once, so we must call that function to get the right data out of out query.


• Refresh Object Data - XSRefreshObjectData
In order to get updated data of an object, call the XSRefreshObjectData function and pass the tableName and the object ID parameters.
Here's an example:
 var refreshedObject = XSRefreshObjectData("Users", "as34FiPrT");
 console.log(refreshedObject['ST_username']);
 ...


• Get Pointer - XSpointer
You can get the object's data of a Pointer object by calling the XSGetPointer() function and passing it the columnName and tableName parameters.
Here's an example - check the index.php file:
  var userPointer = XSGetPointer(obj['PO_userPointer_Users'], 'Users');
Then, you can get the Pointer's data as a JSON object:
  console.log(userPointer['ST_username']);
  console.log(userPointer['ST_email']);
  ...

• Add/Edit an Object - XSObject
In order to save/update an Object, you need to call the XSObject() function and pass it the necessary parameters, usually via HTML inputs with id and name tags set as the column names that need to be saved.
Here's an example - check the obj-details.php and add-object.php files:
 <!-- Text -->
 <textarea type="text" id="ST_text" name="ST_text" rows="2" ></textarea>
 <!-- Likes -->
 <input type="number" step="any" id="NU_likes" name="NU_likes" value="0">
 <!-- GPS coordinates -->
 <input type="number" step="any" id="latitude" name="latitude" >
 <input type="number" step="any" id="longitude" name="longitude" >
 ...

 <!-- Save button -->
 <a href="#" id="saveButton" onclick="saveData()">Save Object

 <script>
function saveData() {
  // Prepare data
  var params = {'tableName=':'Posts'};  // <- Mandatory!
  params['ID_id'] = objectID;  // USE THIS TO UPDATE AN OBJECT / REMOVE THIS LINE TO SAVE A NEW OBJECT
  params['ST_text'] = $('#ST_text').val();
  params['NU_likes'] = $('#NU_likes').val();
  params['GPS_coords'] = $('#latitude').val() +','+ $('#longitude').val();
  params['PO_userPointer_Users'] = currentUser['ID_id'];

  // Save
  var result = XSObject(params);
  if (result.includes('ID_id')) {
    console.log('Object updated: ' + result);
  }
});
</script>

• Delete an Object - XSDelete
In order to delete an Object you need to call the XSDelete() function and pass the tableName and id parameters.
Here's an example - check the obj-details.php file:
 <!-- Delete Object button -->
 <a href="#" id="deleteButton" class="btn btn-danger btn-block">Delete Object</a>

 <script>
  // Get object's ID
  objectID = obj['ID_id'];

  // Delete object [XSDelete]
  $("#deleteButton").click(function () {
    var params = 
      'tableName=' + 'Posts' +
      '&id=' + objectID;
    var result = XSDelete(params);
    if (result == 'deleted') {
      console.log('Object successfully deleted!');
    }
  });
 </script>

• Utility functions
The XServerSDK.php file contains a few useful functions like:
  • XSRemoveDuplicatesFromArray()
  • uploadFile()
  • roundBigNumber()
  • Custom alerts
Do not edit those functions, otherwise the API won't work properly.

• Conclusion
Check the files included in the Web folder to learn how to use XServer REST API, and also use those files as a starter project to build your own website.


[iOS SDK]

The iOS folder contained in the package includes a demo XCode project written in Swift language, for you to get started with the XServer REST API.
That Xcode project contains the XServerSDK.swift file that hosts all the necessary functions for the XServer backend, as well as the SwiftyJSON.swift file to handle JSON data.
I recommend you to use the XServer project as your starter template to build your own application, you can easily rename the Xcode project and edit it as you wish, from the Swift code to the Storyboard design.
Just make sure to keep a copy of the original XServer.xcodeproj and its relative XServer folder somewhere in your computer.



• Configurations
Open the XServerSDK.swift file in Xcode and start by setting your app name in this variable:
 let APP_NAME = "XServer"
As you've done for the API, you must set the path to where you've uploaded the xserver folder in your server:
 let DATABASE_PATH = "https://xserver.app/__apps/xserver/"
So, replace https://xserver.app/__apps/ with your own server's URL - let's say https://mydomain.com/ - and, in case you have renamed the xserver folder, set the name you gave to it - let's say as45DfR6y9S.

Final result example:
 let DATABASE_PATH = "https://mydomain.com/xserver/"
OR:
 let DATABASE_PATH = "https://mydomain.com/as45DfR6y9S/"


Then you must replace the Google Sign In client key of the following variable with the one you created in your Google Cloud Platform:
 let GOOGLE_SIGN_IN_CLIENT_ID = "191162618244-qmjf889os6jffa53d53el3dsk87..."
In order to obtain your own iOS OAuth Google Sign In key, please refer to the Official Google Documentation, you can find the code to execute in the Terminal


• Data format
The objects data of the iOS app are in JSON format and can be retrieved as follows:
 Object Name["Column name"].Data Type
Let's make a practical example: you have launched a query to get data form the Posts table and need to get the text of an object.
 myPostObject["ST_text"].string!
The code above will print the text string of your JSON object -> "ST_text" column.

The JSON data types you can get are the following:
 String
 Integer
 Double
 Array
 Boolean
Here are some examples about how to get data values:
 myObj["ST_string"].string!
 myObj["NU_number"].int! 
 myObj["NU_number"].double! 
 myObj["AR_array"].array! 
 myObj["BL_bool"].bool! 



• Current User - XSCurrentUser
You can get the Current User data by calling the XSCurrentUser() function.
Here's an example (check the Home.swift file):
 XSCurrentUser { (currentUser) in
 if currentUser != nil  {
   // User is logged in
   print(currentUser!["ST_username"].string!)
 } else {
   // User is logged out -> You may open a Login screen
}

• Sign In - XSSignIn
The Sign In function can be called in a Login screen with a couple of TextFields: username and password.
Here's an example (check the Login.swift file):
 XSSignIn(username: usernameTxt.text!, password: passwordTxt.text!) { (succ, e) in
  if e == nil {
    print("Signed in!")
    // Go to the Home screen...
    
  // Wrong username/password
  } else { print(e!) }
}// ./ XSSignIn

• Sign Up - XSSignUp
The Sign Up function can be called in a SignUp screen with 4 TextFields: username, password, email and fullname (this last one is optional, but we'll keep it for this example).
Here's an example (check the SignUp.swift file):
 XSSignUp(username: self.usernameTxt.text!, password: self.passwordTxt.text!, email: self.emailTxt.text!, signInWith: "") { (userID, e) in
  if e == nil {
    var params = ["tableName": "Users"]
    params["ID_id"] = userID!

    // Additional data (optional)
    params["ST_fullname"] = self.fullnameTxt.text!

    self.XSObject(params) { (succ, e) in
      if e == nil {
        print("Signed up!")
        // Do something...

      // error
      } else { print(e!)
    }}// ./ XSObject

   // error
   } else { print(e!)
 }}// ./ XSSignUp()
As you may notice from the code above, it calls 2 functions, the XSSignUp one to store the default User's data, such as username, password and email. Then it calls the XSObject function to update the just created User with additional data - in this case, it's the fullname string, but you may need to add other data, as the demo Xcode Project actually does.

So, in case you have additional data to store in the Users table while signing up, you must add them as parameteres inside the XSSignUp function, as shown above.
If you also open the Intro.swift file, where you can sign in with Google and Apple, you'll see that the code calls the XSObject function with additional parameters in both the appleAuthLogin() and googleAuthLogin() functions.
So, remember to add the same additional parameters you used in the Sign Up screen in those functions as well - unless, of course, you'll remove Google and Apple Sign In functions :)

• Reset Password - XSResetPassword
Users have the ability to also request the app to reset their password, in case they forgot it (or just need to change it).
Here's an example (check the Login.swift file):
 XSResetPassword(email: "myemail@address.com") { (result, e) in
 if e == nil { 
   print(result!)
 } else { 
   print(e!) 
 }
The result string you'll get will be "Thanks, an email with a link to reset your password has been sent. Check your Inbox in a little while.".
This is because the forgot-password.php file of the xserver API folder returns that string in case of success.
If you want to change such message, just edit it in the forgot-password.php file.


• Logout - XSLogout
Users can logout from the app by calling the XSLogout function.
Here's an example (check the Account.swift file):
 XSLogout { (succ) in
  if succ! {
    print("Logged out!")
    // Go to the Login screen...
    
  } else { print("Something went wrong. Try again.")
 }}// ./ XSLogout


• Get Pointer Object - XSGetPointer
In order to retrieve data of a Pointer object use the XSGetPointer function and pass the object[columnName].string! and tableName parameters.
Here's an example (check the Home.swift file):
 XSGetPointer(pObj["PO_userPointer_Users"].string!, tableName: "Users") { (userPointer) in
  print(userPointer!["ST_username"].string!)
  print(userPointer!["NU_age"].int!)
  print(userPointer!["AR_followers"].array!)
 }
As you can see by the code above, you got a full JSON object called userPointer form the Users table. You can get its data like you did for any other object and use it as you wish.


• Refresh Object Data - XSRefreshObjectData
In order to get updated data of an object, call the XSRefreshObjectData function and pass the tableName and Object parameters.
Here's an example:
 XSRefreshObjectData(tableName: "Posts", object: postObj) { (postObj, e) in
    if e == nil {
      // Use the 'postObj' as you wish...

    // error
    } else { self.simpleAlert(e!) }
 } // XSRefreshObjectData 


• Delete an Object - XSDelete
In order to delete an object, call the XSDelete function and pass the tableName and object["ID_id"].string! parameters.
Here's an example (check the ObjDetails.swift file):
 XSDelete(tableName: "Posts", id: pObj["ID_id"].string!) { (succ, e) in
  if e == nil {
    print("Object successfully deleted!")
  } else { 
    print(e!)
  }
 }


• Query Objects - XSQuery
In order to query objects you have to call the XSQuery function and pass it the tableName, columnName and orderBy parameters.
Then, inside a FOR loop, based on the length of a JSON objects array, set an IF statement to filter your query by the desired columns and values.
Here's an example (check the Home.swift file):
 XSQuery(tableName: "Posts", columnName: "DT_createdAt", orderBy: "") { (objects, e) in
  if e == nil {
    // For
    for i in 0..< objects!.count {
      let pObj = objects![i]
      
      // [Search for keywords] --------------------------
      let keywords = self.searchText.components(separatedBy: " ")
      if (self.searchText.count != 0) {
        for j in 0..< keywords.count{
          if pObj["ST_text"].string!.lowercased().contains(keywords[j].lowercased())
          { self.objectsArray.append(pObj) }
        }// ./ For • Search
      
      // [No keywords -> Query filters] ---------------------------
      } else if
        pObj["ST_category"].string! == "Fun"
        || pObj["NU_likes"].int! == 789789
        { self.objectsArray.append(pObj) }
        
    // [Finalize array of objects]
    if i == objects!.count-1 { self.objectsArray.XSRemoveDuplicatesFromArray() }
   }// ./ For
   
   
   if self.objectsArray.count != 0 {
     // Show data in a TableView or somewhere else...
   
   } else {
     print("No results!")
   }// ./ If
   
  // error on query
  } else { print(e!) }
            
 }// ./ XSQuery
As you may notice at the end of the FOR loop, the code checks when the loop ends and calls a very important function called XSRemoveDuplicatesFromArray. That's because the IF statements may find the same object(s) more than once, so we must call that function to get the right data out of out query.

• Add/Edit an Object - XSObject
In order to save an Object you need to call the XSObject function and pass it the necessary parameters.
Here's an example (check the ObjDetails.swift and AddObject.swift files):
 var params = ["tableName": "Posts"]  // <- Mandatory
 params["ID_id"] = myObj["ID_id"].string!  // USE THIS TO UPDATE AN OBJECT / REMOVE THIS LINE TO SAVE A NEW OBJECT
 params["ST_text"] = textTxt!.text!
 params["NU_number"] = numberTxt!.text!
 params["FL_file"] = fileURL!
 params["DT_date"] = XSGetStringFromDate(self.selectedDate) // Used to save a Date()
 params["AR_array"] = self.XSGetStringFromArray(likedBy) // Used to save an Array[String]
 params["GPS_coords"] = latitudeTxt.text! + "," + longitudeTxt.text!
 params["PO_userPointer_Users"] = currentUser["ID_id"].string!)

 XSObject(params) { (e, obj) in
   if e == nil {
     print("Object Updated: " + obj!["ID_id"].string!)

   // error
   } else { print(e!)
 }}// ./ XSObject
IMPORTANT:
  1. In order to UPDATE AN OBJECT, add its ID in the parameters array.
    Example:
     params["ID_id"] = myObj["ID_id"].string!
    
  2. In order to save a File, make sure to get its URL with the XSUploadFile function.
    Example:
     XSUploadFile(fileData: imageData!, fileName: "image.jpg") { (fileURL, e) in
      if e == nil {
        print(fileURL!)
    
        var params = ["tableName":"Posts"]
    
        // Add parameter to save the file
        params["FL_file"] = fileURL!
        ...
        
      // error
      } else { print(e!)
     }}// ./ XSUploadFile()
    
  3. In order to save a GPS value (a CLLocation object with latitude and longitude coordinates), you must convert your coordinates into a String with the XSGetStringFromLocation function.
    Example:
     params["GPS_coords"] = XSGetStringFromLocation(myLocation)
    
  4. In order to save a Pointer object, you must get its ID.
    Example:
     params["PO_userPointer_Users"] = currentUser["ID_id"].string!
    
  5. In order to save an Array value, you must convert it into a String with the XSGetStringFromArray function.
    Example:
     var myArray = ["asD4e5Fo9","oIU8fDe23"]
     params["AR_array"] = XSGetStringFromArray(myArray)
    
  6. In order to save a Number, you must convert it into a String.
    Example:
     params["NU_number"] = "\(1234)"
     // OR
     paramas["NU_number"] = "\(45.678)"
    
  7. In order to save a Boolean value, you must convert it into a String.
    Example:
     var myBool = false
     var bool = ""
     if myBool { bool = "1" } else { bool = "0" }  // "0" is True, "1" is False
     params["BL_boolean"] = bool
    
  8. In order to save a Date value, you must convert it into a String with the XSGetStringFromDate function.
    Example:
     var myDate = Date()
     param(columnName: "DT_date", value: XSGetStringFromDate(myDate))
    
  9. In order to save a String value, just pass it as a String.
    Example:
     params["ST_text"] = "Lorem ipsum dolor sit amet quantum estit sum"
    

• Send a Push Notification
You can send Push Notifications through the app to iOS and Android devices by calling the XSSendiOSPush and XSSendAndroidPush functions and passing the message, deviceToken and pushType parameters.
The pushType value can also be empty, like "", that's needed just in case you need to pass an extra parameter to your Push Notification, the Push alert will not show that parameter in its message.
Here's an example (check the ObjDetails.swift file):
 // Send iOS Push notification
 XSSendiOSPush(message: "Hi there, this is a Push!", deviceToken: userPointer!["ST_iosDeviceToken"].string!, pushType: "chat") { (succ, e) in
  if e == nil {
    print("iOS PUSH SENT!")
  }
 }// ./ XSSendiOSPush()
 
 // Send Android Push notification
 XSSendAndroidPush(message: "Hi there, this is a Push!", deviceToken: userPointer!["ST_androidDeviceToken"].string!, pushType: "chat") { (succ, e) in
   if e == nil {
     print("ANDROID PUSH SENT!")
   }
 }// ./ XSSendAndroidPush()
Don't forget to perform the Push Notification configurations in the XServer's _config.php file, as explained in the beginning of this guide.

• Utility functions
The XServerSDK.swift file contains a few utility functions like:
  • getImage(from : String)
  • XSRemoveDuplicatesFromArray()
  • XSUploadFile()
  • Custom alerts and more

• Conclusion
Check the XServer demo project included in the iOS folder to learn how to use XServer REST API, and also use it as a starter project to build your own app.



[Android SDK]

The Android folder contained in the package includes a demo Android Studio project written in Java language, for you to get started with the XServer REST API.
That Android Studio project contains the XServerSDK.java file that hosts all the necessary code for the XServer backend, as well as the _FCMService.java file to handle Push Notifications.
I recommend you to use the XServer project as your starter template to build your own application, you can easily rename the Android Studio project and edit it as you wish, from the Java code to the XML design.
Just make sure to keep a copy of the original XServer project folder somewhere in your computer.

• Configurations
Open the XServer project with Android Studio, then open the XServerSDK.java file and, as you've done for the API, you must set the path to where you've uploaded the xserver folder in your server:
 public static String  DATABASE_PATH = "https://xserver.app/__apps/xserver/";
So, replace https://xserver.app/__apps/ with your own server's URL - let's say https://mydomain.com/ - and, in case you have renamed the xserver folder, set the name you gave to it - let's say as45DfR6y9S.

Final result example:
 public static String  DATABASE_PATH = "https://mydomain.com/xserver/"
OR:
 public static String  DATABASE_PATH = "https://mydomain.com/as45DfR6y9S/"

Then you must create an Android Google Sign In OAuth Key in your Google Cloud Platform, in order for the app to allow you to sing in with your Google account.
In order to obtain your own OAuth Google Sign In key, please refer to the Official Google Documentation, you can find a button to quickly create it

You can also change the app name from the strings.xml file:
 <string name="app_name">XServer</string>


• Data format
The objects data of the Android app are in JSON format and can be retrieved as follows:
 Object Name.key("Column name").Data Type
Let's make a practical example: you have launched a query to get data form the Posts table and need to get the text of an object.
 myObj.key("ST_text").stringValue()
The code above will get the text string of your JSON object -> "ST_text" column.

The JSON data types you can get are the following:
 String
 Integer
 Double
 Array
 Boolean
Here are some examples about how to get data values:
 pObj.key("ST_text").stringValue()
 pObj.key("NU_number").intValue();
 pObj.key("NU_number").doubleValue();
 pObj.key("AR_array").getJSONArray();
 pObj.key("BL_boolean").booleanValue();



• Current User - XSCurrentUser
You can get the Current User data by calling the XSCurrentUser() function.
Here's an example (check the Home.java file):
 XSCurrentUser(this, new XSCurrentUserHandler() { @Override public void done(final JSON currentUser) {
   // currentUse IS LOGGED IN!
   if (currentUser != null) {
     Log.i("xs", currentUser.key("ST_username").stringValue());

   // currentUse IS NOT LOGGED IN...
   } else { startActivity(new Intent(ctx, Intro.class)); }
 }}); // ./ XSCurrentUser


• Sign In - XSSignIn
The Sign In function can be called in a Login screen with a couple of EditText widgets: username and password.
Here's an example (check the Login.java file):
 XSSignIn((Activity)ctx, usernameTxt.getText().toString(), passwordTxt.getText().toString(), new XSSignInHandler() {
  @Override
  public void done(boolean success, String e) {
    if (e == null) {
      Log.i("xs", "Signed in!");
      // Go to the Home screen...

    // error
    } else { Log.i("xs", e); }
 }});// ./ XSSignIn


• Sign Up - XSSignUp
The Sign Up function can be called in a SignUp screen with 4 EditText widgets: username, password, email and fullname (this last one is optional, but we'll keep it for this example).
Here's an example (check the SignUp.java file):
 XSSignUp((Activity) ctx, usernameTxt.getText().toString(), passwordTxt.getText().toString(), emailTxt.getText().toString(), "", new XSSignUpHandler() {
  @Override public void done(String result, String e) {
    if (e == null) {
      RequestParams params = new RequestParams();
      params.put("tableName", "Users"); // <- Mandatory
      params.put("ID_id", result); // <- Mandatory
      // Add additional data
      params.put("ST_fullname", fullnameTxt.getText().toString());
      
      XSObject((Activity)ctx, params, new XSObjectHandler() { @Override public void done(boolean success, String e) {
        if (e == null) {
          Log.i("xs", "Signed up!");
   		  // Go to the Home screen...

   		// error
   	    } else { Log.i("xs", e);
      }}});// ./ XSObject
    
    // error
    } else { Log.i("xs", e); }
 }});// ./ XSSignUp
As you may notice from the code above, it calls 2 functions: the XSSignUp one to store the default User's data, such as username, password and email, then the XSObject function. This updates the new User with additional data - in this case, it's the fullname string, but you may need to add other data, as the demo project actually does.
So, in case you have additional data to store in the Users table while signing up, you must add them as parameteres inside the XSSignUp function, as shown above, keeping in mind the the "tableName" and the "ID_id" parameters must be included.
If you also open the Intro.java file, where you can sign in with Google, you'll see that the code calls the XSObject function with additional parameters in the handleSignInResult() function.
So, remember to add the same parameters you did for the Sign Up screen in those functions as well - unless, of course, you'll remove the Google sing in function :)


• Reset Password - XSResetPassword
Users have the ability to also request the app to reset their password, in case they forgot it (or just need to change it).
Here's an example (check the Login.java file):
 XSResetPassword((Activity)ctx, "myemail@address.com", new ResetPasswordHandler() {
   @Override
   public void done(String result, String error) {
     if (error == null) {
       Log.i("xs", result);
     } else {
       Log.i("xs", error);
     }
 }});// ./ XSResetPassword
The result string you'll get will be "Thanks, an email with a link to reset your password has been sent. Check your Inbox in a little while.".
This is because the forgot-password.php file of the xserver API folder returns that string in case of success.
If you want to change such message, just edit it in the forgot-password.php file.


• Logout - XSLogout
Users can logout from the app by calling the XSLogout function.
Here's an example (check the Account.java file):
 XSLogout(new LogoutHandler() { @Override public void done(boolean success) {
   if (success) {
     Log.i("xs", "Logged out!");
   } else {
     Log.i("xs", Something went wrong. Try again");
   }
 }});


• Get Pointer Object - XSGetPointer
If you've set a column of type Pointer in your Dashboard and you need to retrieve data of its object, use the XSGetPointer function and pass the object.key(columnName).stringValue() and tableName parameters.
Here's an example (check the Home.java file):
 XSGetPointer((Activity) ctx, pObj.key("PO_userPointer_Users").stringValue(), "Users", new XSPointerHandler() {
  @SuppressLint("SetTextI18n")
  @Override
  public void done(final JSON userPointer, final String e) {
    if (e == null) {
      Log.i("xs", userPointer.key("ST_username").stringValue());
      Log.i("xs", userPointer.key("NU_age").intValue());
      Log.i("xs", userPointer.key("AR_followers").getJsonArray());
    // error
    } else { log.i("xs", e);
 }}}); // ./ XSGetPointer
As you can see by the code above, you got a full JSON object called userPointer form the Users table, and can get values like you did for any other object.


• Refresh Object Data - XSRefreshObjectData
In order to get updated data of an object, call the XSRefreshObjectData function and pass the tableName and Object parameters.
Here's an example:
 XSRefreshObjectData((Activity)ctx, "Posts", postObj, new XSRefreshObjectDataHandler() {
  @Override
  public void done(JSON postObj, String error) {
    if (error == null){
      // Use 'postObj' as you wish...

    // error
    } else { hideHUD(); simpleAlert(error, ctx); }
 }}); // XSRefreshObjectData


• Delete an Object - XSDelete
You can delete an object by calling the XSDelete function and passing the tableName and object.key("ID_id").stringValue() parameters.
Here's an example (check the ObjDetails.java file):
 XSDelete((Activity)ctx, "Posts", pObj.key("ID_id").stringValue(), new XSDeleteHandler() {
   @Override
   public void done(boolean success, String e) {
     if (e == null) {
       Log.i("xs", "Object successfully deleted!");

     // error
     } else { Log.i("xs", e);
 }}});// ./ XSDelete


• Query Objects - XSQuery
You can query objects by calling the XSQuery function and passing it the tableName, columnName and orderBy parameters.
Then, inside a FOR loop based on the length of a JSON objects array, set an IF statement to filter your query by the desired columns and values.
Here's an example (check the Home.java file):
 XSQuery((Activity)ctx, "Posts", "DT_createdAt", "descending", new XSQueryHandler() {
    @Override public void done(JSON objects, String error) {
    if (error == null) {

      for (int i = 0; i < objects.count(); i++) {
        JSON pObj = objects.index(i);

        // [Search for keywords] --------------------------
        String[] keywords = searchText.toLowerCase().split(" ");
        if (searchText.length() != 0) {
          for (String keyword : keywords) {
            if (
              pObj.key("ST_text").stringValue().toLowerCase().contains(keyword.toLowerCase())
            ) { objectsArray.add(pObj); }
          }// ./ For • Search

        // [No keywords -> Query filters] ---------------------------
        } else if (
          pObj.key("ST_category").stringValue().matches("Fun")
          || pObj.key("NU_likes").intValue() == 789789
        ){ objectsArray.add(pObj); }

        // [Finalize array of objects]
        if (i == objects.count()-1) { objectsArray = XSRemoveDuplicatesFromArray(objectsArray); }
      }// ./ For


      if (objectsArray.size() != 0) {
        // Show data in a ListView or somewhere else...

      } else {
        Log.i("xs", "No results!");
      }// ./ If

    // error
    } else { Log.i("xs", error); }
 }});// /. XSQuery
As you may notice at the end of the FOR loop, we check when the loop ends and call a very important function called XSRemoveDuplicatesFromArray. That's because the IF statements may find the same object(s) more than once, so we must call that function to get the right data out of out query.

• Add/Edit an Object - XSObject
In order to save a new Object you need to call the XSObject function and pass it the necessary parameters.
Here's an example (check the ObjDetails.java and AddObject.java files):
 // Parameters
 RequestParams params = new RequestParams();
 params.put("tableName", "Posts");
 params.put("ID_id", pObj.key("ID_id").stringValue()); // Used to update an object
 params.put("ST_text", textTxt.getText().toString());
 params.put("NU_number", numberTxt.getText().toString());
 params.put("FL_file", fileURL);
 params.put("DT_date",  XSGetStringFromDate(selectedDate)); // Used to save a Date()
 params.put("AR_array", XSGetStringFromArray(myArray)); // Used to save a ListArray<String>()
 params.put("GPS_coords", latitudeTxt.getText().toString() + "," + longitudeTxt.getText().toString());
 params.put("BL_bool", "1");

 XSObject((Activity)ctx, params, new XSObjectHandler() { @Override public void done(String e, JSON obj) {
   if (e == null) {
     Log.i("xs", "Object updated: " + obj.key("ID_id").stringValue());

   // error
   } else { Log.i("xs", e);
 }}});// ./ XSObject
IMPORTANT:
  1. In order to UPDATE an object, add its ID in the parameters array.
    Example:
     params.put("ID_id", myObj.key("ID_id").stringValue());
    
  2. In order to save a File, make sure to get its URL with the XSUploadFile function.
    Example:
      XSUploadFile(filePath,"image.jpg", (Activity)ctx, new XSFileHandler() {
        @Override public void done(String fileURL, String e) {
          if (fileURL != null) {
            // Prepare data...
            params.put("FL_file", fileURL);
            // ...
    
          // Upload failed
          } else { Log.i("xs", e); }
     }});// ./ XSUploadFile
    
  3. In order to save a GPS value (a Location object with latitude and longitude coordinates), you must convert them into a String wiht the XSGetStringFromLocation function.
    Example:
     params.put("GPS_coords", XSGetStringFromLocation(myLocation));
    
  4. In order to save a Pointer object, you must get its ID.
    Example:
     params.put("PO_userPointer_Users", currentUser.key("ID_id").stringValue());
    
  5. In order to save an Array value, you must convert it into a String with the XSGetStringFromArray function.
    Example:
     List<String> myArray = new ArrayList<>();
     myArray.add("asD4e5Fo9");
     params.put("AR_array", XSGetStringFromArray(myArray));
    
  6. In order to save a Number, you must convert it into a String.
    Example:
     params.put("NU_number", String.valueOf(1234));
     // OR
     params.put("NU_number", String.valueOf(45.678));
    
  7. In order to save a Boolean value, you must convert it into a String and set it either as "0" or "1".
    Example:
     String bool = "1"; // "0" is False, "1" is True
     params.put("BL_bool", bool);
    
  8. In order to save a Date value, you must convert it into a String with the XSGetStringFromDate function.
    Example:
     Date date = new Date();
     params.put("DT_date",  XSGetStringFromDate(date));
    
  9. In order to save a String value, just pass it as a String.
    Example:
     params.put("ST_text", "Lorem ipsum dolor sit amet quantum est sum");
    


• Send a Push Notification
You can send Push Notifications through the app to iOS and Android devices by calling the XSSendiOSPush and XSSendAndroidPush functions and passing the message, deviceToken and pushType parameters.
The pushType value can also be empty, like "", that's needed just in case you need to pass an extra parameter to your Push Notification.
Here's an example (check the ObjDetails.java file):
 // Send Android Push Notification
 XSSendAndroidPush((Activity)ctx, pushMessage, userPointer.key("ST_androidDeviceToken").stringValue(), "chat", new XSAndroidPushHandler() {
   @Override
   public void done(boolean success, String e) {
     if (e == null) {
       Log.i("xs", "ANDROID PUSH SENT!");

     // error
     } else { Log.i("xs", e); }
 }});// ./ XSSendAndroidPush

 // Send iOS Push Notification
 XSSendiOSPush((Activity)ctx, pushMessage, userPointer.key("ST_iosDeviceToken").stringValue(), "chat", new XSiOSPushHandler() {
   @Override
   public void done(boolean success, String e) {
     if (e == null) {
       Log.i("xs", "iOS PUSH SENT");

     // error
     } else { Log.i("xs", e); }
 }});// ./ XSSendiOSPush
Of course you first have to configure both Push Notification settings in the XServer API, as explained in the beginning of this guide.


• Utility functions
The XServerSDK.java file contains a few utility functions like:
  • roundBigNumber();
  • XSRemoveDuplicatesFromArray();
  • XSUploadFile();
  • etc...

• Conclusion
Check out the XServer demo project included in the Android folder to learn how to use XServer REST API, and also use it as a starter project to build your own app.

[Unity SDK]

The Unity folder contained in the package includes a demo Unity 3D project written in C# language, for you to get started with the XServer REST API.
The Unity project contains the XServerSDK folder that hosts all the necessary files for the XServer backend - including the XServerSDK.cs file.
You may use the XServer project as your starter template to build your own application, you can easily rename the project and edit it as you wish, from the C# code to the Scene layout.
Just make sure to keep a copy of the original XServer project folder somewhere in your computer.

• Configurations
Open the XServer project with Unity, then open the XServerSDK.cs file with your favorite editor and, as you've done for the API, you must set the path to where you've uploaded the xserver folder in your server:
 public static String  DATABASE_PATH = "https://xserver.app/__apps/xserver/";
So, replace https://xserver.app/__apps/ with your own server's URL - let's say https://mydomain.com/ - and, in case you have renamed the xserver folder, set the name you gave to it - let's say as45DfR6y9S.

Final result example:
 public static String  DATABASE_PATH = "https://mydomain.com/xserver/"
OR:
 public static String  DATABASE_PATH = "https://mydomain.com/as45DfR6y9S/"


• Data format
The objects data of the Unity project are in JSON format and can be retrieved as follows:
 Object Name["Column name"]
Let's make a practical example: you have launched a query to get data form the Posts table and need to get the text of an object.
 myObj["ST_text"]
The code above will get the text string of your JSON object -> "ST_text" column.

The JSON data types you can get are the following:
 String
 Integer
 Double
 Array
 Boolean



• Current User - XSCurrentUser
You can get the Current User data by calling the XSCurrentUser() function.
Here's an example (check the Home.cs file):
 // Get Current User
 JSONNode currentUser = XServerSDK.XSCurrentUser();
 if(currentUser == null) { Debug.Log("Current User is logged out...");
 } else { Debug.Log(currentUser["ST_username"]); }


• Sign In - XSSignIn
The Sign In function can be called in a Login scene, for instance, with a couple of InputField components: usernameField and passwordField.
Here's an example (check the SignInScreen.cs file):
 if (usernameField.text == "" || passwordField.text == ""){
 XServerSDK.simpleAlert("Please type a username and a password.");
 } else {
   var result = XServerSDK.XSSignIn(usernameField.text, passwordField.text);
   if(result) { SceneManager.LoadScene("MainScene"); }
 }


• Sign Up - XSSignUp
The Sign Up function can be called in a SignUp scene with 4 InputField components: usernameField, passwordField, emailField and fullnameField (this last one is optional, but we'll keep it for this example).
Here's an example (check the SignUpScreen.cs file):
 if (usernameField.text == "" || passwordField.text == "" || emailField.text == "" || fullnameField.text == ""){
 XServerSDK.simpleAlert("Please insert username, password, email and full name.");
 } else {
   var signUpResult = XServerSDK.XSSignUp("unityUser", "qqq", "unity@mail.com", "");
   // Additional user's data
   List<String> parameters = new List<String>();
   parameters.Add(XServerSDK.param("tableName", "Users"));
   parameters.Add(XServerSDK.param("ID_id", signUpResult));
   parameters.Add(XServerSDK.param("ST_fullname", "Unity Gamer"));
   parameters.Add(XServerSDK.param("BL_bool", "0")); 
   parameters.Add(XServerSDK.param("FL_aFile", "0"));

   var result = XServerSDK.XSObject(parameters);
   if (result.ToString().Contains("ID_id")){
     Debug.Log("NEW USER SIGNED UP: " + result.ToString());
     SceneManager.LoadScene("Home");
   }
 }
As you may notice from the code above, it calls 2 functions: the XSSignUp one to store the default User's data, such as username, password and email, then the XSObject function. This updates the new User with additional data - as the demo project actually does.
So, in case you have additional data to store in the Users table while signing up, you must add them as parameteres inside the XSSignUp function, as shown above, keeping in mind the the "tableName" and the "ID_id" parameters must be included.


• Reset Password - XSResetPassword
Users have the ability to also request the app to reset their password, in case they forgot it (or just need to change it).
Here's an example (check the SignInScreen.cs file):
 var result = XServerSDK.XSResetPassword("my@email.com");
 if(result != null){ XServerSDK.simpleAlert(result); }
The result string you'll get will be "Thanks, an email with a link to reset your password has been sent. Check your Inbox in a little while.".
This is because the forgot-password.php file of the xserver API folder returns that string in case of success.
If you want to change such message, just edit it in the forgot-password.php file.


• Logout - XSLogout
Users can logout from the app by calling the XSLogout function.
Here's an example (check the Home.cs file):
 if (EditorUtility.DisplayDialog(XServerSDK.GAME_NAME, "Are you sure you want to logout?", "Logout", "Cancel")){
  // Logout
  if(XServerSDK.XSLogout()) { Debug.Log("Logged out!"); }  	
 }


• Get Pointer Object - XSGetPointer
If you've set a column of type Pointer in your Dashboard and you need to retrieve data of its object, use the XSGetPointer function and pass the object[columnName] and tableName parameters.
Here's an example (check the Home.cs file):
 var userPointer = XServerSDK.XSGetPointer("Users", obj["PO_userPointer_Users"]);
 Debug.Log("USERNAME: " + userPointer["ST_username"]);
 Debug.Log("FULLNAME: " + userPointer["ST_fullname"]);
As you can see by the code above, you got a full JSON object called userPointer form the Users table, and can get values like you did for any other object.


• Refresh Object Data - XSRefreshObjectData
In order to get updated data of an object, call the XSRefreshObjectData function and pass the tableName and Object parameters.
Here's an example (check the Home.cs file):
 var refreshedObj = XServerSDK.XSRefreshObjectData("Posts", myObject);
 Debug.Log("refreshed Object: " + refreshedObj.ToString());


• Delete an Object - XSDelete
You can delete an object by calling the XSDelete function and passing the tableName and object["ID_id"] parameters.
Here's an example (check the Home.cs file):
 var result = XServerSDK.XSDelete("Posts", "Abc123Def");
 if(result) { Debug.Log("Object deleted!"); }


• Query Objects - XSQuery
You can query objects by calling the XSQuery function and passing it the tableName, columnName and orderBy parameters.
Then, inside a FOR loop based on the length of a JSON objects array, set an IF statement to filter your query by the desired columns and values.
Here's an example (check the Home.cs file):
 List<JSONNode> objectsArray = new List<JSONNode>();
 var objects = XServerSDK.XSQuery("Posts", "DT_createdAt", "");
 
 for(int i=0; i<objects.Count; i++){
   var obj = objects[i];

   // [Query Filters]
   if (obj["NU_likes"] == 123
     || obj["ST_category"] == "Game"
     || obj["AR_likedBy"].ToString().Contains("item1")
   ){ objectsArray.Add(obj); }
 } //./ for
 
 // Show data
 if (objectsArray.Count != 0){
   for (int i = 0; i < objectsArray.Count; i++){
     var obj = objectsArray[i];

     Debug.Log(obj["ST_text"]);
     Debug.Log(obj["BL_aBool"]);

     var date = XServerSDK.XSGetDateFromString(obj["DT_myDate"]);
     Debug.Log(date.ToString("MMM dd, yyyy")); 
     
     // Get image from URL
     StartCoroutine(XServerSDK.GetImageFromURL(obj["FL_aFile"], myImage));
  } //./ For
 
 // No results
 } else { Debug.Log("No results!"); }


• Add/Edit an Object - XSObject
In order to save a new Object you need to call the XSObject function and pass it the necessary parameters.
Here's an example (check the Home.cs file):
 // Prepare Data
 List parameters = new List();
 parameters.Add(XServerSDK.param("tableName", "Posts"));
 parameters.Add(XServerSDK.param("ST_text", "Text from Unity Game!"));
 parameters.Add(XServerSDK.param("AR_likedBy", XServerSDK.XSGetStringFromArray(myArray))); // Save a List<String>()
 parameters.Add(XServerSDK.param("NU_likes", 12.12.ToString())); // Save a Number
 parameters.Add(XServerSDK.param("GPS_coords", latitude.ToString() + "," + longitude.ToString())); // Save a GPS Location
 parameters.Add(XServerSDK.param("DT_aDate", XServerSDK.XSGetStringFromDate(myDate)));   // Used to save DateTime
 parameters.Add(XServerSDK.param("BL_aBool", "1"));  // "0" -> FALSE | "1" -> TRUE
 parameters.Add(XServerSDK.param("FL_aFile", fileURL));
 // Save
 var result = XServerSDK.XSObject(parameters);
 if (result.ToString().Contains("ID_id")){
  Debug.Log("OBJECT SAVED/UPDATED: " + result.ToString());
 } 
IMPORTANT:
  1. In order to UPDATE an object, add its ID in the parameters array.
    Example:
     parameters.Add(XServerSDK.param("ID_id", myObj["ID_id"]));
    
  2. In order to save a File, make sure to get its URL with the XSUploadFile function.
    Example:
     // Get bytes[] of file
     byte[] bytes = File.ReadAllBytes(Application.dataPath + "/Res/image.jpg");
     // Upload a file
     StartCoroutine(XServerSDK.XSUploadFile(bytes, "image.jpg", fileURL => {
       Debug.Log("UPLOADED FILE URL: " + fileURL);	
     }})); //./ XSUploadFile
    
  3. In order to save a GPS value (a Location object with latitude and longitude coordinates), you must convert the coordinates into a String
    Example:
     parameters.Add(XServerSDK.param("GPS_coords", 12.123456.ToString() + "," + -14.654987.ToString()));
    
  4. In order to save a Pointer object, you must get its ID.
    Example:
     parameters.Add(XServerSDK.param("PO_userPointer_Users", currentUser["ID_id"]));
    
  5. In order to save an Array value, you must convert it into a String with the XSGetStringFromArray function.
    Example:
     List<String> myArray = new ArrayList<>();
     myArray.Add("asD4e5Fo9");
     parameters.Add(XServerSDK.param("AR_array", XServerSDK.XSGetStringFromArray(myArray)));
    
  6. In order to save a Number, you must convert it into a String.
    Example:
     parameters.Add(XServerSDK.param("NU_number", 1234.ToString()));
    
  7. In order to save a Boolean value, you must convert it into a String and set it either as "0" or "1".
    Example:
     String bool = "1"; // "0" is False, "1" is True
     parameters.Add(XServerSDK.param("BL_bool", bool));
    
  8. In order to save a Date value, you must convert it into a String with the XSGetStringFromDate function.
    Example:
     var myDate = System.DateTime.Now;
     parameters.Add(XServerSDK.param("DT_aDate", XServerSDK.XSGetStringFromDate(myDate)));
    
  9. In order to save a String value, just pass it as a String.
    Example:
     parameters.Add(XServerSDK.param("ST_text", "Lorem ipsum dolor sit amet"));
    


• Send a Push Notification
You can send Push Notifications through the game to iOS and Android devices by calling the XSSendiOSPush and XSSendAndroidPush functions and passing the message, deviceToken and pushType parameters.
The pushType value can also be empty, like "", that's needed just in case you need to pass an extra parameter to your Push Notification.
Here's an example (check the Home.cs file):
 var iosPush = XServerSDK.XSSendiOSPush("Push from Unity!", userPointer["ST_ioDeviceToken"], "chat");
 var anPush = XServerSDK.XSSendAndroidPush("Push from Unity!", userPointer["ST_androidDeviceToken"], "chat");
Of course you first have to configure both Push Notification settings in the XServer API, as explained in the beginning of this guide.


• Utility functions
The XServerSDK.cs file contains a few utility functions like:
  • GetImageFromURL();
  • XSGetStringFromArray();
  • XSUploadFile();
  • etc...

• Conclusion
Check out the XServer demo project included in the Unity folder to learn how to use XServer REST API, and also use it as a starter project to build your own game.

Support

FREE SUPPORT: I can offer FREE support for bugs/errors encontered in the original code.
Click HERE to ask for Support.