All the APIs within BitBroker conform to a common set of core principles. These are consistently applied across each API set:
In the section, we outline these foundational principles in detail.
This the multi-page printable view of this section. Click here to print.
All the APIs within BitBroker conform to a common set of core principles. These are consistently applied across each API set:
In the section, we outline these foundational principles in detail.
All the API sets within BitBroker conform to the commonly accepted standards of a RESTful API.
There are many resources around the web to learn and understand what RESTful APIs are and how to work with them. If you are unfamiliar with this API architecture, we encourage you to investigate it further before you use the BitBroker APIs.
RESTful APIs use HTTP concepts to access and manipulate resources on the hosting server. Typical manipulations are to Create, Update and Delete resources. As with the standard RESTful convention, BitBroker maps HTTP methods to resource actions as follows:
HTTP Method | Resource Action |
---|---|
HTTP/GET |
Read a resource or a list of resources |
HTTP/POST |
Create a new resource |
HTTP/PUT |
Update an existing resource |
HTTP/DELETE |
Delete an existing resource |
All data exchange with BitBroker APIs, both to and from the server, is in JavaScript Object Notation (JSON) format.
When posting data via an API (most often as part of a create or update action), the message body must be a valid JSON document and all the JSON keys within it should be “double-quoted”. If you are seeing validation errors indicating the JSON is incorrectly formed, you might want to try a JSON validator to get more detailed validation information.
When posting data via an API, the HTTP header Content-Type
should always be set to application/json
.
RESTful APIs use HTTP response codes to indicate the return status from the call. BitBroker uses a subset of the standard HTTP response codes and maps them to call state as follows:
HTTP Response | Type | API Call State |
---|---|---|
HTTP/1.1 200 OK |
success |
The request completed successfully and data is present in the response body |
HTTP/1.1 201 Created |
success |
The requested resource was successfully created - the new resource’s URI will be returned in the Location attribute of the response header |
HTTP/1.1 204 OK |
success |
The request completed successfully, but there is no data in the response body |
HTTP/1.1 400 Bad Request |
error |
The request was rejected because it resulted in validation errors - for example, a mandatory attribute was not sent in the request |
HTTP/1.1 401 Unauthorized |
error |
The request was rejected because it contains an unapproved context - for example, a supplied authorization token was not valid or has expired (most often a failure of authorization) |
HTTP/1.1 403 Forbidden |
error |
The request was rejected because it contains an invalid or expired context - for example, a supplied authorization token referring to a deleted policy |
HTTP/1.1 404 Not Found |
error |
The request was rejected because the specified resource is not present |
HTTP/1.1 405 Method Not Allowed |
error |
The request was rejected because the action is not permitted - for example, a user deleting themselves |
HTTP/1.1 409 Conflict |
error |
The request was rejected because the action would cause a conflict on existing resource state - for example, creating a policy with a duplicate id |
HTTP/1.1 429 Too Many Requests |
error |
The request was rejected because a limit has been exceeded - for example, the policy defined call rate or call quota has been breached |
Whenever you receive an error response (HTTP/1.1 4**
), the response body will contain further information within a standard error response format.
HTTP/1.1 500 Server Error
should never be returned in normal operation. If you see such an error, do help us to identify and rectify the underlying problem. Please raise an issue in our GitHub repository describing, in as much detail as possible, the circumstances which lead to the error.
As the system develops, there may be changes to the API structure to encompass new concepts or features. Where API modifications imply code changes for existing clients, a new version of the API will be released.
All the APIs within BitBroker include a version string as the lead resource. For example, the /v1/
part of the following:
http://bbk-coordinator:8001/v1/user
A version string must be present in every API call in each API set.
All the API sets within BitBroker require authorization by callers. Whilst the process for authorization is common across the APIs, the context and reasons for authorization differ:
Except in some development modes, there is no access to BitBroker services without authorization and hence without having a corresponding authorization token.
When you have obtained the relevant authorization token (see below), you can use it to authorize API calls by using a specified HTTP header attribute. The same authorization header structure is used for all three BitBroker API sets.
x-bbk-auth-token: your-token-will-go-here
The header must be exactly as it appears here, with the same casing and without spaces. If you do not correctly specify the authorization header, or you use an invalid authorization token, you will get an HTTP/1.1 401 Unauthorized
error.
It can be useful to make test calls to the API to check that your authorization token is valid and that your authorization header is formatted correctly.
The base end-point of all the three API servers respond with a small announcement. Like all BitBroker API end-points, these require a working authorization to be in place. Hence, this announcement can be used for testing or verification purposes.
See the section on testing installations for Kubernetes or local modes for more details.
You are encouraged to make successful test calls to these end-points before launching into more complex scenarios.
The method used to obtain an authorization token differs across the three API sets. However, once you have a authorization token, the mechanics of authorization are the same. All authorization tokens are in the form of a long hexadecimal string, such as:
4735d360-dc03-499c-91ce-68dfc1554691.5d5c9eab-1d9c-4c88-9478-9f4ab35568a7.423c9101-315a-4929-a64c-9b905837799c
These authorization tokens should be kept by their owner in a secure location and never shared with unauthorized users.
Coordinator authorization tokens are required to authorize calls to the Coordinator API. This API is used to perform administrative services for a BitBroker instance.
Coordinator authorization tokens are obtained by utilizing end-points on the Coordinator API, in order to promote a user to coordinator status. To do this you must first create a new user and then you must promote that user to be a coordinator.
Once you promote a user to be a coordinator, then their coordinator authorization token will be returned in the body of the response to that API call.
If a coordinator authorization token is lost, then a new token will have to be generated. This can be done by first demoting the user from being a coordinator and then promoting them again. Note that, in this scenario, the old coordinator authorization token will be rescinded.
Contributor authorization tokens are required to authorize calls to the Contributor API. This API is used to contribute data to a designated entity type.
Contributor authorization tokens are obtained by utilizing end-points on the Coordinator API, in order to create a connector on a given entity type.
Once the connector is created, then its contribution authorization token will be returned in the body of the response to that API call. More information about data connectors and data contribution is available in the key concepts section of this documentation.
If a contributor authorization token is lost, then a new token will have to be generated. This can be done by first deleting the connector and then creating it afresh. Note that, in this scenario, the old contributor authorization token will be rescinded.
It is expected that the coordinator user, who creates the data connector, will distribute the contribution authorization token in a secure manner to the relevant party.
Consumer authorization tokens are required to authorize calls to the Consumer API. This API is used to access data via a policy definition.
Consumer authorization tokens are obtained by utilizing end-points on the Coordinator API. To do this you must create an access, which is a link between a user and a policy definition.
Once you create such an access, then the consumer authorization token will be returned in the body of the response to that API call.
If a consumer authorization token is lost, then you can reissue the access to obtain a new token. Note that, in this scenario, the old consumer authorization token will be rescinded.
All errors returned by all API services are presented in a standard error format. This complete list of errors which you may encounter are listed in the earlier page detailing the API architecture.
All errors will be present in a common structure as follows:
{
"error": {
"code": 404,
"status": "Not Found",
"message": ""
}
}
In such circumstances, there will only ever be one error
object with the following attributes:
Attribute | Presence | Description |
---|---|---|
code |
always |
The standard HTTP response code |
status |
always |
The standard text associated with the HTTP response code |
message |
always |
A string (sometimes) containing extra information about the error condition |
In situations which lead to a validation error on inbound data, the response code will always be HTTP/1.1 400 Bad Request
. In the case of such errors, the message
attribute will always contain an array of validation errors:
{
"error": {
"code": 400,
"status": "Bad Request",
"message": [
{
"name": "name",
"index": null,
"reason": "does not meet minimum length of 1"
},
{
"name": "email",
"index": null,
"reason": "does not conform to the 'email' format"
}
]
}
}
Here, the message attributes will be as follows:
Attribute | Presence | Description |
---|---|---|
message |
always |
An array of validation error objects |
message.name |
always |
A string indicating the id of the erroring attribute - this can be present multiple times, when there are multiple validation issues with the same attribute |
message.index |
always |
An integer indicating the index of the erroring item, when it is within an array - this will be null for attributes which are not arrays |
message.reason |
always |
A string indicating the validation error |
The validation error structure is designed to make it simple to integrate such errors into an end-user experience.