close anchor

Introduction

This describes the endpoints and basic usage of the Elebase API pre-launch version 0.1.

Version

The present version of the Elebase API is 0.1. Include this version in the URL path, for example:

https://api.elebase.io/0.1/test

Protocol and Domain

The Elebase API is provided exclusively via HTTPS on the api.elebase.io domain. Endpoint data is provided as JSON.

$ curl -i https://api.elebase.io/0.1/test

HTTP/1.1 401 
Date: Tue, 19 Jul 2016 19:11:00 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-Content-Type-Options: nosniff
X-Powered-By: Elebase
X-Xss-Protection: 1; mode=block
X-Usage-Limit-Info: 1/1200
X-Usage-Limit-Time: 60
Cache-Control: public
Last-Modified: Tue, 19 Jul 2016 19:11:00 GMT
Vary: Accept-Encoding
{"error":{"id":"invalid_key","data":null}}

Authentication and Authorization

The Elebase API incorporates hash-based message authentication (HMAC) for developer identification purposes. This enables both the interface and the developer to know and use a private key without ever transmitting the key itself, like a password, in transactions.

In order to enable usage of this technique, the developer is provided both a public and private key. The public key is effectively a developer ID, identified with an Elebase Project. The private key is a protected value (encrypted in the project database) that is used to prepare an HMAC SHA-256 hash with the input data being provided (JSON-encoded) and a timestamp.

The Elebase API includes functionality, throughout, which is based on individual user level- and group-driven privileges. In order for endpoints to perform functions on behalf of a user, that user would tend to be expected to log in by providing their e-mail and password. The /user/login endpoint provides this functionality. If the user login is valid, this endpoint delivers a token for persistent login on their behalf, if desired. This persistent login token is explicitly tied to both the individual user and the developer key it was provided for, therefore it would not persist between expressions using different keys. Elebase does not proactively expire user tokens because this is a project- or expression-level decision; therefore, in order to log a user out, either as a user- or policy-driven event (based on elapsed time of inactivity, for example), the expression ought to delete this user token for itself. In order to identify an endpoint transaction with a user, not expecting that user to first log in, include an Elebase User ID in place of this token.

The below is an example of using this technique in PHP for both developer and user identification purposes, in which the values for both the public and private developer keys would of course be declared:

$curl = curl_init();

$input = (object)array(
    'type' => isset($type) && in_array($type, array('POST','PUT','DELETE')) ? $type : 'GET',
    'data' => isset($data) && is_object($data) ? json_encode($data) : null,
    'time' => time(),
    'user' => isset($user->token) ? $user->token : null
);

$key = (object)array('public' => '', 'private' => '');

curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $input->type);
curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate');
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
    'Accept: application/json',
    'Accept-Encoding: gzip, deflate',
    'Accept-Language: en',
    'Authorization: Elebase '.implode(':', array(
        $key->public,
        hash_hmac('sha256', $input->data.$input->time, $key->private),
        $input->time,
        $input->user
    ))
));
if( in_array($input->type, array('POST','PUT'))) {
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $input->data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 0);
curl_setopt($curl, CURLOPT_URL, 'https://api.elebase.io/0.1/test');
curl_setopt($curl, CURLOPT_VERBOSE, false);

$obj = (object)array('body' => curl_exec($curl), 'info' => curl_getinfo($curl));

curl_close($curl);

print_r($obj);

This includes an 'Elebase' prefix and colon-delimited public key, the prepared hash, timestamp and (optional) user login token in the HTTP Authorization header. The private key itself is not included in the transaction. The public key is used to identify the developer, their project and private key. Elebase then prepares an identical hash based on that private key, the JSON-encoded input data and timestamp provided. If this hash is not identical, then either an invalid private key was used, the hash was improperly prepared, or there was potentially interference with the transaction data, perhaps by an uninvited third party. In this event, the transaction will be denied and an error provided instead.

The example below, in Javascript, is partial in that it uses a third-party library to prepare the hash and includes no technique to prevent the private key from being exposed:

var input = {
    'type': type ? type : 'GET',
    'data': data ? JSON.stringify(data) : null,
    'time': Math.round(Date.now() / 1000),
    'user': user.token ? user.token : null
};
var post = ['POST','PUT'].indexOf(input.type) !== -1 && input.data !== null;
var key = {'public': '', 'private': ''};
var hash = new Hashes.SHA256;
var obj = new XMLHttpRequest();

obj.open(input.type, 'https://api.elebase.io/0.1/test', true);
obj.setRequestHeader('Accept', 'application/json');
obj.setRequestHeader('Accept-Encoding', 'gzip, deflate');
obj.setRequestHeader('Accept-Language', 'en');
obj.setRequestHeader('Authorization', 'Elebase ' + [
    key.public,
    hash.hex_hmac(key.private, (post ? input.data : '') + input.time),
    input.time,
    input.user
].join(':'));
obj.onreadystatechange = function() {
    if( obj.readyState == 4 ) {
        console.log(obj);
    }
}
obj.send(post ? input.data : null);

If preferred, this would be the jQuery equivalent to use in place of the obj in the previous example:

$.ajax({
    complete: function(obj) {
        console.log(obj);
    },
    data: post ? input.data : null,
    headers: {
        'Accept': 'application/json',
        'Accept-Language': 'en',
        'Authorization': 'Elebase ' + [
            key.public,
            hash.hex_hmac(key.private, (post ? input.data : '') + input.time),
            input.time,
            input.user
        ].join(':')
    },
    type: input.type,
    url: 'https://api.elebase.io/0.1/test'
});

In order to initiate a POST, PUT, or DELETE endpoint transaction and not be denied, enable those verb(s) for the developer key in use.

Internationalization and Localization

Elebase provides for localization of text based on the locale(s) included for a project. To indicate the locale for an endpoint transaction (being of those provided by the /locales endpoint), include it in the HTTP Accept-Language header. This will inform the endpoint of the language or locale in which text is being entered (POST, PUT), or that in which to provide a translation if one exists (GET). If, for the latter, a known locale is not provided, or no value exists in the locale indicated, the endpoint will infer a locale based on the project fallback locale graph (defined via the /project/locales endpoint), or the Elebase platform default locale ('en').

If, for example, the locale indicated for an endpoint transaction is Latin ('la'), for which English ('en') is the fallback locale defined in the project, and no Latin translation for the entity or property in question exists yet, the endpoint will provide English text in favor of an empty value. In order to bypass this logic for GET transactions, indicate both locales ('en,la') and the endpoint will deliver an object with both values, keyed by locale, thereby enabling the developer to use exactly the locale intended, empty or not.

{"text":{"en":"info","la":null}}

In order to force a locale-keyed object to be delivered for textual data even if only indicating one locale for the endpoint transaction, include the locale followed by ',*' (i.e., 'en,*').

HTTP Verbs

The Elebase API uses HTTP verbs intended for different types of endpoint functionality:

Verb Description
GET Information delivery: used for pulling data on entities throughout the platform.
POST Used to provide data on new entities that do not yet exist (insert).
PUT Used for editing data on entities present in the database (update). PUT transactions tend to be idempotent, in that if an entity is updated with identical values twice, it will be no different than it was upon finishing the initial transaction. The exception to this will be information kept in transaction logs (if, for example, the date/time of each update would be preserved).
DELETE Used to delete an entity.

Endpoints

Individual per-endpoint documentation is provided below. Endpoints are prefixed with the following URL:

https://api.elebase.io/0.1

Parameters

Individual endpoints throughout the API take in expected or optional parameters, depending on the type(s) of entity and information being provided. This is documented on a per-endpoint basis individually; but in general, for endpoints using GET (or DELETE), any parameters not included in the path can be passed in the HTTP query, for example:

$ curl -i https://api.elebase.io/0.1/test?key=value

If doing POST and PUT endpoint transactions, encode parameters not included in the URL as JSON.

Errors

The Elebase API delivers an error object if there is a failure to execute the query or function provided by an endpoint, or if there is a problem with user input:

Field Type Description
id string The error ID, or type, providing a brief indication of the kind of error being delivered.
data -- If provided, this will include data the endpoint identified as being problematic.

Individual endpoints deliver errors unique to the queries or functionality they provide. This is documented on a per-endpoint basis, while the errors described below pertain to endpoints throughout the platform:

ID/Type Description
data_not_provided The endpoint function or query expects JSON-encoded parameters that were not included.
entity_not_found The entity for which data is of interest does not exist based on the unique identifier(s) provided. If not empty, the data included for this error will be the ID for which no entity is found.
id_not_provided The endpoint function or query depends on a unique identifier that was either badly formed or not provided. If not empty, the data included for this error will be either the badly formed ID or an object indicating the type of entity for which the ID was badly formed or not provided.
illegal_verb The HTTP verb used is not known or provided for by the endpoint.
internal_error The endpoint partially failed due to a technical problem or unidentified bug, and therefore no further information exists (yet) to provide. This ought to be extremely infrequent, and the error will be logged to enable further investigation.
invalid_key The developer key provided does not exist or is not identified with a live Elebase project.
invalid_user_token The user login or password initialization token is invalid or expired.
path_not_found The endpoint URL or path does not exist.
privilege_denied_internal The endpoint is intended for Elebase platform-level functionality exclusively, and is therefore not exposed to a developer for an individual project-based transaction.
privilege_denied_key The developer key in use is not identified with the privilege to execute this transaction, for example if the HTTP verb is not enabled for it.
privilege_denied_user The endpoint or data is login-protected. If no user is logged in, or if the user is not of the expected user type or privilege level, the endpoint transaction is denied. If not empty, the data included for this error will be an object indicating the type of entity, and the id thereof, for which privilege is denied.
project_not_identified The Elebase project is not identifiable either by the unique ID provided or the developer key in use.
usage_limit_exceeded The quota of transactions per interval, as indicated by the X-Usage-Limit-Info header, is exceeded and the intended transaction ought to be delayed until the expiry time, provided in the X-Usage-Limit-Time header (in seconds), is elapsed.
user_not_found The user does not exist in the Elebase project identified with the developer key in use. If not empty, the data included for this error will be the ID provided for which no user is found.

HTTP Codes

The Elebase API delivers HTTP codes based on the input parameters and data provided to, or by, individual endpoints:

Code Description
100 In general, this will not be delivered by an endpoint but is used internally for processing queries or logging transaction errors.
200 Indicates the endpoint function or query was performed with no error(s) and the data is provided as expected.
201 In general, this will pertain only to POST endpoints in which an entity that did not previously exist is inserted to the project database.
304 If the endpoint data to be provided would be identical to that of prior transaction(s), based on a date indicated by the client in the If-Modified-Since header (time-based) or a value for If-None-Match (being an ETag identified with a previous transaction), the endpoint will deliver this code and provide no data. This enables conditional GET transactions in which time-based queries do not count toward usage quota limitations, and bandwidth is decreased for either. In order to base caching on this effectively, identify and provide for any query parameter(s) that would be unique to an individual endpoint transaction for which data is being cached.
400 If provided, this will typically indicate a problem with input data provided to the endpoint, for example if an expected parameter was not included or data was provided in an invalid format.
401 Indicates a problem with the developer key in use or with an individual user's login or token.
403 Indicates the user presently logged in is not identified with the expected privilege(s) for an entity.
404 Indicates the path or entity in question was not found, and therefore no data exists to be provided.
405 Indicates the HTTP verb used is either not known, not enabled for the developer key in use, or not provided for by the endpoint in question, typically only delivered with an illegal_verb or privilege_denied_key error.
429 In general, this will only be provided with the usage_limit_exceeded error.
500 Internal error, delivered only if the transaction experienced a problem not yet identified, on which no further information therefore exists. This ought to be extremely infrequent.
Register for an Invitation
Thank you!
We'll be in touch.
First Name*
Last Name*
(optional) Business Name
Role*
Email*