Core - RESTful API Support¶
The framework allows the creation of RESTful web API for a Service that enables access to ecosystem’s resources and data.
Call a REST API method¶
To read from or write to a resource such as a user or an email message, you construct a request that looks like the following:
{HTTP-method} https://{public-url}/api/{service}/{version}/{resource}?{query-parameters}
The components of a request include:
{HTTP-method}
: The HTTP method used on the request to the endpoint.{public-url}
: The external URL use to reach WebTop installation.{service}
: The service ID.{version}
: The version of API provided by the Service.{resource}
: The resource exposed by the Service that you’re referencing.{query-parameters}
: Optional query options or REST method parameters that customize the response.
After you make a request, a response is returned that includes:
Status code
: An HTTP status code that indicates success or failure. For details about HTTP error codes, see Errors.Response message
: The data that you requested or the result of the operation. The response message can be empty for some operations.
HTTP methods¶
Endpoints uses the HTTP method on your request to determine what your request is doing. Depending on the resource, the API may support operations including actions, functions, or CRUD operations described below.
Method | Description |
---|---|
GET | Read data from a resource. |
POST | Create a new resource, or perform an action. |
PATCH | Update a resource with new values. |
PUT | Replace a resource with a new one. |
DELETE | Remove a resource. |
- For the CRUD methods
GET
andDELETE
, no request body is required. - The
POST
,PATCH
, andPUT
methods require a request body, usually specified in JSON format, that contains additional information, such as the values for fields of the resource.
Version¶
Services can manage versions completely autonomously. A dedicated endpoint will be created for each version defined in the spec.
Resource¶
A resource can be an entity or complex type, commonly defined with properties. Entities differ from complex types by always including an id property.
Your URL will include the resource you are interacting with in the request, such as me
, user
, group
, and domain
. Often, top-level resources also include relationships, which you can use to access additional resources, like me/messages
or me/drive
. You can also interact with resources using methods; for example me/my-method
.
Each resource might require different permissions to access it. You will often need a higher level of permissions to create or update a resource than to read it.
Query parameters¶
Query parameters can be standardized query options, or other strings that a method accepts to customize its response.
You can use optional standardized query options to include more or fewer properties than the default response, filter the response for items that match a custom query, or provide additional parameters for a method.
Standardized query options¶
A Rest API operation might support one or more of the following query options.
Name | Description |
---|---|
_filter | Filters results (rows). |
_orderBy | Orders results. |
_select | Filters properties (columns). |
_update | Specifies the properties (columns) to update. |
_pageNo | The specific page to get, if set activates paging (client-side paging). |
_pageSize | The number of items to return for each page (client-side paging). |
_return_count | Specifies whether to return the total count of items. |
_syncToken | Specifies the token that tracks changes from a precise state (used in delta apis). |
_filter parameter¶
Use the _filter
query parameter to restrict the results of a request to match a search criterion.
It’s syntax and behavior adhere to REST API Query language, see section RSQL for more info about it’s grammar.
The expression specified with _filter
is evaluated for each resource in the collection, and only items where the expression evaluates to true
are included in the response. Resources for which the expression evaluates to false
or to null
, or which reference properties that are unavailable due to permissions, are omitted from the response.
For example, the following request returns only items whose name is equal to Kill Bill
:
?_filter=name=="Kill Bill"
_orderBy parameter¶
Use the _orderby
query parameter to specify the sort order of the items returned. The default order is ascending order.
For example, the following request returns items ordered by their display-name in ascending order:
?_orderBy=displayName
To sort the results in ascending or descending order, append either ASC
or DESC
to the field name, separated by a space; for example, ?$_orderBy=name DESC
(unencoded), ?_orderBy=name%20DESC
(URL encoded). If the sort order isn’t specified, the default ascending order is inferred.
_select parameter¶
Use the _select
query parameter to return a subset of properties for a resource. With _select
, you can specify a subset or a superset of the default properties.
The parameter needs to be specified as a comma-separated list of field names:
?_select=from,subject
Note
In general, we recommend that you use _select
to limit the properties returned by a query to those needed by your app. This is especially true of queries that might potentially return a large result set. Limiting the properties returned in each row will reduce network load and help improve your app’s performance.
_pageNo parameter¶
Use the _pageNo
query parameter to specify the exact page number to return when pagination is used. See Pagination for more info.
?_pageNo=1
_pageSize parameter¶
Use the _pageSize
query parameter to specify how many items to return when pagination is used. See Pagination for more info.
?_pageSize=100
_returnCount parameter¶
Use the _returnCount
query parameter to return the total count of items, useful when paginating data. See Pagination section for more info.
?_returnCount=true
_syncToken parameter¶
Use the _syncToken
query parameter to specify in delta queries the initial state from which return changes. See Synchronization section for more info.
?_syncToken=
Authentication¶
Almost all of exposed RESTful web API needs some credentials to authenticate requests.
Credentials can be provided in the following three ways:
- Basic Authentication
- Bearer Authentication
- APIKeys
Basic Authentication¶
Basic authentication is a simple authentication scheme built into the HTTP protocol.
The client sends HTTP requests with the Authorization
header that contains the word Basic
followed by a space and a base64-encoded string username:password
.
For example, to authorize as demo
/ p@55w0rd
the client would send
Authorization: Basic ZGVtbzpwQDU1dzByZA==
Because base64 is easily decoded, Basic authentication should only be used together with other security mechanisms such as HTTPS/SSL.
You can find this authentication scheme in OpenAPI specs referenced as basic-auth
.
Note
This authentication scheme is used when you need to authenticate as a specific user, calls will inherith any authorizations bound to the targeted user.
Bearer Authentication¶
Bearer authentication (also called token authentication) is an HTTP authentication scheme that involves security tokens called bearer tokens. The name “Bearer authentication” can be understood as “give access to the bearer of this token.” The bearer token is a cryptic string, usually generated by the server in response to a login request.
The client must send this token in the Authorization
header when making requests to protected resources:
Authorization: Bearer <token>
Similarly to Basic authentication, Bearer authentication should only be used over HTTPS (SSL).
You can find this authentication scheme in OpenAPI specs referenced as bearer-auth
.
Note
This authentication scheme is used in environment provisioning only where a generated token can be specified in order to authorize requests with the role of system-administrator.
API Keys¶
An API Key is a kind of token used for authentication; it’s a unique identifier that authenticate and grant access to RESTful endpoints. Like passwords, be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
From the perspective of the server, a single API Key does not univocally identify a user, so during the authentication process providing an API Key only is not enough. A dedicated HTTP header X-Auth-Username will help us providing the missing data: the full username in email-style form.
Authorization: Bearer <api-key>
X-Auth-Username: <auth-username-email>
You can find this authentication scheme components in OpenAPI specs referenced as auth-apikey-bearer
and auth-apikey-username
; both of them needs to be specified.
API Keys can be generated and managed through the dedicated section under the administrative panel.
Note
This authentication scheme is designed to authenticate as a specific user, calls will inherith any authorizations bound to the targeted user.
RSQL¶
RSQL is a query language for parametrized filtering of entries in RESTful APIs. It’s based on FIQL (Feed Item Query Language) – an URI-friendly syntax for expressing filters across the entries in an Atom Feed. FIQL is great for use in URI; there are no unsafe characters, so URL encoding is not required. On the other side, FIQL’s syntax is not very intuitive and URL encoding isn’t always that big deal, so RSQL also provides a friendlier syntax for logical operators and some of the comparison operators.
Grammar and semantic¶
RSQL expression is composed of one or more comparisons, related to each other with logical operators:
- Logical AND :
;
orand
- Logical OR :
,
oror
By default, the AND operator takes precedence (i.e. it’s evaluated before any OR operators are). However, a parenthesized expression can be used to change the precedence, yielding whatever the contained expression yields.
input = or, EOF;
or = and, { "," , and };
and = constraint, { ";" , constraint };
constraint = ( group | comparison );
group = "(", or, ")";
Comparison is composed of a selector, an operator and an argument.
comparison = selector, comparison-op, arguments;
Selector identifies a field (or attribute, element, …) of the resource representation to filter by. It can be any non empty Unicode string that doesn’t contain reserved characters (see below) or a white space. The specific syntax of the selector is not enforced by this parser.
selector = unreserved-str;
Comparison operators are in FIQL notation and some of them has an alternative syntax as well:
- Equal to:
==
- Not equal to:
!=
- Like to:
=like=
- Not like to:
=nlike=
- Less than:
=lt=
- Less than or equal to:
=le=
- Greater than operator:
=gt=
- Greater than or equal to:
=ge=
- Between:
=btw=
- Not between:
=nbtw=
- In:
=in=
- Not in:
=out=
Argument can be a single value, or multiple values in parenthesis separated by comma. Value that doesn’t contain any reserved character or a white space can be unquoted, other arguments must be enclosed in single or double quotes.
arguments = ( "(", value, { "," , value }, ")" ) | value;
value = unreserved-str | double-quoted | single-quoted;
unreserved-str = unreserved, { unreserved }
single-quoted = "'", { ( escaped | all-chars - ( "'" | "\" ) ) }, "'";
double-quoted = '"', { ( escaped | all-chars - ( '"' | "\" ) ) }, '"';
reserved = '"' | "'" | "(" | ")" | ";" | "," | "=" | "!" | "~" | "<" | ">";
unreserved = all-chars - reserved - " ";
escaped = "\", all-chars;
all-chars = ? all unicode characters ?;
If you need to use both single and double quotes inside a quoted argument, then you must escape one of them using \
(backslash). If you want to use \
literally, then double it as \\
. Backslash has a special meaning only inside a quoted argument, not in unquoted argument.
Examples¶
Examples of RSQL expressions in both FIQL-like and alternative notation:
?_filter=name=="Kill Bill";year=gt=2003
?_filter=name=="Kill Bill" and year=gt=2003
?_filter=actor=like=*Bale;year=btw=(2000,2010)
?_filter=actor=like=*Bale and year=btw=(2000,2010)
Paging¶
Client-side paging
In client-side paging, a client app specifies the number of results it wants to get back in a single page by using the _pageSize
query parameter.
Then using _pageNo
it can control the nth page it wants to being retrieved.
You can get the real items total count using _return_count
query parameter.
Synchronize items¶
This guide describes how to implement “incremental synchronization” of data. Using this method, you can keep data for all items collections in sync while saving bandwidth.
Overview¶
Incremental synchronization consists of two stages: 1. Initial full sync is performed once at the very beginning in order to fully synchronize the client’s state with the server’s state. The client will obtain a sync-token that it needs to persist. 2. Incremental sync is performed repeatedly and updates the client with all the changes that happened ever since the previous sync. Each time, the client provides the previous sync-token it obtained from the server and stores the new sync-token from the response.
Note
A sync-token is a piece of data exchanged between the server and the client, and has a critical role in the synchronization process. An example would look like the following:
“nextSyncToken”: “CPDAlvWDx70CEPDAlvWDx70CGAU=”,
Initial full sync¶
The initial full sync is the original request for all the resources of the collection you want to synchronize. You can optionally restrict the list request using request parameters if you only want to synchronize a specific subset of resources.
In the response to the list operation, you will find a field called nextSyncToken
representing a sync token. You’ll need to store the value of nextSyncToken
.
Incremental sync¶
Incremental sync allows you to retrieve all the resources that have been modified since the last sync request. To do this, you need to perform a list request with your most recent sync-token specified in the _syncToken
parameter.
Documentation UI¶
The framework provides a documentation page that allows to to visualize and interact with the API’s resources without having any of the implementation logic in place.
Powered by the popular SwaggerUI project, this page it’s automatically generated from provided OpenAPI spec, with the visual documentation making it easy for back end implementation and client side consumption.
Each installed service has it’s own documentation endpoint, but the URL can be schematized in the following way:
https://{public-url}/api-docs/{service}/index.html
Where the components of the URL are:
{public-url}
: The external URL use to reach WebTop installation.{service}
: The service ID.
The page will show you the actual RESTful server base URL with a direct link to the active Specification, that at the moment of writing is always tha latest version of the spec. The oldest releases, still active, do not have a documentation page and you have to dig sources to extract their specs.
Note
Documentation URL is not active by default, since it consumes server resources and is only useful for development purposes it can be activated only when needed.
So, remember to set webtop.openapi.ui.enabled
property appropriately. See System system-properties section for more details.