0% found this document useful (0 votes)
20 views

Api Guide

This document provides guidelines for developing REST APIs including defining resources and collections, URI structure, request methods, pagination, caching and other considerations. It covers topics like versioning, HATEOAS, headers and designing item and collection resources.

Uploaded by

tiso_feri
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Api Guide

This document provides guidelines for developing REST APIs including defining resources and collections, URI structure, request methods, pagination, caching and other considerations. It covers topics like versioning, HATEOAS, headers and designing item and collection resources.

Uploaded by

tiso_feri
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

REST API Guidelines V1.

0
Table of Contents
Release notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
General definitions and rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Resources and API Structuring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
API Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Versioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
HATEOAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Billboard. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
HTTP Headers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
ETag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
If-Match, If-None-Match . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Location . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Content-Disposition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Collection resource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
URI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Resource root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Paging, sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Paging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Page object fields. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Sorting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Templated URI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Query . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
GET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
HEAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
OPTIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
POST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Item resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
URI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
GET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
HEAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
OPTIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
PATCH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
PUT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Create new resource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Update an existing resource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Create or Update a resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
SOA endpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
URI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Error handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
VND Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Preauthorize . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Object types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Standard header types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Method Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
GET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
HEAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
OPTIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
PUT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Create new resource. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Override an existing resource (Optimistic Concurrency Control) . . . . . . . . . . . . . . . . . . . . . . . . 31
PATCH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
DELETE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
POST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
HATEOAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
HAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
HAL Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
How to serve HAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
The structure of a HAL document. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
URL TEMPLATE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Release notes
• Increased General definitiions and rules section with notes about REST resources and API
Documentation

• Corrected typos

• Enhanced examples

• REST call example for filtering

• More detailed section of API versioning

1
Overview
The REST API Guidelines helps the developers of the MindSphere platform to plan the RESTful
interfaces of individual services. It defines consistent practices and patterns for all API endpoints
across MindSphere. Besides the document there is also a sample application. The examples in the
document were generated using Spring REST Docs tests for the sample application. The first part of
the guideline covers project specific information. It addresses among others the following topcis:

• Billboard URL

• Resource endpoints

• Resource collection endpoints and paging

• Use of HTTP verbs

• Use of HTTP headers

• Endpoint versioning

• Optimistic concurrency control

• Response filtering

• Error handling

The second part of the document (Appendix) attempts to briefly summarize the standards the
document is based on.

2
General definitions and rules
MindSphere applications expose RESTful API endpoints in a resource-oriented Architecture (ROA)
style.

Resources
A REST resource is an entity with a type, relationships to other resources, data values, and a set of
methods that operate on it. Resources can be distinguished from mere data values by the following
criteria. A resource

• has an identity that does not change when its state changes

• can have a lifetime independent of other entities

• can be related to more than one other entity

• is queried independently from other entities

Resources and API Structuring


The operations on resources should be offered via HTTP verbs whenever possible. Among such
operations are creation, deletion, query, and update. Service-oriented architecture (SOA) endpoints
should only be used if an operation cannot be exressed by an HTTP verb directly. Resource
endpoints should be named using nouns, SOA-endpoints with help of verbs.

Every type of resource has its own collection endpoint at the api root. For example, a car resource
would have a collection endpoint

/api/cars

Every resource instance should have a GUID (or other suitable unique identifier) and should be
reachable below the root collection endpoint.

/api/cars/<guid>

Relations between resources can be expressed by nesting paths or by referring to the related
resource’s collection endpoint. In either way, a HATEOAS link to the related resource(s) must be
provided at the resource instance’s address. The related resources are at home at their own
collection endpoint, not at the nested endpoint of the other resource.

For the car resource, a nested path is used to relate to the wheels of the car. The wheels are located
at the wheels-collection endpoint, however. One way to relate to the wheels of a specific car can be
to provide the proper query parameter in the link to the wheels collection endpoint.

/api/cars/<guid>/wheels

3
relates to or draws information from

/api/wheels?car=<guid>

As alternative to the approach of nesting related resources is to only provide the proper HATEOAS
links at the resource instance endpoint.

API Documentation
MindSphere applications are documented with Spring REST Docs, just like this REST API Guidelines.
It is quite easy to create the documentation by combining hand-written documentation with auto-
generated snippets produced with Spring MVC Test. Endpoints with sample response payload and
integration tests are only needed for an API only documentation. See ApiDoc for details.

With a good documentation there is no need to hide unfinished endpoints or give


 back 501 not implemented status code.

4
Versioning
API versioning allows you to alter behaviour between different clients of the API. Versioning is
done based on the headers of the incoming client request.

This scheme requires the client to specify the version as part of the media type in the Accept
header. The version is included as a media type parameter, that supplements the main media type.

Here’s an example HTTP request using the accept header versioning style.

GET /api/assets/68d12ce6-248a-4b66-b49e-f209e9c3ef45 HTTP/1.1


Host: tenant.apps.mindsphere.io
Accept: application/json; version=1.0

The version schema is: version={MAJOR.MINOR}

Increasing the MAJOR version number expresses a non-backwards compatible change in the API.
Increasing the MINOR version number expresses a backwards compatible change.

What are backwards compatible changes that should be versioned with MINOR? Adding something
new that is optional to use, without changing what exists. E.g.: adding

• an endpoint

• an HTTP verb to an endpoint

• a subpath to an endpoint

• optional query parameters to an endpoint

• JSON fields in the response, which are optional to be used

• optional JSON fields in the request

• headers which are optional to be used

What is NOT backwards compatible and needs to be versioned with MAJOR?

• Removing any of the things mentioned in the list of backwards compatible changes

• Changing (e.g., renaming) any of the above mentioned things

• In general: changing the observable functional behavior of the API from a client’s point of view.
Functional, as in functional requirements, ignoring things such as performance.

Which changes do not require to change the version?

• performance improvements

• bugfixes, if they don’t break existing client code!!!

5
When a client calls the resource and requests a specific version, the service can
always handle the request with same major but higher minor version. For
 instance, a request which specifies version 1.2 can be answered with version 1.2
(as requested), but also with any 1.x as long as x > 2.

When no version is specified in the client request, the latest version of the service
 should be used.

6
HATEOAS
You can find MindSphere specific description in the next section, if you are interested in general
about HATEOAS, HAL or TEMPLATED URI, then go to the Appendix.

Billboard
A REST client typically starts using a service at a well-known URI, referred to as billboard URI. The
billboard URI lists all the resources available at this service (e.g., assets, aspects, …).

Ideally, the billboard URI is the only address a REST client needs to know. From there onwards, it
must be able to discover all other URIs of the service by using the returned "_link"s provided with
for every returned resource representation.

The billboard endpoint of MindSphere services is at their base path, built from https://{host}/api.

In presence of an 'X-Forwarded-host' header, HATEOAS links need to be


 constructed using the host provided in the header.

GET /api HTTP/1.1


Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK
Content-Type: application/hal+json;version=1.1;charset=UTF-8
ETag: "0803f087565a2c0171cb68a3b34071c51"
Content-Length: 197

{
"_links" : {
"assets" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets"
},
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api"
}
}
}

7
Caching
Caching of retrieved resource respresentations on client side can help to reduce the amount of
exchanged data with the backend and also the required operations in the backend. This section
deals with caching of the overall response from the backend. In order to enable caching of
responses, the following steps are to be used in MindSphere: first, the backend response must
contain a header 'ETag' with an identifier for this particular response. The client, after obtaining
the identifier, needs to include an 'If-None-Match' header with the corresponding identifier in its
next requests to the backend. The backend can then check whether the response would be the
same, and return a response code '304 (Not Modified)' instead of the actual response. The client
then knows that the response didn’t change since he obtained the identifier.

To easily allow conditional GET requests Spring provides ShallowEtagHeaderFilter


that simply calculates a hash for the response and sends it as ETag header. This
 ETag is compared to the If-None-Match header of the request. If these headers are
equal, the response content is not sent, but rather a 304 (Not Modified) status
instead.

8
HTTP Headers
This section lists some selected HTTP headers that are used in a particular fashion in MindSphere. A
more complete list of used headers is given in the Appendix.

Authorization
Every service in MindSphere must require a valid authorization from an incoming request. This
authorization, usually a bearer token, is provided via the authorization header. If the client does
not send a valid authorization it gets a 401 Unauthorized response.

See also RFC 2616 for general use of the authorization header.

Authorization: Bearer
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJzdmxhZGFE0NzIwMzQyMDh9.41rxtplFRw5xggssdWUU8CDOher

ETag
The ETag header enables response caching on client side. Its use is described in Section Caching.

Different from their use as header, ETags can also be used for optimistic concurrency control to
help prevent simultaneous updates of a resource from overwriting each other. The ETag is then
provided in the response body (see Section Optimistic Locking for more information).

ETag: "707894212"

If-Match, If-None-Match
These headers area used by clients to request optimistic concurrency control (Optimistic Locking)
or caching (Section Caching). They need to be used together with the identifier obtained from an
ETag.

If-Match: "707894212"

Location
See description

Location: https://tenant.apps.mindsphere.io/api/assets/1d276a3c-bbe4-45d3-bbd4-
c082cff470a6

9
Content-Disposition
See description

GET /api/assets/68d12ce6-248a-4b66-b49e-f209e9c3ef45/getThumbnail HTTP/1.1


Content-Type: application/octet-stream
Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK
Content-Disposition: attachment; filename='thumbnail.jpg'; filename*=utf-
8''thumbnail.jpg
Content-Length: 1978
Content-Type: application/octet-stream;version=1.1
ETag: "00e2cc575cff3ad872378ef99a288ab35"

10
Collection resource
URI

(e.g.: assets) . URLs are case insensitive generally but URIs consisting of multiple
words should be **camelCase**.

/dataSources

Therefore these two client calls are also valid: /datasources, /DATASOURCES

 Use nouns in plural form to name resource collection endpoints.

Resource root
The response for querying this endpoint contains the first (default) page of item resources, and
also links for:

• searching

• related resource endpoints (to nested path or to resource collection endpoint with query filter
param)

• service-oriented endpoints

Resource root URL

https://tenant.apps.mindsphere.io/api/assets

Paging related links should be augmented with the search parameters


 programmatically.

Paging, sorting
Paging

Collections in HAL are literally just arrays of embedded resources. A typical collection will include a
self relational link, but also pagination links - first, last, next, and prev are standard relations.

By default the name of the resource collection within the embedded section is
 anyResourceList. Instead of that it should be simply anyResource. Use the
annotation @Relation(collectionRelation="anyResource")!

Each paged response will return links to the previous and next pages of results based on the
current page using the IANA defined link relations prev and next. If you are currently at the first
page of results, however, no prev link will be rendered. The same is true for the last page of results:

11
no next link will be rendered. By default a page contains 10 elements and the first page is returned.

 If an endpoint overrides the default settings do not forget to document it!

See the example in the Collection resource section.

At the bottom is extra data about the page settings, including the size of a page, total elements, total
pages, and the page number you are currently viewing.

 Index of first page is 0

Page object fields

• number: number of the current page

• size: size of the page

• totalPages: number of total pages

• totalElements: total amount of elements

Sorting

To have your results sorted on a particular property, add a sort URL parameter with the name of
the property you want to sort the results on. You can control the direction of the sort by appending
a "," to the property name plus either asc (default) or desc.

The service API documentation needs to contain a list with all possible search
 parameters.

curl -v "http://localhost:8080/people/search/nameStartsWith?name=K&sort=name,desc"

Templated URI

Templated URIs are used when a parametrized link is provided without specifying all the
parameters in it. If you use templated uri, then you have to indicate it with a templated property
besides the given link.

An example:

12
{
"_links": {
"findByParentIDsAndSubpathLevel": {
"href":
"https://tenant.apps.mindsphere.io/api/assets/search/findByParentIDsAndSubpathLevel{?t
enantName,parentAssetIDs,pathLevel,excludeChildrenOf}",
"templated": true
},
"findAllFilteredByTypes": {
"href":
"https://tenant.apps.mindsphere.io/api/assets/search/findAllFilteredByTypes{?tenantNam
e,parentAssetIDs,pathLevel,excludeChildrenOf}",
"templated": true
}
}
}

Query
Filtering a collection resource can be done by exposing filter query parameter in the url. The value
of the filter parameter is JSON. The following definitions contain elements that can be only one of
the allowed types:

• ROOT element can be:

◦ FIELD block

◦ LOGICAL block

• FIELD blocks can contain:

◦ inline value (string, int, boolean) which defaults to an eq PREDICATE block

◦ PREDICATE blocks which relationship defaults to an and LOGICAL block

◦ LOGICAL blocks

• LOGICAL blocks can contain:

◦ LOGICAL blocks

◦ FIELD block

◦ array of PREDICATE blocks

• PREDICATE blocks can contain:

◦ inline value

◦ value of the predicate (QUESTION: constant value, but could be e.g. a reference to a field or
dynamic like now() ?!)

Examples

The following examples show SQL and JSON predicate representation of the same filtering

13
One field filtering with single expressions

GET /api/assets?filter=%7B%22name%22%3A%22Test+asset2%22%7D&page=0&size=1 HTTP/1.1


Host: mindgate.apps.mindsphere.io

14
HTTP/1.1 200 OK
Content-Type: application/hal+json;version=1.1;charset=UTF-8
ETag: "066f62397791ad73a427e51e59c49fb95"
Content-Length: 1056

{
"_embedded" : {
"assets" : [ {
"name" : "Test asset2",
"etag" : "812546061",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/4eb859e8-58cb-4072-
8892-88aa8ca48730"
}
},
"id" : "4eb859e8-58cb-4072-8892-88aa8ca48730"
} ]
},
"_links" : {
"first" : {
"href" :
"https://mindgate.apps.mindsphere.io/api/assets?filter=%7B%22name%22:%22Test%20asset2%
22%7D&page=0&size=1"
},
"self" : {
"href" :
"https://mindgate.apps.mindsphere.io/api/assets?filter=%7B%22name%22:%22Test%20asset2%
22%7D&page=2&size=2"
},
"next" : {
"href" :
"https://mindgate.apps.mindsphere.io/api/assets?filter=%7B%22name%22:%22Test%20asset2%
22%7D&page=1&size=1"
},
"last" : {
"href" :
"https://mindgate.apps.mindsphere.io/api/assets?filter=%7B%22name%22:%22Test%20asset2%
22%7D&page=99&size=1"
}
},
"page" : {
"size" : 1,
"totalElements" : 100,
"totalPages" : 100,
"number" : 0
}
}

15
SELECT * FROM assets WHERE assetName = "MyMotor"
{
//default EQ
"assetName" : "MyMotor" // FIELD block
}

One field filtering with multiple expressions

SELECT * FROM assets WHERE assetName = "testName" OR assetName = "nameTest"


{
"assetName": {
"or": [
{"eq": "testName"},
{"eq": "nameTest"}
]
}
}

Two fields filtering with AND operator

SELECT * FROM assets WHERE assetName = "MyMotor" AND assetOwnername = "Doe"


{
//default AND and EQ
"assetName": "MyMotor",
"assetOwnerName": "Doe"
}

Two fields filtering with OR operator

SELECT * FROM assets WHERE assetName = "MyMotor" OR assetOwnername = "Doe"


{
"or" : { // LOGICAL block
//default EQ
"assetName": "MyMotor", // FIELD block with inline value
"assetOwnerName": "Doe"
}
}

16
Like operator

SELECT * FROM assets WHERE assetName = "MyMotor" OR assetOwnerName LIKE "%Doe"


{
//specified OR
"or": { // LOGICAL block
"assetName": { // FIELD block with PREDICATE block
"eq": { // PREDICATE block
"value": "MyMotor"
}
},
"assetOwnerName": {
"endsWith": {
"value": "Doe"
}
}
}
}

Composite filtering with precedence

SELECT * FROM assets WHERE (assetName = "MyMotor" OR assetName LIKE "%Doe") AND
(assetColor = "blue" OR assetOnboarded = true)
{
"and": {
"and": {
"assetName": {
"or": {
"eq": {
"value": "testName"
},
"endsWith": {
"value": "Doe"
}
}
}
},
"or": {
"assetColor": "blue",
"assetOnboarded": true
}
}
}

Methods
GET

The result is always paged.

17
GET /api/assets?page=2&size=2 HTTP/1.1
Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK
Content-Type: application/hal+json;version=1.1;charset=UTF-8
ETag: "0bfc9f2f546966238c99abd48b1906534"
Content-Length: 1862

{
"_embedded" : {
"assets" : [ {
"name" : "Test asset2",
"etag" : "812546061",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/4eb859e8-58cb-4072-
8892-88aa8ca48730"
}
},
"id" : "4eb859e8-58cb-4072-8892-88aa8ca48730"
}, {
"name" : "JustCreatedAsset",
"etag" : "366675860",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/60beaf32-f57a-40e9-
82a9-e4936e7127f6"
}
},
"id" : "60beaf32-f57a-40e9-82a9-e4936e7127f6"
}, {
"name" : "MyBrandNewAsset",
"etag" : "806063237",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/d3ed828c-6493-46f1-
beb1-5b6558b673b3"
}
},
"id" : "d3ed828c-6493-46f1-beb1-5b6558b673b3"
}, {
"name" : "ExistingAsset",
"etag" : "34138281",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/47496d20-9a93-4138-
ab45-8a2443173308"
}
},

18
"id" : "47496d20-9a93-4138-ab45-8a2443173308"
} ]
},
"_links" : {
"first" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets?page=0&size=2"
},
"prev" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets?page=1&size=2"
},
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets?page=2&size=2"
},
"next" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets?page=3&size=2"
},
"last" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets?page=49&size=2"
}
},
"page" : {
"size" : 2,
"totalElements" : 100,
"totalPages" : 50,
"number" : 2
}
}

HEAD

The server SHOULD send the same header fields in response to a HEAD request as it would have
sent if the request had been a GET, except that the payload header fields MAY be omitted.

HEAD /api/assets HTTP/1.1


Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK
Content-Type: application/hal+json;version=1.1;charset=UTF-8
ETag: "0d41d8cd98f00b204e9800998ecf8427e"

OPTIONS

OPTIONS /api/assets HTTP/1.1


Host: mindgate.apps.mindsphere.io

19
HTTP/1.1 200 OK
Allow: GET,HEAD,POST

POST

A successful creation returns with a status 201: Created. Location header and ETag is mandatory in
the result. Returning the newly created resource is not mandatory, but allowed based on the actual
use case.

POST /api/assets HTTP/1.1


Content-Type: application/hal+json
Host: mindgate.apps.mindsphere.io
Content-Length: 35

{
"name" : "JustCreatedAsset"
}

HTTP/1.1 201 Created


Location: https://mindgate.apps.mindsphere.io/api/assets/b09fedff-1fa6-4a66-a477-
7d2b420bc4f2
Content-Type: application/hal+json;version=1.1;charset=UTF-8
Content-Length: 257

{
"name" : "JustCreatedAsset",
"etag" : "748470669",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/b09fedff-1fa6-4a66-
a477-7d2b420bc4f2"
}
},
"id" : "b09fedff-1fa6-4a66-a477-7d2b420bc4f2"
}

20
Item resource
URI
The collection resource uri with the primary ID of the item.

/assets/{assetId}

Response
The item resource containing its primary ID and self link as well as any link to associated resources.

Methods
GET

GET /api/assets/47496d20-9a93-4138-ab45-8a2443173308 HTTP/1.1


Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK
Content-Type: application/hal+json;version=1.1;charset=UTF-8
ETag: "097261ab398b641bbc4719825f8d3ef8d"
Content-Length: 390

{
"name" : "Test asset1",
"etag" : "1599225774",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/47496d20-9a93-4138-
ab45-8a2443173308"
},
"onboard" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/47496d20-9a93-4138-
ab45-8a2443173308/onboard"
}
},
"id" : "47496d20-9a93-4138-ab45-8a2443173308"
}

HEAD

HEAD /api/assets/47496d20-9a93-4138-ab45-8a2443173308 HTTP/1.1


Host: mindgate.apps.mindsphere.io

21
HTTP/1.1 200 OK
ETag: "0d41d8cd98f00b204e9800998ecf8427e"

OPTIONS

OPTIONS /api/assets/47496d20-9a93-4138-ab45-8a2443173308 HTTP/1.1


Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK
Allow: GET,HEAD,PUT,DELETE

PATCH

Handling input of PATCH commands is not trivial. Investigation of supporting libraries is in


progress. Until decision is made please don’t use this HTTP Verb.

PUT

The request has to send either If-Match header or If-None-Match header. Without providing ETag
both creation and update fails with HTTP status code 412: Precondition Failed.

Create new resource

If PUT is used to create a new resource If-None-Match should be provided with value "*".

Though PUT is idempotent method from the point of view of resource state, but
 executing the same request more than once will result in a 409 (Conflict).

To support PUT to create new resource, clients must be able to assign URIs for resources. When
using this method to create new resources, take the following into consideration:

• To let clients assign URIs, the server needs to explain to clients how URIs on the server are
organized, what kind of URIs are valid, and what kind are not.

• You also need to consider any security and filtering rules set up on servers based on URI
patterns and may want to restrict clients to use a narrow range of URIs while creating new URIs.

22
PUT /api/assets/db56809a-1fe5-4334-a910-b163c2cdfbb8 HTTP/1.1
Content-Type: application/hal+json
If-None-Match: *
Host: mindgate.apps.mindsphere.io
Content-Length: 34

{
"name" : "MyBrandNewAsset"
}

HTTP/1.1 201 Created


Location: https://mindgate.apps.mindsphere.io/api/assets/db56809a-1fe5-4334-a910-
b163c2cdfbb8
Content-Type: application/hal+json;version=1.1;charset=UTF-8
Content-Length: 257

{
"name" : "MyBrandNewAsset",
"etag" : "2092656048",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/db56809a-1fe5-4334-
a910-b163c2cdfbb8"
}
},
"id" : "db56809a-1fe5-4334-a910-b163c2cdfbb8"
}

Update an existing resource

If PUT is used to update an existing resource the last known ETag value should be provided in If-
Match header.

PUT /api/assets/47496d20-9a93-4138-ab45-8a2443173308 HTTP/1.1


Content-Type: application/hal+json
If-Match: 726b7187-4a72-4245-9ca6-5d5c617c9a53
Host: mindgate.apps.mindsphere.io
Content-Length: 32

{
"name" : "ExistingAsset"
}

23
HTTP/1.1 200 OK
Content-Type: application/hal+json;version=1.1;charset=UTF-8
Content-Length: 253

{
"name" : "ExistingAsset",
"etag" : "34138281",
"_links" : {
"self" : {
"href" : "https://mindgate.apps.mindsphere.io/api/assets/47496d20-9a93-4138-
ab45-8a2443173308"
}
},
"id" : "47496d20-9a93-4138-ab45-8a2443173308"
}

Create or Update a resource

In some scenarios the PUT method should support "create or update" operations for the given
resource. In that case the client does not care whether the resource item exists or not the request
either creating or updating the resource item depending on its existence.

 There is no standard that supports this operation!

DELETE

Deletion is only possible with providing the actual ETag value in If-Match header. A successful
deletion should always return status "204: No Content".

DELETE /api/assets/47496d20-9a93-4138-ab45-8a2443173308 HTTP/1.1


If-Match: 47496d20-9a93-4138-ab45-8a2443173308
Host: mindgate.apps.mindsphere.io

HTTP/1.1 204 No Content

24
SOA endpoints
SOA-endpoints are nested below a resource.

URI
If the particular method is performed on an item then it should be under the item resource.

 Use verbs to name SOA-endpoints (e.g.: onboard).

/agent/{agentId}/onboard

POST /api/assets/4eb859e8-58cb-4072-8892-88aa8ca48730/onboard HTTP/1.1


Host: mindgate.apps.mindsphere.io

HTTP/1.1 200 OK

25
Error handling
VND Error
The message must not contain information about the internal architecture, used technologies,
service boundaries, etc. The message must be easily understandable for the user, and specify, if
they should or should not try again the same request, and what modifications they should make if
the latter.

The logref is a unique identifier of the request, which can be used to investigate the problem.

Currently we do not provide links, future use may include a link to a general help page. Also based
on the exception type a link to a specific FAQ page could be returned (e.g. bad email format), or a
link including the logref to a ticketing system (for errors suggesting possible bugs).

The service tools project contains a Controller Advice class to handle the generation of these
messages. This Controller Advice is automatically applied to all RestControllers. Certain exceptions
are mapped to http response codes, the default is 500. Do not add exceptions used only by a handful
of services. In the majority of cases the exceptions under the package
com.siemens.isb.shared.servicetools.exceptions should be used.

The error messages are returned in application/vnd.error+json format:

GET /api/assets/error HTTP/1.1


Host: mindgate.apps.mindsphere.io

HTTP/1.1 404 Not Found


Content-Type: application/hal+json;version=1.1;charset=UTF-8
Content-Length: 90

{
"logref" : "692e9dbb71b44334944b1e18716b2124",
"message" : "An error occurred."
}

 Always use VND Error for 400 or greater status codes!

26
Security
We use OAuth2 authorization based on JWTs. Our microservices are the resource servers, the SAP
provided IDP is the authorization server, and the approuter is the oauth client, which replaces the
incoming jsessionid cookie with the bearer token authorization header.

Spring OAuth2 implementation

OAuth2 description

The security can be enabled using the custom @EnableOAuth2Security annotation after adding the
oauth2 security library to the gradle file.

Internal communications may use technical tokens retrieved from the authmanager, when the
action cannot be associated with an acting user, e.g. when SmartAgentCom requests information
about an incoming agent from the SmartAgentBasicServices. The Southbound api gateways also
request tokens for the agents to propagate date inside the platform.

Preauthorize
Access to specific endpoints is restricted by the @PreAuthorize annotation, where a SPEL
expression can be used. It usually check for an oauth2 scope in the access token. Certain endpoints
do not require authorization, e.g. the endpoint to download bootscript in SmartAgentCom.

27
Appendix
Object types
Entities

An entity is identifiable and remains same throughout the states of the product/services. Entities
are not defined by its attributes, but by its identity and thread of continuity.

Standard header types


Accept
The client sends an Accept header to tell the server what media types it would prefer the server
use for its representations.

Accept: application/hal+json

Cache-Control
This header contains a directive to any caches between the client and the server (including local
caches on the client or server machines themselves). It spells out the rules for how the data
should be cached and when it should be dumped from the cache.

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Content-Disposition
Defined in RFC 6266

The Content-Disposition header is generally used to indicate that the client should save the entity-
body as a file, rather than processing it as a representation. A browser typically opens a "Save As"
dialogue when the response contains this header with the filename parameters (if present) as the
default name.

Content-Disposition: attachment; filename="ServiceScript_3.log"

Content-Length
This response header gives the size of the entity-body in bytes.

Content-Length: 219

Content-Type
Gives the media type of the entity-body.

28
Content-Type: application/hal+json

Date
As a request header, this represents the time on the client at the time the request was sent. As a
response header, it represents the time on the server at the time the request was fulfilled.

Date: Wed, 07 Dec 2016 13:38:46 GMT

ETag
Defined in RFC 2616

The value of ETag is an opaque string designating a specific version of a representation. Whenever
the representation changes, the ETag should also change.

Servers should send ETag in response to GET requests whenever possible. Clients can make a
conditional GET request by sending the previous value of ETag as the value of the If-None-Match
request header. Should also be used as a mean to "Optimistic locking" used in POST, PUT and
DELETE requests.

Expires
This header tells the client, or a proxy between the server and client, that it may cache the HTTP
response (not just the entity-body!) until a certain time.

Expires: 0

Location
Defined in RFC 2616

• When the client’s request creates a brand new resource, the response code is 201 (Created),
and the Location header is a link to the newly created resource.

• When the client’s request causes a resource to change its URL, the response code is 301
(Moved Permanently) and the Location header is a link to the original resource at its new
location.

• The response should always contain the location header because in some cases self link is
absent. e.g.: file upload

Pragma
The Pragma header is a slot for special directives between the client, server, and intermediaries
such as proxies. Usually used to turn off caching.

Pragma: no-cache

29
Method Definitions
The request method is the primary source of request semantics. It indicates the purpose of request
and what is expected by the client as a successful result. The request method’s semantics might be
specialized by the semantics of some header.

The GET, HEAD and OPTIONS methods are said to be safe, because nothing will happen on the
server as a result of the HTTP request. Semantically they are considered as read-only methods.

A request method is considered idempotent that can be called many times without different
outcomes. PUT, DELETE and safe request methods are idempotent.

Request methods can be defined as cacheable to indicate that responses are allowed to be stored for
future reuse on the server. GET, HEAD and in some cases POST can be cached.

Table 1. Table Overview of HTTP methods

Methods Idempotent Safe Resource type


GET yes yes Item / Collection
HEAD yes yes Item / Collection
OPTIONS yes yes Item / Collection
POST no no Collection
PUT yes no Item
PATCH no no Item
DELETE yes no Item

GET

The client send a request to the server. In the response it gets back the resource entity and in the
header its ETag. The ETag header provides the current entity-tag for the selected resource entity

A conditional GET allows a client to ask a server if a resource has changed. If it has not changed, it
can assume it’s current knowledge is up to date and send back 304 Not Modified status. If it has
changed, the server will send the resource back along with 200 OK status to the client. The client
uses the [If-None-Match] header with the ETag as the value. It’s asking the server "Return the
resource if it’s ETag does not match mine." Because an ETag changes when a resource has changed,
this effectively asks the server to return the resource only if it has changed.

HEAD

The HEAD method is identical to GET except that the server must not send a message body in the
response.

Use HEAD for the following:

• Find out about a resource (e.g., determine its type) without getting it

• See if an object exists, by looking at the status code of the response

30
• Test if the resource has been modified, by looking at the ETag

OPTIONS

Use OPTIONS for the following: * To determine the options associated with a resource or the
capabilities of a server, without implying a resource action

When the client sends an OPTIONS request to the server the server responses with the list of
supported methods via the [Allow] header.

PUT

Use PUT for the following:

• To create new resources only when client is able to assign URIs for the resources. To let clients
assign URIs, the server needs to explain to clients how URIs on the server are organized, what
kind of URIs are valid, and what kind are not

• To override an existing resource with a modified version of the one residing on the server

Create new resource

The response status can be:

• 201 (Created): if a new resource is created

• 404 (Not Found): if the server does not support resource creation

Override an existing resource (Optimistic Concurrency Control)

We must handle in some cases concurrent updates on a resource, but all resources are suited for
concurrency control. Once the ETag is received, it allows the client to perform the update. However,
the changes will only apply if the ETag is still valid. If the resource exists, take the following steps:

• First client must obtain an ETag for the update operation

• The client has to send the new representation of the resource along with the If-Match
conditional header that contains the ETag

The response should be:

• 412 (Precondition Failed): if the supplied If-Match header do not match the actual ETag value
of the resource on the server

• 200 (OK) or 204 (No Content): if the supplied conditions match the server updates the resource,
and sends back with the updated value of ETag header. The response also includes a Content-
Location header.

The method requests that the state of the target resource be created or replaced with the state
defined by the representation enclosed in the request message payload.

31
PATCH

Use PATCH for the following:

• To support partial updates in contrast with PUT that is defined for the complete update or
replacement of a resource

The client can check whether the PATCH is supported via the Allow header of the OPTIONS
response or the resource can include an Accept-Patch header with the supported media types for
the PATCH method.

Similar to PUT method PATCH can handle Optimistic Concurrency Control

DELETE

Use DELETE for the following:

• To remove a resource entity identified by the Request URI

Similar to PUT method DELETE can handle Optimistic Concurrency Control The response should be:

• 200 (OK): if the response includes an entity describing the status

• 202 (Accepted): if the action will likely succeed but has not yet been enacted

• 204 (No Content): if the action has been enacted and no further information is to be supplied

• 403 (Forbidden): if the client submits an unconditional DELETE request

• 412 (Precondition Failed): if the supplied conditions do not match

If the request fails, the body should contain the explanation of the failure.

POST

Use POST for the following:

• To create a new resource

• To perform any unsafe or non idempotent operation via calling a SOA endpoint

• To run queries with large inputs Using POST to create new resources, the server decides the URI
for the newly created resource. If the resources has been created on the server as a result of
successfully processing a POST request, the server should send a 201 Created response along
with the following headers:

• Location that provides an identifier for the resource created.

• ETag for the resource

The response body should contain the resource’s representation.

The response should be the following:

• 201 (Created): if a new resource is created

32
• 409 (Conflict): if the resource already exists

HATEOAS
HATEOAS (Hypermedia as the Engine of Application State) is a constraint of the REST application
architecture. A hypermedia-driven site provides information to navigate the site’s REST interfaces
dynamically by including hypermedia links with the responses. This capability differs from that of
SOA-based systems and WSDL-driven interfaces. In the representations only those links are
presented that are reachable taking into account the actual state of the application. A HATEOAS-
based response would look like this:

{
"name": "Alice",
"links": [ {
"rel": "self",
"href": http://localhost:8080/customer/1
} ]
}

HAL

HAL specification

HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your
API. Adopting HAL will make your API explorable, and its documentation easily discoverable from
within the API itself. In short, it will make your API easier to work with and therefore more
attractive to client developers.

HAL Model

The HAL conventions revolve around representing two simple concepts: Resources and Links.
Resources

• Embedded

◦ an array of Resources used by querying a collection of resources. (i.e. other resources


contained within them)

• Links

◦ A target (a URI)

◦ A relation aka. 'rel' (the name of the link)

◦ A few other optional properties to help with deprecation, content negotiation, etc.

◦ Registered link relation names

How to serve HAL

HAL has a media type for both the JSON and XML variants, whose names are application/hal+json
and application/hal+xml respectively. When serving HAL over HTTP, the Content-Type of the

33
response should contain the relevant media type name. When using Spring REST controllers HAL
support could be enabled by adding: @EnableHypermediaSupport(type = HypermediaType.HAL)

The structure of a HAL document

For JSON resources, the minimum you must do is providing a _links property containing a self
relational link. As an example:

{
"_links": {
"self": {
"href": "http://example.org/api/user/matthew"
}
},
"id": "matthew",
"name": "Matthew Weier O'Phinney"
}

URL TEMPLATE
A URL Template is a way to specify a URL that includes parameters that must be substituted before
the URL is resolved. The syntax is usually to enclose the parameter in Braces ({example}). The
convention is for a parameter to not be Percent encoded unless it follows a Question Mark (?).

Examples:
* http://example.com/{username}/
* http://example.com/dictionary/{term:1}/{term}
* http://example.com/search{?q,lang}

You can found more info:

• RFC HAL

• RFC URI TEMPLATE

34

You might also like