Getting Started

alt text

What is Hurakann?

Hurakann is a computing distributed, decentralized, concurrent and lightweight software platform for building private or public applications in the cloud. Hurakann was built on the following premises:

  • Concurrent: Support unlimited concurrent connections without side effects in performance.
  • Massive Data Processing: Store unlimited amounts of information of objects and keep high performance.
  • Scalability: Increase the capacity for process requests and storage adding nodes to a cluster as needed, adjusting automatically for higher performance.
  • Dynamical: Store, fetch, update or delete information as needed, using API’s or SDK’s.
  • Availability: Store, replicate and synchronize data between a collection of nodes, making it “clusterizable”
  • No-downtime: Even updating any resource, always run in “mode on” in a transparent layer.

Motivation

Actually building an application (mobile, web, desktop) could be a tedious, large and slow task because developers need:

  • A cloud server hardware to mount the back-end.
  • To develop the back-end for data access.
  • To design the database or how the data is structured.

Then, integration with the back-end side becomes a bottleneck in the development plan. Hurakann solves the problem providing a dynamic API to store, fetch, update and delete data that any application uses.

Managing users, objects and entities, “come on IoT (Internet of Things)!”

In real world almost every application require managing USERS, like register, manage profiles, login, relationships and the integration with the newly called IoT (Internet of Things), so each user, object or entity could be linked to devices, actions or specific features, or a USER can be considered an ENTITY, and ARTEFACT or a THING.

Hurakann is able to manage all actions related to a single USER so adding functionality, integrating other applications and adding iterations to such USER translates in lowering development time and cost savings.

All applications are built in a “static” way so when something requires to be integrated or something requires to be added, the task becomes really complicated and time consuming.

Hurakann provides a dynamic access to objects or actions so they may be changed in versatile ways. The platform is able to grow up on data volume and design on the fly without side effects in performance. At this point Hurakann becomes a dynamic database for any application using native code.

API - your database in the cloud simple and intelligible

Hurakann exposes the access to data stored in the database via RESTful services called API.

API is the collection of RESTful services that is designed for specific actions over your stored objects. The API uses single resources allocated in the private or public clouds using a standard data formatting like JSON or XML.

Any application looking for integration with Hurakann simply could access the platform through the API, using http protocol and following the correct structured file formats for each service.

SDK - jumping to implementation, don’t worry about the black side

When an application is built with Hurakann, developers don’t have to worry about how data is structured and accessed. However, in most cases, developers don’t want to learn or become related to work with integration protocols, file formats, encode and decode data, and collect things that could become a “headache”.

At this point using Hurakann API could produce a backlog in development time and slow down integration, because developers don’t know things such as: parse a file format, access to data parsed, send http requests, read responses, and other related things based on working with API’s.

In response to that, Hurakann provides a native integration for managing objects and actions, using a native programming language that developers are able to use for integration. Languages sucha as java, object C or javascript.

And that is something called “SDK” (Software Development Kit). The SDK is designed for each language to bind better with integration so Hurakann SDK is faster and easier to use than the Hurakann API.

Hurakann SDK provides a native way for a language to consume an API and guarantee developers not to spend extra time in integration and testing.

How it works?

Cluster (Nodes)

Hurakan is designed for distributed computing, what it means is that the system runs over "nodes".

Hurakann is written in Erlang taking advantage of concurrency, native lightweight processes and availability.

Each node in Hurakann is a set of tools of a package, ready for building a cluster.

Hurakann is designed so that each node in the cluster balances the incoming requests among nodes avoiding that one member processes all. Each node in the cluster is an identical copy of other members so that all incoming requests are able to be processed by all members.

Hurakann uses primitive remote procedure calls (RPC) to balance the load of requests among nodes, so that a node receiving the request lookup for a "free node of load" or for a "node with less load" in the cluster and passes the request for processing.

One node could be of type:

  • Neighbor: the node is a worker in a cluster, and only processes required requests. It is like an extension in the cluster.

  • Root: the node works as "main", controlling neighbor nodes and balancing requests among them. This node type has a special feature: if it is disconnected from a cloud node then it will keep changes on the database for synced when it detects a connection. This node type is intended to work as an "offline" node, and the synced could be set as: enabled or disabled at any time. When a connection is detected the root node could handoff all data in the cloud to sync up the database, using vclocks.

  • Cloud: the node is in the cloud and could have root nodes connected. The node is responsible for keeping all set of data of all root nodes connected or simply work as a “root” node but in the cloud. Root nodes could be added, as you need them at any time.

Vnodes

Vnode (Virtual Node) is a term used for describing virtual unique processes into a node, each virtual node is responsible for treating data, logging transactions and ensure atomicity and consistency of data. The vnode is a temporal process that lives while the processing of data is taking place.

A vnode starts when incoming a request (from client) and it keeps alive while the request is processed, stops when the process of data has finished (commonly when client receive response). A vnode uses last write wins so for example if two or more request collide in the system at the same time, the last of them writting, updating or deleting data will win and this will be the final data preserved into the backend database.

Vnodes are built with 3 processes linked, each process is responsible for a specific task into the vnode, they are:

  • Worker
  • Tracer
  • Transactor

A worker process executes the dirty work in the vnode, so the worker process and validate the data flow ensuring the consistency in the data when writting, deleting or updating in the backend database, so in more simple words the worker execute transaction by transaction (write, update, delete, fetch) in the backend database.

A tracer process looks each transaction executed by the worker, so the tracer knows which one data is being modified at time, in others words the tracer is logging each transaction (write, update, delete, fetch) in the database backend.

A transactor process saves the log of data that the tracer is looking and is 'supervising' to the worker so if the worker finish the transactor can determinate if it terminates with a success or failure. If the worker (for any reason) terminates in a success state the transactor can commit all data to the database backend, otherwise if the worker (for failure reasons) terminates (or abort) in a failure state the transactor can rollback all data to the database backend to a previous state and keeps the entire database in a state before executes the client request.

Plugins or addons

Plugins or addons is a special feature to allow adding modules, workers or applications into Hurakann node, and becomes an extension arm of the system.

Plugins allow Hurakann to process specific tasks on the node, replicating all behaviour in the cluster. For example if you need to process incoming messages on a specific port and format, a nicely protocol implementation for a specific message, generating random data can be created with plugins.

Plugins must be written in erlang and they are managed by Hurakann.

Security Concerns

Ckey (Client Key Token) is an id to access the API, so it’s is used as an auth method against the black-box side, is an unique and unrepeatable value for each segment in the database. This token joined to another certificates in the core system ensures that all data are encrypted and stored in a specific segment of the database isolated from others, so only vnodes that are certificates to use the ckey can access data in the database. Ckey must be send in the Headers of each request in order to retrieve or push data. The certificates (including ckey) are created at the first time using the CLI and provided to the client.

HQL

With HQL you can query (search) over your stored and indexed objects into your database segment. HQL has many features to satisfy the most common search cases in a common system. HQL is inspired and based in Solr queries but with a powerful model that has many differences from the original.

In difference to other QL (Query Languages), HQL uses a specific syntax and commands to retrieve data. Hurakann can interpret your query from a single line of code as in SQL SELECT, but without specifiying the SELECT and FROM on the same query, just over your entity.

In the last version of HQL you must provide the datatype to each field in the query, so, if you save your object with some field as int, boolean or string, just provide that info to the query:

WHERE name:s=Allison AND years:i=40 

The datatype must be after ':'. The supported datatypes are:

Prefix Datatype
i integer
s string
b boolean
f float
dt date

date type must be in format ISO 8601

Let’s do it!

Simple Querying

For example, in our database we saved our object whit name, lastname and also a custom parameters called _box_id, _years and _company_id, then our object looks like this:

{
  "name":"Allison",
  "lastname":"Mosshart",
  "_box_id":"1AB456",
  "_years":40,
  "_company_id":"1abcb718ajcnakaks819"
}

Now, how we can search all objects with ‘Allison’ in the field name?, simple, in the search API use HQL:

WHERE name:s=Allison

HQL uses AND, OR, NOT condition to satisfy logic operators, for example, search the objects with name ‘Allison’ or with name ‘Jack’ but NOT name ‘Meg’:

WHERE name:s=Allison OR name:s=Jack NOT name:s=Meg

Wildcard

You can use the wildcard * to match everything after or before a string comparison, example, search the objects that name starts with ‘Jac’ like ‘Jack’, ‘Jackie’:

WHERE name:s=Jac*

Ranges

You can use ranges on fields that are numeric fields, for example, search the objects with years mayor than 30 and minor than 50:

WHERE years:i<50 AND years:i>30

Ranges apply for datatypes: float, integer and date.

Ranges must be set with mayor and minor, for that purpose use wildcard * if one of limits are not provided, example, search years only mayor to 50:

WHERE years:i<* AND years:i>50

#### Time Series

In every object stored in the database there are two attributes indexed by default: inserted_at and updated_at. The timestamp is useful when you want retrieve objects in a range of time so for example you can query data from the first of this month until today (updated or inserted). In order to execute the query in a successful state the date must be converted to ISO 8601:

WHERE inserted_at:dt>2017-03-09T00:00:00Z AND inserted_at:dt<2017-03-13T00:00:00Z...	

If you noticed the date is passed in ISO 8601 format, so in the example the query will retrieve all objects created between 2017-March-09 and 2017-March-13.

Grouping

When you perform a complex search maybe grouping data could be useful, example, search the objects with name ‘Allison’ or Jack and box_id that starts with ‘ABC’:

WHERE (name:s=Allison OR name:s=Jack) AND box_id:s=ABC*

Grouped data are enclosed into parentheses ( ). HQL only allows one group at time, no group into group

Included Fields

Included fields is a feature of HQL to retrieve specific fields of a object in a search, example, search the objects with name ‘Allison’ and include on each result the years:

WHERE name:s=Allison INCLUDE years

For more included fields, just separate with ‘,’ delimiter

Parent Fields

When you create your object, any of your custom fields could have an id of another object inside (like a link), then in your search you want to know the parent object fields, example, search the objects with name ‘Allison’ and include on each result the years, also retrieve the name of the company that belongs the object:

WHERE name:s=Allison INCLUDE years PARENT_FIELDS company_id

For more parent fields, just separate with ‘,’ delimiter

HQL just retrieve parent fields from the actual object, just for one level

Then on each object you can extract the tag ‘company_id_obj’ that is the object representing the company, similar to make a GET request. To extract the PARENT_FIELDS result from each object just concat to your field the prefix ‘obj’, so in the example we set PARENT_FIELDS with company_id, then extract company_id_obj

Sorting

With HQL you can sort your query results in ascendent or descendent form. To use this just use SORT_BY_ASC (for ascendent) or SORT_BY_DESC (for descendent) and the field that you want sort by, example, search the objects where name starts with Jac and then sort by name in ascendent form:

WHERE name:s=Jac* SORT_BY_ASC name_s

You must set a valid field to sort by, the field must follow by the type of it, for example if your field is string, then: name_s, if it’s integer: name_i or if it’s boolean: name_b.

The new version of HQL now support the LINK operation and it’s very simple to use, since it works like a JOIN in SQL systems. The LINK operation can be used when you want query your objects with a relationship between them in only one query (in one sentence), so for example, this allows you query data from different objects and link them to generate only one output.

Example: imagine a system that a user can publish posts (in a blog), then each post is a single object in the database and the users publishing are other objects in the same system, then, how we can query the posts from the user with the nickname equals to almoss?, simple, use LINK:

WHERE nickname=almoss AS user LINK entity=post AND owner=user.id INCLUDE favs,text

Explaining the query: HQL evaluates the first query that is: nickname=almoss, then retrieve objects from database where the condition is true, so the result of this query is stored in a variable called user, and linked to another query searching the objects where entity equals to post and owner equals to id of the variable user.

The id in the alias is the id of the objects (when saving post, each of them have an owner attribute with the id of the user), but however you can use the attributes of the objects queried and assigned to the alias, for example, if our user has an attribute age, then we can use user.age to insert the value of the attribute using the alias.

The alias always have an attribute id that is the id of the object in the system.

Regular Expressions

As in solr v4 the HQL supports regular expressions in queries, only in string fields, for example:

WHERE name:s=/.*[Mm]egan.*/

The above query will search over objects where the string Megan or megan is present somewhere in the field. If you need more info about how to use and examples how to use regular expression consult this tutorial.

HQL BIFs (built-in functions)

HQL also supports a feature called BIFs that is a built-in functions in the backend system, the built-in functions need a function declared over a field followed by a query and returns a single response instead many records as the common searches. The next are the BIFs supported for now:

BIF Description
MAX Returns the max value of a rows
MIN Returns the min value of a rows
AVG Returns the average of a rows (for a field)
SUM Returns the sum of a rows (for a field)

For example, let’s say we want to know the total likes of all user’s posts, then to perform that we must use the SUM BIF:

SUM likes:i WHERE entity=post AND nickname:s=Allison

The above query could return the sum of all likes: json {"sum": 5004}

Another good example could be if we want to know the age of the older employee and the average of all ages of all employees:

MAX years:i WHERE name:s=* AND type:s=employee
AVG years:i WHERE name:s=* AND type:s=employee

The result of each BIF is a single json with one attribute, containing the name of the BIF as key and the value will be the numeric result. Each BIF must be sent with a single field and the field must contains the prefix for datataype.

Restrictions

  • A query could start with reserved words for a BIF: MAX, MIN, AVG, SUM
  • A query could start with reserved word WHERE
  • In a query, if not provide sort field, default is set to name
  • All fields must contains datatype, if not provided then s is used.
  • Conditions must be separated by spaces
  • OR, AND, NOT are reserved words and must be used in uppercase
  • PARENT_FIELDS and INCLUDE are reserved words and must be used in uppercase
  • For many fields on INCLUDE or PARENT_FIELDS use comma as delimiter
  • For SORT_BY_DESC and SORT_BY_ASC field must have a prefix of data type
  • For AS _ LINK the sentence must start with AS, after a var and finish with a LINK, then other query
  • Allowed operators are: =, >, <, <=, >=

Nested Procedure Operations

Nested Procedure Operations (N.P.O) allows executing many operations in a row step-by-step, so you won’t deal with callbacks from your app. This method avoid inconsistence in data, for example, if you get an object and use the info to update another using your app, maybe external factors such as network connection issues or even programming validations could affect data if some of operations fail before executing the others.

Hurakann creates a single process to keep the order of steps and execute one by one, if some fails, then the entire operation is applied as rollback, otherwise commit the transaction.

The N.P.O works using a single interface (API Restful) with a JSON format, and the steps are described based on the web-services in Hurakann API, even you can use a nested procedure into another nested procedure!.

Features

  • Many operations in a row step-by-step
  • Dynamical data injection using jsonpath

How it works?

You must define the steps in your procedure, and then model into the JSON request using the /nested/procedures endpoint, for example, let’s say, we want get an object from the database and then create another object so then a relantionship will be created

First we need to know which one web-service is used for getting info of an object:

URI Method Inject Request Next Phase
user GET [ {"from": "name", "to": "_parent_name"} ] String Json Skip

Now we have our first step, this will look like this:

{
  "uri": "user",
  "method": "GET",
  "inject": [{"from": "name", "to": "_parent_name"}],
  "request":"{\"user_id\":\"id\",\"branch_id\":\"bid\",\"phase\":\"phase1\"}",
  "next": { }
}

Now we must design the next step, and in this case the next step use the result of the first step searching the jsonpath equals to name and inject in a new attribute of the newly created object using again a jsonpath this time equals to _parent_name, so our next step looks like this:

{
  "uri": "user",
  "method": "POST",
  "request":"{
    \"branch_id\":\"bid\",
    \"coloruser\":\"black\",
    \"name\":\"John\",
    \"phase\":\"phase1\",
    \"user_id\":\"id\",
    \"profile_id\":\"pid\",
    \"_parent_name\":\"_\"
  }" 
}

if you noticed, the final element of the request is a _parent_name, with this in the to (inject) we are indicating to the N.P.O that inject the value returned by the first step in this field.

Now putting all together:

{
  "uri": "user",
  "method": "GET",
  "inject": [
    { "from": "name", "to": "_parent_name"}
  ],
  "request": "{
    \"user_id\":\"id\",
    \"branch_id\":\"bid\",
    \"phase\":\"phase1\"
  }",
  "next": {
    "uri": "user",
    "method": "POST",
    "request": "{
      \"branch_id\":\"bid\",
      \"coloruser\":\"black\",
      \"name\":\"John\",
      \"phase\":\"phase1\",
      \"user_id\":\"id\",
      \"profile_id\":\"pid\",
      \"_parent_name\":\"_\"
    }"
  }
}

Cool!, now we dont worry about data inconsistence, since all operations all managed by Hurakann and we just use one request to do that!.

Lexical Rules

  • The uri is the original URI in the API Restful, but without versioning and if the uri contains more than once slash (/), replace this with dot (.).
  • The Method is the method used by the URI, always must be in uppercase.
  • Inject is an array of objects (from, to) with a jsonpath of data result, so the jsonpath is evaluated to get the value to send in next step (taken from the result of the actual step). The from argument represent the value to search (using jsonpath) in the response of the step. The to argument represent the path to replace (using jsonpath) with the new value.
  • In the injection of a value, set _ as the value of the attribute to replace.
  • Request is a JSON STRINGIFY of the request body or query-string (if GET Method)
  • Next is an object containing the next step, again uri, method, inject, request, and other next step (if any).

JsonPath

JsonPath is very similar to the XPath in Xml, so we use that for a common format of injection data. If you need more info about how JSONPATH works click here

You can found the doc for the API here

GeoSpatial - Search points using GPS

GeoSpatial allows you store (index) and update "locations" in your database segment to use for searching and calculating distances from locations stored to a single given point.

Imagine that you want implement a system to geo-referencing your users (for example, retail or proximity cases), so when some of your users (using a device), provide their location (latitude and longitude) and then you perform a search into your database to search the nearest location (previously registered) and Hurakann answers with a resultset with that locations.

Use case

For example, we saved this locations in our database using the API geospatial:

	Location Store One: 18.956952,-99.2315226
	Location Store Two: 18.9613766,-99.2344753
	Location Store Three: 18.63222,-99.1615037

Now one of our users provide his location with a point nearest of the location Location Store One then, sending that with the geospatial GET you should receive a resultset, ordered from the location nearest:

{"geos":
  [
    {"km":0.13275527391449998,"id":"IDLOCONE","name":"Location Store One"},
    {"km":0.4584615115187,"id":"IDLOCTWO","name":"Location Store Two"},
    {"km":36.955166644128,"id":"IDLOCTHREE","name":"Location Store Three"}
  ]
}

Let’s analyze the results, as you can see, the nearest location is Location Store One since it is 0.1327 Km away, and the other locations are away from the user actual location.

You can found the doc for the API here

Schemas

Schemas are the base to 'mapping' an entity or object into a backend database, similar to create a table structure in SQL systems. The base for an entity or object (the minimal unity) is the attribute or field, each entity or object has many attributes than can be stored into the whole object, the main characteristic is that each attribute is defined with a set of tools that can define its behaviour in the core and backend system.

Schemas are defined with an XML with a specific structure that the core can parse and store, versioning your entity or object.

When the Schema is uploaded it also translates the entity or object to a RESTful API, so the entity or object can be created, updated or fetched with a specific endpoint defined also in the schema, this is useful because a client can connect and implement this methods instead using the 'RAW' API exposed by Hurakann and have a plus: all data is passed for a serie of validations, so the consistency of each field or attribute is guaranteed by the core instead of implement outside of the box.

Schema definition

The schema must contain the certificates info of your account, so when using the dynamic endpoint you dont need pass this tedious info.

The certificates must include:

  • [x] name: the canonical name of entity or object.
  • [x] version: the version of schema.
  • [x] user_id: the user_id provided along with the certificates.
  • [x] branch_id: the branch_id provided along with the certificates.
  • [x] profile_id: the profile_id provided along with the certificates.

Attributes

Attributes or fields are the minimal unit of an entity or object, and in a schema you can define its behaviour before reach the durability into the backend database.

Each attribute can contain:

  • [x] name: the name of your attribute, this define how your attribute is written in backend database, must start with '_'.
  • [x] required: if attribute is required or not when creating the entity, if not provided 'false' is used.
  • [x] datatype: the datatype of your attribute, the options are: boolean, integer, float, date or string.
  • [x] indexed: if attribute is searchable using HQL, default set to false.
  • [x] length: optional, the length of your attribute, must be expressed as an integer value even for integer datatype, if not provided 'unlimited' is used.
  • [x] validation: optional, a valid regex to run against the attribute value before write or update in backend database.
  • [x] default: optional, if the attribute has a default value when not provided.

Dynamic Endpoint (RESTful API)

Dynamic Endpoint define how the entity or object can be stored, updated or fetched using the rules declared in the attributes section.

The endpoint must contain:

  • [x] uri: the uri to write, update or fetch the entity or object.
  • [x] methods: the methods that can enable the uri, the options are: POST, PUT, GET.
  • [x] auth: the auth method to the uri, the supported for now are: oauth2 or none.

How to use

First to all, you must define a XML containing: definition, attributes and dynamic endpoint, in this example we are using a schema that defines an entity called post:

<schema name="post" version="1.5" user_id="YOUR-USER-ID" branch_id="YOUR-BRANCH-ID" profile_id="YOUR-PROFILE-ID">
  <attributes>
    <attribute datatype="string" name="_title" required="true" length="30" indexed="true" />
    <attribute datatype="string" name="_body" required="true" length="140" indexed="true" />
    <attribute default="0" datatype="integer" name="_likes" required="true" length="3" indexed="true" />
    <attribute datatype="string" name="_date" required="false" length="10" indexed="true" validation="20[1-3][0-9]-[0-1][0-2]-[0-3][0-9]" />
  </attributes>
  <endpoint>
    <uri>/post</uri>
    <methods>POST,PUT,GET</methods>
    <auth>none</auth>
  </endpoint>
</schema>

In the above schema we are defining four attributes for the post and each attribute has a specific behaviour, also an endpoint is defined in order to access to the write, update or fetch operations.

The next step is upload the schema, so Hurakann can parse and create the dynamic endpoint:

curl -i -XPUT -H "Ckey: YOUR-CKEY" -d @schema_post.xml "http://127.0.0.1:8099/v1/schema"

If all goes ok the above request must respond with a 200 OK and then the dynamic endpoint is ready!!.

Operations

Storing

Storing method run all validations for each attribute, ensuring that data passed all validations before be written into backend database. To store an entity/object into the system using your custom defined schema (with the custom endpoint):

curl -i -XPOST -H "Ckey: YOUR-CKEY" -d '{"_title": "Schemas", "_body": "Hello, I am using schemas", "_likes": 1, "_date": "2016-01-01"}' "http://127.0.0.1:8099/v1/post"
Updating

Updating method run almost all validations, except for required attributes since in a update the required attributes can be updated or not (not always). To update an entity/object into the system using your custom defined schema (with the custom endpoint):

curl -i -XPUT -H "Ckey: YOUR-CKEY" -d '{"_title": "My Schemas", "id": "POST-ID"}' "http://127.0.0.1:8099/v1/post"
Fetching

To fetch info of an entity/object from the system using your custom defined schema (with the custom endpoint):

curl -i -XGET -H "Ckey: YOUR-CKEY" "http://127.0.0.1:8099/v1/post?id=POST-ID"

Future Implementations

For future works more auth methods can be added to the dynamic endpoints.

Authentication & Codes

The main way of API authentication is a client token provided along with your Hurakann credentials, so sending this value in the headers of each request will be enough.

If not provided Ckey is sent then the API will return an auth error code: 401 Unauthorized

The uri is built with a prefix of v1 for all listed API endpoints, for example: /v1/user/file

The next are a list of http codes returned by the API and its meaning

Code Name Description
200 Ok Success
201 Created Creation successful
204 No Content No content in response, similar to 404 but for GET
400 Bad Request Something went wrong in the core
404 Not Found Some attribute provided in the request was not found in the datastore
501 Not Implemented Could not resolve the uri
401 Unauthorized No ckey present or not found in datastore (wrong token)
412 Precondition Failed Some required attribute was not send in the request

Fast Track

Coming soon

/user

Create object with custom data into datastore

Parameters
branch_id
The branch id provided along with credentials
profile_id
The profile id provided along with credentials
user_id
The user id provided along with credentials
coloruser
The color of the object, black objects cannot create a tree below them, blue can do it.
phase
The phase for the object. Default to phase1.
password
The password for the object (used login service).
name
The name for the object. This value is set for default purposes and you can use it in your own way.
email
The email for the object (used in login service)
username
The username for the object (used in login service)
latitude
If object is a location
longitude
If object is a location
lastname
The lastname for the object. This value is set for default purposes and you can use it in your own way.
lastname2
The lastname2 for the object. This value is set for default purposes and you can use it in your own way.

For custom attributes add them starting with a _ and the name for the attribute. Value of attribute will be determinating automatically based on format

The object will be automatically stored and indexed into datastore

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"branch_id": "YOUR_BRANCH_ID", "profile_id": "YOUR_PROFILE_ID", "user_id": "YOUR_USER_ID", "coloruser": "black", "phase": "phase1", "_greeting": "hello", "_likes": 10}' http://api.hurakann/v1/user

/user

Update object with custom data into datastore

Parameters
branch_id
The branch id provided along with credentials
user_id
The id of the object previously stored

For custom attributes add them starting with a _ and the name for the attribute. Value of attribute will be determinating automatically based on format

The object will be automatically updated and re-indexed into datastore

curl -i -XPUT -H "Ckey: YOUR_APP_CKEY" -d '{"branch_id": "YOUR_BRANCH_ID", "user_id": "ID", "_greeting": "hello", "_likes": 10}' http://api.hurakann/v1/user

/user

Get object with custom data from datastore

Parameters
branch_id
The branch id provided along with credentials
user_id
The user id for the object previously stored
phase
The phase for the object, can be phase1 or all.

The response contains the object previously stored with custom data from datastore

{
  "user": {
    "branch_id": "ID"
  },
  "profile": {
    "name": "PROVISIONING-PROFILE-APP",
    "profile_id": "YOUR_PROFILE_ID"
  },
  "phase": "phase1",
  "created_at": "2017-03-09T00:00:00Z",
  "updated_at": "2017-03-09T00:00:00Z",
  "fmd": false,
  "greeting": "hello",
  "likes": 10
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user?branch_id=YOUR_BRANCH_ID&user_id=ID&phase=all

/user/availability

Check the existence of an object into datastore

Parameters
identity
The attribute to eval, can be: an email or username of an object previously stored

If response code is 200 object exists in datastore otherwise 404 is returned.

curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/availability?identity=wind@hurakann.com

/user/is_color

Check if an object is the color requested from datastore

Parameters
user_id
The id of the object previously stored
color
The color to check, can be: blue or black

If object is in the color requested return its branch id

{
  "branch_id": "ID"
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/is_color?user_id=ID&color=black

/user/file

Upload a file into datastore

Parameters
multipart/form-data
The file in a multipart form-data format

The file will be stored into datastore and return its id

{
  "file_id": "ID"
}
curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -H "Content-Type: multipart/form-data" -F "file=@storm.png" http://api.hurakann/v1/user/file

/user/file

Removes a file from datastore

Parameters
file_id
The id for the file previously uploaded

The file will be removed from datastore

curl -i -XDELETE -H "Ckey: YOUR_APP_CKEY" -d '{"file_id": "ID"}' http://api.hurakann/v1/user/file

/user/file

Download a file from datastore

Parameters
file_id
The id for the file previously uploaded

The file will be downloaded from datastore with a custom mime type

curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/file?file_id=ID

/user/login

Executes a login of an object from datastore

Parameters
user
The key for the object, can be: email or username
password
The password for the object

Performs the login action and return the results

{
  "user_id": "ID",
  "name": "NAME_IF_SET",
  "lastname": "LASTNAME_IF_SET",
  "lastname2": "LASTNAME2_IF_SET",
  "branch_id": "ID"
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/login?user=wind@hurakann.com&password=storm

/user/login/restore

Provides a valid code during next 24 hours to reset object password

Parameters
email
The email for the object

Provides a code valid next 24 hours to reset password

{
  "code": "WIND"
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/login/restore?email=wind@hurakann.com

/user/login/reset

Reset object password using a valid code

Parameters
email
The email for the object
new_password
The new password for the object
code
The code previously generated with restore api

Reset the object password using a valid code

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"email": "wind@hurakann.com", "new_password": "WIND", "code": "STORM"}' http://api.hurakann/v1/user/login/reset

/user/login/change_password

Change the object password with a new one

Parameters
user_id
The id for the object previously stored
old_password
The old password for the object
new_password
The new password for the object

Change the object password with a new one into datastore

curl -i -XPUT -H "Ckey: YOUR_APP_CKEY" -d '{"user_id": "ID", "old_password": "STORM", "new_password": "WIND"}' http://api.hurakann/v1/user/login/change_password

/user/merge

Merges two or more objects into a collection

Parameters
branch_id
The branch id of the main object
main_user_id
The id of the main object in the collection
users_id
The ids of the objects to be set into collection

Merge two or more objects into a collection and set an object as the main of the collection

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"branch_id": "ID", "main_user_id": "ID", users_id: ["ID", "ID"]}' http://api.hurakann/v1/user/merge

/user/merge

Update objects in merged collection

Parameters
branch_id
The branch id of the main object
main_user_id
The id of the main object in the collection
users_id
The ids of the objects to be set into collection
new_main_user_id
The id of the new main object in the collection

Updates merged collection and set an object as the main of the collection

curl -i -XPUT -H "Ckey: YOUR_APP_CKEY" -d '{"branch_id": "ID", "main_user_id": "ID", users_id: ["ID", "ID"], "new_main_user_id": "ID"}' http://api.hurakann/v1/user/merge

/user/merge

Get objects from merged collection

Parameters
user_id
The id of the main object in the collection

Gets merged collection using the main object

[
  {
    "user_id": "ID",
    "name": "NAME_IF_SET",
    "merge": "main"
  },
  {
    "user_id": "ID",
    "name": "NAME_IF_SET",
    "merge": "merge"
  }
]
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/merge?user_id=ID

/user/notifications

Mark as read or unread the notification

Parameters
notification_id
The id for the notification previously stored
read
The status of the read, true or false

Mark the notification read or not into datastore

curl -i -XPUT -H "Ckey: YOUR_APP_CKEY" -d '{"notification_id": "ID", "read": true}' http://api.hurakann/v1/user/notifications

/user/notifications

Creates a notification linked to an object or its tree into datastore

Parameters
title
The title for the notification
message
The body for the notification
broot
The branch id of the object to send notification to all its objects under its branch
branch_id
The branch id of the object to link directly the notification

Creates a notification for a complete tree or single linked to an object

curl -i -XGET -H "Ckey: YOUR_APP_CKEY" -d '{"title": "Welcome", "message": "This is Hurakann", "branch_id": "ID"}' http://api.hurakann/v1/user/notifications

/user/notifications

Deletes a notification from datastore

Parameters
branch_id
The branch id where the notificatio was linked
notification_id
The id for the notification previously stored

Deletes a notification from datastore

curl -i -XDELETE -H "Ckey: YOUR_APP_CKEY" -d '{"branch_id": "ID", "notification_id": "ID"}' http://api.hurakann/v1/user/notifications

/user/notifications

Get a list of notifications or a single one linked to an object

Parameters
branch_id
The branch id where the notificatio was linked
notification_id
The id for the notification previously stored

Get a single notification if provides notification_id, if not return all linked to branch id

[
  {
    "title": "A new storm",
    "read": true,
    "notification_id": "ID",
    "time": "10:00",
    "date": "2017-01-01",
    "message": "Welcome to Hurakann"
  }
]
{
  "title": "A new storm",
  "read": true,
  "notification_id": "ID",
  "time": "10:00",
  "date": "2017-01-01",
  "message": "Welcome to Hurakann"
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/notifications?branch_id=ID

/user/search/ql

Executes a HQL search into datastore

Parameters
branch_id
The branch id of the tree level
thql
The query to execute, see HQL for more info
pagination
The number of rows for page
page
The page to return, only when using pagination
pagination_id
The pagination id, only when using pagination

In the users array are the resultset, all INCLUDE field should be placed here

Executes a HQL query into datastore, page and pagination must be sent when walk into pages

{
  "total_results": 100,
  "pagination_id": "ID",
  "pages": 10,
  "users": [
    {
      "user_id": "ID",
      "profile_id": "ID",
      "phase": "phase1",
      "merge": "main",
      "broot": "ID"
    }
  ]
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/notifications?branch_id=ID&pagination=10&thql=WHERE name:s=Hurakann

/user/tags

Add tags to object into datastore

Parameters
user_id
The id for the object previously stored
tags
The list of tags to be added

Add tags to object into datastore

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"user_id": "ID", "tags": ["wind", "cold"]}' http://api.hurakann/v1/user/tags

/user/tags

Update tags to object into datastore

Parameters
user_id
The id for the object previously stored
tags
The list of tags to be updated

Update tags to object into datastore

curl -i -XPUT -H "Ckey: YOUR_APP_CKEY" -d '{"user_id": "ID", "tags": ["wind", "cold"]}' http://api.hurakann/v1/user/tags

/user/tags

Get tags of object from datastore

Parameters
user_id
The id for the object previously stored

Get tags of object from datastore

{
  "tags": ["wind", "storm"]
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/user/tags?user_id=ID

/fingerprint/verify

Check if provided fingerprint match the fingerprints of object into datastore

Parameters
user_id
The id for the object previously stored
id
The fingerprint in base64

Fingerprint base64 must be in format ISO-19794-2-2005

Check if provided fingerprint match the fingerprints stored

curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/fingerprint/verify?user_id=ID&id=BASE64

/match/fingerprint

Compare two fingerprints and check if match

Parameters
fmd_right
The right fingerprint in base64
fmd_left
The left fingerprint in base64

Fingerprints base64 must be in format ISO-19794-2-2005

Compare two fingerprints and check if they match or not

curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/match/fingerprint?fmd_left=BASE64&fmd_right=BASE64

/mobile/register

Update the status of token mobile device to send push notifications

Parameters
user_id
The id of the object previously stored
token
The token of the mobile device
status
The status of the token, active or inactive

Update the status of token mobile device to send push notifications

curl -i -XPUT -H "Ckey: YOUR_APP_CKEY" -d '{"user_id": "ID", "token": "TOKEN", "status": "active"}' http://api.hurakann/v1/mobile/register

/mobile/register

Link an object with a mobile device to send push notifications

Parameters
user_id
The id of the object previously stored
branch_id
The branch id of the object previously stored
broot
The parent branch id of the object
token
The token of the mobile device
status
The status of the token, active or inactive
platform
The platform for the device, can be: android or IOS

Link an object with a mobile device to send push notifications, an object can have multiple devices!

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"user_id": "ID", "branch_id": "ID", "broot": "ID", "token": "TOKEN", "status": "active", "platform": "IOS"}' http://api.hurakann/v1/mobile/register

/mobile/send

Send a push notification to the provided objects

Parameters
users_id
The ids of the objects previously stored to send push notification
payload
The payload of the push notification
expiry
The expiry of the push notification, only for iOS
identifier
The identifier for the push notification, only for iOS

Send a push notification to the provided objects in the token platform registered

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"users_id": ["ID"], "payload": "Hurakann!", "expiry": 30, "identifier": "I"}' http://api.hurakann/v1/mobile/send

/geospatial

Index a location into geospatial datastore

Parameters
latitude
The latitude for the location
longitude
The longitude for the location
id
The id of the object previously stored into datastore
name
An optional name for the location in geospatial datastore

Index a location into geospatial datastore

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"latitude": "0", "longitude": "0", "id": "ID", "name": "Wind"}' http://api.hurakann/v1/geospatial

/geospatial

Re-index a location into geospatial datastore

Parameters
latitude
The latitude for the location
longitude
The longitude for the location
id
The id of the object previously stored into geospatial datastore
name
An optional name for the location in geospatial datastore

Re-index a location into geospatial datastore

curl -i -XPOST -H "Ckey: YOUR_APP_CKEY" -d '{"latitude": "0", "longitude": "0", "id": "ID", "name": "Wind"}' http://api.hurakann/v1/geospatial

/geospatial

Search locations near of a given point into geospatial datastore

Parameters
lat
The latitude for the location
lon
The longitude for the location
d
The distance from the given point (in km)
max
The max resultset of locations near of given point

Search locations near of a given point into geospatial datastore

{
  "geos": [
    {
      "km": 10.4,
      "id": "ID",
      "name": "Wind Avenue"
    } 
  ]
}
curl -i -XGET -H "Ckey: YOUR_APP_CKEY" http://api.hurakann/v1/geospatial?lat=0&lon=0&max=10&d=10