Welcome

Welcome to Backendless, a powerful API services platform. The platform can be used to build and run mobile and web applications. Backendless consists of built-in, general purpose API services and also supports deployment of custom, developer-defined services and functions. The built-in API services support common backend tasks and operations such as user login and logout, password recovery, data persistence, file upload, etc. Developer-defined services and functions can be used for custom server-side business logic. The diagram below illustrates major components of the Backendless architecture:

backendless-architecture

The sections below describe individual service APIs. It is recommended to go through the Setup section first to configure your environment.

Quick Start Guide

This guide will help you develop a basic mobile application up and running with the Backendless 4 backend.

 

Once the product is installed, there are two URLs to keep in mind:

1. Backendless Console URL - available at http://HOSTNAME:8080, where HOSTNAME is the IP address or the hostname confirmed/entered during  the installation. It is not recommended to use localhost if you plan to run your application in a device emulator.
2. API Endpoint URL - this is the URL where the server accepts and processes the API requests. The API endpoint URL is the same as console URL with /api appended at the end. For example, http://HOSTNAME:8080/api. When Backendless Pro is running, you can confirm that the API endpoint is working, by entering it in a browser. You should see the following (or similar) response:
api-endpoint-response

 

Follow the steps below to build your first app with Backendless:

1. Login to Backendless Console. The username and password are what you entered during the installation process. If you cannot remember the login, click the Register link on the Backendless Console login screen and create a new developer account.
 
2. Select or create an app. If you do not have any applications in your account, you will be prompted to create one.
 
3. Click the Download Project Template button:
download-proj-template.zoom50
 
4. To verify the object in Backendless, return to Backendless Console, and click the Data icon. The TestTable table shows the persisted object:
saved-object.zoom50

Client-side Setup

Backendless requires that all REST operations include application ID and REST API key into the URL where API request is sent to. The general structure of the endpoint URL is:

https://api.backendless.com/<application-id>/<api-key>/<operation-specific-path>

The values for <application-id> and <api-key> are needed so that Backendless can identify the application and ensure that a legitimate client makes the request.

Application ID and API Key

Values for the application-id and api-key headers must be obtained through the Backendless Console:

1. Login to your account and select the application.
2. Click the Manage icon from the vertical icon-menu on the left.
3. The App Settings section is selected by default. The interface contains values for Application ID and API keys for each supported client-side environment.
4. Use the Copy icon to copy the value into the system clipboard.
appsettings-keys.zoom60

Make sure to use the "REST API Key" for the api-key argument.

 

Migration from 3.x to 4.x

Version 4 of Backendless introduces some changes in the client-side API. This section of the developer guide describes the changes which should be made in the client application to migrate it to Backendless version 4.x.

 

The general process of application migration from 3.x to 4.0 is:

1. Create an app in the version 4 of Backendless.
2. Migrate data and files from the 3.x application.
3. Make changes in the API usage in the cloud application (if applicable).

Version Differences

Functional Area

Version 3.x

Version 4.0

Application identification (REST Only)

REST requests must include the application-id and secret-key HTTP headers with the API requests.

Application ID and API key (previously known as secret key) are included into the endpoint URL.

Application initialization API.
This is a mandatory  method call required to initialize a native SDK implementation in a client app. Applies to all SDKs except for REST.

This does not apply to the REST API

This does not apply to the REST API

Data Query.

The API for configuring data query parameters such as sorting, paging and identifying columns of the related objects to return in the response.

This does not apply to the REST API

This does not apply to the REST API

Retrieval of data collections.
This applies to retrieving data objects, geopoints and listing of files.

Native SDKs
All SDK implementations use the BackendlessCollection class to represent a collection of data from the backend. The class provided a paging mechanism enabling retrieval of additional pages of data.

Native SDK and REST

BackendlessCollection is completely eliminated. Instead the backend returns an array of objects (represented as a native collection in the native SDKs). The totalObjects property is replaced with a separate API (see below)

REST
REST operations returned a JSON structure containing an array of objects (paged) as well as the totalObjects property

Object counting.
This is a mechanism used by the server to calculate:

total number of objects in a table, optionally satisfying a search query.
total number of files in a directory listing, optionally matching a pattern.
total number of geopoints in a category, optionally satisfying search query (search in radius, rectangular area and/or search query).

Object counting is coupled with collection retrieval (see the row above). Total number of data objects/files/geopoints is returned to the client through the totalObjects property in the response object (BackendlessCollection for native SDKs)

Since BackendlessCollection is removed and thus is never returned in the API operations, there is a new API to obtain object/file/geopoint counts.

 

See Migrating Object/File counts API for additional information.

Object relationship management.
This is a mechanism for establishing or breaking down relations between two or more data objects using the API. Once a relationship is established, client application can use data retrieval API to fetch related object(s) for a parent object.

To establish a relationship between a parent object and the related children, client application must save the parent object instance which references the child object(s). Backendless processes the entire object hierarchy, determines which child objects must be saved/updated, persists them and establishes object relationship between the parent and the children. To remove a relationship, parent object instance must be fetched from the server with its related child objects. Client app deleted from the collection any children for which the relationship must be removed and saves back to the server the parent object.

New API is introduced for:

1. establishing a relationship between two or more objects. See the "Set" API.
2. adding related objects to an existing relation. See the "Add" API.
3. removing objects from a relation. See the relation removal API.

 

See Migrating Related Objects API for additional information.

 

Migrating App Data

The process of migrating application data and files from 3.x to 4.0 is:

 

1. Export application from Backendless Cloud. Login to Backendless Console for your Cloud-based backend and select the app. You will see the "Migrate to Backendless 4.0" button:
migrate-button.zoom79
 
2. Click the Migrate to Backendless 4.0 button. You will see the following popup. If you have more than one version in your Backendless Cloud backend, make sure to select the version for which Backendless will prepare a migration archive. The reason a version must be selected is because 4.0 uses the one-version-per-app approach:
migration-popup
 
3. Select a version and click "Create migration archive for 4.0". The first step in replicating your app in 4.0 is creating a "migration archive". Backendless creates two archives, one with data and another with files. The data archive contains the entire backend. It includes, application settings, data table schemas, data objects, users, security roles, all security permissions, business logic, geopoints and geofences.  To initiate creation of the migration archives, click the "Create migration archive for 4.0" button.
 
4. Download archives. Backendless starts preparing the migration archive and will send out an email as soon as the data and file archives are ready. The archives are placed into the /migration-to-4 directory in the File storage of your app. You will see two files with the names matching the following patterns:

<versionName>-data-<timestamp>.zip
<versionName>-files-<timestamp>.zip

 

5. Create an application in the version 4.0 of the Backendless. You can do that by switching to version 4 (see the arrows icon next to the Backendless logo in the developer console) and creating an app there.
6. Upload file archive into 4.0 app. Open Backendless Console for 4.0 and select the app where you will import the data/files. It is recommended to start with a blank/new app to avoid any conflicts during the import. Select the Files section in Backendless console and upload the "files" archive into the root directory. This can be done either by using the Upload File menu or by drag-and-drop of the file into Console. Once the file is uploaded, the console will appear similar to the image below:
uploaded-file-archive.zoom84
 
7. Upload "Data" archive into 4.0 app. Click the Manage icon, then click Import. Click the Browse button located next to "Backendless app" and browse to the "data" archive downloaded from Backendless Cloud. Once the file is selected, click the IMPORT button at the bottom of the screen to initiate the import process:
start-import-v4.zoom56
 
8. Migration is complete. Once Backendless 4.0 finishes processing the data, it will send out an email informing you of the results. You can see the migration progress or its status after it is complete in the migration log available in the Files section of your app:
migration-logv4.zoom90

Related Objects

Establishing object relationship:

The process of establishing a relationship between multiple objects in Backendless 3.x is by saving the parent object which references its child(ren) in the same object hierarchy/tree. Version 4 changes the mechanism by introducing a dedicated operation which establishes a relationship between the objects. The example below stores two objects in Backendless Data service: Contact and Address and then sets up a relationship between them:

Version 3.x:

Save Contact object:

curl \
-H application-id:application-id-value-from-console \
-H secret-key:secret-key-value-from-console  \
-H Content-Type:application/json  \
-X POST  \
-d "{\"name\": \"Joe\", \"age\": 27, \"phone\": \"1-972-5551212\", \"title\": \"Plumber\" }" \
-v https://api.backendless.com/v1/data/Contact

Server response:

{
 "phone": "1-972-5551212",
 "created": 1485820899000,
 "___class": "Contact",
 "name": "Joe",
 "title": "Plumber",
 "ownerId": null,
 "updated": null,
 "age": 27,
 "objectId": "660B5250-BBCF-1A37-FF9E-7887C67ABD00",
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
            \"phone\",\"created\",\"___saved\",\"___class\",\"name\",
            \"title\",\"ownerId\",\"updated\",\"age\",\"objectId\"],
            \"relatedObjects\":{}}"
}

Save Address object:

curl \
-H application-id:application-id-value-from-console \
-H secret-key:secret-key-value-from-console  \
-H Content-Type:application/json  \
-X POST  \
-d "{\"street\": \"123 Main St.\", \"city\": \"Denver\", \"state\": \"Colorado\"}" \
-v https://api.backendless.com/v1/data/Address

Server response:

{
 "city": "Denver",
 "street": "123 Main St.",
 "created": 1485821090000,
 "___class": "Address",
 "state": "Colorado",
 "ownerId": null,
 "updated": null,
 "objectId": "FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00",
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
             \"city\",\"street\",\"created\",\"___saved\",
             \"___class\",\"state\",\"ownerId\",\"updated\",
             \"objectId\"],\"relatedObjects\":{}}"
}

Establish relationship between the two objects:

It is important to note that the request URL includes parent's objectId (Contact). The request body references the child object (Address) by its objectId and the table where it is stored:

curl \
-H application-id:application-id-value-from-console \
-H secret-key:secret-key-value-from-console  \
-H Content-Type:application/json  \
-X PUT  \
-d "{\"addresses\":[{\"objectId\":\"FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00\", \"___class\":\"Address\"}]}" \
-v https://api.backendless.com/v1/data/Contact/660B5250-BBCF-1A37-FF9E-7887C67ABD00

Server response:

{
 "addresses": [
   {
     "___class": "Address",
     "objectId": "FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00",
     "updated": 1485821315000,
     "city": "Denver",
     "created": 1485821090000,
     "street": "123 Main St.",
     "state": "Colorado",
     "ownerId": null,
     "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
                 \"___class\",\"objectId\",\"updated\",\"city\",
                 \"created\",\"street\",\"state\",\"ownerId\"],
                 \"relatedObjects\":{}}"
   }
 ],
 "created": 1485820899000,
 "title": "Plumber",
 "ownerId": null,
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
             \"addresses\",\"phone\",\"created\",\"___savedRelations\",
             \"___class\",\"__relatedschemaaddress\",\"name\",\"title\",
             \"ownerId\",\"updated\",\"objectId\",\"age\"],
             \"relatedObjects\":{\"addresses\":[\"FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00\"]}}",
 "phone": "1-972-5551212",
 "___class": "Contact",
 "name": "Joe",
 "updated": 1485821315000,
 "objectId": "660B5250-BBCF-1A37-FF9E-7887C67ABD00",
 "age": 27
}

 

Version 4.x:

Save Contact object:

curl \
-H Content-Type:application/json  \
-X POST  \
-d "{\"name\": \"Joe\", \"age\": 27, \"phone\": \"1-972-5551212\", \"title\": \"Plumber\" }" \
-v https://api.backendless.com/application-id/rest-api-key/data/Contact

Server response:

{
 "phone": "1-972-5551212",
 "created": 1485820899000,
 "___class": "Contact",
 "name": "Joe",
 "title": "Plumber",
 "ownerId": null,
 "updated": null,
 "age": 27,
 "objectId": "660B5250-BBCF-1A37-FF9E-7887C67ABD00",
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
            \"phone\",\"created\",\"___saved\",\"___class\",\"name\",
            \"title\",\"ownerId\",\"updated\",\"age\",\"objectId\"],
            \"relatedObjects\":{}}"
}

Save Address object:

curl \
-H Content-Type:application/json  \
-X POST  \
-d "{\"street\": \"123 Main St.\", \"city\": \"Denver\", \"state\": \"Colorado\"}" \
-v https://api.backendless.com/application-id/rest-api-key/data/Address

Server response:

{
 "city": "Denver",
 "street": "123 Main St.",
 "created": 1485821090000,
 "___class": "Address",
 "state": "Colorado",
 "ownerId": null,
 "updated": null,
 "objectId": "FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00",
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
             \"city\",\"street\",\"created\",\"___saved\",
             \"___class\",\"state\",\"ownerId\",\"updated\",
             \"objectId\"],\"relatedObjects\":{}}"
}

Establish relationship between the two objects:

It is important to note that the request URL includes parent's objectId (Contact) and the relation column name which also identifies the name of the table (addresses:Address:n). The request body references the child object (Address) by its objectId and the table where it is stored:

curl \
-H Content-Type:application/json  \
-X POST  \
-d "[ \"FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00\" ]" \
-v https://api.backendless.com/application-id/rest-api-key/data/Contact/660B5250-BBCF-1A37-FF9E-7887C67ABD00/addresses:Address:n

Server response is the number of objects set in the relation:

1

 

Deleting/breaking object relationship:

Similar to establishing a relationship between objects, Backendless 3.x relied on the update operation which sends the parent object to the server with an updated list of child objects. Any children removed from the collection on the client-side, are removed on the server as a result of the update call. Version 4 introduces a dedicated method to remove a relationship between objects. The example below removes a relationship between a Contact object and the first related Address object:

Version 3.x:

Retrieve Contact object with the related Address objects. The request fetches Contact object with objectId 660B5250-BBCF-1A37-FF9E-7887C67ABD00.

curl -X GET \
-H application-id:application-id-value-from-console \
-H secret-key:secret-key-value-from-console \
http://api.backendless.com/v1/data/Contact/660B5250-BBCF-1A37-FF9E-7887C67ABD00?loadRelations=addresses

Server response:

{
 "addresses": [
   {
     "city": "Denver",
     "created": 1485821090000,
     "street": "123 Main St.",
     "___class": "Address",
     "state": "Colorado",
     "ownerId": null,
     "updated": 1485821315000,
     "objectId": "FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00"
   }
 ],
 "phone": "1-972-5551212",
 "created": 1485820899000,
 "name": "Joe",
 "___class": "Contact",
 "title": "Plumber",
 "ownerId": null,
 "updated": 1485821315000,
 "objectId": "660B5250-BBCF-1A37-FF9E-7887C67ABD00",
 "age": 27,
 "__updated__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":
                     [\"addresses\",\"phone\",\"created\",\"name\",
                      \"___class\",\"title\",\"ownerId\",\"updated\",
                      \"objectId\",\"age\",\"__meta\"],
                     \"relatedObjects\":{
                     \"addresses\":[\"FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00\"]}}",
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":
            [\"__updated__meta\",\"addresses\",\"phone\",\"created\",
             \"name\",\"___class\",\"title\",\"ownerId\",
             \"updated\",\"objectId\",\"age\"],
            \"relatedObjects\":{\"addresses\":[\"FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00\"]}}"
}

Send updated Contact to the server. The updated contact object must have the same __meta property, but modified "addresses" array:

curl -X PUT \
-H "application-id: 31CB9FED-F34C-5541-FF26-6C2B6719F200" \
-H "secret-key: CDB792A6-99FF-6AB4-FFE7-6D0BCB22AA00" \
-H "Content-Type: application/json" \
-d '{"addresses":[],"phone":"1-972-5551212","created":1485820899000, \
    "name":"Joe","___class":"Contact","title":"Plumber", \
    "ownerId":null,"updated":1485821315000,"objectId":"660B5250-BBCF-1A37-FF9E-7887C67ABD00", \
    "age":27.0,"__meta":"{\"relationRemovalIds\":{},\"selectedProperties\": \
    [\"__updated__meta\",\"addresses\",\"phone\",\"created\",\"name\", \
     \"___class\",\"title\",\"ownerId\",\"updated\",\"objectId\",\"age\"], \
    \"relatedObjects\":{\"addresses\":[\"FAF7E515-3A04-91B9-FF17-CA8BEEC0EB00\"]}}"}' \
http://api.backendless.com/v1/data/Contact/660B5250-BBCF-1A37-FF9E-7887C67ABD00

Server response:

{
 "addresses": [],
 "phone": "1-972-5551212",
 "created": 1485820899000,
 "___class": "Contact",
 "name": "Joe",
 "ownerId": null,
 "title": "Plumber",
 "updated": 1485985183000,
 "objectId": "660B5250-BBCF-1A37-FF9E-7887C67ABD00",
 "age": 27,
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[\"addresses\",\"phone\",\"created\",\"___class\",\"name\",\"ownerId\",\"title\",\"updated\",\"objectId\",\"age\",\"__meta\"],\"relatedObjects\":{}}"
}

 

Version 4.x:Retrieve Contact object with the related Address objects. The request fetches Contact object with objectId 50E31E37-7E1B-99F5-FF65-DFC01AD11A00.

curl -X GET \
http://api.backendless.com/application-id/rest-api-key/data/Contact/50E31E37-7E1B-99F5-FF65-DFC01AD11A00?loadRelations=addresses

Server response:

{
 "addresses": [
   {
     "city": "Denver",
     "street": "123 Main St.",
     "created": 1485987106000,
     "___class": "Address",
     "state": "Colorado",
     "ownerId": null,
     "updated": null,
     "objectId": "9017A169-DC95-422F-FFDB-D659327F7D00"
   }
 ],
 "phone": "1-972-5551212",
 "created": 1485987070000,
 "name": "Joe",
 "___class": "Contact",
 "title": "Plumber",
 "ownerId": null,
 "updated": null,
 "objectId": "50E31E37-7E1B-99F5-FF65-DFC01AD11A00",
 "age": 27,
 "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
             \"__updated__meta\",\"addresses\",\"phone\",\"created\",
             \"name\",\"___class\",\"title\",\"ownerId\",\"updated\",
             \"objectId\",\"age\"],\"relatedObjects\":{\"addresses\":[
             \"9017A169-DC95-422F-FFDB-D659327F7D00\"]}}"
}

Break the relation between Contact and Address:

curl -X DELETE \
-H "Content-Type: application/json" \
-d '[ \"9017A169-DC95-422F-FFDB-D659327F7D00\" ]' \
http://api.backendless.com/application-id/rest-api-key/data/Contact/50E31E37-7E1B-99F5-FF65-DFC01AD11A00/addresses

Server response:

1

 

 

Additional resources:

Object/File Counts

Backendless version 4.x introduces new API to calculate total number of objects and files in a remote collection. In the previous version of Backendless, that number was included as a property of the returned collection. See the examples below:

Version 3.x

Request to get objects and object count. The example retrieves objects for a query age > 21. Object count is returned as a part of the response.

curl -X GET -H 'application-id:application-id-from-console' -H 'secret-key:rest-secret-key-from-console' https://api.backendless.com/v1/data/Contact?where=age%20%3E%2021

Server response. Notice the totalObjects property in the response.

{
 "offset": 0,
 "data": [
   {
     "addresses": [],
     "phone": "1-972-5551212",
     "created": 1485820899000,
     "name": "Joe",
     "___class": "Contact",
     "title": "Plumber",
     "ownerId": null,
     "updated": 1485985183000,
     "objectId": "660B5250-BBCF-1A37-FF9E-7887C67ABD00",
     "age": 27,
     "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[
                 \"addresses\",\"phone\",\"created\",\"name\",\"___class\",
                 \"title\",\"ownerId\",\"updated\",\"objectId\",\"age\"],
                \"relatedObjects\":{}}"
   }
 ],
 "nextPage": null,
 "totalObjects": 1
}

 

Version 4.x

Request to get object count. The example retrieves objects for a query age > 21:

curl https://api.backendless.com/application-id/rest-api-key/data/Contact?where=age%20%3E%2021

Server response - the number of objects matching the query:

3

 

 

Additional resources:

Sync and Async Calls

 

Error Handling

When the backend reports an error, it is returned as a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}


Error Codes

Click here for the complete list of Backendless Error Codes

User Service API

Overview

The Backendless User Service provides the functionality related to the user accounts such as user registrations, logins, password recovery and logouts. The core concept which the User Service relies on is the User entity. The structure of the entity is configurable, that is a developer can decide which properties "describe" a user in the context of the application. Typically, properties describing a user are the ones collected during the user registration process.  The User Service provides the API enabling the following functionality for the applications built on top of Backendless:

 

User Registration - Applications use the Backendless' registration API to let the users register and create accounts for subsequent logins. Application developers can restrict access to the server-side resources for specific user accounts or based on roles.
User Login - the API lets the registered users login to establish their identity within the application.
Password Recovery - Backendless supports a complete workflow allowing users to recover lost or forgotten passwords.
User Logout - the API lets the logged in users terminate their session and disassociate their identity from the application.
Updating User Registration - the API supports the operation of updating user information.

Retrieve User Schema

An application can get a list of the properties associated with the user schema by using the following API:Method:

GET

URL:

/application-id/REST-api-key/users/userclassprops

where:

application-id - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
REST-api-key - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.

Request Body:

None

Response Body:

[
 {
   "name":"emailaddress",
   "required":true|false,
   "type":"STRING"|"STRING_ID"|"DATETIME"|"RELATION"|"INT"|"DOUBLE",
   "relatedTable":tableName,
   "identity":true|false
 },
 {
   "name":"password",
   "required":true|false,
   "type":"STRING"|"STRING_ID"|"DATETIME"|"RELATION"|"INT"|"DOUBLE",
   "relatedTable":tableName,
   "identity":true|false
 }
]

where:

"name" - name of the property/column in the Users table.
"required" -  indicates whether the property is required for user registration.
"type" - property data type.
"defaultValue" - default value of the property. The value is used if it is not provided during the registration API call.
"identity" - indicates whether the property is marked as user identity
"relatedTable" - if type is "RELATION", contains the name of the related table

 

Example:

curl -X GET https://api.backendless.com/application-id/rest-api-key/users/userclassprops

User Registration

The user registration API can be used to create user accounts in the application. A registration request must provide a user object as a collection of key/value properties. The collection must contain all the required properties which must include a property marked as identity as well as the "password" property. The default identity property is "email", however, it can be changed in Backendless Console. Additionally, the "email" property is required if the application is configured to confirm email addresses for the registered users.Method:

POST

URL:

/application-id/REST-api-key/users/register

where:

application-id - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
REST-api-key - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.

Request Headers:

Content-Type:application/json

where:

Content-Type - must be set to application/json. This header is mandatory.

 

Request Body:

{
 "email" : value,
 "password" : value,
 ...
}

Response Body:

{
 "objectId" : value,
 "email" : value,
 "password" : value,
 ...
}

Error Codes:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during User Registration API calls.

Error Code

Description

2002

Invalid application info (application id or api key)

3009

User registration is disabled for the application

3010

User registration has an unknown property and dynamic properties are disabled for this version of the application

3011

Missing "password" property

3012

Required property is missing

3013

Missing value for the identity property

3014

External registration failed with an error.

3021

General user registration error. Details included with the error message.

3033

User with the same identity already exists

3038

Missing application-id or collection of properties for the registering user

3039

Property "id" cannot be used in the registration call

3040

Email address is in the wrong format

3041

A value for a required property is missing

3043

Duplicate properties in the registration request

8000

Property value exceeds the length limit

 

curl
 -H Content-Type:application/json
 -X POST
 -d '{"name":"James Bond", "password":"watchingya", "email":"jbond@007.com"}'
 -v
 https://api.backendless.com/application-id/rest-api-key/users/register

Turning Registration Off

User registration can be disabled for a particular version of the application using the Backendless Console:

1. Login to the console and select the application.
2. Click the Users icon in the vertical icon menu on the left.
3. Click User Registration.

The Registration toggle turns the registration API on or off. When the registration is turned off and a user attempts to register, the system returns error 3009.

registration-togglev4.zoom70

Email Confirmations

Backendless can send out an email requesting new registered users to confirm their email address. This feature can be configured in the Backendless Console:

1. Log into the console and select the application.
2. Click the Users icon in the vertical icon menu on the left.
3. Click User Registration.

email-confirmationv4.zoom70

When email confirmations are turned on (the feature is disabled by default), the "email" user property is required and must contain a value formatted as an email address. To configure the text of the email message, select Email Templates from the Users menu in the console and select the User made registration event.

Login

Registered users can login to establish their identity with the application using the API below. The login operation requires two properties: one marked as user identity and the second is password. Backendless automatically assigns the "AuthenticatedUser" role to all successfully logged in users. The role can be used to differentiate access to various resources (persistent objects, messaging channels, files) between authenticated users and guests.

Method:

POST

URL:

/application-id/REST-api-key/users/login

where:

application-id - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
REST-api-key - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.

Request Headers:

Content-Type:application/json

where:

Content-Type - must be set to application/json. This header is mandatory.

 

Request Body:

{
 "login" : value,
 "password" : value,
}

The "login" key must contain the value for the property marked as identity.

Response Body:

{
 "objectId" : value,
 "user-token": value,
 //all user properties (except for password) in the "prop-name":"prop-value" format
 "prop-name1":value,
 "prop-name2":value,
 "prop-name3":value,
 ...
}

The "objectId" property is a unique identifier assigned by Backendless to the user account. The "user-token" value identifies the user session initiated by the Login operation. Both of these values ("objectId" and "user-token") are required for Updating User Properties.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the Login API call.

Error Code

Description

2002

Version is disabled or provided wrong application info (application id or secret key)

3000

Login has been disabled for the user account.

3001

Missing login settings, possibly invalid application id or version.

3002

User cannot login because Multiple Logins disabled and there is a logged in user for the account.

3003

Invalid login or password.

3006

Either login or password is an empty string value.

3034

User logins are disabled for the version of the application.

3036

Account locked out due to too many failed logins.

3038

One of the required parameters (application id, version, login or password) is null

3044

Multiple login limit for the same user account has been reached.

8000

Property value exceeds the length limit

 

curl
 -H Content-Type:application/json
 -X POST
 -d '{"login":"jbond@007.com", "password":"watchingya"}'
 -v
 https://api.backendless.com/application-id/rest-api-key/users/login

Maintaining User Session:

The "user-token" value returned from the login must be used in the subsequent requests to Backendless in order to maintain user session. The value uniquely identifies both the user and the session on the server and is used to enforce security policy, apply user and roles permissions and track usage analytics. For all requests made after the login, the user-token value must be sent in the HTTP header:

"user-token":value

Validating User Login

The login operation provides a way to persist the user-token on the client side so it can be used when the application is restarted. This helps in streamlining the user experience since the user of the application does not need to login again. However, when the application restarts, it needs to check if the underlying user token, and hence the user session are still valid. This can be accomplished with the API below:Method:

GET

URL:

https://api.backendless.com/<application-id>/<rest-api-key>/users/isvalidusertoken/<userToken>

where:

<application-id> - the ID of your application generated upon its creation. You can find this header in the Manage > App Settings section of the Backendless Console.
<rest-api-key> - the key of your application generated upon its creation. You can find this header in the Manage > App Settings section of the Backendless Console.
<userToken> - user token to validate. The value of the user token is returned by Backendless as a result of the login call.

 

Sample Request:

curl
-X GET
-v https://api.backendless.com/application-id/rest-api-key/users/isvalidusertoken/<userToken>

Return value:

The server returns a boolean value of true if token is valid, false otherwise.

 

Login with Facebook

Backendless integrates with Facebook to support user authentication and login into a Backendless application with a Facebook account. Using the integration application developer can provide a way to skip the application registration step and allow users to use their Facebook identity to register with and experience the application.

 

In order to integrate Facebook login with Backendless, client application must use the Facebook SDK to authenticate the user and then makes a Backendless API call to link the Facebook identity to a BackendlessUser instance.

 

Property Mapping

Backendless User objects may have their own set of user properties. As a result, when a user logs in using their Facebook account, their Facebook Graph API user fields are mapped to the Backendless user properties via "property mapping". There may be multiple mapping, each must reference  a Facebook user field and a name of a Backendless property. Once a user is authenticated, Backendless obtains the field values from the Facebook user graph object and populates the mapped properties in the BackendlessUser object. For the very first login, Backendless also creates the user in its internal system.

Backendless Configuration

A Backendless application (the server side) must be configured with Facebook's application App ID and secret key. See the "Social Settings" chapter of the user guide (the Manage section) for detailed instructions for configuring Backendless with Facebook.

Integration API

The API provides a way to "exchange" Facebook access token for Backendless user object which represents the corresponding Facebook user. Before using the API, application must perform login to Facebook using its SDK. The integration process consists of the following steps:

Configure Backendless backend with the Facebook App ID/API Key.

Method

POST

URL

https://api.backendless.com/<application-id>/<REST-api-key>/users/social/facebook/sdk/login

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.

Request Body

{
 "accessToken" : value,
 "fieldsMapping" :
  {
     "first_name" : "FirstName",
     "last_name" : "LastName"
  }
}

where:

accessToken - Access token received from the Facebook SDK authentication request. This is a required value.
fieldsMapping - an optional mapping between the Facebook fields and Backendless user properties. Keys must be the names of the Facebook fields, values - the names of the Backendless properties. The Facebook keys correspond to the Facebook Graph API keys. Social properties will be copied to the Backendless user properties and should be updated manually in case of their change.

Response Body

a JSON representation of a BackendlessUser object.

Example:

Login request with field mappings:

curl \
-H 'Content-Type: application/json' \
-X POST \
-d'{"accessToken" : "CAANVVCKZA1Y0BAA4Z....", "fieldsMapping":{"first_name":"First", "last_name":"Last", "email":"email", "name":"name"}}' \
-v https://api.backendless.com/application-id/REST-api-key/users/social/facebook/sdk/login

Login response:

{"lastLogin":1454524395923,"created":1454524396000,"ownerId":null,"__meta":"{\"relationRemovalIds\":{},
\"selectedProperties\":[\"__updated__meta\",\"Last\",\"created\",\"name\",\"___class\",\"First\",
\"ownerId\",\"updated\",\"email\",\"objectId\",\"__meta\"],\"relatedObjects\":{}}","user-registered":
true,"Last":"Bond","name":"James Bond","___class":"Users","First":"Bond","user-token":
"E6D5DD4F-4F0D-4D99-FF3D-CCB8DFFB3400","updated":null,"email":"james@mi6.gov.uk"
"objectId":"3CBA1744-0487-320F-FF4D-E69B3F6D8500"}

 

Login with Twitter

Twitter Login

To enable Twitter account log in to your Backendless application:

1. Create your application at https://apps.twitter.com/.
2. In the application's Settings tab, set the Website and Callback URL to https://api.backendless.com
3. From the Keys and Access Tokens tab, copy the Consumer Key and the Consumer Secret values.
4. Click the Permissions tab and select the Request email addresses from users checkbox. Click Update Settings.
5. Log in to your account in the Backendless Console, select your app and click Manage.
6. Scroll down to the Social Settings section and insert the values copied on step 4 into the Twitter Consumer key and Twitter Consumer secret fields.

Add the fields mapping with Twitter to allow the users to log in to your application with their Twitter account:

 

Method

POST

URI

https://api.backendless.com/<application-id>/<REST-api-key>/users/social/oauth/twitter/request_url

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.

Sample Request Body

{
 "fieldsMapping" : {
     "userId" : "UserID",
     "screenName" : "ScreenName"
  },
 "redirect" : true
}

where:

fieldsMapping - a mapping between the Facebook fields and Backendless user properties. Keys must be the names of the Twitter fields, values - the names of the Backendless properties. Social properties will be copied to the Backendless user properties and should be updated manually in case of their change.
redirect - if set to true, the authorization URL will return the '303 See other' response code.

Response Body

HTTP Response: 200 : response contains BackendlessUser object (with all props, except for password).
HTTP Response other than 200 in case of a social authorization, registration or a login error

Example:

curl
-H Content-Type:application/json
-X POST
-d'{"fieldsMapping":{"userId":"First", "screenName":"Last"}, "redirect":true}'
-v https://api.backendless.com/application-id/REST-api-key/users/social/oauth/twitter/request_url

 

User Properties

When a user registers with an application, he provides information which establishes user's identity. For one application these properties may include name, phone number and email address, for another it could be user id, age and gender. Backendless User Service allows each application to have a custom set of properties associated with the user entity.

Retrieving properties with the API

URL:

/<application-id>/<REST-api-key>/users/<user_objectId>?props=propname1,propname2

where:

application-id - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
REST-api-key - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<user_objectId> - objectId of the user object for which to load the values of the specified properties
propname1, propname2 - names of the properties for which  to load the corresponding values.

 

Request Body:

None

Response Body:

{
 "propName1" : value,
 "propName2": value,
}

 

Update User Object

User property values of the logged in users can be updated with an API operation described below. This operation is useful if an application needs to provide to the users the functionality for updating user profiles and registration properties. A user must be logged in in order to update his registration properties.

Method:

PUT

URL:

/<application-id>/<REST-api-key>/users/<user-id>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<user-id> - a value of the "id" property received in the response for the Login operation.

Request Headers:

Content-Type:application/json
user-token:value-of-the-user-token-header-from-login

where

Content-Type - must be set to application/json. This header is mandatory.
user-token - a value returned by Backendless in the response for the preceding Login operation. If user-token is set in this request, the currently logged in user will be assigned to the ownerId property of the user object which is being updated. This is done to facilitate the user object retrieval according to "Owner Policy." This header is optional.

Request Body:

{
 "email" : value,
 "password" : value,
 ...
}

Response Body:

{
 "email" : value,
 "password" : value,
 ...
}

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the Update User Properties API call.

Error Code

Description

2002

Version is disabled or provided wrong application info (application id or secret key)

3018

The property marked as "identity" is being updated and another user already has the specified value which must be unique.

3024

General "update registration" error. Error message should contain additional details.

3028

User is not logged in.

3029

Cannot modify properties of another user. Returned when one user is logged and the call attempts to modify properties of another user.

3030

Unable to locate user account - invalid user id.

3031

A new "dynamic" property is being added, but dynamic property definition is disabled.

3045

Required properties in the provided object do not contain values.

 

curl
 -H user-token:value-of-user-token-from-login
 -H Content-Type:application/json
 -X PUT
 -d '{"phoneNumber":"5551212"}'
 -v
 https://api.backendless.com/application-id/rest-api-key/users/value-of-id-from-login

 

Logout

The Logout operation terminates user session and disassociates the AuthenticatedUser role from the subsequent requests made by the client application.

Method:

GET

URL:

/<application-id>/<REST-api-key>/users/logout

where

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.

Request Headers:

user-token: value-of-the-user-token-header-from-login

where

user-token - a value returned by Backendless in the response for the preceding Login operation. The value identifies the user to be logged out. This header is mandatory.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the Logout API call.

Error Code

Description

2002

Version is disabled or provided wrong application info (application id or secret key)

3007

Invalid application-id or version.

3023

General error while executing logout. Error details should be available in the message property.

Example:

curl
 -H user-token:value-of-user-token-from-login
 -v
 https://api.backendless.com/application-id/rest-api-key/users/logout

 

Password Reset

Backendless supports two kinds of password reset:

1. Reset to system (backend) generated password.
2. Reset to password assigned by the user.

With the first option, an email is sent to the user with a regenerated password assigned to the user account. With the second option, an email is sent with a link to a webpage which contains a form where the user can enter the new password.

You can choose the type of reset for your application using Backendless Console. To change the password reset approach navigate to Users > Email Templates and select either User requests password recovery or User requests password recovery by link. Only one of these options can be active at a time. To make an option active, make sure the Do not send email for the event checkbox is not selected. If you make a change, make sure to click the SAVE button at the bottom of the screen.

 

For example, the following screenshot shows a configuration where the system will send out a link so the user can assign his own password. Notice the red color for the User requests password recovery option - this indicated that the option is disabled for the app:

active-mail-template.zoom80

 

In both cases (system-assigned or user-assigned passwords), the password reset sequence must initiated through the API. When the system assigns a password, it is still possible to update the user password using the Data Service API.

 

For the "password change via a link" option Backendless provides a default HTML form the link in the email points to. The HTML page is located in the File storage of the application where it can be edited and customized for branding purposes. The files are located in the /web/templates/change_password directory:

password-change-template.zoom80

Method:

GET

URL:

/<application-id>/<REST-api-key>/users/restorepassword/<user-identity-property>

where

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<user-identity-property> - a value for the property marked as identity. The value must be URL-encoded.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the Password Recovery API call. See the Error Handling section for details on how to retrieve the error code when the server returns an error.

Error Code

Description

2002

Version is disabled or provided wrong application info (application id or secret key)

3020

Unable to find user with the specified login (invalid user identity).

3025

General password recovery error. Additional details should be available in the "message" property of the response.

3038

One of the requirement arguments (application id, version or user identity) is missing.

 

curl
-X GET
 https://api.backendless.com/application-id/rest-api-key/users/restorepassword/myusername

 

User to Geo Relations

Backendless Geo Service manages application's geo location data and provides APIs to work with Geo points. Backendless supports integration between user objects managed by User Service and geo points for the scenarios when a logical connection between the two entity types must exist in an application.

Relations between a user object and a geo point are built the same way as between a data object and a geo point. The User-to-Geo integration is implemented through object relations. The Users table schema may declare a table column with a special data type - "GeoPoint Relationship". As a result, the user objects in the table may contain a reference to one or more GeoPoints. When a user object with a related GeoPoint is saved, Backendless persists information about both the user object and the geopoint in the corresponding persistent systems and sets up the relationship. Likewise, when a user object is retrieved by using the API, any related geopoints can be retrieved by using the same principle for loading  user relations. The user-to-geo relation is bidirectional, it means a geopoint may reference a user object in its metadata. You can learn more about it in the Relations with Data Objects section of the Geolocation service documentation.

Relation between a user object and a geopoint (or a collection of) can be established by using either the "code first" or the "schema first" approaches. With the former, the relationship is determined by the data structure persisted with the API. If a user object references a GeoPoint (or a collection of) in one of its properties, Backendless interprets it as a relation and, as a result, will create a relation column in the user table schema. With the latter ("schema first") approach, application developer can declare a user-to-geo property first. In either one of these approaches, once a relationship is declared, user objects and geopoints may be linked together by using the Backendless console as well. For information on how to declare Users to Geo relation columns and how to link User objects with GeoPoints using Backendless console, see the Relations with Geo Objects of the Data Service documentation.

Creating User-to-Geo Relations with the API

Creating a relationship between a user object and a geopoint (or a collection of) uses the same API as saving a user object with a related entity. In the case of the user-to-geo relations, the related entity is a geopoint or a collection of geopoints.

The example below demonstrates how to assign coordinates to a user's location, that is link a user object with one or several geopoints. A user object is retrieved for the example purposes (to have an object the example will be working with):

curl -X GET https://api.backendless.com/application-id/rest-api-key/data/Users/first

Server will respond as follows:

{
  "created": 1429497163000,
  "email": "foo@foo.com",
  "updated": null,
  "ownerId": null,
  "objectId": "C3DD2773-246A-87D8-FF41-A52C0AC38500",
  "name": "name",
  "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[\"phoneNumber\",\"created\",\"email\",\"updated\",\"ownerId\",\"objectId\",\"name\",\"__updated__meta\",\"___class\",\"password\"],\"relatedObjects\":{}}",
  "___class": "Users"
}

One-to-one Relation

To create a one-to-one relation, add a geopoint with the latitude:48.85,longitude:2.35 coordinates as a property of the user object retrieved earlier (the property name in the example below is location):

curl
-H Content-Type:application/json
-X PUT http://api.backendless.com/application-id/rest-api-key/data/Users/C3DD2773-246A-87D8-FF41-A52C0AC38500 -d '{"location":{"___class":"GeoPoint", "latitude":48.85,"longitude":2.35}}'

Server responds as follows:

{
  "email": "foo@foo.com",
  "created": 1429497163000,
  "updated": 1429497944000,
  "location": {
     "objectId": "DBDCC51A-FBD1-2887-FF9B-13E31F931B00",
     "categories": [
        "Default"
     ],
     "metadata": {},
     "latitude": 48.85,
     "longitude": 2.35
  },
  "ownerId": null,
  "objectId": "C3DD2773-246A-87D8-FF41-A52C0AC38500",
  "name": "name",
  "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[\"phoneNumber\",\"email\",\"created\",\"updated\",\"location\",\"ownerId\",\"objectId\",\"name\",\"___savedRelations\",\"password\",\"__relatedschemageopoint\",\"___class\"],\"relatedObjects\":{\"location\":[\"DBDCC51A-FBD1-2887-FF9B-13E31F931B00\"]}}"
}

Backendless Console can be used to verify the new relation. The geopoint will show up as a property in the location column of the user object.

One-to-many Relation

To create a one-to-many relation, add two geopoints with the coordinates latitude:48.85,longitude:2.35 and latitude:40.40,longitude:3.68 to an array. Then, assign this array as the locations property of the user object retrieved earlier:

curl
-H Content-Type:application/json
-X PUT http://api.backendless.com/application-id/rest-api-key/data/Users/C3DD2773-246A-87D8-FF41-A52C0AC38500 -d '{"location":[{"___class":"GeoPoint", "latitude":48.85,"longitude":2.35},{"___class":"GeoPoint", "latitude":40.40,"longitude":3.68}]}'

Server will respond as follows:

{
  "email": "foo@foo.com",
  "created": 1429497163000,
  "updated": 1429498286000,
  "location": [
     {
        "objectId": "774FFE0C-F6D5-49AD-FF07-2135230CCC00",
        "categories": [
           "Default"
        ],
        "metadata": {},
        "latitude": 48.85,
        "longitude": 2.35
     },
     {
        "objectId": "535F64EB-2C94-CEB4-FF56-EE6B93F6BD00",
        "categories": [
           "Default"
        ],
        "metadata": {},
        "latitude": 40.4,
        "longitude": 3.68
     }
  ],
  "ownerId": null,
  "objectId": "C3DD2773-246A-87D8-FF41-A52C0AC38500",
  "name": "name",
  "__meta": "{\"relationRemovalIds\":{},\"selectedProperties\":[\"phoneNumber\",\"email\",\"created\",\"updated\",\"location\",\"ownerId\",\"objectId\",\"name\",\"___savedRelations\",\"password\",\"__relatedschemageopoint\",\"___class\"],\"relatedObjects\":{\"location\":[\"774FFE0C-F6D5-49AD-FF07-2135230CCC00\",\"535F64EB-2C94-CEB4-FF56-EE6B93F6BD00\"]}}"
}

Backendless Console can be used to verify the new relation. The geopoint will show up as a property in the locations column of the user object.

Security and User Roles

Application's user accounts can be mapped to roles using the API documented below. A Backendless backend contains some system roles and may include developer-defined roles. There several system roles available in all Backendless backends. These roles are automatically assigned to every user under various conditions. Each role can configured with global, container and asset permissions.

 

Core security roles are assigned based on user authentication status and whether the user logged in via "classic" backendless login or through a social network. These roles are:

Security Role

Assigned to user when an API request is made by:

NotAuthenticatedUser

...a user who is not logged in.

AuthenticatedUser

...a user who is logged in.

SocialUser

...a user who is logged in via a social network (Facebook, Twitter, Google)

FacebookUser

...a user who is logged in via Facebook

GooglePlusUser

...a user who is logged in via Google

TwitterUser

...a user who is logged in via Twitter

 

Additionally the following roles are automatically assigned by Backendless to an API request when a corresponding secret API key is used. By configuring access permissions to these roles an application may allow to custom server-side code (ServerCodeUser role), but completely reject access to the client apps (all other roles).

Security Role

Role is assigned when API uses secret key:

ASUser

ActionScript secret key

AndroidUser

Android secret key

DotNetUser

.NET secret key

IOSUser

iOS secret key

JSUser

JavaScript secret key

RestUser

REST secret key

ServerCodeUser

CodeRunner secret key

 

Backendless assigns multiple security roles for the same API request. For example, an API request made from a JavaScript application where user is not logged will have the following roles assigned: NotAuthenticatedUser and JSUser.

 

Adding Roles

A developer-defined role can be added using Backendless Console:

1. Login to Console and select an application.
2. Click the Users icon.
3. Click the Security and Permissions section.
4. Click the Add Role button and enter a name for the role.
5. Click OK to save the role.

Role Permissions

A role may have multiple permissions assigned to it. A permission may either allow (GRANT) or reject (DENY) an API operation. Every operation which can be restricted with a permission has a subject. For example, the subject of a Data Service operation is a data record. For the File Service operations, the subject is a file.

All permissions are organized into a hierarchy: The global permissions apply to everything in the system. They either allow (GRANT) or reject (DENY) an API operation without distinguishing the subject. For example, a global permission may reject the Data Service's find operations for the users in the NotAuthenticatedRole. As a result, any not-authenticated user will not be able to retrieve an object from any data table in the application.

The asset container permissions inherit from the global ones and apply to a specific asset container, such as a data table. These permissions are scoped to a specific container type. For example, you may reject the get operation on file directory /privatefiles/ for the users in role X. As a result, any user who belongs to the role X will not be able to retrieve files from that directory.

Finally, the asset permissions inherit from the ones for the corresponding asset container (if they are available) or from the global set. For example, an asset permission may reject access to a specific data object for one role and grant access to the same object for another role.

The diagram below illustrates the permissions inheritance ladder:

permission-inheritance

Once a role is assigned to a user account, any permissions assigned to the role (either granting or denying an API operation) automatically apply to the operations executed by the application on behalf of the user.

Retrieving Available User Roles

This operation returns a list of the roles associated with the user account currently logged in to the Backendless application. If the request is sent without logging in, the system will return only one role - NotAuthenticatedUser.

Method:

GET

URL:

/<application-id>/<rest-api-key>/users/userroles

where

<application-id> - the ID of your application generated upon its creation. You can find this header in the Manage > App Settings section of the Backendless Console.
<rest-api-key> - the key of your application generated upon its creation. You can find this header in the Manage > App Settings section of the Backendless Console.

Request Body:

None

Response Body:

Returns an array of roles assigned to the currently logged in user:

[
 "roleName 1",
 "roleName 2"
 ...
 "roleName N"
]

Assigning a Role to a User:

This operation is available only from Custom Business Logic. Applications must use the "Code Runner API key" in order for the API call to be  accepted on the server. The reason for this restriction is that a malicious use of this API can easily compromise application's security. As a result, this API must be used from a controlled environment.

 

Method:

POST

URL:

/<application-id>/<bl-api-key>/users/assignRole

where:

<application-id> - the ID of your application generated upon its creation. You can find the value in the Manage > App Settings section of the Backendless Console.
<bl-api-key> - Business logic API key. You can find the value in the Manage > App Settings section of the Backendless Console.

Request Headers:

Content-Type:application/json

where:

Content-Type - must be set to application/json. This header is mandatory.

Request Body:

{
 "user" : user-value,
 "roleName" : roleName-value,
}

where:

user-value - user identification. A value for the property marked as identity.
roleName-value - name of the role to assign to the user account.

Response Body:

None

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

Unassigning a Role from a User:

This operation is available only from Custom Business Logic. Applications must use the "Code Runner API key" in order for the API call to be  accepted on the server. The reason for this restriction is that a malicious use of this API can easily compromise application's security. As a result, this API must be used from a controlled environment.

Method:

POST

URL:

/<application-id>/<bl-api-key>/users/unassignRole

where:

<application-id> - the ID of your application generated upon its creation. You can find the value in the Manage > App Settings section of the Backendless Console.
<bl-api-key> - Business logic (server-code) API key. You can the value in the Manage > App Settings section of the Backendless Console.

Request Headers:

Content-Type:application/json

where:

Content-Type - must be set to application/json. This header is mandatory.

Request Body:

{
 "user" : user-value,
 "roleName" : roleName-value,
}

where:

identity - user identity. A value for the user property marked as identity.
roleName - name of the role to remove from the user account.

Response Body:

None

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the API calls described above. See the Error Handling section for details on how to retrieve the error code when the server returns an error.

Error Code

Description

2002

Version is disabled or provided wrong application info (application id or secret key)

2005

Could not find role.

3038

One of the required parameters (user identity or roleName) is null.

3057

Could not find user by id or identity.

3058

Could not assign role to user.

3059

Could not unassign role to user.

Global Permissions

The global service permissions apply to all operations of a Backendless service. For example, global Data Service permissions assigned to a role apply to all API operations without distinguishing the subject of an operation. (A subject is a resource targeted by an API operation - for example a data object in a "save" call).

Global permissions can be viewed and managed in Backendless Console.  After selecting an application, click Users, then Security Roles:

user-rolesv4.zoom70

 

Every Backendless service is represented by a column. Each cell in a column is a group of API operations. For example "Find" under "Data" represents all Find operations of the Data Service. The check mark in a cell indicates that that the operation is globally permitted. Each global permission has two states:

Grant - represented by a green check mark - grants the rights to execute an operation for the users in the selected role.
Deny - represented by a red X - denies the rights to execute an operation.

Asset Container Permissions

Asset Container permissions apply to all subjects within a specific container. Supported containers may be:

Data tables                - a permission assigned at that level applies to all operations on the table. For example, storing, deleting or updating objects in the table and running queries.
Messaging channels        - a permission assigned to a channel applies to all operations on the channel - publishing a message, subscribing to receive messages, etc.
File directories        - a permission assigned to a file directory applies to all file-related operations in the directory - file upload, fetching a file, etc.
Geo categories        - a permission assigned to a geo category applies to all geo point-related operation in the category - adding, deleting or updating a geo point
Media tubes        - a permission assigned to a media tube applies to all operation on media streams in the tube.

To view, assign or modify an asset container permission, use a corresponding screen in the Backendless Console. For example, to restrict access to a data table, switch to the Data view, select a table and click the Permissions menu. The user interface has two views - one is for managing user permissions and the other for roles. To modify permissions for a user account:

1. Click the User Permissions menu.
2. Enter the user name in the search field to locate the user account..
3. Click an icon representing the permission state to modify the permission.

user-permissionsv4.zoom70

Similarly permissions can be assigned or modified for specific roles - use the Role Permissions menu.

Asset Permissions

Asset permissions are the most granular in the Backendless security system as they apply to a specific object. Currently this type of permissions is available only for data objects stored in Backendless Data Service and files stored in Backendless File Service. Permissions assigned to an asset (data objects or files) supersede all other permissions - including global and asset container ones. Similar to the asset container permissions, asset permissions may apply to specific user accounts or roles. This approach becomes particularly useful when different objects/files in the same container (table or directory) should have different access levels. For example, suppose a data table called Orders contains purchase orders entered by different sales people. Every sales person should be able to see only their purchase orders, but the sales manager should see the purchase orders of his subordinates. This can be accomplished by using an asset permission scheme.

Data Service Asset Permissions

Permissions for individual data objects can be managed either with Backendless Console or using the API. To manage object's permissions with console:

1. Login to console and select an application.
2. Click Data, then select the table containing the object for which permissions should be managed.
3. There is a special "lock" icon in the ACL column for every object in the table.
acl-iconv4.zoom80
4. Click the lock icon to manage object's permissions.
5. The permissions user interface includes two menu items: Users Permissions and Roles Permissions. The former is responsible for assigning permissions for the selected object to specific users. The latter does the same but for application roles.

The screenshot below explains various parts of the user interface:

roles-permissions-v4.zoom80

The intersection of each column and a role/user either grants or denies access to the operations represented by the column. The intersections may contain the following visualizations:

ico-checkmark-disable (gray check mark)        - INHERIT. This state represents the permissions for the user/role and the operation are inherited from either asset container or global permissions.
ico-checkmark2 (green check mark) - GRANT. This state represents that the permission is granted for the user/role to perform the corresponding operation.
ico-error (red cross)                - DENY. This state represents that the permission to execute the corresponding operation is denied to the user/role.

 

Data Service API

Overview

The Backendless Data Service is a highly scalable object storage system. The system has the qualities of both a traditional structured/relational (SQL) storage and an unstructured NoSQL database. Objects are stored in tables, which have columns with assigned data types. A table can be created dynamically, when an object is being persisted and there is no table corresponding to the object's type. Similarly, when an object is saved or updated  and contains properties which do not have corresponding columns, Backendless dynamically creates the columns in the table.

 

Data Service supports table relations which means a table may declare a column referencing another table. At the object level it is implemented through an object property which contains a reference to another object (one to one relation) or a collection of objects (one to many relations). When an object is retrieved from the server, its related objects can be retrieved in the same request (single-step retrieval) or later on through a separate request (two-step retrieval).

 

Object search in Backendless can be done using the SQL syntax. A search request is sent to a specific table and a search query identifies a condition the found object must match. As a result, the query must be the format of what goes into the WHERE clause of a traditional SQL query. For more details see the Search with the Where clause section of the guide.

Saving Data Objects

This operation persists an object in a table. If the table does not exist, it is automatically created based on the name of the table in the request URL. When Backendless creates a data table, it also creates columns based on the names of object properties from the request.

Saving Data Object

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where the object needs to be saved. If the table does not exist, Backendless creates the table and configures its schema to match the object structure (properties).

Request Headers:

user-token: value-of-the-user-token-header-from-login
Content-Type:application/json

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.
Content-Type - Must be set to application/json. This header is mandatory.

Example:

curl \
-H Content-Type:application/json \
-X POST  \
-d "{\"name\":\"Bob\", \"age\":20}" \
-v https://api.backendless.com/application-id/REST-api-key/data/Person

 

Updating Data Objects

This operation updates an existing object in the Backendless object storage. An object must have objectId assigned by Backendless as a result of the create object operation. You can update an object individually (single object deletion) or several objects at a time (bulk update).

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<object-id>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where the object needs to be updated.
<object-id> - ID of the object to update assigned by Backendless in the create object operation.

Request Headers:

Content-Type:application/json
user-token:value-of-the-user-token-header-from-login

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Example:

curl \
-H Content-Type:application/json \
-X PUT  \
-d "{\"name\":\"Bob\", \"age\":20 }" \
-v https://api.backendless.com/application-id/REST-api-key/data/Person/6C77C11B-E9B3-EB14-FFA2-69F38CF48800

Notice the objectId value is put directly into the URL. The same value is optional in the JSON body of the request.

Bulk Update

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/bulk/<table-name>?where=<where clause>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where the objects need to be updated.
<where clause> - condition for selecting the objects for the bulk update. Must be URL encoded.

Request Headers:

Content-Type:application/json
user-token:value-of-the-user-token-header-from-login

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Return Value:

Number of updated objects.

Example:

The following request updates all objects in the Order table where the value of the amount column is greater than 100. Every object which satisfies the where condition is updated with the property set in the request body:

curl \
-H Content-Type:application/json \
-X PUT \
-d "{\"Representative\":\"Joe Salesguy\"}" \
-v https://api.backendless.com/application-id/REST-api-key/data/bulk/Order?where=amount>100

 

 

 

Deleting Data Objects

The API completely removes an object from the persistent store. If the object is successfully delete, the API returns the timestamp of the exact deletion time in milliseconds.

You can delete an object individually (single object deletion) or several objects at a time (bulk delete).

Single object deletion

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<object-id>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where the object needs to be deleted.
<object-id> - ID of the object to delete. The ID assigned by Backendless in the create object operation.

Request Headers:

user-token:value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Request Body:

None

Return Value:

{
 "deletionTime" : timestamp in milliseconds
}

Example:

curl \
-X DELETE \
-v https://api.backendless.com/<application-id>/<REST-api-key>/data/Orders/6C77C11B-E9B3-EB14-FFA2-69F38CF48800

Bulk delete

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/bulk/<table-name>?where=<where clause>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where the objects need to be deleted.
<where clause> - condition for selecting the objects for bulk deletion. Must be URL encoded.

Request Headers:

user-token:value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Return Value:

Number of deleted objects.

Example:

The following sample request deletes all objects in the Order table where the value of the amount column is greater than 100:

curl \
-X DELETE \
-v https://api.backendless.com/application-id/REST-api-key/data/bulk/Order?where=amount>100

 

Retrieving Schema Definition

Backendless provides API for data table schema introspection. The API returns information about table's columns and their data types, whether a value for a column is required or if there is a default value.

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/properties

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table to retrieve the schema for.

Request Headers:

user-token:value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

An array of JSON objects each with the following structure:

{
autoLoad: true or false,
customRegex: value,
defaultValue: null or value,
isPrimaryKey: true or false,
name: value,
relatedTable: null or table name,
required: true or false,
type: data type
}

where:

autoLoad - applies only to relations. If true, the property is set to auto-load related data for the data retrieval queries.
customRegex - a regular expression assigned to the column as a validator. The validator applies when a new object is saved in the table or an existing one is updated.
defaultValue - a default value assigned to any object saved/updated in the table where the column does not have a value.
isPrimaryKey - true if the column is or is a part of a primary key.
name - contains the name of a property.
relatedTable - contains the name of the related table. This is applicable only to relation columns.
required - defines whether a property is optional or required for the requests which save the initial object or update an existing one.
type - defines the column type.

Example:

Suppose the Person table has the following schema - there are two developer-defined columns, age and name.

person-schema.zoom50

To retrieve the schema of the Person table using API, run the following request:

curl "http://api.backendless.com/application-id/REST-api-key/data/Person/properties"

The response is an array of JSON objects, each representing a column:

[
 {
   "name": "updated",
   "required": false,
   "type": "DATETIME",
   "defaultValue": null,
   "relatedTable": null,
   "customRegex": null,
   "autoLoad": false,
   "isPrimaryKey": false
 },
 {
   "name": "created",
   "required": false,
   "type": "DATETIME",
   "defaultValue": null,
   "relatedTable": null,
   "customRegex": null,
   "autoLoad": false,
   "isPrimaryKey": false
 },
 {
   "name": "objectId",
   "required": false,
   "type": "STRING_ID",
   "defaultValue": null,
   "relatedTable": null,
   "customRegex": null,
   "autoLoad": false,
   "isPrimaryKey": true
 },
 {
   "name": "ownerId",
   "required": false,
   "type": "STRING",
   "defaultValue": null,
   "relatedTable": null,
   "customRegex": null,
   "autoLoad": false,
   "isPrimaryKey": false
 },
 {
   "name": "name",
   "required": false,
   "type": "STRING",
   "defaultValue": null,
   "relatedTable": null,
   "customRegex": null,
   "autoLoad": false,
   "isPrimaryKey": false
 },
 {
   "name": "age",
   "required": false,
   "type": "INT",
   "defaultValue": null,
   "relatedTable": null,
   "customRegex": null,
   "autoLoad": false,
   "isPrimaryKey": false
 }
]

 

Get Object Count

The Object Count API provides a way to obtain the following values from the server:

Number of objects in a table
Number of objects matching query
Number of related objects

 

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/count?where=<whereClause>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table to get an object count from.
<whereClause> - Optional argument. If set, it is a search query used by the server it to determine the number of objects matching the condition. The value must be URL-encoded.

Request Headers:

user-token:value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

The number of objects in a table (if the whereClause is not set), otherwise the number of objects matching the search query.

Example:

Total object count for a table:

The following sample request retrieves total number of objects in table Order:

curl "https://api.backendless.com/<application-id>/<REST-api-key>/data/Order/count"

 

Object count for a query:

The following sample request retrieves total number of objects in table Order which satisfy the condition of orderAmount > 100:

curl "https://api.backendless.com/<application-id>/<REST-api-key>/data/Order/count?where=orderAmount%20%3E%20100"

 

Related object count:

The following sample request retrieves total number of related "child" objects for a parent object. The parent table is Person. It contains a relation column called address pointing to the Address table. The query below retrieves a count of related child objects for a parent object with objectID of XXXX-XXXX-XXXX-XXXX. The whereClause query syntax for this scenario is:
 

Person[address].objectId = 'XXXX-XXXX-XXXX-XXXX'

 
The whereClause must be URL-encoded, which results in the following sample request:

curl "https://api.backendless.com/<application-id>/<REST-api-key>/data/Address/count?where=Person%5Baddress%5D.objectId%20%3D%20%27XXXX-XXXX-XXXX-XXXX%27"

 

Basic Object Retrieval

Backendless supports multiple basic search operations. These include finding an object by ID, finding first or last object in the collection or retrieving the entire persisted collection.

Retrieving Data Objects

Method:

GET

URL:

Find by ID:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<object-id>

Find first:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/first

Find last:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/last

Basic Find (retrieving a collection):

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where to search for the object.
<object-id> - ID of the object to retrieve. The ID assigned by Backendless in the create object operation.

Request Headers:

user-token:value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Request Body:

None

Example:

Find first object:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person/first"

Find last object:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person/last"

Find object by ID:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person/XXXX-XXXX-XXXX-XXXX"

Load 'Person' objects:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person"

 

Advanced Object Retrieval

Advanced search use-cases supported by Backendless include:

Search with a query (a "where clause" search) -retrieves data objects which satisfy a condition.
Paged data retrieval - retrieves a "page" of data of the given size from the specified offset.
Sorted data object retrieval - retrieves a collection of data objects sorted by specified properties.
Retrieval of related objects - fetching data objects through special "relation" properties. See retrieval of related data objects.

 

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>?props=prop1,prop2&loadRelations=relprop1,relprop2&where=whereClause&pageSize=XX&sortBy=prop1,prop2&offset=ZZ

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where to search for the object.
props - references object properties which should be returned with every object. In this example, objects in the result will contain only the "prop1" and "prop2" properties.
loadRelations - references object properties which are relations and should be initialized and returned with the parent object. By default relations are not returned with the parent object and require a separate API call to load. Using the loadRelations query parameter Backendless pre-initializes the specified relations and returns them with the parent object.
where - contains an SQL query (the where clause part) which is used to search for the objects. The value must be URL encoded.
pageSize - sets the page size which is the number of objects to be returned in the response.
sortBy - lists properties by which the returned collection should be sorted by.
offset - zero-based index of the object in the persistent store from which to run the search. This parameter should be used when implementing paged access to data. Suppose the first request returned 20 objects (if pageSize is set to 20) and there are 100 objects total. The subsequent request can set offset to 20, so the next batch of objects is loaded sequentially.

Request Headers:

user-token:value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and roles assigned to the user will be enforced by Backendless.

Request Body:

None

Examples

For examples on using the advanced object retrieval API, see the following sub-sections:

Search with the Where clause

A where clause is a condition which references columns of a data table where the query is sent. For any given query Backendless returns the data records which match the condition in the where clause. A where clause is a query string which must conform to a subset of the SQL-92 standard. The subset of the syntax supported by Backendless is the part that goes into the WHERE clause of an SQL query. This is the reason why we refer to it as the where clause. For example, consider the following data objects, specifically notice the columns name and age:

sample-table.zoom70

 

Suppose you need to retrieve an object where the value of the name property is "Joe". This can be accomplished with the following where clause:

name = 'Joe'

 

Or if you need all objects where the age column contains a value less than 30:

age < 30

 

Just like in SQL, columns can be combined in a single where clause. The following condition would retrieve all objects containing letter J in the name and the age column's value is greater than 20:

name LIKE 'J%' and age > 20

 

Condition

Sample where clause

Column type

Value in a column equals a string literal.

name = 'foo'

STRING, TEXT or EXTENDED STRING

Value in a column does not equal a string literal.

name != 'foo'

STRING, TEXT or EXTENDED STRING

Value in a column is not assigned

name is null

STRING, TEXT or EXTENDED STRING

Value in a column is assigned

name is not null

STRING, TEXT or EXTENDED STRING

Value in a column contains a substring literal

name LIKE '%foo%'

STRING, TEXT or EXTENDED STRING

Value in a column ends with a substring literal

name LIKE '%foo'

STRING, TEXT or EXTENDED STRING

Value in a column starts with a substring literal

name LIKE 'foo%'

STRING, TEXT or EXTENDED STRING

Value in a column is one of enumerated string literals.

name IN ('value1', 'value2', 'value3)
 
or
 
name = 'value1' OR name = 'value2' or name = 'value3'

STRING, TEXT or EXTENDED STRING

Value in a column equals a numeric literal

age = 21

INT or DOUBLE

Value in a column is greater than a numeric literal

age > 21

INT or DOUBLE

Value in a column is greater than or equal a numeric literal

age >= 21

INT or DOUBLE

Value in a column is less than a numeric literal

age < 21

INT or DOUBLE

Value in a column is less than or equal a numeric literal

age <= 21

INT or DOUBLE

 

The following queries demonstrate data retrieval from the table:

 

Find all contacts where the value of the "age" property equals 20. The where parameter contains a URL encoded value of "age = 20";

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=age%3D20"


Find all contacts where the value of the "age" property is greater than 21. The where parameter contains a URL encoded value of "age > 21";

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=age%3E21"


Find all contacts where the value of the "age" property is between 21 and 40. The where parameter contains a URL encoded value of "age >= 21 AND age <=30";

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=age%3E%3D21%20AND%20age%20%3C%3D%2040"


Find all contacts whose "age" property is 30 or 10.

Use the IN operator to identify several values of the "age" property for the search. That is, the "where" parameter should be set to "=age in (30,10)". Numbers in the parenthesis define the age groups, for which you will be searching. You can specify more than two groups if necessary. If an object value matches any of the values in the parenthesis, the object will be included into the search response.

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=age%2Bin%2B(30%2C10)"


Find all contacts by name. The where parameter contains a URL encoded value of "name = 'Joe'";

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=name%20%3D%20%27Joe%27"


Find all contacts whose name is Joe or Kevin:

Use the IN operator to identify several values of the "name" property for the search. That is, the "where" parameter should be set to "=name in ('Joe','Kevin')". The value of the "where" parameter should URL-encoded. Values in the parenthesis define the names, for which you will be searching. You can specify more than two values if necessary. if an object value matches any of the values in the parenthesis, the object will be included into the search response.

curl "https://api.backendless.com/application-id/REST-api-key/data/Users?where=name%20in%20(%27Joe%27%2C%27Kevin%27)"


Find all contacts by partial name match. The where parameter contains a URL encoded value of "name LIKE 'J%'";

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=name%20LIKE%20%27J%25%27"

 

Using Dates in Search

There is a special consideration for the whereClause-based queries which reference a column of the DATETIME data type. Typically a DATETIME column is referenced in a comparison against a scalar value describing a specific date or a timestamp. The scalar value can be a number of milliseconds since the epoch (UNIX timestamp as milliseconds) or a string. Backendless supports a variety of date formats for the latter. For example, the queries below will find all the objects which were updated after March 23rd, 2015:

updated > '23-Mar-2015'

updated > '03/23/2015'

updated > 1427068800000

Comparison Operators

Backendless supports the following date comparison operators:

Column's value is after the specified date/time: use either > or the after keyword:

birthDate > '22-Dec-1980'

birthDate after 1427068800000

Column's value is before the specified date/time: use either < or the before keyword:

birthDate < '22-Dec-1980'

birthDate before 1427068800000

Column's value is either at or after the specified date/time: use either => or the at or after keyword:

birthDate >= '28-10-1988'

birthDate at or after '10/28/1988 00:00:00 GMT-0200'

Column's value is either at or before the specified date/time: use either <= or the at or before keyword:

birthDate >= '28-10-1988'

birthDate at or after '10/28/1988 00:00:00 GMT-0200'

Note: the whereClause-based queries can be tested in the Backendless Console with the SQL Search turned on.

Supported Date Formats

Date/time string values may be in any of the following formats. The pattern letters have the same definition as in Java's SimpleDateFormat:

EEE MMM dd HH:mm:ss zzz yyyy
yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
MM/dd/yyyy HH:mm:ss 'GMT'z
MM.dd.yyyy HH:mm:ss 'GMT'z
MM-dd-yyyy HH:mm:ss 'GMT'z
MM/dd/yyyy HH:mm:ss z
MM.dd.yyyy HH:mm:ss z
MM.dd.yyyy HH:mm:ss
MM-dd-yyyy HH:mm:ss
MM/dd/yyyy HH:mm:ss
MM.dd.yyyy
MM-dd-yyyy
MM/dd/yyyy HH:mm:ss 'GMT'Z
MM/dd/yyyy HH:mm
MM/dd/yyyy
dd/MMM/yyyy
dd-MMM-yyyy
EEEEE, d MMMMM yyyy
yyyy/MM/d/HH:mm:ss
yyyy-MM-dd'T'HH:mm:ss
EEEEE, MMMMM d, yyyy
MMMMM d, yyyy
yyyy M d
yyyyMMMd
yyyy-MMM-d
yyyy-M-d, E
'Date' yyyy-MM-dd
yyyy-MM-dd'T'HH:mm:ssZ
yyyy-MM-dd'T'HH:mmZ
yyyy-MM-dd
yyyy-'W'w
yyyy-DDD
d MMMMM yyyy, HH'h' mm'm' ss's'

Example

Finding objects created after 12/16/2014:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=created>1418680800000"

where where=created>1418680800000 is the number of milliseconds since epoch or December, 12, 2014.

Alternatively, the query may have the following format:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?where=created>'12/16/2014'"

 

Data retrieval with Paging

Backendless operations returning a collection of objects automatically break up the complete result set into pages. Backendless paging uses two parameters to enable paged data retrieval:

page size - identifies how many objects a single page contains
offset - identifies the position of the object from which to retrieve the number of records identified by page size

 

The diagrams below illustrate the paging process. The first diagram shows the first request to retrieve a collection of records. The request includes the parameters of 5 objects in the page, starting from offset 0:

findrequest1

 

To retrieve the next page of data, the client must set the offset to the index of the first not retrieved object, which is 5:

findrequest2

 

Backendless server sets the maximum allowed value for the page size to 100 objects. The minimum value is 1.

 

Paging using the REST API is implemented with the pageSize and offset parameters in the data retrieval URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>?pageSize=XX&offset=ZZ

pageSize and offset can be used with all other parameters supported by Backendless. Suppose a data table on the server contains 200 objects. To retrieve the first page of data with 100 objects in it, use the following request:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?pageSize=100"

The following request can retrieve the next page (the remaining 100 objects):

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?pageSize=100&offset=100"

 

 

 

Sorting

Data retrieval and search API can request the server to return sorted data. Data can be sorted by one or more columns. The sorting direction can be either ascending (default) or descending for each individual column. To request sorting with the REST API use the sortBy parameter in a data retrieval request:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>?sortBy=prop1,prop2

sortBy can be used with all other parameters supported by Backendless. The following sample request retrieves objects from the Person table sorted by the name (descending order) and age (ascending order) columns:

curl "https://api.backendless.com/application-id/REST-api-key/data/Person?sortBy=name%20desc%2Cage%20asc"

The descending sorting order can be requested by adding DESC to the name of the column (separated by space).

Search by distance

With the ability to link data objects with geo points, you can search for data objects by distance. This type of search returns a paged set of data objects which satisfy the whereClause condition and located within the specified distance. Distance-based search uses a special function in whereClause of the search request. The syntax of the function is:

distance( 
   center point latitude, 
   center point longitude, 
   columnname which contains geo point.latitude,
   columnname which contains geo point.longitude )<operator> units-function(value)

where:

<operator> - Possible values are <, >, =, >=, <=
units-function - Defines the units of measure for the distance. Possible values are:
ft( X ) - the distance value X is expressed in feet
km( X ) - the distance value X is expressed in kilometers
mi( X ) - the distance value X is expressed in miles
yd( X ) -  the distance value X is expressed in yards

For example, the following whereClause expression searches for data objects located within 200 miles from the point at 30.26715, -97.74306. Each data object must have the "coordinates" property of type GeoPoint. It is important that the entire whereClause which contains the distance function is URL-encoded.

distance( 30.26715, -97.74306, coordinates.latitude, coordinates.longitude ) < mi(200)

The following example demonstrates a search-by-distance query. The example uses three data objects stored in the Friend table: Bob, Jane, and Fred who respectively live in Austin, Houston, San Antonio. The search query in the example finds all friends who live within the specified distance. Before running the search query, create the objects in the data storage with the corresponding geo points.

 

The application must be setup with demo data in order to run the example and see the distance operator in action. See the setup code in the expandable block below:

 

Run the following query/code to store a data object representing Bob with a link to his home in Austin, TX:

 

curl -H Content-Type:"application/json" \
-X POST \
-v "http://api.backendless.com/application-id/REST-api-key/data/Person" \
-d "{\"name\":\"Bob\", \"age\":33, \"phoneNumber\":\"512-555-1212\", \"coordinates\": {\"___class\":\"GeoPoint\",\"latitude\":30.26715,\"longitude\":-97.74306,\"categories\":[\"Home\"],\"metadata\":{\"description\":\"Bob's home\"}}}"

 

Run the following query/code to store a data object representing Jane with a link to her home in Houston, TX:

curl -H Content-Type:"application/json" \
-X POST \
-v "http://api.backendless.com/application-id/REST-api-key/data/Person" \
-d "{\"name\":\"Jane\", \"age\":28, \"phoneNumber\":\"281-555-1212\", \"coordinates\": {\"___class\":\"GeoPoint\",\"latitude\":29.76328,\"longitude\":-95.36327,\"categories\":[\"Home\"],\"metadata\":{\"description\":\"Jane's home\"}}}"

 

Run the following query/code to store a data object representing Fred with a link to his home in San Antonio, TX:

curl \
-H Content-Type:"application/json" \
-X POST \
-v "http://api.backendless.com/application-id/REST-api-key/data/Person" \
-d "{\"name\":\"Fred\", \"age\":35, \"phoneNumber\":\"210-555-1212\", \"coordinates\": {\"___class\":\"GeoPoint\",\"latitude\":29.42412,\"longitude\":-98.49363,\"categories\":[\"Home\"],\"metadata\":{\"description\":\"Fred's home\"}}}"

 

 

Once the data is in the persistent object and geo location storage, you can verify it in Backendless Console by opening the Geolocation screen and selecting the Home geocategory:

distance-search

 

Suppose you need to get all objects located within 300 miles radius from Beaumont, TX, which has the GPS coordinates of 30.084, -94.145. The following code/query performs that distance-based search:

curl -H Content-Type:"application/json" \
"http://api.backendless.com/application-id/REST-api-key/data/Person?where=distance(%2030.084%2C%20-94.145%2C%20coordinates.latitude%2C%20coordinates.longitude%20)%20%3C%20mi(300)"

 

The search result is an array of objects sorted in the ascending order:

[
 {
   "phoneNumber": "210-555-1212",
   "created": 1481454024000,
   "name": "Fred",
   "___class": "Person",
   "coordinates": null,
   "location": null,
   "ownerId": null,
   "updated": null,
   "age": 35,
   "objectId": "BD612F56-C21E-0B2E-FF0D-F1B0D153A800",
   "__meta": "..skipped for brevity.."
 },
 {
   "phoneNumber": "512-555-1212",
   "created": 1481453836000,
   "name": "Bob",
   "___class": "Person",
   "coordinates": null,
   "location": null,
   "ownerId": null,
   "updated": null,
   "age": 33,
   "objectId": "84EAFDA6-FDEB-C645-FF7B-2E8530394700",
   "__meta":  "..skipped for brevity.."
 },
 {
   "phoneNumber": "281-555-1212",
   "created": 1481453944000,
   "name": "Jane",
   "___class": "Person",
   "coordinates": null,
   "location": null,
   "ownerId": null,
   "updated": null,
   "age": 28,
   "objectId": "10888A63-5997-B3A0-FF59-E4A922854300",
   "__meta":  "..skipped for brevity.."
 }
]

The search returns all data objects within the specified distance. Each data object has the Coordinates property containing the coordinates of a geo point associated with this data object.

Relations Overview

A data object stored in Backendless may reference other objects from the same or other data tables. These references are called relations. When an object references a single object, it is a one-to-one relation. If a reference is for a collection of objects, it is a one-to-many relation. Relations can be established using either API or Backendless Console. When working with console, a relation in a table must be declared through a relation column. Console allows two types of relation columns: data object relationship and geopoint relationship. The former identifies a relation between two data tables, while the later declares a relationship between a data table and geopoint storage. It is not required to declare relation columns in console - Backendless can derive these relations from the API calls and subsequently creates columns in data tables.

 

The rest of this chapter describes relationship management using Backendless console. For the API reference, see the corresponding chapters.

Declaring a Relation Between Tables

Creating Relations Between Objects in Related Tables

Editing (Update/Delete) Relations

Deleting Relation Column

Declaring a Relation Between Tables

The instructions below describe how to declare a relation between two tables. As an example, the instructions below create a relation column address in the Person table. The new column will reference the Address table:

1. Select the Person table where a relation column should be declared.
2. Click the Schema menu.
3. Click the New button. The pop-up window will display as shown below:

adding-new-column.zoom80

4. Enter column name that will identify the relation.
5. Click the Type drop-down list and select the Data Object Relationship option.
6. Select a related table and the cardinality of the relations from the corresponding drop-down menus. The one-to-one relation means that a table's object can be linked with only one object from the related table. The one-to-many relation means that a table's object can be linked with more than one object from the related table.

relationship-column.zoom80

7. Click CREATE to save the changes.

Once a relationship column is declared, it will appear along other columns in the Data Browser view of the Backendless Console.

Creating Relations Between Objects in Related Tables

Once you have declared a relation between table schemas, you can establish a relation between objects in these tables. Follow the instructions below to link the objects:

1. Click the table name where you declared a relation. Console displays the columns representing relations slightly different than the other ones. The header for these columns includes:
- name of the related table;
- relation type (cardinality) visualized as either a single red line for one-to-one relations or three red lines for one-to-many relations;
- the "auto-load" checkbox.

relation-column-data-browser.zoom70

2. Every object in the table displays a plus icon on mouse hover which can be used to create a relation between that object and one from the related table:
plus-for-relation
3. Click the plus icon for the object to create a relation. The Set Related Object pop-up window will display the list of objects from the related table.

set-relation-popup.zoom70

4. Each object in the displayed popup has either a radio button or a checkbox next to the object's data. Radio buttons are used for one-to-one relations, while checkboxes apply for the one-to-many relations. Select the object(s) which will be linked to the parent object.
5. Click the ADD RELATION button to save the changes.
6. Once a relation between the objects is established, the related object(s) appear as hyperlinks which can be clicked to navigate to them:
relation-created

Editing (Update/Delete) Relations

You can edit the relations between the data objects. Editing a relation allows changing the related object or breaking the relation between the objects.

1. Click the name of the table containing the object with relations. Click the plus icon in the cell displaying the related object (the same plus icon you used to create a relation above):

editing-relation-plus-icon.zoom80

2. The Set Related Object pop-up window will open and display the related object. If you want to link a data object with other object(s), click the radio-button or check-box(s) next to the necessary object(s).
remove-relation.zoom70
3. Depending on the made changes, the action button at the bottom of the popup will say either REMOVE RELATION or UPDATE RELATION. Click the button to finalize the changes.

Deleting Relation Column

When a relation column is deleted, all references between the related objects are also removed. This operation does not delete the actual objects - it removes the column and any references between the related objects.

To delete a relation column using the Backendless Console:

1. Click the name of the table where you want to delete a relation column.
2. Click the Schema menu
3. Click the check-box next to the column you need to delete.
4. Click the Delete menu:

delete-relation-column

 

Relations API (Set/Add)

This and other relation API sections refer to objects in a relation as parent and child(ren). The parent object is the one that contains a reference to a related object. A child object is one that is being referenced by the parent.

There are two operations supporting creating a relation between objects - setting a relation and adding a relation:

Setting a relation - sets specified child objects as the related objects for the parent. If the parent had other child objects prior to the operation, the relation between them and the parent is removed. This is a replacement operation.
Adding a relation - this operation adds specified child objects to the collection of existing child objects. This is a concatenation operation. For one-to-one relations, if the parent object has a child for the specified column at the time when the operation is called, an error is returned back to the client

 

Other implementation details:

Both parent and child objects must exist in the Backendless storage.
If a column identifies a 1:1 relation which already exists between the parent and some other object, the "set" operation must replace the child object with the one identified in the operation. The "add" operation must return an error.
Add/set methods must return the number of objects added/set, that is, for example, if a whereClause is used and identifies an object (among others) which is already in the relation, that object must not be "accounted for" in the returned number of object.
If add/set receives a non-existing object, it must be ignored and the returned count of objects set/added must not reflect the ignored object.
Both operations create the relation column if it does not exist at the time of the method call.

 

There are two ways to add/set a relation:

Explicit relation list - an API request identifies specific objects to be added/set as children of the parent object.

Implicit relation list - an API request uses a query (the where clause) to identify objects which should be added/set as children of the parent object

Explicit Relation List

API request must identify the child objects to set/add to the relation explicitly by referencing their IDs.

Methods:

 Set relation - POST

 Add relation - PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<parentObjectId>/<relationName>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where which contains the parent object as identified by <parentObjectId>.
<parentObjectId> - id of the object for which the relation will be created/set.
<relationName> - name of the column which identifies the relation within the parent table (identified as <table-name>). The column name may optionally include table name separated by the colon character as well as cardinality which determines the type of relationship (one to one or one to many) (see the note below):

If the column does not exist in the parent table at the time when the API is called, the value of the "relationColumnName" argument must include the name of the child table separated by colon and the cardinality notation. The cardinality is expressed as ":1" for one-to-one relations and ":n" for one-to-many relations. For example, the value of "myOrder:Order:1" will create a one-to-one relation column "myOrder" in the parent table. The column will point to the Order child table. Likewise, the value of "myOrder:Order:n" will create a one-to-many relation column "myOrder" pointing to the Order table.

Request Headers:

user-token: value-of-the-user-token-header-from-login
Content-Type:application/json

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved. Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.
Content-Type - Must be set to application/json. This header is mandatory.

Request Body:

Must be an array of child object IDs as string values.

[
 "childObjectId1", "childObjectId2"
]

Return Value:

Error or number of objects the operation sets for the relation.

Example:

The example below sets a relation for a one-to-one column named address declared in the Person table. The column must be declared in the table prior to the execution of the request shown below. This necessity is explained by missing table name qualifier in the URL - notice the relation column is address. If it were specified as address:Address, then the column would be created automatically.
relation-column

curl request:

curl \
-H Content-Type:application/json \
-X POST
-d "{ \"XXXXX-XXXXX-XXXXX-XXXXX\" }" \
https://api.backendless.com/application-id/REST-api-key/data/Person/parentObjectId/address

 
The following example sets a relation for a one-to-many column named friends which will be created if missing in the Person table. The column points to the Users table:

curl \
-H Content-Type:application/json \
-X POST
-d "{ \"XXXXX-XXXXX-XXXXX-XXXXX\" }" \
https://api.backendless.com/application-id/REST-api-key/data/Person/parentObjectId/friends:Users

Since the path includes the name of the child table (see the part of the path which included friends:Users), Backendless will create the column if it does not exist. Once created, you can see the column in Backendless console:
friends-column-created

 


Implicit Relation List

In this API request, child objects are referenced implicitly - through a whereClause defining the condition for object selection.

Methods:

 Set relation - POST

 Add relation - PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<parentObjectId>/<relationName>?whereClause=<whereClause>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where which contains the parent object as identified by <parentObjectId>.
<parentObjectId> - id of the object for which the relation will be created/set.
<relationName> - name of the column which identifies the relation within the parent table (identified as <table-name>). The column name may optionally include table name separated by the colon character as well as cardinality which determines the type of relationship (one to one or one to many) (see the note below):

If the column does not exist in the parent table at the time when the API is called, the value of the "relationColumnName" argument must include the name of the child table separated by colon and the cardinality notation. The cardinality is expressed as ":1" for one-to-one relations and ":n" for one-to-many relations. For example, the value of "myOrder:Order:1" will create a one-to-one relation column "myOrder" in the parent table. The column will point to the Order child table. Likewise, the value of "myOrder:Order:n" will create a one-to-many relation column "myOrder" pointing to the Order table.

<whereClause> - a where clause condition identifying objects in the child table which will be set as the related objects for the parent object.

Request Headers:

user-token: value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved. Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Return Value:

Error or number of objects the operation sets for the relation.

Example:

The following request creates a relation between a Person object and all objects in the Users table which match the provided query. The query is specified in the whereClause parameter in the URL. The value of the whereClause parameter is URL-encoded. The decoded version of the query is: name='Joe' or name = 'Frank'. As a result of the operation, all User objects where the name property is either Joe or Frank will be set in the relation.

The relation column is created if it does not exist. This is done because the column contains the child table qualifier, defined as ":Users" right after the column name.

curl \
-X POST
https://api.backendless.com/application-id/REST-api-key/data/Person/parentObjectId/friends:Users?whereClause==name%3D%27Joe%27%20or%20name%20%3D%20%27Frank%27

 

Relations API (Delete)

This and other relation API sections refer to objects in a relation as parent and child(ren). The parent object is the one that contains a reference to a related object. A child object is one that is being referenced by the parent.

Relation deletion API disconnects a relation between the parent object and some (or all) related children. The API does not delete any objects, it is responsible strictly for breaking the relationship. For object deletion API, see the Deleting Data Objects section of the documentation.

 

There are two ways to delete a relation:

Explicit deletion list - an API request identifies specific child objects to be disconnected from the parent object.

Implicit deletion list - an API request uses a condition (the where clause) to identify the child objects which should be disconnected from the parent object.

Delete Relation with object IDs

API request must identify the child objects to delete from the relation explicitly, by referencing their IDs.

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<parentObjectId>/<relationName>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where which contains the parent object as identified by <parentObjectId>.
<parentObjectId> - id of the object for which the relation will be deleted.
<relationName> - name of the column which identifies the relation within the parent table (identified as <table-name>).

Request Headers:

user-token: value-of-the-user-token-header-from-login
Content-Type:application/json

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved. Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.
Content-Type - Must be set to application/json. This header is mandatory.

Request Body:

Must be an array of child object IDs as string values.

[
 "childObjectId1", "childObjectId2"
]

Return Value:

Error or number of objects the operation deleted for the relation.

Example:

The example below deletes a relation between a Person object and its children. The child objects are referenced explicitly in the API call (see the object IDs in the body as "XXXXX-XXXXX-XXXXX-XXXXX" and "ZZZZ-ZZZZ-ZZZZZ-ZZZZZ").The relation column is address.

curl \
-H Content-Type:application/json \
-X DELETE
-d "{ \"XXXXX-XXXXX-XXXXX-XXXXX\", \"ZZZZ-ZZZZ-ZZZZZ-ZZZZZ\" }" \
https://api.backendless.com/application-id/REST-api-key/data/Person/parentObjectId/address

Deletion Relation with condition

API request must identify the child objects to delete from the relation explicitly, through a whereClause condition.

Method:

 DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<parentObjectId>/<relationName>?whereClause=<whereClause>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table where which contains the parent object as identified by <parentObjectId>.
<parentObjectId> - id of the object for which the relation with the child objects will be deleted.
<relationName> - name of the column which identifies the relation within the parent table (identified as <table-name>).
<whereClause> - a where clause condition identifying objects in the child table which will be removed from the relation to the parent object.

Request Headers:

user-token: value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved. Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Return Value:

Error or number of objects the operation sets for the relation.

Example:

The following request deletes a relation between a Person object and all the related objects in the related table (Users) which match the provided query. The column name identifying the relation is friends. The query is specified in the whereClause parameter in the URL. The value of the whereClause parameter is URL-encoded. The decoded version of the query is: name='Joe' or name = 'Frank'. As a result of the operation, all related objects where the name property is either Joe or Frank will be deleted from the relation.

curl \
-X DELETE
https://api.backendless.com/application-id/REST-api-key/data/Person/parentObjectId/friends:Users?whereClause==name%3D%27Joe%27%20or%20name%20%3D%20%27Frank%27

 

Relations (Retrieve)

When a data object or a collection of objects is retrieved using the client API, Backendless does not automatically include related objects into the returned object hierarchy. The reason for this is it would make it very easy to load a lot of unnecessary data which could impact application's performance. There are multiple ways to retrieve related data:

Relations auto-load - a mechanism built-into Backendless Console for configuring specific relations to be included into responses with the parent objects.
Single-step relations retrieval - initializing and including related objects into the response when running a find query for parent objects.
Two-step relations retrieval - a process of retrieving relations where the first step is to load the parent object and the second step is to load specific relations for the given parent.
Loading with relations depth - retrieving related objects by specifying the depth of the object hierarchy
Relation paging API - enables "chunked" (or paged) retrieval of related objects
Inverted Retrieval - loading related child objects by condition applied to parent - load related objects using a search query where the condition applies to the parent object properties.

Auto Load

The auto-load feature is designed to be used for quick prototyping. One of its benefits is reduction of client-side code. However, for production quality apps, it is not recommended to use the auto-load relation retrieval as it can greatly impact performance.

By default when an object is retrieved from Backendless using any of the find APIs (basic or advanced), its related objects are not included into the response, unless explicitly referenced in the request. This behavior can be easily modified using Backendless Console:

auto-load

For any two tables A and B where A has a relationship column linking it to B, the console includes the "auto load" checkbox for the relationship column. Selecting the checkbox instructs Backendless to return a paged set of related B objects when the parent instance of A is retrieved through an API call. For example, in the image above, the shown table has a one-to-many "address" relationship with the Address table. When the "auto load" checkbox in the "address" column is selected, a paged set of the related Address objects will be included into the response for a find query for the shown table.

Single Step Retrieval

Single Step Retrieval loads only a partial set of the related objects (default size of the retrieved related collection is 10). To load additional related objects, use the Relation Paging API.

This approach allows retrieval of a partial set of the related objects along with the parent object in a single find request. Each relationship property (column) must be uniquely identified by name using the API documented below.

 

Retrieve a specific object with relations:

GET http://api.backendless.com/[application-id]/[REST-api-key]/data/[TABLE-NAME]/[OBJECT-ID]?loadRelations=[RELATED-PROPERTY-NAME][,RELATED-PROPERTY-NAME]

The comma between the RELATED-PROPERTY-NAME names must be URL-encoded as %2C.

 

Retrieve multiple objects from the table with relations:

GET http://api.backendless.com/[application-id]/[REST-api-key]/data/[TABLE-NAME]?loadRelations=[RELATED-PROPERTY-NAME]

where:

[application-id] - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
[REST-api-key] - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
[TABLE-NAME] - name of the table from which the data is to be loaded.
[OBJECT-ID] - objectId of the object to retrieve.
[RELATED-PROPERTY-NAME] - name of the related property to load. For example, if table Person has a relation column homeAddress pointing to an object in the Address table, the value of the prameter would be homeAddress. The syntax allows to add relations of relations. For example, if the same Address table has a relation country pointing to the Country table, then homeAddress.country would instruct the backend to load the related Country object. It is possible to specify multiple related property names. In this case they must be separated by URL-encoded (%2C) commas

Two-step Retrieval

Two Step Retrieval loads only a partial set of the related objects (default size of the retrieved related collection is 10). To load additional related objects, use the Relation Paging API.

With this approach a collection of related objects for a specific relation property in a parent object is retrieved from the server. The client application must know parent object's objectId. The API loads a collection of related children for one property at a time. Child objects retrieved in paged sets, see the Relation Paging API sectionfor additional details.

 

 

GET http://api.backendless.com/[application-id]/[REST-api-key]/data/Order/[OBJECT-ID]/[relatedPropertyName]

where:

[application-id] - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
[REST-api-key] - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
Order - name of the table where the data is to loaded from.
[OBJECT-ID] - ID of the object for which to load specified relations.
[relatedPropertyName] - name of a related property to load. For example, if table Person has a relation column homeAddress pointing to an object in the Address table, the value would be homeAddress.

Suppose the Person table has a one-to-many relationship column friends pointing to the Users table. The code below retrieves related BackendlessUser objects  for a specific Person object:

 

Retrieval with Relation Depth

The Data Service API supports a mechanism for loading related objects without identifying each by its name. Instead, the API includes a parameter which specifies the "depth" of the relations to include into the response. Consider the following diagram:

relation-depth

The diagram shows a hierarchy for class structure - the Order class has two relations: with OrderItem and Customer classes. Each in turn has a relation to the Manufacturer and Address classes. When an instance or a collection of Order objects is retrieved from Backendless, the API may include a parameter specifying the depth of relations to include into the response. If the relation depth is 1, then all related instances of OrderItem and Customer will be included into each Order object. If the relation depth is 2, then not only OrderItem and Customer instances will be included, but the corresponding Manufacturer and Address objects as well.

Loading relations with relation depth retrieves only a partial set of the related objects (default size of the retrieved related collection is 10). To load additional related objects, use the Relation Paging API.

API methods supporting relations depth

 

GET http://api.backendless.com/[application-id]/[REST-api-key]/data/[TABLE-NAME]?relationsDepth=[RELATIONS-DEPTH-VALUE]

where

[application-id] - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
[REST-api-key] - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
[TABLE-NAME] - name of the table from which the data is to be loaded.
[RELATIONS-DEPTH-VALUE] - depth of the relations to include into the response.

Relation Paging

API operations described above provide a way to retrieve a limited (initial) set of related data. In most real world scenarios, there may be more related objects than returned by Single Step, Two Step or Relation Depth Retrieval APIs. To obtain a complete set of related objects Backendless supports Relation Paging API described below.

1. To understand the concept of paged data retrieval, see the Data retrieval with Paging section of the documentation.
2. When working with paging, it may be important to know the total size of the related collection. See the Get Object Count section for details on how to get the related objects count.

Methods:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/data/<table-name>/<parentObjectId>/<relationName>?pageSize=<pageSize>&offset=<offset>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of the table which contains the parent object identified by <parentObjectId>.
<parentObjectId> - id of the object for which the related objects will be retrieved.
<relationName> - name of the column which identifies the relation in the parent table (shown in the URL as <table-name>). This is the relation for which the related data will be retrieved.
<pageSize> - sets the page size which is the number of objects to be returned in the response.
<offset> - zero-based index of the object in the persistent store from which to start object retrieval. Suppose the first request returned 10 related objects and there are 100 objects total. The subsequent request can set offset to 20, so the next batch of objects is loaded sequentially.

Request Headers:

user-token: value-of-the-user-token-header-from-login

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved. Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Return Value:

Array of related objects or error.

Example:

The example below includes two API requests to load separate "pages" or related data. The first page includes 20 data objects from offset  0 and the second page loads another 20 objects from offset 20. The data is loaded for the orderItem relation declared in the Order table.

 

Load page 1:

curl "https://api.backendless.com/<application-id>/<REST-api-key>/data/Order/<parentObjectId>/orderItem?pageSize=20&offset=0"

Load page 2:

curl "https://api.backendless.com/<application-id>/<REST-api-key>/data/Order/<parentObjectId>/orderItem?pageSize=20&offset=20"

 

Inverted Relation Retrieval

Backendless supports a special query syntax for loading a subset of child objects for a specific parent. Consider the following table schemas:

 

PhoneBook table:

phonebook-table-schema

 

Contact table:

contact-table-schema

 

Address table:

address-table-schema

These tables will be used to demonstrate how to query Backendless for conditional related object retrieval.

 

The general structure of a whereClause query to load a collection of child objects for a specific parent object is:

ParentTableName[ relatedColumnName ].parentColumnName COLUMN-VALUE-CONDITION

Both columns relatedColumnName and parentColumnName must be declared in a table with name of ParentTableName. The relatedColumnName must be a relation column. The table relatedColumnName points to is the table where the objects must be loaded from.  The examples below demonstrate the usage of this syntax:

Find all contacts in a city for a specific phone book:

Suppose objectId of the PhoneBook object for which we need to find contacts is XXXX-XXXX-XXXX-XXXX, then the where clause in the query must look as shown below:

PhoneBook[contacts].objectId= 'XXXX-XXXX-XXXX-XXXX' and address.city = 'New York'

The where clause must be URL encoded when submitted in a REST request:

PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20address.city%20%3D%20%27New%20York%27

The final curl command to run the query is:

curl https://api.backendless.com/application-id/REST-api-key/data/Contact?where=PhoneBook%5Bcontacts%5D.objectId%3D%27DC5B7BDD-2AF6-8949-FFB3-56C2093CBC00%27%20and%20address.city%20%3D%20%27New%20York%27


Find all contacts for the specific phone book where the city name contains letter 'a':

Suppose objectId of the PhoneBook object for which we need to find contacts is XXXX-XXXX-XXXX-XXXX, then the where clause in the query must look as shown below:

PhoneBook[contacts].objectId= 'XXXX-XXXX-XXXX-XXXX' and address.city like '%a%'

The where clause must be URL encoded when submitted in a REST request:

PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20address.city%20like%20%27%25a%25%27

The final curl command to run the query is:

curl https://api.backendless.com/application-id/REST-api-key/data/Contact?where=PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20address.city%20like%20%27%25a%25%27


Find all contacts where age is greater than 20 for a specific phone book:

Suppose objectId of the PhoneBook object for which we need to find contacts is XXXX-XXXX-XXXX-XXXX, then the where clause in the query must look as shown below:

PhoneBook[contacts].objectId= 'XXXX-XXXX-XXXX-XXXX' and age > 20

The where clause must be URL encoded when submitted in a REST request:

PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20age%20%3E%2020

The final curl command to run the query is:

curl https://api.backendless.com/application-id/REST-api-key/data/Contact?where=PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20age%20%3E%2020


Find all contacts for a specific phone book where age is within the specified range:

Suppose objectId of the PhoneBook object for which we need to find contacts is XXXX-XXXX-XXXX-XXXX, then the where clause in the query must look as shown below:

PhoneBook[contacts].objectId= 'XXXX-XXXX-XXXX-XXXX' and age >= 21 and age <= 30

The where clause must be URL encoded when submitted in a REST request:

PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20age%20%3E%3D%2021%20and%20age%20%3C%3D%2030

The final curl command to run the query is:

curl https://api.backendless.com/application-id/REST-api-key/data/Contact?where=PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20age%20%3E%3D%2021%20and%20age%20%3C%3D%2030


Find all contacts for a specific phone book where age is greater than 20 and the city is Tokyo:

Suppose objectId of the PhoneBook object for which we need to find contacts is XXXX-XXXX-XXXX-XXXX, then the where clause in the query must look as shown below:

PhoneBook[contacts].objectId= 'XXXX-XXXX-XXXX-XXXX' and age > 21 and address.city = 'Tokyo'

The where clause must be URL encoded when submitted in a REST request:

PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20age%20%3E%2021%20and%20address.city%20%3D%20%27Tokyo%27

The final curl command to run the query is:

curl https://api.backendless.com/application-id/REST-api-key/data/Contact?where=PhoneBook%5Bcontacts%5D.objectId%3D%20%27XXXX-XXXX-XXXX-XXXX%27%20and%20age%20%3E%2021%20and%20address.city%20%3D%20%27Tokyo%27

 

Relations with Geo Points

Backendless Geo Service manages application's geo location data and provides APIs to work with Geo points. Backendless supports integration between data objects managed by Data Service and geo points for the scenarios when a logical connection between the two entity types must exist in an application. For instance, in a taxi ordering application a data object may represent a taxi car, while a geo point represents its location on the map. Linking the two entity types together provides great benefits such as retrieving both objects at once and managing as a consistent, cohesive object hierarchy.

The Data-to-Geo integration is implemented through object relations. Data table schema may declare a table column with a special data type - "GeoPoint Relationship". As a result, the data objects in the table may contain a reference to one or more GeoPoints. When a data object with a related GeoPoint is saved, Backendless persists information about both the data object and the geo point in the corresponding persistent systems and sets up the relationship. Likewise, when a data object is retrieved by using the API, any related geo points can be retrieved using the same principle for loading data relations. The data-to-geo relation is bidirectional, it means a geo point may reference a data object in its metadata. You can learn more about it in the Relations with Data Objects section of the Geolocation documentation.

The relationship between a data object and a geo point (or a collection of) can be established by using either the "code first" or the "schema first" approaches. With the former, the relationship is determined by the data structure persisted with the API. If a data object references a GeoPoint (or a collection of) in one of its properties, Backendless interprets it as a relation and, as a result, will create a relation column in the data table schema. With the latter ("schema first") approach, application developer can declare a relationship in the data table schema first. In either one of these approaches, once a relationship is declared, data objects and geo points may be linked together by using the Backendless console as well.

 

This chapter consists of the following sections:

Declaring a Data-to-Geo Relationship in Table Schema

Linking a Data Object with Geo Points

Update/Delete Relations

Deleting Relation Column in Table Schema

Establishing Relations with Geo Points via API

Declaring a Data-to-Geo Relationship in Table Schema


To declare a relationship in a data table schema:

1. Select a table where a relation column should be declared.
2. Click the Schema menu.
3. Click the New button. Enter a name for the new column in the Name field. This column will represent a data-to-geo relationship.
4. Select the Geopoint Relationship option from the Type drop-down list.
geo-point-relationship-type
5. Select the constraints and/or cardinality of the relation from the corresponding drop-down menus.
 
Constraints:
There are two available constraints: "Not Null (Required)" and "Unique Value". The former (NN) establishes the column as required. It means when a new object is created or an existing one is updated, server will be expecting a value for the column. The latter constraint (UQ) will enforce a rule that the column must contain a unique value, thus no two objects will be able to contain the same GeoPoint.
 
Cardinality:
The one-to-one relation means that a table's object can be linked with only one geo point, while the one-to-many relation means that a table's object can be linked with multiple geo points.
location-column
6. Click the CREATE button to save the changes.

Linking a Data Object with Geo Points


Once a data-to-geo relationship column is declared, data objects from the table can be linked to geo point(s) as described below:

1. Click the name of the table containing an object you want to link with a geo point.
2. Table columns representing the data-to-geo relationships are identified as "GEOPOINT relationship" in the header row. The cardinality of the relation is visualized as one red line for the one-to-one relations and three red lines for the one-to-many relations:
geopoint-column.zoom70
3. To create a relationship between an object and a geopoint, click the plus icon next in the cell for a GEOPOINT column.
plus-icon-for-geopoint.zoom70
4. The Set Related GeoPoint pop-up window will display the list of the geo points. Use the Geo Category drop-down list to select a geo category from which the points should be displayed. Additionally, you can use the search bar to locate a geopoint by its metadata:
geopoint-search.zoom80
5. If you declared a one-to-one relation for a table the object belongs to, you will be able to link this object with only one geo point (by the means of a radio button). If it is a one-to-many relationship, the interface uses check boxes, which allow for multiple selection. Click a radio-button or select check-boxes next to the geo points which you want to link with the data object.
6. Click the ADD RELATION button to save the changes.

Once a relation is established, it is shown in the data browser as a hyperlink. The hyperlink for the one-to-one relations displays the coordinates of the related geo point. For the one-to-many relations the link says "multiple Geopoints". In both cases, the link opens the Geolocation screen of the console which displays the related geo point(s). Additionally, the link has a mouse-over preview for the related geopoints:

geopoint-preview

Update/Delete Relations


To update a data-to-geo relation, use the same plus icon that opened the popup to create a geopoint relation. The popup tracks the selection changes and allows update or deletion of the relation.

Deleting Relation Column in Table Schema


A data-to-geo relationship can be removed at the schema level. When a relationship column is removed, the "links" between the corresponding data objects and geopoints are deleted, however, it does not remove the objects themselves.

To delete a relationship definition between a data table and the geo points:

1. Click the name of the table which contains a "GeoPoint relationship" column you need to remove.
2. Click the Schema menu
3. Click the check-box next to the column you need to delete.
4. Click the Delete menu.
delete-geopoint-relation-column

Establishing Relations with Geo Points via API


Creating a relationship between a data object and a geo point (or a collection of) uses the same API as saving a data object with a related entity. In the case of data-to-geo relations, the related entity is a geopoint or a collection of geopoints. Consider the example that below saves a data object with a related geopoint. The geopoint is also persisted in the Geo Service:

curl -H Content-Type:"application/json" \
-X POST \
-d '{"name":"Bob", "age":33, "phoneNumber":"212-555-1212", "coordinates":  {"___class":"GeoPoint", "latitude":12.21, "longitude":32.0, "categories":["City"]}}' \
-v "http://api.backendless.com/application-id/REST-api-key/data/Person"

Notice coordinates property of the data object being saved. It contains a JSON object with a special "___class":"GeoPoint" property. The presence of that property identifies the coordinates object as a GeoPoint. Additionally, the latitude and longitude properties in the GeoPoint object are required. The categories property is optional. If present, it must be an array of strings, where each string identifies the category the geo point belongs to. If the categories property is not present, the geo point will be saved in the default category.

The example above saves a one-to-one relationship between the data object and a geo point. To make it a one-to-many relationship change the value of the coordinates property to an array:

curl -H Content-Type:"application/json" \
-X POST \
-d '{"name":"Bob", "age":33, "phoneNumber":"212-555-1212", "coordinates": \
[{"___class":"GeoPoint", "latitude":48.85, "longitude":2.35, "categories":["City"],"metadata":{"description":{ \
"___class":"City", "name":"Paris", "population":2249975, "country":"France", "website":"www.paris.fr"}}}, \
{"___class":"GeoPoint","latitude":40.40, "longitude":3.68, "categories":["City"], "metadata":{"description":{ \
"___class":"City", "name":"Paris", "population":3236344, "country":"Spain","website":"www.madrid.es"}}}]}' \
-v "http://api.backendless.com/application-id/REST-api-key/data/Person"

 

After you run the code, you will see the following data object and geopoints created in the application:

Data object:

taxi-data-object.zoom70

Geopoints:

taxi-geo-points.zoom70

Data Security

Data Service supports a very flexible security mechanism for restricting access to objects stored in Backendless. Security permissions apply to users and roles. A permission can either grant or reject an operation for a particular asset. In the context of Data Service, the asset is an object which your app can retrieve, update or delete. Permissions can be granted or rejected globally, where they apply to all tables and all objects in the data store. Additionally, every table may have its own permission matrix and owner policy - a special instruction whether object owners can or cannot retrieve/update/delete the objects they 'own'. Finally, every object has its own Access Control List (ACL) which is a matrix of permissions for the operations applicable specifically to the object:

backendless-security-components

The security system is multi-layered. For any API call the system goes through several layers where each can trim the scope of the operations. The layered order of the decision making is important and consists of the following points of validation:

1. ObjectACL for the user who makes the call
2. ObjectACL for user-defined roles assigned to the user who makes the call.
3. Table permissions for the User account
4. Table permissions for the user-defined roles
5. Owner Policy
6. ObjectACL for system roles
7. Table permissions for system-level roles
8. Global user-defined roles
9. Global system roles

Where:

"User-defined roles" - roles created by the application developer.
"System roles" - roles built into Backendless (Authenticated User, NonAuthenticated User, SocialUser, etc).

 

Consider the following guide which illustrates the decision making process:

Backend receives an API request to load data from a table (the Find operation). For the sake of the example, user's identity is "bob@backendless.com" and the user belongs to a custom role called "MyRole".
 
All objects in the table become candidates for the retrieval. Backendless goes through the security permissions layers to determine which objects must be included into the response.
 

1. [LAYER 1] ObjectACL for the user who makes the call.
Backendless checks if there are any restrictions for the user account at the object level. Any object in the collection with ACL which rejects access to the user is excluded from the result. To see or modify the permissions for a particular object, click the 'lock' icon in the ACL column in the data browser in management console to see and manage Object ACL permissions for a specific object.
object-acl-access.zoom80
 
2. [LAYER 2] ObjectACL for user-defined roles assigned to the user who makes the call.
This is the same check as the one above, except Backendless looks into the permissions for the roles defined by the application developer. If the user who made the call belongs to any of the custom roles, Backendless checks if these roles are allowed to perform the current operation for every object in the collection. In the screenshot below, only the "MyRole" role will be checked in this step, since this is the only custom role in the application:
object-acl-custom-role.zoom80
 
3. [LAYER 3] Table permissions for the User account.
Every table in Backendless may have its own set of permissions for users and roles. At this point Backendless checks if the currently logged in user is allowed to run the current operation. For example, if the Find operation is denied for the user, no objects would be returned. To see the permissions for a user account in Backendless Console, select a table and click PERMISSIONS, then USER PERMISSIONS menu:
table-permissions-for-users.zoom80

 

4. [LAYER 4] Table permissions for the user-defined roles.
This step is identical to the one described above with the exception that is checks custom roles for the table. Since this guide reviews the decision making process for the Find operation, Backendless checks the column for Find. If any of the custom roles which the user belongs to deny access, the operation is rejected and no data is returned.
custom-user-roles-for-table.zoom80
 
5. [LAYER 5] Owner Policy.
When a new object is created in Backendless, the system automatically links it with the account of the user that made the call to save the object. You can see that information in the 'ownerId' column in any of your tables in the data browser.  With the association between objects and users (owners), Backendless provides a way to control whether users can get access to the data they created. This is done through a concept we call 'Owner Policy'. To navigate to Owner Policy, select a table in the data browser and click the PERMISSIONS menu. Click the OWNER POLICY menu item.
Granting a permission for an operation in Owner Policy, guarantees that the objects owned by the current user will be allowed access for the specified operations. Denying a permission, takes out the 'owned' objects from the collection of candidate objects to return.
 
6. [LAYER 6] Object ACL for system roles.
This check is identical to step 2 ([LAYER 2] Object ACL for custom roles). The difference is the system roles cover larger groups of users. For example, this step would make possible to restrict access to specific objects for all authenticated (or not authenticated) users, yet the object would be returned with a query made by the object's owner if the Owner Policy (previous step) grants access.
 
7. [LAYER 7] Table permissions for system roles.
Identical to step 4 (table permissions for custom roles), this checks if any of the system roles reject the operation at the table level.
 
8. [LAYER 8] Global custom roles.
Global policy applies to all tables and objects. By default all table level permissions inherit from the global policy. You can configure in the console at: Users > Security Roles. Create a new role and click it to configure the permission matrix:
custom-role-global-matrix.zoom70

Permissions API

Every data object in Backendless has its own access control list (ACL) - a matrix of operations and principals (application's users or roles). An intersection of an operation and a principal contains a permission which determines whether the principal has the right to execute the operation. These permission could be either grant or deny. Backendless console provides an easy to understand way to see and manage these permissions. For example, the screenshot below demonstrates an ACL matrix for an object. Notice the intersection of a column for the Create operation and the AuthenticatedUser role. The cell contains a green checkmark icon representing that the permission is granted:

permission-matrix

In addition to managing the ACL permissions with Backendless Console there is also Permissions API:

Method:

PUT

URI:

/<application-id>/<REST-api-key>/data/<table-name>/permissions/<permission type>/<object-id>

where:

<application-id> - the ID of your application generated upon its creation. You can the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can the value in the Manage > App Settings section of the Backendless Console.
<table-name> - name of a table containing a data object, for which you want to specify the permission.
<permission type> - type of the permission, that is either grant or deny.
<object-id> - object ID of the data object for which the permission is updated.

Sample Request Body:

To set permissions for a user

{
   "permission": "FIND" | "REMOVE" | "UPDATE",
   "user": userid
}

To set permissions for all users, use the value of "*" for userid.

To set permissions for a role

{
   "permission": "FIND" | "REMOVE" | "UPDATE",
   "role": rolename
}

To set permissions for all user roles, specify the "*" value for rolename.

Sample Response Body:

void or error

 

Messaging API

Overview

Data Messaging is an essential function of mobile and desktop applications. It can be used for a multitude of functions including chat or private messaging, system update broadcast, maintaining game scores, etc. The Backendless Messaging Service provides API and software infrastructure enabling publish-subscribe message exchange pattern and mobile push notifications. The service consists of the following core concepts: channels, publishers, subscribers and registered devices:

channel        -  a logical medium "transporting" the messages.
publisher        - a program using the Publishing API to send messages to a channel.
subscriber        - a program using the Subscription API to receive messages from a channel.
registered device        - a mobile device registered with a Backendless channel to receive push notifications.

 

Publish-Subscribe Messaging

With the publish-subscribe pattern, one part of the code (or an entire application) can subscribe to receive messages and another publishes messages. A message can be any data - Backendless supports messages of primitive or complex data types. To enable publish-subscribe messaging, Backendless supports the concept of a channel. Subscriptions are "attached" to a channel (or multiple channels) and messages are published into a channel. By default Backendless sends all messages published into a channel to all the channel's subscribers. However, a subscription can include message filters, in this case Backendless delivers only the messages matching the filter.

 

Push Notifications

A message published to a channel can be tagged as a push notification, thus triggering the logic for distributing it to the registered devices. Backendless supports push notifications for iOS, Android and Windows Phone devices. Messages published as push notifications can target either a specific subscriber (as a device) or a group of subscribers. Subscribers can be grouped by operating system (for example, a message sent to all registered iOS devices) or as a collection of individual registrations. The Backendless messaging API supports different types of push notifications - badge updates, alerts, etc.

Sending Email

Backendless provides API for email delivery on behalf of your application. Before the API can be used, the Backendless backend must be configured with your own SMTP server information. This is an important requirement as the API will not work if the Manage > App Settings > Email Settings section in Backendless Console contains default values.

 

Configuration


To configure the backend:

 

1. Login to Backendless Console.
2. Select an app.
3. Click Manage, then scroll down to Email Settings on the App Settings screen.
4. Fill out the form with the SMTP server information
email-settings.zoom50

 
where:

SMTP Server - Hostname or public IP address of the server where the SMTP server is running.
Port - The port number the SMTP server accepts requests on.
From - The Name which will appear in the From field of the sent out emails.
User ID - The user id or email address for the SMTP server connection authentication
Password - The password for the SMTP server connection authentication.
Security - Choose between SSL or TLS connection.

 

Make sure to click Test before saving any configuration changes. The Reset button discards any unsaved changes.

 

Sending Email API


Delivers an email message using current server-side email settings to the recipient specified in the API call.

 

Method:

POST

 
URL:

https://api.backendless.com/<app-id>/<REST-api-key>/messaging/email

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request body:

JSON Object:

{
 "subject" : value,
 "bodyparts" : {
    "textmessage" : value,
    "htmlmessage" : value
  },
 "to" : [ array of values ],
 "attachment" : [ array of file paths from the Backendless File Service ]
}

where:

subject - Email message subject.
bodyparts.textmessage - Plain text body of the email message.
bodyparts.htmlmessage - HTML version of the body of the email message.
to - An array of email addresses to deliver the email message to.
attachment - An array of file paths for the file entries from the Backendless File Service. Referenced files will be attached to the email message. The path is calculated from the root of the file system without the leading slash. For example if file agreement.txt is located at /documents/legal/, then the path in the REST request must be documents/legal/agreement.txt.

Example:

curl \
-H Content-Type:application/json \
-X POST \
-d '{"subject":"Hello World!", "bodyparts":{"textmessage":"This is an email message sent by Backendless"}, "to":["james.bond@mi6.co.uk"]}' https://api.backendless.com/XXXXX-XXXXX-XXXXX/ZZZZZ-ZZZZZ-ZZZZZ/messaging/email

 

 

Push Notifications

Push Notification Setup (Android)

Backendless can deliver published messages as push notifications to Android devices. Additionally, Backendless Console can be used to publish push notifications. In order to deliver a push notification to Android, the backend must be configured with Google API Key:

2. Click the Get started. Pick a platform button.
server-key-step1
3. Click Enable services for my Android App:
server-key-step2
4. Select your Android app from the list. if the app is not in the list, enter the name of the app, it will be automatically registered in the Google Developer Console.
5. Enter Android package name of your app.
6. Click Continue to Choose and configure services.
server-key-step3
7. Click Cloud Messaging and then click Enable Google Cloud Messaging:
server-key-step4
8. Google generates API key and sender ID. Copy Server API Key:
generated-ids
9. Open Backendless Console and select your application.
10. Click Manage and scroll down to Mobile Settings.
11. Paste the Google API Key into corresponding field located under the Android Push Notifications label:
adding-android-key.zoom50
12. Click Save. At this point the backend is configured and is ready to publish push notifications to Android devices.

 

Google Project Number (Sender ID)

In your project you should register the device in order to receive or send push notifications. To accomplish this, do the following:

1. Return to Step 8 in the instructions above.
2. Copy Sender ID.
3. Use the Sender ID value in Backendless.Messaging.registerDevice(...) method as GCMSenderID argument. For example:
google-project-number-in-code

Push Notification Setup (iOS)

Setting up your backend to support Push Notifications for iOS requires a few steps, most of which are in Apple Developer Member Center and Keychain Access.  The process consists of the following steps:

 

 

Creating App ID

1. First we are going to create an App ID for the mobile application which will receive Push Notifications. Login to Apple Developer Member Center. Click on "App IDs" in the "Identifiers" section. Use the plus sign "+" button to create a new ID:
create-app-id.zoom60
2. When prompted enter App ID Prefix. Make sure it is descriptive enough so you recognize it later when you return to the Member Center.
3. Select Explicit App ID in the "App ID Suffix" section and enter the same bundle ID which you will be using in the application:
appidsuffix.zoom95
4. In App Services select the services which the application will use and click "continue":
appservices.zoom95
5. Make sure that Push Notifications are enabled and click "submit". This will conclude the App ID creation for the app:
confirm-app-id-creation.zoom90

 

Creating Certificate Request

Push Notifications require a certificate which will be used on a device by the means of a provisioning profile. Also the same certificate (transformed to the Personal Information Exchange - .p12 format) will be used by Backendless to publish Push Notifications. If this makes little sense, do not worry, you will need to perform these steps only ones and then can move on to code and using the APIs.

1. In order to create a certificate a Certificate Signing Request (CSR) must be issued. To create a CSR, open Keychain Access and select Keychain Access >> Certificate Assistant >> Request a Certificate from the main menu:
certificaterequest.zoom80
2. Enter your email address and Common Name (leave the CA Email Address field empty), select "Saved to disk" and click "Continue":
CertificateRequestData
3. Select a directory where to save the file and click Save.

 

Generating an SSL Certificate

The CSR file created in the section above will be used to create an SSL Certificate. That certificate will then be used by Backendless to publish push notifications.

1. Return to Apple Developer Member Center and select "All" under "Certificates". Click the plus button "+" to add a new certificate:
membercenteraddcertificate.zoom60
2. Select certificate type - there are two options Development and Production. For now select "Apple Push Notification service SSL (Sandbox)":
push-cert-sandbox.zoom90
3. Select the App ID created earlier in these instructions:
SelectAppId
4. Next you will see the instructions for generating a CSR which you have already created by now. Click Continue to proceed to the next step.
5. Select the CSR file created and saved to the disk earlier and click Generate:
select-csr-file
6. The certificate is ready now, click "Download" to download it:
download-push-cert.zoom90
7. Add the certificate file to Keychain Access.
8. Open Keychain Access and locate the certificate in the "My Certificates" section:
locate-push-cert-keychain-access.zoom60
9. Right click on the certificate and select the Export option:
export-push-cert.zoom70
10. Save the certificate in the p12 format:
save-cert-p12-format
11. Enter a password for the certificate. Make sure to make a record of the password - you will need to use it later in the instructions when you submit the certificate to Backendless:
enter-password
12. Enter your Mac OS X account password to confirm the action. At this point you have a certificate for Push Notifications.

 

Configuring Backendless App/Backend with the Certificate

Since Backendless provides the actual server-side integration for delivering Push Notifications for your application, it needs to have access to the certificate you created above. The steps below provide the instructions for uploading the certificate into Backendless:

1. Login to Backendless Console and select an application which you will use on the server-side.
2. Click Manage > App Settings. Locate the Mobile Settings section and click the IOS menu.
3. Click the Add Certificate button and upload the .p12 certificate created earlier. Make sure to enter the same password you used when created the certificate. The Channels control lets you select the messaging channels which the certificate will be used with. If you intend to use only one certificate, click the Add channels checkbox.
add-ios-cert
4. Now your Backendless server is ready to publish Push Notifications.

Device Registration

In order to receive push notifications from Backendless, a device must be registered using the API documented below. Device registration may optionally include a list of messaging channels and/or an expiration date/time when the registration should be canceled.

 

Push notifications can be published using either API or Backendless Console. When a push notification is published, it goes through a messaging channel. Channels provide a way to establish a level of filtering - devices registered with a channel will receive notifications published to the channel. However, there are other way to narrow down push notification delivery. For example, a push notification may be sent to a specific device or a group of devices.

 

If no channels are specified in the device registration call, Backendless registers the device with the default channel. If the device registration call references a non-existing channel, Backendless creates the channel and registers the device with it. Registration expiration is a point in time (expressed as a timestamp) when the device registration must expire. Backendless removes the device registration at the specified time and the device no longer receives published push notifications.

 

In order to receive push notifications on a mobile device, application running on the device must register with Backendless using the API call below:

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/registrations

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

 

Request Body:

{
 "deviceToken" : value,
 "deviceId" : value,
 "os" : "IOS" | "ANDROID" | "WP",
 "osVersion": value
 [,"channels": [channelName1, channelName2]],
 [,"expiration": timestamp in GMT0]
}

where:

deviceToken - a token assigned by the push notification service provider (Google Cloud Messaging, Apple Push Notifications, Microsoft Push Notification Service).
deviceId - a unique identification of the device where push notifications will be delivered to.
os - operating system identifier
osVersion - version of the operating system
channels - an array of Backendless messaging channels to subscribe to. Backendless delivers channel's message to the devices if the message is marked as a push notification.
expiration - a timestamp indicating when the device registration should expire.

 

Response Body:

{
 "registrationId" : value
}

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

 

The following errors may occur during the message publishing API call:

Error Code

Description

5004

Invalid expiration date. The expiration date must be after the current time.

8000

Property value exceeds the length limit. Error message should contain additional details about the violating property.

Example:

curl \
-H Content-Type:application/json \
-X POST \
-d '{ \
  "deviceToken":"XXXXXXXXXXXXXXXXXXXXXXXXX", \
  "deviceId":"XXXXXXXXXXXXXXXXXXXXXXXXX",    \
  "os":"ANDROID",  \
  "osVersion":"4.1" \
  }' \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZZ-ZZZZZ/messaging/registrations

 

Retrieve Device Registration

Backendless server returns information about device registration with the API documented below. The input parameter of the API is deviceId - the value returned by the device registration API.

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/registrations/<device-id>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<device-id> - ID of the device to retrieve the device registration information for. Must be the same ID used in the Device Registration call.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

{
 "deviceToken" : value,
"deviceId" : value,
"os" : "IOS" | "ANDROID" | "WP",
"osVersion": value
 [,"channels": [channelName1, channelName2]],
 [,"expiration": timestamp in GMT0]
}

where:

deviceToken - a token assigned by the push notification service provider (Google Cloud Messaging, Apple Push Notifications, Microsoft Push Notification Service).
deviceId - a unique identification of the device where push notifications will be delivered to.
os - operating system identifier
osVersion - version of the operating system
channels - an array of Backendless messaging channels device is registered with.
expiration - a timestamp indicating when the device registration should expire.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the device registration API call

Error Code

Description

5000

Unable to retrieve device registration - unknown device ID.

Examples:

curl -X GET \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZZ-ZZZZZ-ZZZZ/messaging/registration/YYYYYYYYYYY

 

Managing Registrations

Application developers can manage device registrations using the Backendless Console. To see the device registrations:

1. Login to Backendless Console and select an app where you would like to see the device registrations.
2. Click the Messaging icon and Devices menu.

devices-screen.zoom50

The table displays all the current device registrations. Using the interface, you can:

Search for device registrations. The search string applies to all columns
Remove device registrations. To remove, use the check boxes and then click the Delete button
Deliver push notifications to the selected devices.

Publish Push Notifications

Backendless supports push notification delivery to iOS, Android and Windows Phone devices. A device must be registered (see the Device Registration API) in order to receive a push notification. A push notification can be published via API or using the Backendless Console. The content of a push notification consists of a message body and the specialized message headers.

 

Publish a Push Notification from Console

To publish a push notification from Backendless console, navigate to the Messaging screen and click the Devices tab. Make sure there are registered devices, otherwise a push notification has nowhere to go.

1. Select the check boxes for the device(s) you would like to send a notification to. Select Android or iOS tab to enter push notification parameters.
2. Enter parameter values into the corresponding fields.
3. Click the Publish Message button to send a push notification.
messaging-screen-v4.zoom50

 

Publish Push Notification with API

Message publishing API supports the following scenarios:

 

Basic push notification - In the simplest form a push notification is sent to a channel and this to all the devices registered with the channel. The notification message must contain appropriate headers which control the appearance of the notification on the devices. Example.

 

Push notification delivered to devices grouped by the OS - With this type of message delivery push notifications can be sent to all devices of a specific operating system (or a group of).  This includes delivery to Android, iOS or Windows Phone devices or a any combination of. Example.
 
Push notification delivered to specific devices - This delivery type allows push notification delivery to individual devices. Example
 
Delayed publishing - For all scenarios described above a push notification request can be configured to be executed at a later time (thus "delayed publishing"). Messages published with this delivery option can be canceled at any time using the message cancellation API. Example.

 

Push Notification Headers

The headers described below must be added to the "publish options" object or in case of REST clients, they are plain message headers:

Operating System

Headers

Description

iOS

"ios-alert":value

Sets the text of the alert message. If the header is not present and the published notification targets the iOS devices, Backendless sets the header to the value of the "message" argument. To disable this behavior, set the ios-alert header to null.

"ios-badge":value

Sets the value to update the badge with

"ios-sound":URL string or array of bytes

Sets either a URL for the sound notification to play on the device or an array of bytes for the sound to play.

Android

"android-ticker-text":value

Sets the text of the ticker showing up at the top of a device's screen when the device receives the notification.

"android-content-title":value

Sets the title of the notification as it is visible in the Android Notification Center

"android-content-text":value

Sets the message of the notification which appears under android-content-title in the Android Notification Center.

Windows Phone

"wp-title":value,
"wp-content":value

Sets the title and the content of a toast notification.

"wp-type":"TILE":
"wp-title" : value,
"wp-backgroundImage" : URL string,
"wp-badge" : number value,
"wp-backTitle" : value,
"wp-backImage" : URL string,
"wp-backContent" : value

Sets the properties for a tile notification.

"wp-type":"RAW",
"wp-raw":XMLString

Sets the properties for a raw notification

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/<channel-name>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<channel-name> - name of the channel to publish the message to.

 

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

Optional parameters are shown in [square brackets]:

{
 "message" : value,
 ["publisherId" : value,]
"headers": {"key1":"value1","key2":"value2"}
 ["pushPolicy":"ONLY" | "ALSO",]
 ["pushBroadcast" : IOS | ANDROID | WP | ALL,] // value is a mask
 ["pushSinglecast": ["regId1", "regId2",] // value is an array
 ["publishAt":timestamp,] // value in milliseconds
 ["repeatEvery":frequency-in-seconds,]
 ["repeatExpiresAt":expiration-timestamp] // value in milliseconds
}

where:

headers - must contain specialized headers controlling the content and appearance of the push notification on the devices.
pushPolicy - if set to ONLY, message is published only as push notification, otherwise if the value is ALSO, the message is published as both push notification and a pub/sub message
pushBroadcast - Must be a value calculated as an OR mask from the following constants: IOS = 1, ANDROID = 2, WP = 4, ALL = 7 (IOS | ANDROID | WP  = 7). For example, to send a push notification to all IOS and ANDROID devices, the value must be (1 | 2 ), which is 3.
pushSinglecast - contains a JSON array of device IDs which will be receiving the push notification.
publishAt - is a timestamp when the push notification should be sent.
releatEvery - is a number of seconds defining the frequency of sending the notification.
repeatExpiresAt - is a timestamp when the repeat publishing operation of the push notification must stop.

Response Body:

{
 "status" : "scheduled" | "failed",
 "messageId": messageId
}

In order to obtain message publishing status, use the Get Message Status API with the messageId value returned by the message publishing request.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the message publishing API call:

Error Code

Description

5003

Invalid repeatExpiresAt date

5007

User does not have the permission to publish messages

5030

Invalid publishAt date

Examples:

Basic push notification

Targeting a group of devices (grouped by OS)

Targeting specific devices

Delayed publishing

Basic push notification
curl -H Content-Type:application/json -X POST \
-d '{"message":"Hi Devices!", \
    "headers":{ \
          "android-ticker-text": "You just got a push notification!", \
          "android-content-title": "This is a notification title",  \
          "android-content-text": "Push Notifications are cool"  \
    }}'  \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/messaging/Default

Targetting a group of devices

curl -H Content-Type:application/json -X POST \
-d '{ \
     "message":"Hi Devices!", \
    "pushBroadcast":"ANDROID|IOS", \
      "headers":{  \
                 "android-ticker-text": "You just got a push notification!", \
                 "android-content-title": "This is a notification title",  \
                 "android-content-text": "Push Notifications are cool"  \
              }  \
   }' \
-v https://api.backendless.com/XXXXX-XXXXX-XXXX/ZZZZZ-ZZZZZ-ZZZZZ/messaging/Default

Targeting specific devices
 

curl  -H Content-Type:application/json -X POST \
-d '{ \
     "message":"this is a private message!", \
     "pushSinglecast": [ "receiver-device-id" ], \
     "headers":{  \
          "android-ticker-text": "You just got a private push notification!", \
          "android-content-title": "This is a notification title", \
          "android-content-text": "Push Notifications are cool" \
     } \
   }'  \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZ/messaging/Default

Delayed publishing

curl -H Content-Type:application/json -X POST  \
-d '{  \
 "message":"hello world!", \
 "headers":{ \
            "android-ticker-text": "You just got a private push notification!", \
            "android-content-title": "This is a notification title", \
            "android-content-text": "Push Notifications are cool" \
           }, \
 "publishAt": timestamp \\
}'  \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZZ/messaging/Default

 

Get Message Status

Backendless processes push notification delivery asynchronously. Even when the client app uses blocking/synchronous API, the server creates a push notification delivery task and adds to a queue. Server assigns an ID to the task and returns it to the client as messageId. As a result, push notification delivery status is not available right away. To retrieve the status, the client application must make a separate API call documented below:

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/<message-id>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<message-id> - ID of the message assigned to the message and returned by the Message Publishing API request.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

{
 "status" : "failed" | "published" | "scheduled" | "cancelled" | "unknown",
 "messageId" : value,
 "errorMessage" : value
}

If the status property is "failed", the errorMessage property should contain the details of the failure.

 

Cancel Device Registration

To cancel the registration of a device with Backendless, an application can use the API described below:

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/registrations/<device-id>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<device-id> - ID of the device to cancel the device registration information for. Must be the same ID used in the Device Registration call.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

{
 "result" : "true" | "false",
}

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the device registration cancellation API call

Error Code

Description

5001

Unable to cancel device registration - unknown device ID.

Example:

curl -X DELETE \
-v https://api.backendless.com/XXXXX-XXXXX-XXXXX/ZZZZZ-ZZZZ-ZZZZ/messaging/registration/wwwwww-device-id-wwwww

 

Publish/Subscribe Messaging

Message Publishing

Application can publish messages to Backendless for subsequent distribution to subscribers. A message must be published to a channel (or a group of channels). Backendless supports unlimited number of channels per application. Channels can be used as a filtering mechanism - channel subscribers see messages published only to the channel. Message publishing supports the following scenarios:

 

Publishing with message headers - headers is a collection of name/value pairs. A subscriber can set filters expressed as SQL "where clause" queries which Backendless uses to determine if a message should be delivered to the subscriber. When the query matches the published data in message headers, message is delivered to the corresponding subscriber. See example.
 
Publishing to a subtopic - Subtopics provide an additional level of message filtering.

Multiple subtopics can be defined within a channel. Both publishers and subscribers can specify a subtopic within a channel. Subtopic names can be defined using a multi-tiered format:

maintoken[.secondaryToken][.additionalToken]

 

To receive messages from more than one subtopic, subscribers can use the wildcard character (*) in place of any tokens in the subtopic name. For instance, a subscriber could subscribe to the following subtopic: "news..business.*", and the publisher sends messages to "news.business.newyork" and "news.business.tokyo". In this case the messages published to either subtopic will be delivered to the consumer.

 

The wildcard character in the last position will match any token in that position as well as tokens after it. For instance, subtopic com.foo.* will match all of the following: com.foo.bar, com.foo.abc.def, etc. However, the wildcard character in any position other than the last will match only one token. For example, subtopic com.*.foo will match com.abc.foo and com.123.foo, but will not match com.foo.

See example.
 

Delayed publishing - Backendless immediately processes any published messages and delivers them to subscribers without any delay. However, publishers can specify the time when the message should be processed. This is applicable to all the publishing options listed above. Message processing can be canceled at any time using the message cancellation API. See example.
 
Scheduled (repeated) publishing - Backendless supports repeated message processing - a message is published once, but delivered to subscribers with the specified frequency. Repeated delivery can stop either at the specified time or they can be canceled using the message cancellation API. For instance, this could be used for reminders or scheduled tasks. See example.

 

Method Signatures

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/<channel-name>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<channel-name> - name of the channel to publish the message to.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

Optional parameters are shown in [square brackets]:

{
 "message" : value,
 ["publisherId" : value,]
 ["headers": {"key1":"value1","key2":"value2"}]
 ["subtopic":value,]
 ["pushPolicy":"ONLY" | "ALSO",]
 ["publishAt":timestamp,] // the value in milliseconds
 ["repeatEvery":frequency-in-seconds,]
 ["repeatExpiresAt":expiration-timestamp] // the value is to be in milliseconds
}

where:

headers - contains message headers. Headers deliver additional content to the subscribers, but also may be referenced by subscribers for message filtering purposes.
pushPolicy - if set to ONLY, message is published only as push notification, otherwise if the value is ALSO, the message is published as both push notification and a pub/sub message. Default value is ALSO.
publishAt - is a timestamp when the push notification should be sent.
releatEvery - is a number of seconds defining the frequency of sending the notification.
repeatExpiresAt - is a timestamp when the repeat publishing operation of the push notification must stop.

Response Body:

{
 "status" : "scheduled" | "failed",
 "messageId": messageId
}

In order to obtain message publishing status, use the Get Message Status API with the messageId value returned by the message publishing request.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the message publishing API call:

 

Error Code

Description

5003

Invalid repeatExpiresAt date

5007

User does not have the permission to publish messages

5030

Invalid publishAt date

Examples:

Basic message publishing

Publishing with message headers

Publishing to a subtopic

Delayed publishing

Repeated publishing

 

Basic message publishing

curl -H Content-Type:application/json -X POST \
-d '{"message":"hello world!"}' \
-v https://api.backendless.com/XXXXX-XXXX-XXXXX/ZZZZ-ZZZZZ-ZZZZZ/messaging/Default

Publishing with message headers

curl -H Content-Type:application/json -X POST \
-d '{"message":"hello world!", "headers":{"city":"Tokyo"}}' \
-v https://api.backendless.com/XXXXX-XXXXX-XXXXX/ZZZZZ-ZZZZZ-ZZZZZ/messaging/Default

Publishing to a subtopic
 

curl -H Content-Type:application/json -X POST \
-d '{"message":"get free coffee at Moonbucks today", "subtopic":"news.business.newyork"}' \
-v https://api.backendless.com/XXXXX-XXXX-XXXXX/ZZZZ-ZZZZ-ZZZZZ/messaging/Default

Delayed publishing

curl -H Content-Type:application/json -X POST \
-d '{ \
 "message":"hello world!", \
 "publishAt": timestamp \
}' \
-v https://api.backendless.com/XXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/messaging/Default

Repeated publishing
 

curl -H Content-Type:application/json -X POST \
-d '{ \
 "message":"this is a recurring message!", \
 "repeatEvery": 20, \
 "repeatExpiresAt": timestamp \
}' \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/messaging/Default

 

Get Message Status

Backendless server handles message publishing as an autonomous task. As a result, the status of the message publishing operation is not available right away. To retrieve publishing status, the client application must make a separate API call documented below:

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/<message-id>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<message-id> - ID of the message assigned to the message and returned by the Message Publishing API request.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

{
 "status" : "failed" | "published" | "scheduled" | "cancelled" | "unknown",
 "messageId" : value,
 "errorMessage" : value
}

If the status property is "failed", the errorMessage property should contain the details of the failure.

 

Message Filtering

Backendless message filtering is a powerful mechanism enabling conditional message delivery, interest-based subscriptions and private messaging. A subscription request may include filters in the form of subtopics and selectors. Backendless applies subscriber's filters to every message published into the channel and they match, the message is delivered to the subscriber.

 

Subtopics

Multiple subtopics can be defined within a channel. Both publishers and subscribers can specify a subtopic within a channel. Subtopic names can be defined using a multi-tiered format:

maintoken[.secondaryToken][.additionalToken]

 

To receive messages from more than one subtopic, subscribers can use the wildcard character (*) in place of any tokens in the subtopic name. For instance, a subscriber could subscribe to the following subtopic: "news..business.*", and the publisher sends messages to "news.business.newyork" and "news.business.tokyo". In this case the messages published to either subtopic will be delivered to the consumer.

 

The wildcard character in the last position will match any token in that position as well as tokens after it. For instance, subtopic com.foo.* will match all of the following: com.foo.bar, com.foo.abc.def, etc. However, the wildcard character in any position other than the last will match only one token. For example, subtopic com.*.foo will match com.abc.foo and com.123.foo, but will not match com.foo.

 

Selectors

A selector is a query expressed using the SQL-92 syntax and formatted as the condition part of the SQL's WHERE clause. A query condition must reference the headers of the published messages. When a message is published and a subscriber has a selector query, Backendless executes the query on the headers of the published message. If the result of the query is true, the message is delivered to the subscriber. Consider the following example where the subscriber will receive only messages containing the "city" header with the value of "Tokyo":

 

Publisher:

curl -H Content-Type:application/json -X POST \
-d '{  \
     "message":{ "temperature":70, "humidity":80 }, \
     "headers":{ "city":"Tokyo" } \
   }' \
-v https://api.backendless.com/XXXX-XXXXX-XXXXX/ZZZZ-ZZZZZ-ZZZZZ/messaging/Default

Subscriber:

curl -H Content-Type:application/json -X POST \
-d "{ \"selector":"city = 'Tokyo'\" }" \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/messaging/Default/subscribe

 

Message Subscription

In order to receive published messages, application must subscribe to a channel using the API described below. Using the API, an application becomes an "API subscriber".

    Message retrieval by REST Clients is a two-step process:

1. REST client must establish a subscription. Subscription request may include filtering options such as a subtopic and/or selector. The result of the subscription request is the subscription ID assigned by Backendless.
2. Once a subscription is established, the client can send requests to retrieve messages for the subscription.

 

Establishing a Subscription

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/<channel-name>/subscribe

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<channel-name> - name of the channel to subscribe to.

Request Headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

Optional parameters are shown in [square brackets]:

{
 ["subscriberId" : value,]
 ["subtopic":value,]
 ["selector":selector-query]
}

Response Body:

{
"subscriptionId" : value
}

Retrieving Messages

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/messaging/<channel-name>/<subscription-id>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<subscripton-id> - ID of the subscription to retrieve the messages for. The ID must be established with the request described above.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

{
 "messages":
 [
   {
     "messageId":value,
     "data":value,
     "publishedAt":timestamp,
     ["publisherId":value,]
     ["headers": {"key1":"value1","key2":"value2"}]
   },
   ...
 ]
}

 

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the message cancellation API call:

Error Code

Description

5008

User does not have permission to create a subscription.

5009

General subscription error. See error message for additional details.

5010

Unknown messaging channel.

Message Object

Each message in the response contains the following parameters:

where:

messageId - unique message ID. The ID is assigned at the time of message publishing.
headers - an associative array which is a collection of key/value pairs. Includes all the headers included with the message publishing. Additionally, Backendless adds the following headers: BL_APPLICATION_ID - contains the ID of the application and BL_VERSION_URL_PREFIX - contains the name of the version of the application.
data - message payload. It is the object sent by a publisher.
publisherID - the property contains sender (publisher) ID if it is provided by the publisher.
timestamp - a timestamp indicating when the message was received by Backendless from the publisher.

 

Examples:

Establishing a subscription:

 

Request:

curl -X POST \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/messaging/Default/subscribe

Response:

{
"subscriptionId":"1BA31C04-CDCA-2AC0-FF76-6E6F81101100"
}

Retrieving messages for the subscription:

 

Request:

curl -X GET
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZZ-ZZZZZ-ZZZZ/messaging/Default/wwwwwwwwwwwwwwwwwwwwwwww

Response:

{
 "messages":[
     {
        "headers":{
           "DSId":"FC6FB0BB-4449-0D1D-FFAE-4670D1138200",
           "DSDstClientId":"AD12813D-7BC1-A216-FF65-E86D00A14000",
           "BL_APPLICATION_ID":"3FAD6F76-617D-7EDD-FF4D-AE26C5C04F00",
           "BL_VERSION_URL_PREFIX":"v1"
        },
        "publishedAt":1359071622226,
        "publisherId":null,
        "data":"Hello World",
        "messageId":"D98A994C-7EF6-7DE2-FFC3-95807BDF8700-4428"
     }
  ]
}

 

Cancel Scheduled Message

Delayed or scheduled messages can be canceled using the API documented below. Backendless processes delayed messages at the time specified by the publisher. Scheduled messages are processed and delivered with a specified interval.

 

Method Signatures

Method:

DELETE

URL:

http://api.backendless.com/<application-id>/<REST-api-key>/messaging/<message-id>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<message-id> - ID of the message to cancel.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

{
"status" : "failed" | "canceled",
"messageId": messageId
}

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The following errors may occur during the message cancellation API call:

Error Code

Description

5040

Message has already been canceled or does not exist.

Example:

curl -X DELETE \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/messaging/yyyyyy-yyyyy-yyyyy

 

Files API

Overview

Every Backendless backend/app is allocated a dedicated file storage space. The file storage is located remotely on the Backendless servers. The file storage can be used to store application's files and on-demand video streams.  Backendless File Service provides the API to work with the file storage. The API supports the following operations:

 

File Upload - upload files to the applications's file storage. The operation creates directories up the hierarchy if necessary. Returns file URL which can be used to download or share the file with others.
File Download - download file using file's URL. The download operation is subject to the permissions from the File access control list (ACL).
File Deletion - delete a file from the file storage. The delete operation is subject to the permissions from the File access control list (ACL).
Directory Deletion - same as file deletion, but applies to the directories.
File/Directory Security (File ACL) - assign/unassign user and roles permissions to upload, download and delete files and directories. This API is used to modify file or directory ACL.

 

In addition to the API implementation, the File Service enables the following capabilities:

 

Git Integration - application developers can interact with the file storage as with a git repository.
Web Hosting - file storage can be used to host static web content.
Custom Domain Name - a custom domain name can be mapped to the file storage in a Backendless backend. This feature in combination with the Web Hosting provides a way to host websites on Backendless.
Custom Web Templates Hosting - includes HTML files and JS scripts for special pages used in various workflows such as user email confirmation, password change and session expiration.

Handling Files in Console

Backendless Console includes a graphical file browser which supports the following operations:

Creating a New File

To create a file:

1. Log in to Backendless Console and select an application. Click the Files icon:
files-screen1.zoom50
2. Select a directory where a new file should created (or create a new directory). Click the New File link from the toolbar.
3. Enter a name in the File name field. Additionally, you can select syntax highlighter from the menu located in the lower-right corner. The highlighter selection is available only for new files. When an existing file is opened for editing, a highlighter is automatically selected based on the file extension.
files-screen2.zoom50
4. To save the file click the Save or the Save and Close button.

Editing a File

To edit a file:

1. Select a directory containing the file on the Files screen of the console.
2. Click the Edit file icon in the Actions column for the file to open it for editing:

files-screen3

3. Once the changes in the file are made click the Save or the Save and Close button.

Getting Public URL for a File

A file in the Backendless File Storage has two URLs:

a public URL which can be used to download the file outside of Backendless console. This URL is subject for any permissions assigned to the file or the directory where it resides.
a private URL which makes the file accessible to the developer of the application.

In order to obtain the public URL:

1. Select a directory containing a file on the Files screen of Backendless console.
2. Click the Get Public URL icon next to the file. Backendless console copies the file's public URL to the computer's clipboard:

files-screen4

To get file's private URL:

Right click file name and select "Copy Link Address" (text of the menu may vary depending on the browser):
files-screen5

File's private URL works only if the request to download the file contains the auth-key HTTP header. The value of the header is a token assigned by Backendless to the developer login to console.

Archiving Files

Backendless Console includes a feature enabling to compress directories into a single ZIP file. The feature applies specifically to directories, meaning an individual file cannot be compressed - it must be placed into a directory first.

Notice: archiving of directories with total content size greater than 100 Mb may take longer time; Backendless sends an email to the application developer upon successful completion of the operation.

To archive a directory:

1. Log in to Backendless Console, select an application and click the Files icon.
2. Navigate to a directory which should be compressed.
3. Click the ZIP Directory button:
files-screen6
4. Once the directory is compressed into an archive, it will appear in the parent directory:
files-screen7

File Upload

The file upload operation delivers and saves a local file in the remote Backendless file storage. The return value of the operation is the file URL which has the following structure:

https://api.backendless.com/<application id>/<REST-api-key>/files/<path>/<file name>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<path> - directory path where the file is saved
<file name> - name of the file

The URL assigned to a file and returned as a result of the upload operation accounts for any security permissions assigned to the file (or the folder it is located in).

Method:

POST

URL:

https://api.backendless.com/<application-id><REST-api-key>/files/<path>/<filename>?overwrite=true

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<path> - directory path in the Backendless file storage where the file should be stored. If the path does not exist, Backendless File Service creates the directory structure.
<filename> - name of the file the upload is saved as.
overwrite - defines whether a newly saved file overwrites the existing file. If the argument value is true, the new file overwrites the existing one. Otherwise, if the value is false or the overwrite parameter is not present, and another file with the same name already exists, the server returns an error.

Request headers:

Content-Type: multipart/form-data
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to multipart/form-data. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

File contents formatted per the multipart/form-data requirements.

Response Body:

{
 "fileURL" : file URL which should be used to download the file
}

Example:

curl -H Content-Type:"multipart/form-data" \
--form upload=@test.txt \
-X POST \
-v http://api.backendless.com/XXXX-XXXXX-XXXX/ZZZZ-ZZZZ-ZZZZZ/files/txtfiles/test.txt

 

Save Files From Byte Arrays

In addition to the classic file upload, files can be saved by uploading a byte array which becomes the content of the saved file.

You can save a file with or without overwriting the existing file. To specify this, use overwrite argument.

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/files/binary/<filePath>?overwrite=true

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<filePath> - path to a directory where the file will be stored located.
overwrite - defines whether a newly saved file overwrites the existing file. If the argument value is true, the new file overwrites the existing one. Otherwise, if the value is false or the overwrite parameter is not present, and another file with the same name already exists, the server returns an error.

Request headers:

Content-Type: multipart/form-data
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to multipart/form-data. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

A byte array encoded as a Base64 string.

Response Body:

URL of the newly saved file or an error.

Example:

The example below saves the "savedNote.txt" file with the content "my cool note". The content must be encoded in the Base64 format, hence the value is "bXkgY29vbCBub3Rl"

curl -H Content-Type: text/plain -X PUT \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/binary/testFolder/savedNote.txt?overwrite=true" \
-d bXkgY29vbCBub3Rl

where

-d - the request body
bXkgY29vbCBub3Rl - a byte array (string) encoded as a Base64 string. The decoded value is "my cool note".

 

The server will return the URL of the newly saved file:

"https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/testFolder%2FsavedNote.txt"

If you opt not to overwrite the existing file,the overwrite argument may be skipped or set to false. In that case, if the file already exists, a new file is not saved and server will return an error. If the file does not exist, the server will return the URL of the newly saved file.

Errors:

When the server-side reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

Error codes returned on attempt to save a file from the byte array.

Error Code

Description

6016

When saving a new file from the byte array, the payload exceeds 2,800,000 bytes.

6003

A file you are trying to save already exists in the system and cannot overwrite since overwrite argument is ether set to false or omitted.

 

File Download

Downloading a File via the Backendless Console

To download a file:

1. Log in to Backendless Console and select the application containing the file.
2. Click the Files tab on the left menu.
3. Locate a file you want to download. Click the Download file icon.

files-screen8

Downloading a File via API

Downloading a file from the Backendless file storage is the basic HTTP GET operation. The operation should use the same URL which Backendless returned as the result of the file upload operation. Alternatively, if the file was uploaded manually using the console, the URL can be composed as:

https://api.backendless.com/<application id>/<REST API key>/files/<path>/<file name>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console.
<REST API key> - REST API key assigned to the application by Backendless. The key is available from the Manage > App Settings screen of the Backendless Console.
<path> - Directory path where the file is saved.
<file name> - Name of the file.

Files fetched with the URL scheme defined above are subject to the security constraints and permissions established by the application developer. See the Files Security section for additional details on how to secure file storage. Fetching a file secured by an access control list (ACL) policy requires an additional HTTP header in the request:

user-token:<value>

where:

<value> - a value identifying currently logged in user (if any). This is the value received in the response for the login API request.  The token uniquely identifies the user and the roles associated with him. It is used by Backendless to establish user's identity for all operations where the token is present. It is necessary in order to determine permissions applicable to the user and the roles associated with the account. This header is optional.

Renaming a File/Directory

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/files/rename

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

A JSON object identifying a file or directory to be renamed and the new name:

{
 "oldPathName" : current-name,
 "newName": new-name
}

where:

current-name - a path identifying file or directory to be renamed. The must start with the root directory for the file storage allocated to the application.
new-name - new name for the file or directory.

 
Return value:

Absolute path of the renamed file or directory.

Example:

The example below describes how to rename a file called readme.txt located in the /documentation directory to readme-first.txt:

curl -H Content-Type: application/json -X PUT \
-v https://api.backendless.com/XXXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/rename \
-d "{ \"oldPathName\":\"/documentation/readme.txt\", \"newName\":\"readme-first.txt\" }"

Errors:

When the backend reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The server may return the following errors:

Error Code

Error message

Notes

4000

User has no permissions to specified resource

Occurs when the user (anonymous or logged in) has no permission to modify the file

6000

File or directory cannot be found.

Occurs when the source file/directory cannot be found.

6006

Path contains prohibited symbols: {path name}


6007

The specified resource was not found

Occurs when the API requests to rename a non-existent file or a directory.

6018

Unable to modify file/folder: file/folder already exists: {file/directory name}

Occurs when the target file/directory already exists.

6028

Parameter {param name} cannot be null

Occurs when one of the parameters is null.

8010

Missing field {field name}

Occurs in REST APIs when one of the required fields is missing in the body.

Copying a File/Directory

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/files/copy

where:

<version> - name of the application's version. Application versions can be managed using Backendless Console. Login to the console, select an application, click Manage, then Versioning. Backendless automatically creates version "v1" for any new application.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

A JSON object identifying a file or directory to be renamed and the new name:

{
 "sourcePath" : source-path,
 "targetPath": target-path
}

where:

source-path        - a path identifying file or directory to be copied. The path must start with the root directory of the remote file storage.
target-path        - a path to a directory where the source file or directory should be copied to. If the directory does not exist, it is created.

Return value:

Absolute path to the copied file or directory.

Example:

The example below describes how to copy a file called readme.txt located in the /documentation directory to the /updated-docs directory:

curl -H Content-Type: application/json -X PUT \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/copy \
-d "{ \"sourcePath\":\"/documentation/readme.txt\", \"targetPath\":\"/updated-docs\" }"

Errors:

When the backend reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The server may return the following errors:

Error Code

Error message

Notes

4000

User has no permissions to specified resource

Occurs when the user (anonymous or logged in) has no permission to modify the file

6000

File or directory cannot be found.

Occurs when the source file/directory cannot be found.

6006

Path contains prohibited symbols: {path name}


6007

The specified resource was not found

Occurs when the API requests to rename a non-existent file or a directory.

6018

Unable to modify file/folder: file/folder already exists: {file/directory name}

Occurs when the target file/directory already exists.

6028

Parameter {param name} cannot be null

Occurs when one of the parameters is null.

8010

Missing field {field name}

Occurs in REST APIs when one of the required fields is missing in the body.

8011

Content type should be 'application/json'

Occurs in REST API when the request's content type is not application/json

Moving a File/Directory

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/files/move

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

A JSON object identifying a file or directory to be renamed and the new name:

{
 "sourcePath" : source-path,
 "targetPath": target-path
}

where:

source-path        - a path identifying file or directory to be moved. The path must start with the root directory of the remote file storage.
target-path        - a path to a directory where the source file or directory should be moved to. If the directory does not exist, it is created.

Return value:

Absolute path to the copied file or directory.

Example:

The example below describes how to move a file called readme.txt located in the /documentation directory to the /updated-docs directory:

curl -H Content-Type: application/json -X PUT \
-v https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/move \
-d "{ \"sourcePath\":\"/documentation/readme.txt\", \"targetPath\":\"/updated-docs\" }"

 
Errors:When the backend reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The server may return the following errors:

Error Code

Error message

Notes

4000

User has no permissions to specified resource

Occurs when the user (anonymous or logged in) has no permission to modify the file

6000

File or directory cannot be found.

Occurs when the source file/directory cannot be found.

6006

Path contains prohibited symbols: {path name}


6007

The specified resource was not found

Occurs when the API requests to rename a non-existent file or a directory.

6018

Unable to modify file/folder: file/folder already exists: {file/directory name}

Occurs when the target file/directory already exists.

6021

Unable to move file to file


6023

File already exists in target directory


6028

Parameter {param name} cannot be null

Occurs when one of the parameters is null.

8010

Missing field {field name}

Occurs in REST APIs when one of the required fields is missing in the body.

8011

Content type should be 'application/json'

Occurs in REST API when the request's content type is not application/json

Directory Listing

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/files/<path>?
                   pattern=<pattern>&
                   sub=<recursive>&
                   pagesize=<pagesize>&
                   offset=<offset>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<path> - path of a directory to get a listing of. The path must start with the root directory identified by forward slash, for example: "/web".
<pattern> - an optional parameter. A pattern which the returned files and directories must match.
<recursive> - an optional parameter. A boolean value of true or false. If present and is true, requests that the listing must be retrieved recursively for all directories contained within <path>.
<pagesize> - an optional parameter. If present, identifies how many items should be returned in the response.
<offset> - an optional parameter. If present, indicates the index of item in the response from which to get the <pagesize> items.

Request headers:

user-token: optional value obtained as a result of the login operation.

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None.

Return value:

A collection of files and directories matching the specified pattern. The returned collection may not include all files and directories as the size of the number of returned entries is limited for paging purposes. To get the next set of file/directory entries, an additional request must be made with a different offset value. The total count of all files/directories in the listing use the Get File Count API.

Each element in the collection contains the following properties:

name - name of the file or directory without any path information
public URL - absolute URL of the file or directory
URL - relative URL of the file or directory starting from the root of the file storage
created on - a timestamp indicating when the file or directory were created

Example:

The example below describes how to get a listing of all HTML files from the /web directory and all subdirectories.

curl "https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/web?pattern=*.html&sub=true"

The result of the command is the following response (the contents of the response for your application may be different):

[
   {
     "name": "disabled.html",
     "createdOn": 1438338861000,
     "publicUrl": "https:\/\/api.backendless.com\/757E349F-C515-5AF3-FF5DEFF0379BFB00\/v1\/files\/web\/templates\/registration\/disabled.html",
     "size": 1024,
     "url": "web\/templates\/registration\/disabled.html"
   },
   {
     "name": "index.html",
     "createdOn": 1438338861000,
     "publicUrl": "https:\/\/api.backendless.com\/757E349F-C515-5AF3-FF5D-EFF0379BFB00\/v1\/files\/web\/index.html",
     "size": 1024,
     "url": "web\/index.html"
   },
   {
     "name": "index.html",
     "createdOn": 1439519289000,
     "publicUrl": "https:\/\/api.backendless.com\/757E349F-C515-5AF3-FF5D-EFF0379BFB00\/v1\/files\/web\/scripts\/examples\/shoppingcart\/index.html",
     "size": 9216,
     "url": "web\/scripts\/examples\/shoppingcart\/index.html"
   },
   {
     "name": "index.html",
     "createdOn": 1438338861000,
     "publicUrl": "https:\/\/api.backendless.com\/757E349F-C515-5AF3-FF5DEFF0379BFB00\/v1\/files\/web\/templates\/change_password\/index.html",
     "size": 1024,
     "url": "web\/templates\/change_password\/index.html"
   },
   {
     "name": "index.html",
     "createdOn": 1438338861000,
     "publicUrl": "https:\/\/api.backendless.com\/757E349F-C515-5AF3-FF5D-EFF0379BFB00\/v1\/files\/web\/templates\/registration\/index.html",
     "size": 1024,
     "url": "web\/templates\/registration\/index.html"
   },
   {
     "name": "index.html",
     "createdOn": 1438338861000,
     "publicUrl": "https:\/\/api.backendless.com\/757E349F-C515-5AF3-FF5D-EFF0379BFB00\/v1\/files\/web\/templates\/session_expiration\/index.html",
     "size": 1024,
     "url": "web\/templates\/session_expiration\/index.html"
   }
]

Errors:

When the backend reports an error, it returns a JSON object in the following format:

{
 "message":error-message,
 "code":error-code
}

The server may return the following errors:

Error Code

Error message

Notes

6000

File or directory cannot be found.

Occurs when the source file/directory cannot be found.

6006

Path contains prohibited symbols: {path name}


6007

The specified resource was not found

Occurs when the API requests to rename a non-existent file or a directory.

6029

Specified resource must be a directory

Occurs when the path to get a listing for is not a directory

Get File Count

This operation returns the number of files and optionally directories located in the specified path. Additional options include:

 

pattern filtering - counts files and directories which match the pattern.
recursive counting - when enabled, counts all matching files and directories while recursively traversing the directory structure.

 

Deleting a File

Method:

DELETE

URL: https://api.backendless.com/<application-id>/<REST-api-key>/files/<path>/<filename>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<path> - Directory path in the Backendless file storage where the file should be deleted.
<filename> - Name of the file to delete.

Request headers:

user-token: optional value obtained as a result of the login operation.

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

None or error.

Example:

curl -X DELETE
-v http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/txtfiles/test.txt

 

Deleting a Directory

 

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/files/<path>

where:

<application-id> - the ID of your application generated upon its creation. You can get the value in the Manage > App Settings section of the Backendless Console.
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<path> - Path of the directory to delete in the Backendless file storage.

Request headers:

user-token: optional value obtained as a result of the login operation.

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

None

Response Body:

None or error.

Example:

curl -X DELETE \
-v http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/files/picsfolder

 

Git Integration

Backendless file storage can also function as a git repository. This could be very convenient for deploying multiple files from the developer's computer with a single command. Git integration is disabled by default. To enable git for the file storage:

1. Open Backendless Console
2. Select your app/backend
3. Click Manage and scroll down to the Enable .git support section
4. Use the toggle to turn git integration on or off:
git-support

When the git integration is turned on, all files present in or uploaded to the file storage are immediately committed to the repository. This integration is bi-directional. It means that any files committed into the git repository by the means of git, will also be copied into the file storage. When git integration is being turned off, the git repository is deleted with all the associated history (the files remain in the file storage).

With the git integration enabled, a new folder (.git) appears in the File Browser on the Files screen. The folder contains the files from the git repository. When a file is uploaded to file storage either via the Upload API or using the File Browser, it is automatically committed to the repository. Likewise, when a file is pushed into the repository, it becomes available and visible in the file storage. The same applies to editing and deleting files either in the Backendless Console or in git repository.

When git is enabled, the repository is available at the following address:

https://git.backendless.com/<application id>/.git

where:

<application id> - application ID available in Backendless Console at Manage > App Settings.

When the Backendless backend is configured with a custom domain name, the repository URL is:

http://<custom domain name>/.git

The repository uses the same authentication as Backendless Console. That means all git commands must use the same developer email address and password as for logging in to Backendless Console.

It is important to note that any system level files created by git are also placed into the file storage (the .git directory). These files are accounted for when calculating the file space used by the app/backend.

Configuring Local Environment

You have no local files and there is a remote GIT repository:

There are files in the Backendless storage and there are no files locally:

Clone existing repository:

mkdir /path/to/your/project
cd /path/to/your/project
git clone http://git.backendless.com/<your application id>/.git
cd <your application id>

Adding a file locally and pushing to Backendless git:

> echo "First file" >> file.txt
> git add file.txt
> git commit -m 'Initial commit with new file'
> git push -u origin master

You have with an existing GIT project in your local environment:

This applies when you already have a local git project. You also enabled git integration in Backendless and need to "integrate" your local git project with the git repository in Backendless.

> cd /path/to/my/repo
> git remote add origin http://git.backendless.com/<your application id>/.git
 
# pushes the repo and its refs for the first time to Backendless git
> git push -u origin --all
 
# pushes any tags to Backendless git
> git push -u origin --tags

You have an existing FILE project in your local environment.

This applies when you have existing files locally and need to add them to the git repository you initialized in Backendless.

> cd /path/to/my/repo
> git init
> git remote add origin http://git.backendless.com/<your application id>/.git
> git pull -u origin master
> git add *
> git commit -m 'merge with existing project'
> git push -u origin master

Web Hosting

Backendless file storage includes a special directory which facilitates web hosting for the app/backend. The directory name is /web:

web-directory

The /web folder serves as the web server root. The web server is available at the following URLs:

With custom domain name enabled for the account:

http://custom domain name

Without custom domain name:

https://api.backendless.com/<application id>/<REST API key>/files/web

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST API Key> - API Key assigned to the application by Backendless. It is available from the Manage > App Settings screen of the Backendless Console.

 

Custom Domain Name

Backendless File Service supports mapping of a custom domain name to the application's backend. As a result, once a domain name is mapped, the following backend's resources become available via the custom URL:

Service API endpoint. The default endpoint for all Backendless services is:

https://api.backendless.com

With a custom domain name, the endpoint is also available at:

http://<custom domain name>/api

Web Hosting. Backendless file storage contains a special directory - /web, which serves as the web site root. When a custom domain name is mapped to a Backendless application/backend, the contents of the /web directory are served for the HTTP requests with the domain name. See the Web Hosting section for additional details.
git endpoint. When the Backendless git integration is enabled, the git endpoint with a custom domain name is:

http://<custom domain name>/.git

Before a custom domain name is assigned to a Backendless application:

1. Create a CNAME record in DNS for your custom domain name
2. Map the CNAME record to develop.backendless.com
3. Open Backendless Console and select your application/backend.
4. Click Manage and scroll down to the "Custom Domain" section.
5. Enter the domain name into the text field and click Save
custom-domain.zoom50

Custom Web Template Hosting

A client-to-backend workflow may include interaction with web pages presented to the users of the application. Consider the following scenarios:

User registration. When a user registers with an application, he receives an email with a link to a page. Clicking the link acknowledges that the email address is valid and the user account is confirmed.
Password change. When a user requests password change (or password recovery), an email is sent to the user with a link to a web page where they can reset the password.
Session expiration. When a user session with the application expires, he is redirected to a webpage.

All these use cases have something in common - they all force the user to interact with a web page. The templates for these pages are available in the /web/templates path of the backend's file storage:

files-web-templates-dirs

The look and feel as well as the logic in the pages can be customized by modifying the HTML/CSS /JS files provided for each template. For example, the contents of the change_password folder is:

change-password-template

The "out-of-the-box" rendering of the pages is shown below:

Registration confirmation page:

backendless-registration-conf

Password change page:

backendless-password-change

Session expiration page:

session-expiration

Files Security

Access to files and directories can be restricted using permissions. Backendless supports the following permissions for files and directories:

Read - permission to download a file. This permission can be applied to a directory, in that case it applies recursively to all files contained therein.
Write - permission to upload a file or modify a directory by uploading files into it.
Remove - permission to delete a file or a directory.

To modify the permission matrix for a file or a directory, click the "Permissions" icon in file browser in Backendless Console:

files-directory-permissions

 

The permission assignment popup contains two sections: USER PERMISSIONS and ROLES PERMISSIONS which allow permission management either for a specific user account or for application roles.  To modify a permission for an operation for a user or a role, click the icon in the corresponding column. The icon has 3 states:

ico-checkmark-gray - inherit GRANT permission from the global permission matrix. This is the default permission.

ico-checkmark-green - explicit GRANT of the permission for the operation. Allows the user to perform the operation.

icon-deny - DENY permission for the operation. Restricts the user from performing the operation.

files-role-permissions.zoom70

Permissions API

Backendless security mechanism assigns an Access Control List (ACL) to every file in the file storage. An ACL defines users and user roles that have permissions to read, write, or delete a file. The Permissions API allows programmatic control over file ACL by granting or denying permissions to a file for a user or a user role. Using the API permissions can be applies for a user or user role individually or in "bulk" - for all users or user roles in a single call.

The path or the url argument in the APIs below must identify a file or directory for which the permission is modified. The value must be the short version of the path. For example, suppose the full URL of a file in the file storage system is:

https://api.backendless.com/31CB9FED-F34C-5541-FF26-6C2B6719F200/23432-A6B2-FF6B-31CB9FED/files/movies/vacation.mp4

The path to the file in the API call must contain only the directory and the file name (without the leading slash):

movies/vacation.mp4

 

The user account (or the role) on which behalf the API is executed must contain the Permission permission. For example, if the call is made by an authenticated user, the role for the user account would be AuthenticatedUser. The role must have the Permission permission in order for the API call to go through.

 

Method:

PUT

URI:

/<application-id>/<REST-api-key>/files/permissions/<permission type>/<path>/<file_name>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<permission type> - type of the permission, that is grant or deny.
<path> - path to a file, for which you want to specify the permission.

Sample Request Body:

To set permissions for a user

{
   "permission": "READ" | "DELETE" | "WRITE",
   "user": userid
}

To set permissions for all users, specify "*" value for the user argument.

To set permissions for a user role

{
   "permission": "READ" | "DELETE" | "WRITE",
   "role": rolename
}

To set permissions for all user roles, specify "*" value for the role argument.

Sample Response Body:

void or error

 

Geolocation API

Overview

Backendless Geolocation Service is a system supporting management and search of geo points. A geo point in the most primitive format consists of a pair of coordinates: latitude and longitude. Optionally a geo point may contain metadata, which is a collection of arbitrary key/value pairs. A geo point belongs to a category, which is a logical grouping of geo points. The diagram bellow illustrates these concepts:

backendless-geo-point-concepts.jpeg

 

Backendless allows infinite number of geo points managed for an application. Geo points can be added via an API call or the import functionality in Backendless console. Once the backend is populated with geo points, the search API can be used to run the following types of geo queries:

Radius-based search - Searches for geo points in a circular map area defined by the coordinates of the central point and a radius. Backendless returns all geo points within the area.
backendless-geo-radius-search
Search in a rectangular map area - Searches for geo points in a rectangular map area identified by the coordinates of two corners defining the area (North West and South East):
backendless-geo-rectangle-search

 

Additionally, the geo search API supports the following search options available in the APIs:

Filtering by categories - Both types of search (radius-based and rectangular) can specify the categories in which the backend should search for the geo points.
Query-based search - The metadata associated with the geo points can be used in queries which should be formatted using the SQL-92 syntax. For example, the geo point shown in the image above can be discovered with the following queries:

cuisine = 'French'

cuisine LIKE 'Fr%' and Atmosphere = 'Casual'

cuisine = 'French' and (Price = '$$$$' or Price = '$$$')

Relative search - Runs a search for a subset of metadata key/value pairs to match up to the specified threshold value. The threshold must be expressed as a percentage of matches.

 

Adding a GeoPoint

This API adds a geo point to the backend geo location storage. Once a geo point is added, it becomes searchable through all geopoint search mechanisms supported by Backendless (search in radius, search in a rectangular area, search in a category). At the present moment there are two ways to add geo points: (1) using the API documented below or (2) using the Backendless console's import function.

 

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/points

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

A JSON object representing a geo point.

{
 "latitude": <latitude>,
 "longitude": <longitude>,
 "categories": <categories>,
 "metadata": <metadata>
}

where:

<latitude> - a numeric value. Latitude of the geopoint to add.
<longitude> - a numeric value. Longitude of the point to add.
<categories> - optional parameter. A JSON array of categories the point is added to. If a category does not exist at the time when a point is added, Backendless creates the category and adds the point to it. If the parameter is not present in the request, the point is added to the "Default" category.
<metadata> - optional parameter. A JSON object representing the metadata associated with the geo point.

Response Body:

A JSON object representing the saved geo point. The object also contains the objectId property assigned by the server. If an error occurs, the response is formatted as described in the Error Handling section.

Example:
 

curl -X POST -H Content-Type:application/json \
-d "{\"longitude\":20.12, \"latitude\":-60.22, \
    \"categories\":[\"MisterySpot\"], \"metadata\":{\"foo\":\"bar\"} }" \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?lat=10&lon=20&metadata=%20%7B%20%22foo%22%3A%22bar%22%20%7D"

When the geo point is saved, you can see it in the Backendless console:
added-geopoint.zoom50

 

Updating a GeoPoint

This API performs the "remove and save" operation on a geo point object in the backend geo location storage. For partial updates use the PATCH request which updates only the parameters present in the request.

Method:

PUT - complete replacement (remove and re-save)
PATCH - partial update only for the parameters present in the request

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/points/<geoPointObjectId>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<geoPointObjectId> - objectId assigned to the geo point which should be modified.

Request Body:

{
 "latitude": <latitude>,
 "longitude": <longitude>,
 "categories": <categories>
 "metadata": <metadata>
}

where:

<latitude> - a numeric value. Latitude to update to.
<longitude> - a numeric value. Longitude to update to.
<categories> - optional parameter. A JSON array of categories to move the point to. If a category does not exist at the time when a point is added, Backendless creates the category and moves the point to it. If the parameter is not present in the request, the point is added to the "Default" category.
<metadata> - optional parameter. A JSON object representing the metadata associated with the geo point.

 

The semantics of the arguments is different between the PUT and PATCH requests:

 

PUT (remove and re-save)

latitude and longitude are required
If categories is not present, the geo point is removed from the current category and moved to "Default"
If categories is present, the geo point is removed from the current category and moved to the specified category
If metadata is not present, the current metadata is removed.
If metadata is present, it replaces the current metadata

PATCH (partial update)

All parameters are optional, but at least one must be present.
latitude and longitude are not required.
If latitude or longitude are present, the new values replace the existing ones.
If categories is present, the geo point is moved to the specified categories (with coordinates and metadata).
If categories is not present, the geo point stays in the current category.
If metadata is not present, the geo point keeps the current metadata.
If metadata is present and not an empty object, the new metadata replaces the existing one.
If metadata is present and it is an empty object, the existing metadata is removed.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Sample PUT Request

curl -X PUT -H Content-Type:application/json \
-d "{\"longitude\":65.32, \"latitude\":-15.22, \
    \"categories\":[\"Cafe\"], \"metadata\":{\"foo\":\"bar\"} }" \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points/YOUR-GEOPOINT-OBJECTID"

Sample PATCH Request:

curl -X PATCH -d "{\"latitude\":10.2, \"longitude\":20.3}" \
-v "https://api.backendless.com/XXXXX-XXXXX-XXXX/ZZZZ-ZZZZZ-ZZZZ/geo/points/YOUR-GEOPOINT-OBJECTID"

If an error occurs, the response is formatted as described in the Error Handling section.

 

Deleting a GeoPoint

There are two ways to delete a geopoint from the Geolocation storage:

 

Deleting a GeoPoint using the Backendless Console

To delete a geo point using the Backendless Console:

1. Log in to the Backendless Console, select your app and click the Geolocation icon.
2. Select a geo category containing the geopoint to be deleted.
3. Click the checkboxes next to the geopoint(s) which should be deleted.
4. Click Delete Selected from the button bar as shown below:
geo-delete-geopoints.zoom50
5. Click Delete in the confirmation popup to confirm the deletion.
6. A confirmation notification will appear in the top right corner.

 

Deleting a GeoPoint with the API

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/points/<objectId>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<objectId> - value of the objectId property of a geopoint to delete.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Response Body:

None

Sample:

curl -X DELETE \
-v "https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points/YOUR-GEOPOINT-OBJECTID"

 

Adding a Geo Category

This API creates a geo category. A geo category is a logical grouping of geo points. Category name may contain the following literals: a-z, A-Z, numbers 0-9 and the underscore (_ ) character. The name must start with a literal. Category names can be inspected using Backendless Console (see the image below) or using the API call retrieving a list of categories.

 

Adding Categories in Console

Backendless Console supports adding a category via the graphical interface. To create a category:

1. Login to Backendless Console and select your app/backend.
2. Click the Geolocation icon in the menu on the left.
3. Use the "plus" icon located above the section containing the list of categories:
create-new-geo-cat
4. Enter the category name in the popup and click "Save".

 
Adding Categories with the API

Method:

PUT

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/categories/<categoryName>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<categoryName> - name of the category to create.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Response Body:

A JSON object representing the added category:

{
 "objectId": "<categoryId>",
 "size": "0",
 "name": "<categoryName>"
}

where:

<categoryId> - object ID assigned to the category by the server
<categoryName> - name of the category created with the request.

If an error occurs, the response is formatted as described in the Error Handling section.
 

Example:
 

curl -X PUT \
-v http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/categories/foobarcategory

 

Deleting a Geo Category

This API deletes a geo category. If the category does not exist, the service returns an error.
 

Removing Categories in Console

Backendless Console supports category deletion via the graphical interface. To delete a category:

1. Login to Backendless Console
2. Select your app/backend.
3. Click the Geolocation icon in the menu on the left.
4. Use the "delete" icon in the section above the list of categories:
delete-geo-category
5. Select DELETE in the confirmation popup.

 
Deleting Categories with the API

Method:

DELETE

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/categories/<categoryName>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<categoryName> - name of the category to delete.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Response Body:

A JSON object wit a boolean value indicating whether the category has been successfully deleted:

{
 "result": true | false
}

If an error occurs, the response is formatted as described in the Error Handling section.
Example:

curl -X DELETE \
-v http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/categories/foobarcategory

 

Retrieving Geo Categories

This API retrieves a list of all the application's geo categories.

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/categories

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Response Body:

A collection of JSON objects. Each object represents a geo category and contains the objectId, name and size properties. The size  property is the number of geopoints the geo category contains. Below is a sample response:

[
 {
   "objectId": "2590AA6B-017D-15AE-FF84-2A13BE19C700",
   "name": "restaurants",
   "size": 2
 },
 {
   "objectId": "6354457C-E82B-5F1F-FF6C-5AB31CA25D00",
   "name": "taxis",
   "size": 2
 },
 {
   "objectId": "BB3428CA-37EE-6EBF-FF3A-67A3F4505900",
   "name": "Default",
   "size": 1
 }
]

If an error occurs, the response is formatted as described in the Error Handling section.

 

Example:
 

curl -X GET
-v http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/categories

 

Get Geopoint Count

// TODO

Importing Geo Data

Backendless console supports bulk import of geo points with metadata. The import procedure automatically places the geo points into the specified categories. The raw data must be in a comma separated values (CSV) format. For more details about geopoint import see the Importing for Geo Service section of the guide.

Search in Category

This API supports two types of geo searches:

Search in one or more geo categories.
Search based on metadata properties in one or more categories .

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/points?categories=<categories>&where=<whereClause>&metadata=<metadata>&pagesize=<pageSize>&includemetadata=<metaInResponse>&offset=<offset>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<categories> - list of categories separated by comma where to run the search. If the parameter is not present in the request, the search is ran in the "Default" category.
<whereClause> - contains an SQL query (the where clause part) which is used to search for the objects. The value must be URL encoded.
<metadata> - metadata which must match in order for a point to be selected for the search result. Must be expressed in as a URL encoded JSON object. For example, { "foo":"bar" } will be URL encoded as:  %20%7B%20%22foo%22%3A%22bar%22%20%7D. Found geo points must match the specified metadata key/value pairs entirely. See partial match search for the search API that does not require complete matches. Accepted values for this parameter are: String, Number (integer and double), and Data Service objects. Date values must be represented as number in the Unix timestamp format (number of milliseconds since January 1, 1970 at UTC). Learn more about using date in search queries for category, radius, or rectangular area search.
<pageSize> - number of geo points to be returned in the response.
<metaInResponse> - Boolean value indicating whether geo point metadata should be included in the response. Supported values are true or false.
<offset> - sequential (zero-based) index from where to run the search. For example, suppose the first search query returned 50 geo points (pageSize is set to 50). A subsequent search should set the offset value to 50 in order to get the next page of search results.

Request headers:

user-token: optional value obtained as a result of the login operation.

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

none

Response Body:

A JSON array of geopoint objects. Each object contains the following properties:

objectId - an ID assigned to a geo point by Backendless.
latitude - geo point's latitude coordinate
longitude - geo point's longitude coordinate
categories - an array of categories the geo point belongs to
metadata - a JSON object of key/value pairs describing geo point's metadata properties

 

Since the search query may produce a large number of geo points, not all of them are returned at once. Instead, all found geo points are divided into 'pages'. The size of each page is determined by the pageSize parameter in the query. The first response returns the first page. Subsequent search requests with the modified offset will return additional pages of data.

 

Calculating offset

All geo points in the entire search result are indexed. The index of the first geo point is 0. The offset parameter in the query specifies the index from which to load the next page of geo points. For example, suppose the entire search result is 200 points. If the initial pageSize is 20, then only 20 geo points are returned in the first response. To get the second page of geo points, they should be loaded from offset 20, third from 40 and so on. The formula for calculating offset is:

[value of offset in the current response] + [size of current page ].

If an error occurs, the response is formatted as described in the Error Handling section. Below is a sample response:

[
 {
  "objectId": "609CEE02-174E-2486-FFD1-2AAE48B89100",
  "latitude": 41,
  "longitude": 2,
  "categories": [
    "Restaurants"
  ],
  "metadata": {
    "foo": "bar"
  }
 },
 {
   "objectId": "80ED18EB-D53B-5E68-FFC0-EA341C213F00",
   "latitude": 41,
   "longitude": -87,
   "categories": [
     "Restaurants"
   ],
   "metadata": {
     "foo": "bar"
   }
   }
]

 

Running Search Queries

The geo query object includes multiple parameters. Depending on which parameters contain values, the semantics of the search would change. Any search must be performed within at least one category. If no category names are provided, the search is performed in the Default category.

 

Search in categories

To search in one or more categories without any constraints on metadata or proximity to a center point, simply set the names of the categories in the query object. The request returns all geo points divided into pages of data, one page at a time.
curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?categories=Restaurants"

Search in categories with metadata

Metadata-based search finds all geo points which match all specified metadata properties in the given categories. The example below searches for the geo points in the Restaurants category with metadata containing "Cuisine = French" and "Atmosphere = Romantic".
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?categories=Restaurants&metadata=%7B%22Cuisine%22%3A%22French%22%2C%20%22Atmosphere%22%3A%22Romantic%22%7D"

 
 

Using dates in where clause when searching in categories

The search query used to retrieve geo points may reference date values. These values must be stored as a number of milliseconds since January 1st, 1970 at UTC. The example below demonstrates the usage of a date/time timestamp in a search query:
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?categories=Restaurants?where=updated<1421234854999"

 

Requesting meta in response

Geo points returned in the search results do not include their metadata properties by default. The search query object includes a property which can be used to request the metadata to be included. This property can be used with any search options described above. For example, the following code runs a search in a category and requests the metadata to be included:
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?categories=Restaurants&includemetadata=true"

 

Search by using the IN operator

Use IN operator to search for the objects in several locations. For instance, to find all objects located in Dallas, Kyiv, or Lviv specify the following  values for where parameter: city in ('DALLAS','KYIV','LVIV'). The value of where parameter should be URL-encoded. Values in the parenthesis define the locations, for which you will be searching. If a location value matches any of the values in the parenthesis, the location will be included into the search response.

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?categories=geoservice_sample&where=city%20in%20(%27DALLAS%27%2C%27KYIV%27%2C%27LVIV%27)&includemetadata=true"

 

Search in Radius

This API supports multiple types of geo searches:

Search for geo points located within specified distance (radius) from a given point.
Search in radius based on metadata.

 

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/points?lat=<latitude>&lon=<longitude>&categories=<categories>&r=<radius>&units=<units>&metadata=<metadata>&pagesize=<pageSize>&includemetadata=<metaInResponse>&offset=<offset>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<latitude> - latitude of the point in the center of the search.
<longitude> - longitude of the point in the center of the search.
<categories> - list of categories separated by comma where to run the search. If the parameter is not present in the request, the search is ran in the "Default" category.
<radius> - distance from the center point within which to run the search.
<units> - unit of measure applied to the radius value. Supported unit values are: METERS, KILOMETERS, MILES, YARDS, FEET
<metadata> - metadata which must match in order for a point to be selected for the search result. Must be expressed in as a URL encoded JSON object. For example, { "foo":"bar" } will be URL encoded as:  %20%7B%20%22foo%22%3A%22bar%22%20%7D. Found geo points must match the specified metadata key/value pairs entirely. See partial match search for the search API that does not require complete matches. Accepted values for this parameter are: String, Number (integer and double), and Data Service objects. Date values must be represented as number in the Unix timestamp format (number of milliseconds since January 1, 1970 at UTC). Learn more about using date in search queries for category, radius, or rectangular area search.
<pageSize> - number of geo points to be returned in the response.
<metaInResponse> - Boolean value indicating whether geo point metadata should be included in the response. Supported values are true or false.
<offset> - sequential (zero-based) index from where to run the search. For example, suppose the first search query returned 50 geo points (pageSize is set to 50). A subsequent search should set the offset value to 50 in order to get the next page of search results.

to get the next page of search results.

Request headers:

user-token: optional value obtained as a result of the login operation.

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

none

Response Body:

A JSON array of geopoint objects. Each object contains the following properties:

objectId - an ID assigned to a geo point by Backendless.
latitude - geo point's latitude coordinate
longitude - geo point's longitude coordinate
categories - an array of categories the geo point belongs to
metadata - a JSON object of key/value pairs describing geo point's metadata properties

 

Since the search query may produce a large number of geo points, not all of them are returned at once. Instead, all found geo points are divided into 'pages'. The size of each page is determined by the pageSize parameter in the query. The first response returns the first page. Subsequent search requests with the modified offset will return additional pages of data.

 

Calculating offset

All geo points in the entire search result are indexed. The index of the first geo point is 0. The offset parameter in the query specifies the index from which to load the next page of geo points. For example, suppose the entire search result is 200 points. If the initial pageSize is 20, then only 20 geo points are returned in the first response. To get the second page of geo points, they should be loaded from offset 20, third from 40 and so on. The formula for calculating offset is:

[value of offset in the current response] + [size of current page ].

If an error occurs, the response is formatted as described in the Error Handling section. Below is a sample response:

[
 {
  "objectId": "609CEE02-174E-2486-FFD1-2AAE48B89100",
  "latitude": 41,
  "longitude": 2,
  "categories": [
    "Restaurants"
  ],
  "metadata": {
    "foo": "bar"
  }
 },
 {
   "objectId": "80ED18EB-D53B-5E68-FFC0-EA341C213F00",
   "latitude": 41,
   "longitude": -87,
   "categories": [
     "Restaurants"
   ],
   "metadata": {
     "foo": "bar"
   }
 }
]

 

Running Search Queries

The geo query object includes multiple parameters, none of them are required. As a result, depending on which parameters contain values, the semantics of the search would change. Any search must be performed within at least one category. If no category names are provided, the search is performed in the Default category.

 

Search in categories with radius

Radius-based search establishes a circular area by setting the coordinates of a central point and a distance (radius). Backendless searches for geo points in the specified distance from the coordinates in the center and includes them into the search result. The value of the distance is interpreted based in the units parameter, which can be METERS, KILOMETERS, MILES, YARDS, FEET:
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?lat=41.48&lon=2.15&r=10000&units=METERS&categories=Restaurants"

Search in categories with radius and metadata

This is the same as above, with the difference that the search result includes only geo points with the matching metadata:
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?lat=41.48&lon=2.15&r=10000&units=METERS&categories=Restaurants&metadata=%7B%22Cuisine%22%3A%22French%22%2C%20%22Atmosphere%22%3A%22Romantic%22%7D"

 

Using dates in where clause when searching in radius

The search query used to retrieve geo points may reference date values. These values must be stored as a number of milliseconds since January 1st, 1970 at UTC. The example below demonstrates the usage of a date/time timestamp in a search condition:

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?lat=41.48&lon=2.15&r=10000&units=METERS&categories=Restaurants?where=updated<1421234854999"

 

Requesting meta in response

Geo points returned in the search results do not include their metadata properties by default. The search query object includes a property which can be used to request the metadata to be included. This property can be used with any search options described above. The syntax for requesting metadata in response is described in the Search in Category section.

Search in Rectangular Area

This API runs a search within a rectangular area of the map. The area is defined with the coordinates of the North West and South East corners of the map rectangle.

Method:

GET

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/rect?nwlat=<nw-latitude>&nwlon=<nw-longitude>&selat=<se-latitude>&selon=<se-longitude>&categories=<categories>&metadata=<metadata>&pagesize=<pageSize>&offset=<offset>&includemetadata=<metaInResponse>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<nw-latitude> - latitude of the North West point used to define the boundaries of the rectangular area.
<nw-longitude> - longitude of the North West point used to define the boundaries of the rectangular area.
<se-latitude> - latitude of the South East point used to define the boundaries of the rectangular area.
<se-longitude> - longitude of the South East point used to define the boundaries of the rectangular area.
<categories> - list of categories separated by comma where to run the search. If the parameter is not present in the request, the search is ran in the "Default" category.
<metadata> - metadata which must match in order for a point to be selected for the search result. Must be expressed in as a URL encoded JSON object. For example, { "foo":"bar" } will be URL encoded as:  %20%7B%20%22foo%22%3A%22bar%22%20%7D. Found geo points must match the specified metadata key/value pairs entirely. See partial match search for the search API that does not require complete matches. Accepted values for this parameter are: String, Number (integer and double), and Data Service objects. Date values must be represented as number in the Unix timestamp format (number of milliseconds since January 1, 1970 at UTC). Learn more about using date in search queries for category, radius, or rectangular area search.
<pageSize> - number of geo points to be returned in the response.
<metaInResponse> - Boolean value indicating whether geo point metadata should be included in the response. Supported values are true or false.
<offset> - sequential (zero-based) index from where to run the search. For example, suppose the first search query returned 50 geo points (pageSize is set to 50). A subsequent search should set the offset value to 50 in order to get the next page of search results.

Request headers:

user-token: optional value obtained as a result of the login operation.

where:

user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request Body:

none

Response Body:

A JSON array of geopoint objects. Each object contains the following properties:

objectId - an ID assigned to a geo point by Backendless.
latitude - geo point's latitude coordinate
longitude - geo point's longitude coordinate
categories - an array of categories the geo point belongs to
metadata - a JSON object of key/value pairs describing geo point's metadata properties

 

Since the search query may produce a large number of geo points, not all of them are returned at once. Instead, all found geo points are divided into 'pages'. The size of each page is determined by the pageSize parameter in the query. The first response returns the first page. Subsequent search requests with the modified offset will return additional pages of data.

 

Calculating offset

All geo points in the entire search result are indexed. The index of the first geo point is 0. The offset parameter in the query specifies the index from which to load the next page of geo points. For example, suppose the entire search result is 200 points. If the initial pageSize is 20, then only 20 geo points are returned in the first response. To get the second page of geo points, they should be loaded from offset 20, third from 40 and so on. The formula for calculating offset is:

[value of offset in the current response] + [size of current page ].

If an error occurs, the response is formatted as described in the Error Handling section. Below is a sample response:

[
 {
  "objectId": "609CEE02-174E-2486-FFD1-2AAE48B89100",
  "latitude": 41,
  "longitude": 2,
  "categories": [
    "Restaurants"
  ],
  "metadata": {
    "foo": "bar"
  }
 },
 {
   "objectId": "80ED18EB-D53B-5E68-FFC0-EA341C213F00",
   "latitude": 41,
   "longitude": -87,
   "categories": [
     "Restaurants"
   ],
   "metadata": {
     "foo": "bar"
   }
 }
]

 

Running Search Queries

The geo query object includes multiple parameters, however, only the coordinates defining the rectangular area are required.  A search query must be performed within at least one category. If no category names are provided, the search is performed in the Default category.

 

Search in a rectangle in categories

Rectangle-based search establishes a geographic area by setting the coordinates of the North West and South East corners of the area. Backendless searches for geo points in the specified area and includes them into the search result:
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/rect?nwlat=32.78&nwlon=-96.8&selat=25.79&selon=-80.22&categories=Restaurants"

Search in categories in a rectangular area and metadata

This is the same as above, with the difference that the search result includes only geo points with the matching metadata:
 

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/rect?nwlat=32.78&nwlon=-96.8&selat=25.79&selon=-80.22&categories=Restaurants&metadata=%7B%22Cuisine%22%3A%22French%22%2C%20%22Atmosphere%22%3A%22Romantic%22%7D"

Using dates in where clause

The search query used to retrieve geo points may reference date values. These values must be stored as a number of milliseconds since January 1st, 1970 at UTC. The example below demonstrates the usage of a date/time timestamp in a search query:

curl -X GET \
-v "http://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/rect?nwlat=32.78&nwlon=-96.8&selat=25.79&selon=-80.22&categories=Restaurants?where=updated<1421234854999"

Requesting meta in response

Geo points returned in the search results do not include their metadata properties by default. The search query object includes a property which can be used to request the metadata to be included. This property can be used with any search options described above. The syntax for requesting metadata in response is described in the Search in Category section.

GeoPoint Clustering

Geo point search in a category, radius or a rectangular area may return too many geo points within close geographic proximity from each other. This might be difficult to view and process in a client application. To address this problem, Backendless supports the geo clustering feature. A geo cluster is a group of several geo points located close to each other. The two screenshots below demonstrate the advantages of clustering: the picture on the top displays search results in the Backendless Console with clustering turned off and the one on the bottom displays search results as clusters when clustering has been enabled:

 

Geo Points View:

clustering-points.zoom50

 

Clusters and Points View:

clustering-clusters.zoom50

 

Backendless creates clusters by splitting the map into a grid of squares. Geo points which belong to a square are placed into the same cluster. When a square contains only one point, it remains non-clustered.

 

Testing Geo Clustering in Backendless Console

The Geolocation page displays non-clustered geo points by default. To see how geoclustering works and test geoclustering search results:

1. Log in to Backendless Console, select an application and click the Geolocation icon.
2. Click the Map-driven navigation toggle. The toggle changes how the geo points are loaded from the backend. In the map-driven mode console loads the geo points for the visible area of the map.
3. Click the Geo Clustering toggle to enable clustering.
4. Console reloads geo points and clusters for the current viewport of the map and displays the results. A cluster is visualized as a blue marker on the map with a number indicating how many geo points it represents.
geofence-screen7.zoom50

 

Geo clustering is also available with the "Search in Radius" option, which searches for geo points in a circular area. To enable this functionality, click the Search in radius toggle:

geofence-screen8.zoom50

 

If you want to see the geo points in a cluster, zoom in the map or double-click a cluster's marker. Zooming the map in too much (when using the clustering along with the search in radius) may result that the search radius will be much bigger than the visible part of the map on the screen. In this case, zoom out so you can adjust the circle position and/or radius.

 

Clicking a cluster's marker will reveal the coordinates and combined metadata of all geopoints in the cluster.

geofence-screen9.zoom50

Retrieving Clustered Geo Points

The API calls for searching the geo points may return clusters if the following parameters are present in the request:

 

1. dpp - degree per pixel. Use the following psuedo algorithm to calculate the value of dpp:

if (eastLongitude - westLongitude) < 0
 
 dpp = ((eastLongitude - westLongitude) + 360) / mapWidth
 
else
 
 dpp = ((eastLongitude - westLongitude) / mapWidth

where:

westLongitude - the longitude of any point on the western boundary of the map in degrees.
eastLongitude - the longitude of any point on the eastern boundary of the map in degrees.
mapWidth - the size of the viewing area of the map in pixels.

 

2. clusterGridSize - the size in pixels of the grid's squares used to group points into clusters. The default value is 100 pixels.

 

These parameters can be added to any request which returns a collection of geo points, including retrieval of geo points from a category, radius or rectangular area search.

 

Sample Request:

curl -X GET \
-v "https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/points?categories=Restaurants,Cafe&dpp=0.01&clusterGridSize=45"

 

Sample Response Body:

The sample response below demonstrates one cluster containing nine geo points and one separate (not included into the cluster) geo point.

[
 {
   "objectId":"1",
   "categories":["Restaurants","Caffee"],
   "metadata":{},
   "latitude":30,
   "longitude":40,
   "totalPoints":9,
 },
 {
   "objectId":"XXXX-XXXX-XXXX-XXXX",
   "categories":["Restaurants"],
   "metadata":{},
   "latitude":45,
   "longitude":30
 }
]

Notice the totalPoints property in the first object in the array. The presence of that property defines the object as a geo cluster. The value of the property is how many geo points the cluster contains. Other than that, all other properties are identical to geo points. If the totalPoints property is not present, it means the geo point was returned non-clustered. This occurs when a geo point does not have any other neighboring points within the same grid's square.

 
Loading Geo Points from a Cluster

With the geo clustering feature enabled, you may need to reveal the geo points gathered in a cluster. In the Backendless Console, you can click the cluster to reveal its details as described above. By using the calls described below, you will be able to reveal the geo points in a cluster via API.

Method

GET

URL

https://api.backendless.com/<application-id>/<REST-api-key>/geo/clusters/<clusterId>/points?lat=x.xxxx&lon=y.yyyy&units=UNITSVALUE&categories=ABC,XYZ&r=ZZ[&nwlat=X.XXXX&nwlon=YY.YYYY&selat=ZZ.ZZZZ&selon=WW.WWWW][&metadata={"AAAA":"foo", "BBBB":"bar"}]&dpp=YY.YY&size=XX[&pagesize=XX][&offset=XX]

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
lat - the latitude of a cluster.
lon - the longitude of a cluster.
<clusterId> - ID of a cluster assigned by Backendless.
<units> - unit of measure applied to the radius value. Supported unit values are: METERS, KILOMETERS, MILES, YARDS, FEET
categories - categories' names of the geo points belonging to a cluster.
<radius> - distance from the center point, within which to run the search.
<metadata> - metadata which must match in order for a point to be selected for the search result. Must be expressed in as a URL encoded JSON object. For example, { "foo":"bar" } will be URL encoded as:  %20%7B%20%22foo%22%3A%22bar%22%20%7D. Found geo points must match the specified metadata key/value pairs entirely. See partial match search for the search API that does not require complete matches. Accepted values for this parameter are: String, Number (integer and double), and Data Service objects. Date values must be represented as number in the Unix timestamp format (number of milliseconds since January 1, 1970 at UTC). Learn more about using date in search queries for category, radius, or rectangular area search.
dpp - degrees per pixel parameter of a cluster. Learn more about this parameter.
<pageSize> - number of geo points to be returned in the response.
<metaInResponse> - Boolean value indicating whether geo point metadata should be included in the response. Supported values are true or false.
<offset> - sequential (zero-based) index from where to run the search. For example, suppose the first search query returned 50 geo points (pageSize is set to 50). A subsequent search should set the offset value to 50 in order to get the next page of search results.

Request Body:

none

Response Body:

A JSON array of geo points, identical to response for the Search in Category request.

 

Relations with Data Objects

Backendless Data Service manages application's data objects and provides APIs to work with data objects. Backendless provides integration between data objects managed by Data Service and geo points managed by Geo Service for the scenarios when a logical connection between the two types must exist in an application. For instance, in a taxi ordering app a data object may represent a taxi car, while a geo point represents its location on the map. It is logical to link the two together so they can be retrieved and managed at once.

The Geo-to-Data integration is implemented through geo point metadata. A metadata property may reference one or more data objects. These relations may be created using the API or with Backendless Console. Once a relation is established, the console displays it in the Metadata column as a link to related data object(s). When a geo point is retrieved using the API, any related data objects can be retrieved by using the same principle for loading geo point metadata. The geo-to-data relation is bidirectoral, that is, a data object may reference a geo point through object properties (table columns). You can learn more about it in the Relations with Geo Points section of the Data documentation.

 

Apart from linking with the data objects, you can also link a geo point with a user object. Establishing relations with a user objects is performed the same way as with a data object.

 

Establishing Relations with a Data Object via Console

To link a geo point with a data object:

1. Click the Geolocation icon to open the Geo location screen.
2. Select a geo category to get a list of geo points from it.
3. Click the plus icon for a geo point you want to link with a data object.
geofence-screen10.zoom50

 

4. The Add Related Object pop-up window will display.
5. Type in a metadata property name in the Property field. This is the name of a new metadata property which will point to a related data object:
geofence-screen11.zoom70
6. Select a data table from from the Table drop-down menu. If you want to establish relation with a user object, select the Users  table from the drop-down menu. A list of the data objects which belong to the selected table will display.
7. Select the check-boxes for the data object(s) you want to link the geo point with.
8. Click the Add Related Objects button to establish a relation and save the changes.

 

Once a relation is established, the name of the property and the related data table name will display for the geo point:

geofence-screen12.zoom50

Updating/Deleting Relations

You can update or delete a geo to data relation by following the same process as above. The only difference is in order to access the"relation management" popup click the yellow box identifying the relation:

Create a Geo to Data Relation with the API

Creating a relationship between a geo point and data objects uses the same API as saving a geo point with metadata. The data object referenced in the metadata is saved in a table in the Data Service storage.

 

The example below adds a geo point representing a location of a taxi cab. The geo point includes the "TaxiCab" metadata property which references an object from the TaxiCab data table. This is an example of a one-to-one relation (one geo point is related to one data object).

 

curl -H Content-Type:"application/json" -X PUT \
-v "http://api.backendless.com/APP-ID/REST-API-KEY/geo/points" \
-d '{"latitude":40.750549,"longitude":40.750549, "categories":["Pickups"], \
"metadata":{"TaxiCab": {"___class":"TaxiCab", "CarMake":"Ford", "CarModel":"Crown Victoria"}}}'

To link a geo point with multiple data objects (a one-to-many realtion) use an array of data objects as shown below with the availableCabs property:

curl -H Content-Type:"application/json" -X PUT \
-v "http://api.backendless.com/v1/geo/points" \
-d '{"latitude":40.750549,"longitude":-73.994232, "categories":["Pickups"], \
"metadata":{"availableCabs": [{"___class":"TaxiCab", "CarMake":"Ford", \
"CarModel":"Crown Victoria"},{"___class":"TaxiCab", "CarMake":"Toyota", \
"CarModel":"Prius"}]}}'

 

Geofence Designer

About Geofencing

Geofencing on the surface, comprises drawing a stationary geometric boundary around an area on a map. This action creates programmatically a set of simple or complex global coordinates which represent a shape. A boundary represents a "fence," which surrounds the area. For Backendless, the boundary and area become meaningful when a Geopoint crosses the boundary or stays within the area.

 

Geofences work with Geopoints. A Geopoint is the most elementary Geolocation concept in Backendless. It is a point (latitude and longitude coordinate pairs) on the map that is accessible via API and allowed to move (change coordinates), i.e., a user carrying a mobile device. In addition to the coordinates, the Geopoint includes metadata in context for the Geopoint.

 

The Geofence Designer

Geofence Designer is a feature of the Geolocation service available under Geolocation > Geofencing. It is a "design time" tool for drawing Geofences on an interactive global map and associating them with events and actions, which can be triggered based on the location of registered Geopoints. Backendless integrates the designer with Google MapsTM, enabling the developer to design precise Geofence positions, locations, and shapes.

 

The Design Tool includes line, rectangle, and circle drawing tools (the cursor changes from hand to crosshairs when selected) for creating Geofence boundaries. Boundaries can be geometrically symmetrical or irregular shapes and have no minimum or maximum size constraints. In use cases, a Geofence conceptually "fences in" a city block, a shopping center, a sports stadium, or perhaps a mall; even smaller geographic areas are possible such as the shoe department in a retail store.

 

fencing11.zoom80

The Line Tool

To define an irregular Geofence, the line tool draws editable line segments and control points. For example, in the United States, the shape of Nevada is irregular. To create this shape, select the line tool to start drawing lines around it.

 

Place the cursor on the map where the first control point should be and click. Drag the cursor to the next place and Click again. The first line segment appears. Repeat these steps until you have nearly completed the shape of your boundary. (It's not a Geofence just yet.) Click the cursor on the last control point (which was the first one set). Backendless detects a closed shape and enables a new Geofence.

 

NOTE: If you accidentally close the Geofence before completing the drawing, the New Geofence dialog box appears. If you click Cancel, the Geofence will be removed. To keep the Geofence, click Save, then re-edit the shape as needed.

geofence-screen1.zoom50

 

Immediately after the shape closes, a popup appears prompting you to name the Geofence. Enter a name in the Geofence Name text box. Since this example uses the state of Nevada, it makes sense to name it Nevada. Click Save to enable the Geofence. (We will refer to this example again.)

geofence-screen2

 

The result is a new item row in the List of Geofences. The Geofence area is filled with green, and the item row is highlighted in yellow when a Geofence is selected on the map or on the list. See the image below.

geofence-screen3.zoom80

The Rectangle Tool

The Rectangle Tool is self-describing. A fence can be drawn quickly around a square or rectangular area. After the Geofence is named and saved, the shape aspect can be adjusted by dragging a line segment or corner control point.  Like the line tool, parameters can be entered in a dialog immediately after the shape is drawn. Should you need to edit the shape, an undo tool appears and to restore the previous edit.

 

fencing13

The Circle Tool

The Circle Tool is also self-describing. A circle can be drawn quickly around an area, repositioned, and resized. Like the line tool, parameters can be entered in a dialog immediately after the shape is drawn.

Deleting a Geofence

A Delete button is positioned directly below the interactive map. For each selected checkbox next to the Geofence name, the Delete button removes those Geofences. Once a Geofence is deleted, it cannot be restored.

geofence-screen4

List of Geofences and Locator Tool

A map filled with Geofences can appear cluttered, especially if the design comprises numerous shapes across several remotely located areas. Backendless organizes the boundary data and actions in a table format below the map, the List of Geofences. The table contains a row for each Geofence along with parameter controls.

 

From left to right, the second column shows the Geofence name, which is hyperlinked to the Update Geofence dialog. The Geofence locator icon is next to the Geofence hyperlink (see image below). The tool repositions the  map view to an optimal zoom-level, from which the Geofence boundary can be easily viewed, accessed, and edited.

geofence-screen5.zoom60

Geofence and Geopoints Events

Geofences and Geopoints are integrated entities of Geolocation. As such, Backendless tracks three specific events:

 

When a Geopoint enters a Geofence, crosses the boundary, On Enter action executes.
When a Geopoint stays inside a shape for a preconfigured amount of time, On Stay actions executes.
When a Geopoint exits the Geofence, it crosses the boundary and is outside the shape, On Exit action executes.

Geopoint Qualification Criteria: Exclusion/Inclusion

Tracking every Geopoint within a Geofence is not desirable in every case. A Geofence plan could specify tracking only Geopoints of a certain nature, for example, visitors or preferred customers.

 

Qualification Criteria, which identifies the types of Geopoints Backendless traces and tracks for a specific geogence, can be defined in the Update Geofence dialog. The Geofence hyperlink opens the dialog. A criterion, in this case, is a special string entered in the Geopoint Qualification Criteria text box. (The string format is the SQL 92 syntax, regular SQL as relates to a database query WHERE clause.) For example, if tracking only visitors, the SQL would need something like usertype=visitor. Where usertype is a Geopoints metadata property. visitor is the metadata property value.

geofence-screen6

Events and Actions

Detecting, tracing, and tracking geopoints in relationship to a geofence establish the event clockwork for execution of developer defined actions. An event occurs as a Geopoint transports into and out of or stays in a Geofence. An action is a set of parameters the developer selects to perform a function, such as deliver a message to a mobile device or add a record to a database.

Events

Three event types are organized in columns in the List of Geofences. The events types are:

 

On Enter - a Geopoint crosses the Geofence boundary into the defined area
On Stay - a Geopoint remains in the Geofence area for at least a specified period
On Exit - a Geopoint crosses the Geofence boundary out of the defined area

Actions

For each of the above events, a developer can select an action and specify parameters to be executed from Backendless. There are four action types:
 

Push notification
Publish-subscribe (pub/sub) message
Send a custom event
Call a URL

 

The scenarios for choosing an action are wildly different; however, they drive the action and parameter choices the developer makes. When an action type is selected for an event, a dialog appears where action parameters can be entered. The fields in the dialog are specific to the action type.

 

fencing-17.zoom30

fencing-18.zoom30

fencing-19.zoom30

fencing-20.zoom30

 

Whenever an action is configured, visual elements indicate whether the parameters are complete. A gear icon and green checkmark indicate proper configuration, where as a red X in place of the checkmark indicates improper configuration. The configuration can be edited by clicking the gear to reopen the currently assigned action dialog.

 

Push Notification Action

All three Geofence events can trigger this action. Push Notification, in basic form, is a message sent to a mobile device associated with a Geopoint or to a group of devices registered with a channel. The Configure Push Notification Action dialog provides flexible parameter options:

 

Content Configuration - configure Push Notification content look and feel for Android, iOS, or Windows Phone.
Message Headers - allows header name and header value.
Delivery - to individual Geopoints or those registered to a channel.

 

fencing-17

Send a Pub/Sub Message Action

This action sends a publish/subscribe message. The developer enters the message parameters in the Configure Pub/Sub Message Action dialog. (Learn more about Message Publishing.) The dialog contains the following fields:

 

Channel name - the name for a channel. Backendless creates the channel if it doesn't exist.
Topic name - the name of a topic used for filtered delivery.
Message headers - optional. Use the key=value format. Comma delimited.
Message body - written in JSON. The body of the message to be delivered.

fencing-18

 

_img2

A probation officer (PO) issues an ankle bracelet to a probationer. He needs to set area from which the probationer cannot leave, such as restricted to travel only within a state. The PO would set up a Geofence outlining Colorado's state-line borders. For that Geofence, he would set the action event On Exit to send a notification to the application on his device that would provide metadata about the probationer such as location, the probationer's photo, phone number, address, etc.

 

Call URL Action

This action executes an HTTP command on the specified URL. Supported commands are GET, POST, or PUT. The developer configures the call in the Configure Call URL Action dialog. The dialog contains the following fields:

 

Command - choice of GET, POST, or PUT
URL - a fully formed internet protocol URL.
Request headers - any of the HTTP header types in the form of key=value.
Body - text message for calling the URL.

fencing-20

Send Custom Event

Provides a means for enabling Geofencing processing logic to execute your custom server-side code deployed to Backendless. Send Custom Event issues an event that you define in the Send Custom Event dialog box. See Custom Events under Business Logic. Backendless acts as a functional intermediary for your custom event handler which contains business logic specific to the application such as sending out an email or saving a record to a database.

fencing-19

Is Active - Geofence Monitoring

Is Active is the final column in the List of Geofences. It indicates whether server-side Geofence monitoring can be activated. When monitoring is ON, Backendless tracks any movements of the Geopoints in relation to the corresponding Geofence. The list below shows item content:

 

Missing Actions - look for red X next to the edit action gear. An action is improperly configured.
ON/OFF Toggle - click to switch either on or off. ON activates the server-side monitoring for the selected Geofence.

 

When an action is properly configured, i.e. complete, the Is Active toggle for the selected Geofence appears. When set to ON, a popup provides cautionary information and a checkbox option, which applies actions to Geopoints located within the Geofence at the time when the monitoring is turned on (i.e. the toggle is being set to ON). See the image below.

fencing-21

 

Once server-side monitoring is activated by setting the Is Active toggle to ON, a play button appears next to the gear icon. This button executes the action on-demand for any Geopoints within the Geofence. (This function can be useful when debugging.)

View Geopoints in a Geofence

For any Geofence that is currently active (i.e. is under server-side monitoring), a checkbox option displays Geopoints located within the Geofence. Geopoints located within the Geofence  are represented by a marker for Google Maps inside the Geofence.

 

The frequency of refresh on the screen is controlled by the refresh interval. The data is being refreshed every 10 seconds. You can force a refresh by clicking the refresh button. See the image below.

fencing-22

 

Geofence API

The Geolocation service provides the following APIs:

Run the OnEnter action

Run the OnStay action

Run the OnExit action

Retrieve geopoints from a geofence

 

Run the OnEnter Action


Requests the server to run the configured OnEnter action for a geofence either for all geopoints located within the geofence or for the specified geopoint.

 

Method:

POST

URL:

https://api.backendless.com/<applicaton-id>/<REST-api-key>/geo/fence/onenter?geoFence=<geofenceName>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<geofenceName> - name of the geofence for which the OnEnter action will run.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request body:

The body may optionally contain a geopoint object. If specified, the geopoint will be used as the context for the action execution. Any substitutions which the action may be configured with will be resolved against the geopoint. If there is no geopoint in the body, the action is executed on all geopoints located within the geofence.

Response body:

Number of geopoints for which the action has been executed.

Example:

curl -H "Content-Type:application/json" \
-d "{ \"latitude\": 10, \"longitude\": 20}" \
-X POST \
https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/fence/onenter?geoFence=RadioCityHall

Run the OnStay Action


Requests the server to run the configured OnStay action for a geofence either for all geopoints located within the geofence or for the specified geopoint.

 

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/fence/onstay?geoFence=<geofenceName>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<geofenceName> - name of the geofence for which the OnStay action will run.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request body:

The body may optionally contain a geopoint object. If specified, the geopoint will be used as the context for the action execution. Any substitutions which the action may be configured with will be resolved against the geopoint. If there is no geopoint in the body, the action is executed on all geopoints located within the geofence.

Response body:

Number of geopoints for which the action has been executed.

Example:

curl -H "Content-Type:application/json" \
-d "{ \"latitude\": 10, \"longitude\": 20}" \
-X POST \
https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/fence/onstay?geoFence=RadioCityHall

Run the OnExit Action


Requests the server to run the configured OnExit action for a geofence either for all geopoints located within the geofence or for the specified geopoint.

 

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/fence/onxit?geoFence=<geofenceName>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<geofenceName> - name of the geofence for which the OnExit action will run.

Request headers:

Content-Type: application/json
user-token: optional value obtained as a result of the login operation.

where:

Content-Type - Must be set to application/json. This header is mandatory.
user-token - Optional header. Contains a value returned by Backendless in a preceding user Login API call. If user-token is set in the request, the currently logged in user will be assigned to the ownerId property of the user object which is being saved.  Additionally, the operation will be executed with the security policy associated currently logged in user. This means all permissions associated with the user and the roles assigned to the user will be enforced by Backendless.

Request body:

The body may optionally contain a geopoint object. If specified, the geopoint will be used as the context for the action execution. Any substitutions which the action may be configured with will be resolved against the geopoint. If there is no geopoint in the body, the action is executed on all geopoints located within the geofence.

Response body:

Number of geopoints for which the action has been executed.

Example:

curl -H Content-Type:application/json \
-d "{ \"latitude\": 10, \"longitude\": 20}" \
-X POST \
https://api.backendless.com/XXXX-XXXX-XXXX/ZZZZ-ZZZZ-ZZZZ/geo/fence/onexit?geoFence=RadioCityHall

Retrieve Geopoints from a Geofence


Retrieves a collection of geopoints currently located within a geofence

 

Method:

POST

URL:

https://api.backendless.com/<application-id>/<REST-api-key>/geo/points?geoFence=<geofenceName>&pagesize=<pageSize>&offset=<offset>&includemetadata=<metaInResponse>

where:

<application id> - ID of the application which can be obtained from the Manage > App Settings screen of the Backendless Console
<REST-api-key> - REST API key of your application. You can get the value from the Manage > App Settings section of the Backendless Console.
<geoFenceName> - name of a geofence to retrieve the geopoints from.
<pageSize> - number of geo points to be returned in the response.
<metaInResponse> - a Boolean value indicating whether geo point metadata should be included in the response. Supported values are true or false