Busit REST API

Concepts

The entire Busit platform relies on a cental REST API. The user panel, routing of messages,... all are handled via this endpoint.
Here are the main characteristics of the Busit REST API:

  • The URL is https://api.busit.com
  • Everything is explicit, you can use the API without messing with headers, generators,... just type it in the URL.
  • There are many alias for most operations to simplify your guesses. I.e.: /user/list is the same as /user/select.
  • The api structure is in Big Endian which means that most important thing comes first. I.e.: /system/group/user/delete means: the main system, for the given group, the specified user, delete him !
  • The API may have new releases and versions may differ. The version is named after spices or condiments and appears first in the URL.

Request / Response

  • The request is verb agnostic. This means that you can use any HTTP verb (POST, GET, PUT,...) for any operation. However, in order to avoid problems with too long URLs, we recommend to use POST all the time. (Discussion)
  • The request character encoding should be UTF-8, if another charset is used, it will be treated as UTF-8 without conversion and accents or special characters may be displayed incorrectly.
  • The response is return code agnostic. This means that it will always return 200 OK. You may encounter another return code from an upstream proxy but it will never come from the API itself. (Discussion)
  • The response character encoding is UTF-8.
  • You can speficy the output format using the f parameter (or format, or output or out as you like). Alternatively, you may use the Accept header.
    Supported output formats are:
    • json (default) : json, j, application/json
    • pretty json : pjson, jsonp, jp, pj, application/pjson
    • xml : xml, x, application/xml, text/xml
    • html : html, h, text/html
  • Using the html format, a quick documentation is generated automatically.
  • When uploading files, you should use a multipart/form-data encoding. Otherwise, use application/x-www-form-urlencoded
  • The response will either be an error or a content. Responses in JSON will be wrapped as a "response" object.
    
    {
    	"response":
    	{
    		"user_name":"test",
    		"user_id":"2"
    	}
    }
    

If multiple output formats are provided using different methods, the order of preference is first the query parameter, then the Accept header.
If multiple output formats are provided using different query parameters, then the peference is undefined.

Authentication

Most operations require specific grants. Those grants are associated with a user token.

  • The token is in the form user:token. The user is the user ID and the token is a 32 hexadecimal character string.
  • It can be passed as a parameter with the request as either of auth, credentials or api_key.
    ?auth=1234:1234567890abcdef1234567890abcdef
  • Alternatively, you may specify the token in the Authorization header, either as Basic or as Bearer. When using Basic, it should be encoded in base64.
    Authorization: Bearer 1234:1234567890abcdef1234567890abcdef
  • Tokens may expire at a certain point, but some of them are permanent.
  • Special application tokens can be issued for specific limited actions and may take another form, but you can use them just like a regular token.

If multiple tokens are provided using different methods, the order of preference is first the query parameter, then the Authorization Bearer header, then the Authorization Basic header.
If multiple tokens are provided using different query parameters, then the peference is undefined.

Self

When the user needs to perform an action on his own behalf, you should use the /self prefix in the URL. This forces the user parameter to be that of the matching token.

The /self prefix also allows privilegied actions that would otherwise not be granted. It is usually enforced by SELF_* grants.

Example:
The endpoint /system/user/delete requires an elevated USER_DELETE grant that regular users cannot use.
However, the endpoint /self/system/user/delete allows a SELF_USER_DELETE grant that is available to the current user authenticated with his token.

Errors

Every API error is composed of a message in English, a code to indicate the nature of the error, and some optional data that provide more detail about the error.

Caution: remember that the API will always return a HTTP response code of 200. (Discussion)

Possible error codes:

  • 400 : Generic error caused by the input parameters. More detail may be provided in the message.
  • 401 : Authentication is required but was not provided
  • 402 : Precondition related to quotas, limits, or user subscription plan was not met
  • 403 : Invalid authentication or unsufficient privileges
  • 404 : The API endpoint exists but the targetted item does not exist or is not available for the user
  • 405 : The API endpoint does not exist
  • 406 : Unsupported output format
  • 412 : Parameters do not pass validation or preconditions
  • 415 : Request encoding not supported
  • 500 : Generic internal error
  • 501 : Not implemented or deprecated
  • 503 : Internal resource dependency error (Database, SecurityStore, CryptoEngine,...)

{
	"error":
	{
		"message": "Unsufficient privileges",
		"data": {"grants":["access"]},
		"code":401
	}
}

Rate limit

There are many internal limits and quotas about a bunch of things. Starting with the number of requests to the API itself.

A quota is a fixed increment counter. If it is reached, it can only be decremented by removing items.

A limit is a time-based increment counter. It is not reset at specific interval, it is a sliding window. Most of the time, waiting some time will solve it.

When a limit is exceeded, a 402 error is raised and the response will contain a X-Rate-Limit-Next header with an approximation of when the next request may be accepted in milliseconds.

X-Rate-Limit-Next: api=3600000

Localization

For some actions, the response or processing may be adjusted to match the user language. Hence, you may always set the user preferred language as either:

  • Using a lang or language or locale query parameter.
  • Using the Accept-Language header.

If both the query parameter and the header are specified, the query parameter has precedence.
If multiple languages are provided in different query parameters, the precedence is undefined.

In any case, the language code considered will be transformed to stick to ISO_639-1.
This implies that any unordered language preference set in the Accept-Language header will not be considered.

Note that the error messages issued by the API will not be localized.

BusApp Authorization

Third party applications that want to gain control over a user BusApp instance can perform an OAuth2-like implicit authorization process as described in RFC6749. (Discussion)

In order to use BusApp Authorization, you should register with Busit in order to authorize your requestor and referer.

Contact us !

  1. In an iframe, a new window or in the current window, call the url https://apps.busit.com/auth
  2. You should provide a single query string parameter called data that contains the following JSON:
    • instance: A numeric BusApp instance id
    • grants: A list of specific grant names separated by colon, if missing, empty or null, full control will be requested
    • requestor: The name of your service that will be displayed to the user
    • referer: The callback URL to your service
    • lease: The lifetime of the generated token in seconds. If 0, missing, empty or null, the token will never expire
    • state: An internal state parameter that you choose that allows you to identify the return request
    Example: (decomposed for clarity)
    
    https://apps.busit.com/auth?data=
    {
    	"instance": 12345,
    	"grants": null,
    	"requestor": "My Service",
    	"referer": "https://my.domain.com/callback",
    	"lease": 3600,
    	"state": "session_12345"
    }
    
  3. The end user will be presented a login screen and a validation to authorize access to his BusApp
  4. Upon approval, the URL provided by the referer parameter will be called with both a query string parameter called token that contains a token you can use to perform API calls on the user bahalf concerning that specific BusApp; and the state parameter that you provided in the initial request.
    Example:
    https://my.domain.com/callback?token=abcdef123456&state=session_12345
    

When using a BusApp token to perform requests to the API, the auth parameter MUST be formatted as follows : i:[instance_id]:[token]
Example:

https://api.busit.com/?auth=i:12345:abcdef123456
Any user API parameter will be automatically induced and should be omitted.
Any instance API parameter will be automatically induced and should be omitted.

When using this mechanism, you are bound to Busit's Tems and Conditions. If you do not fully understand those, do not use this procedure.

Note that to ensure the security of the user information, you MUST use https communications

Workflow:

  USER         YOUR SERVICE        BUSIT
    |               |                |
    |-------------->|                |
    |               | (1) iframe to /auth
    |               |--------------->|
    |                                |
    |    (2) user login              |
    |<-------------------------------|
    |------------------------------->|
    |                                |
    |                  (3) token     |
    |   (4) done    |<---------------|
    |<--------------|                |

Forward Authorization

Third party applications that want to gain control over a user external service via Busit can perform an OAuth-like authorization process.
Example:
External service My Service wants to get the user token for his Third Party Service account that is compatible and supported by Busit.

Each external service have a distinct URL endpoint of the form https://apps.busit.com/[service]/[...]

In order to use Forward Authorization, you should register with Busit in order to get the endpoint URL and authorize your redirect_uri.

Contact us !

  1. In an iframe, a new window or in the current window, call the endpoint URL
  2. You should provide both a query string parameter called redirect_uri that contains the callback URL to your service; and a second query string parameter called state that allows you to identify the return request
    Example:
    https://apps.busit.com/service/config?redirect_uri=https://my.domain.com/callback&state=session_12345
    
  3. The end user will proceed through the external authentication mechanism
  4. Upon success, the URL provided by the redirect_uri parameter will be called with a query string parameter access_token that contains the json-encoded response from the third party; and the state query string parameter that you provided in the initial request.
    Example:
    https://my.domain.com/callback?access_token={...}&state=session_12345
    

When using this mechanism, you are bound to the third party service's Terms and Conditions as well as Busit's Tems and Conditions. If you do not fully understand those, do not use this procedure.

Note that to ensure the security of the user information, you MUST use https communications

Workflow:

  USER         YOUR SERVICE        BUSIT             THIRD PARTY
    |               |                |                    |
    |-------------->|                |                    |
    |               | (1) iframe to service               |
    |               |--------------->|                    |
    |                                |                    |
    |    (2) user busit login        |                    |
    |<-------------------------------|                    |
    |------------------------------->|                    |
    |                                | (3) redirect to OAuth
    |                                |------------------->|
    |    (4) user third party login                       |
    |<----------------------------------------------------|
    |---------------------------------------------------->|
    |                                                     |
    |                                   (5) token         |
    |                  (6) token     |<-------------------|
    |   (7) done    |<---------------|                    |
    |<--------------|                |                    |

Internal Security Considerations

All messages are encrypted with a 2048 bit asymetric keypair specific to each user. This guarantees integrity, confidentiality and non-repudiation of the messages. Moreover, if any user key is compromised, it does not affect other users.

All tokens and passwords are in the form of 128 bit hexadecimal strings (32 characters) derived from the MD5 hash function. (Discussion)

Wherever applicable, encrypted communications should be used. As such, all requests to the API happen in HTTPS.

Comprehensive JSON

Anywhere JSON parsing is required, an efficient loose parsing is performed. This allows to circumvent common mistakes, trailing characters, comments and deviation from strict JSON. Some example of accepted syntax are shown below but there are more subtle things. (Discussion)

Features supported by the loose parser:

  • Block or line comments
  • Unescaped newlines in string values
  • Single quotes, double quotes or no quotes for string values where there is no ambiguity
  • Unterminated array, object or quoted string
  • Case insensitive keywords for true, false, null
  • Unquoted string value starting with digits
  • Single quotes, double quotes or no quotes for object keys
  • Colon, space, equals sign, arrow (=>) or even nothing in some cases as separator between object key and value
  • Coma, semicolon, space, colon, equals sign, arrow (=>) or even nothing in some cases as separator between array elements
  • Coma, semicolon, space or even nothing in some cases as separator between object elements
  • Implicit null as key or value when explicit element is missing in object or array
  • Overterminated array or object (unmatched closing braces)

Strict JSON example:


{
	"key1": "value", 
	"key2": ["string", false, null, 42]
}

Loose JSON alternative:


{
	key1 'value' /*	comment */
	"key2" => [string fAlSE;;42
	}
	}
}

Pushing messages to Busit

The most frequent operation you will probably need is to push messages into the system. Fortunately, this is just a simple HTTP call to the API. You will need:

  1. The URL : https://api.busit.com/vanilla/message/push
  2. An instance token in the form i:[instance_id]:[token_value]
  3. The name of the channel to push data to
  4. Some data... duh!

Remember that you may pass parameters as a query string, or as form-data, that you can pass the authentication in the HTTP header if you like,... as explained previousely.

https://api.busit.com/vanilla/message/push
	?auth=i:123:abcdef12345
	&channel=my_channel
	&data=my_data

If the data is a JSON object, then it will be interpreted and all key/value pairs will be added to the message as properties. Otherwise, the message will contain one single property named data with the provided value. For convenience, you may also post a JSON body as the data. In that case, the data query string parameter must be omitted.

Example 1:
		POST /vanilla/message/push HTTP/1.1
		Host: api.busit.com
		Authorization: Bearer i:123:abcdef12345
		Content-Type: application/x-www-form-urlencoded

		channel=my_channel&data=my_data
Will be sent to the BusApp instance 123 on channel my_channel with a message of the form:

		{"data": "my_data"}
Example 2:
		POST /vanilla/message/push HTTP/1.1
		Host: api.busit.com
		Authorization: Bearer i:123:abcdef12345
		Content-Type: application/x-www-form-urlencoded
		
		channel=my_channel&data={"foo":"bar","key":42}
Will be sent to the BusApp instance 123 on channel my_channel with a message of the form:

		{"foo": "bar", "key": 42}
Example 3:
		POST /vanilla/message/push?channel=my_channel HTTP/1.1
		Host: api.busit.com
		Authorization: Bearer i:123:abcdef12345
		Content-Type: application/json

		{"foo": "bar", "key": 42}
Will be sent to the BusApp instance 123 on channel my_channel with a message of the form:

		{"foo": "bar", "key": 42}
Is something unclear, you've spotted a mistake, or you need more details ?

Then please help us improve this doc.
Or contact us directly.