Resource representation format¶
Resources¶
Serialization format: HAL in UTF-8 encoding¶
HAL MUST be used as representation format for all non-binary resources. See HAL and our deviations for more information.
Example representation of a category resource with an expanded (embedded) parent category:
{
"_links": {
"self": { "href": "/v1/categories/92" },
"curies": [
{
"href": "/v1/docs/rels/{rel}.html",
"templated": true,
"name": "ec"
}
],
"ec:parent-category": { "href": "/v1/categories/91" }
},
"_embedded": {
"ec:parent-category": {
"_links": {
"self": { "href": "/v1/categories/91" }
},
"name": "Auto's",
"shortName": "Auto's"
}
},
"name": "Alpha romeo",
"shortName": "Alpha romeo"
}
Also see these articles:
The base URL is a HAL resource¶
The base URL is a HAL resource with appropriate documentation links.
For example:
GET /v1 HTTP/1.1
Host: api.platform.com
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "d9087df677dgh"
{
"_links": {
"self": { "href": "/v1" },
"curies": [
{
"href": "/v1/docs/rels/{rel}.html",
"templated": true,
"name": "ec"
}
],
"ec:categories": { "href": "/v1/categories" },
"ec:advertisements": { "href": "/v1/advertisements" },
"ec:users": { "href": "/v1/users" }
},
"message": "A welcome message targeted at client developers. See documentation at http://.../v1/docs."
}
It is possible and RECOMMENDED to add more meta-data to the links, for example a title. See the HAL specification or existing implementations of these guidelines.
Adding a welcome message in the message field is RECOMMENDED.
Each resource SHOULD contain a self link¶
Each resource SHOULD have a self link as described by HAL.
Example:
{
"_links": {
"self": { "href": "/v1/categories/1" }
}
}
When available IANA registered relation types SHOULD be used as link relations¶
A link relation is a descriptive attribute attached to a hyperlink in order to define the type of the link, or the relationship between the source and destination resources.
A standardized link relation SHOULD be used when such a relation is available.
Examples of commonly used IANA relation types are : self, item, first, prev, next, and last.
Custom link relation types SHOULD be uri’s that when dereferenced in a web browser provide relevant documentation, in the form of an HTML page¶
If no suitable IANA relation type is available, you SHOULD use a custom relation type. In accordance with the web linking RFC custom link relation types SHOULD be uri’s that when dereferenced in a web browser provide relevant documentation, in the form of an HTML page.
The references page is intended for the developer that is using the API.
This page should contain the following information:
- A list of request methods (GET, PUT, POST etc) supported for this URI.
- A description of the responses you can expect from any of the allowed request methods. This description should contain the status code and a description of the links and embedded resources included in the response.
See also Documentation requirements.
Binary resources¶
Binary resources MAY use any format. Binary resources MUST be linked to from another HAL resource. The link is RECOMMENDED to be in the _links section but MAY be in any other field.
Resource collections¶
Collections MUST be homogeneous¶
Depending on use cases, you can group resources into collections by using similarities (e.g. different types of listings in a single collection). However, no matter what criteria you choose for any collection, it is important to keep the representation homogeneous so that it is easy to use by clients.
Design the representation of the collection such that members in a collection are structurally and syntactically similar.
URL templates are RECOMMENDED in Links¶
HAL allows for URI templates in links (section 5.1 in HAL specification). These are perfect to describe to links to items in a resource collection.
Representation and pagination of collection resources¶
As described in the section on paginate collections results query parameters offset and limit are used to paginate collections.
When offset is not specified it SHOULD get a default value of 0. When limit is not specified it SHOULD get a default value that makes sense for a client developer that is exploring the API.
The link relation item MUST be included to define links to separate items in the resource.
The link relations first, prev, next and last SHOULD be added to enable automated pagination, for example with the HAL Browser.
For collection resources that can be embedded in a single page, the first, prev, next and last links SHOULD NOT be included. The first and prev links SHOULD NOT be included on the first page. The next and last links SHOULD NOT be included on the last page.
The actual values for offset and limit MUST be included in the fields offset and limit.
Total size of the collection SHOULD be included as field totalCount. When included, the value MUST be the exact size.
Example:
GET /v1/users?offset=0&limit=2 HTTP/1.1
Host: api.platform.com
HTTP/1.1 200 OK
Content-Type: application/json
{
"_links": {
"self": { "href": "/v1/users?offset=0&limit=2" },
"curies": [
{
"href": "/v1/docs/rels/{rel}.html",
"templated": true,
"name": "mp"
}
],
"item": { "href": "/v1/users{?id}", "templated": true },
"next": { "href": "/v1/users?offset=2&limit=2" },
"last": { "href": "/v1/users?offset=8&limit=2" }
},
"_embedded": {
"mp:user": [
{
"_links": {
"self": { "href": "/v1/users/1" }
},
"sellername": "Robin",
"email": "1@hotmail.com"
},{
"_links": {
"self": { "href": "/users/2" },
},
"name": "Richard",
"email": "2@gmail.com"
}
]
},
"offset": 0,
"limit": 10,
"totalCount": 10
}
Representation and pagination of embedded collection resources¶
As described in the section on zooming and expansion, query parameter _expand is used to paginate collections.
The offset, limit parts of the _extend query parameter MUST be interpreted as in the paginate collections results.
Embedded collections MUST be extended with fields offset, limit and totalCount as described in the paginate collections results. The additional link relations that are described there (‘item’, ‘next’, etc.) do not need be included.
A full example for a linked collection resource (expand messages in a conversation resource):
GET /v1/conversations/1234?_expand=ec:messages:0:10
Host: api.platform.com
HTTP/1.1 200 OK
Content-Type: application/json
{
"_links": {
"self": {
"href": "/v1/conversations/1234?_expand=mc:messages:0:10"
},
"curies": [
{
"href": "/v1/docs/rels/{rel}.html",
"templated": true,
"name": "ec"
}
],
"ec:messages": {
"href": "/v1/conversations/1234/messages",
"title": "The messages in this conversation."
}
},
"_embedded": {
"ec:messages": {
"offset": 0,
"limit": 10,
"totalCount": 25,
"_embedded": {
"ec:message": [
{
"_links": {
"self": {
"href": "/v1/conversations/1234/messages/79p8233c8"
}
},
"id": "79p8233c8",
"from": "b.q0282bxpw61q0@mail.platform.com",
"to": "a.joup3go87dhjs@mail.platform.com",
"body": "Thanks!"
},
{
"_links": {
"self": {
"href": "/v1/conversations/1234/messages/12211aad9"
}
},
"id": "12211aad9",
"from": "a.joup3go87dhjs@mail.platform.com",
"to": "b.q0282bxpw61q0@mail.platform.com",
"body": "Hi!"
}
]
}
}
},
"id": "1234",
"more": "conversation fields"
}
Note that the expanded resource collection ec:messages is a single element in the top-level field _embedded. Inside the collection there is another _embedded field to contain the separate items of the collection.
Relation names¶
Relation names MUST be in English unless they represent a product or company name¶
The consumers of the API are developers which might come from any country. However, developer will for sure understand English. Product and company names are excluded from this rule.
Words in relation names MUST be separated by a dash -¶
Relation names are used in URL and words MUST therefore be separated by dash -.
Field names¶
Field names MUST be in English unless they represent a product or company name¶
The consumers of the API are developers which might come from any country. However, developer will for sure understand English. Product and company names are excluded from this rule.
Field names MUST have consistent semantics and representation¶
When two fields have the same name (even if they are in different entities), they MUST mean the same thing and they MUST use the same representation.
This rule does not apply to deprecated fields.
Field names MUST use camelCase, contain only latin characters a - z, A - Z, 0 - 9¶
Fields MUST use only alphanumeric characters and MUST use the camelCase notation.
{ "asqEnabled" : true } // correct
{ "asq_enabled" : true } // NOT correct
{ "asq_enabled?" : true } // NOT correct
Field names MUST start with a lowercase letter, a - z¶
Fields MUST start with a lower case letter. In particular they MUST NOT start with an underscore _.
Field deprecation¶
See Versioning.
Field values¶
See the list of supported field types: Field types
Structure field values¶
You are RECOMMENDED to represent complex fields with a JSON object. This allows for better composability, the struct might later move to a separate entity.
Optional fields SHOULD NOT be serialized when they have no value¶
When an optional field has no value, it SHOULD be left out of the representation. When returning a resource with optional fields, and there is no value for a given field, then the field should be left out entirely in case of a String, Numeric or Object value. In the case of an Array, an empty list may be returned.
The rationale for leaving omitting the field when creating or updating a resource (POST, PUT or PATCH), is that it is not allowed to specify a key without a value. Theoretically, the value null could be used, but this will only lead to confusion and complicate the parsing of the JSON object.
You are RECOMMENDED to design each field such that it always has a value.
Field values that represent a timestamp are in ISO 8601¶
Timestamp values are represented using the ISO 8601 format full syntax in UTC (Z) with milliseconds (e.g. 2013-20-02T18:02:24.000Z).
Some systems will store dates in a lower precision. For consistency even those dates are represented in the full format. However, clients should be prepared to see timestamps rounded, for example to the second.
Field values that represent a date are in ISO 8601¶
Date values are represented using the ISO 8601 in the format YYYY-MM-DD (eg. 2013-01-20 to represent January 20th 2013).
Field values that represent countries are in ISO 3166-1 alpha-2 format¶
Country codes are defined by the ISO 3166-1-alpha-2 code standard. You can find the complete list here. For example NL.
The codes are case sensitive.
Field values that represent a currency are in ISO 4217¶
Currencies are encoded using the ISO 4217 currency format. For example EUR, and not €.
The codes are case sensitive.
All monetary amounts are represented as integers in its smallest currency unit¶
All money types are integers and conform to its smallest commonly used currency unit. For example, if the currency of a payment is in euros (EUR), the values of money fields conform to euro cents. So an amount of EUR 9,95 is represented as 995.
See the currency exponent as defined by ISO 4217 to find the smallest commonly used currency unit for a given currency.
All numbers are integers unless precision is not important¶
Most numbers need to be precise. Rounding due to using a floating point (64-bit IEEE754, or 32-bit IEEE754) can lead to unexpected errors. There are 2 allowed representations for numbers:
- represent the number in some exponent (e.g. in cm instead of m), this is REQUIRED for monetary amounts (see previous rule),
- represent the precise number as a string.
The first option is preferred. However, for larger numbers (JSON does not support numbers above 2^52), the second option MUST be selected.
There are few exceptions to this rule. Here is the list of known and allowed exceptions:
- Coordinates as described by WGS84 (or other geographic coordinate systems that use floating point numbers).
- Rates or ratios that have a value between 0.0 and 1.0.
See also the list of supported field types: Field types
Binary field values¶
See the list of supported field types: Field types
Errors¶
This section was inspired by the article Error handling considerations and best practices and vnd.error format.
Error messages follow a standard format¶
Here is an example request that produces an error response:
POST /v1/categories/95 HTTP/1.1
Host: api.platform.com
Accept-Language: nl, en
If-Match: "qg7968osihugw"
{
"id": "abc",
"parentCategoryId": 91,
"shortName": "Walnoot"
}
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Language: nl
{
"_links": {
"help": {
"href": "/v1/docs/errors/validation-failure"
}
},
"logref": "4298asfpohsa98yasohq97q3yff22",
"statuscode": 400,
"code" : "validation-failure",
"message": "Validatie mislukt",
"details": [
{ "field": "is", "message": "Is geen geldig getal.", "code": "not-a-number" },
{ "field": "name", "message": "Minstens 15 karakters.", "code": "too-short", "value": "15" },
{ "field": "name", "message": "'%' is niet toegestaan.","code": "pattern-did-not-match", "value": "[a-zA-Z0-9]{15,30}" },
{ "field": "shortName", "message": "Is geen auto-merk.", "code": "not-a-car-brand" },
{ "fields": ["field1", "field2"], "message": "Some error over multiple fields.", "code": "a-b-c" }
]
}
The error format supports the following features:
- It contains messages that are suitable for display to a human (in the correct language).
- It contains enough data to allow highlighting fields in a UI with relevant messages (again in the correct language).
- It contains enough information to allow for automated processing.
- It is suitable for JSONP.
Here follows a description of the error format.
Error responses MUST follow the same representation rules as other resources: HAL, JSON in UTF-8 and content-type MUST be application/json.
_link.help.href (REQUIRED) : A URL that refers to a help page that can be used by the developer that uses the API. (See Documentation requirements.) Note that we’re not using describedby (as in other HAL resource representations).
logref (REQUIRED) : A unique identifier that can be used to find the error in the application logs on the server side (for example a request id).
message (REQUIRED) : A human readable message related to the current error which may be displayed to the user of the api. The language of the message SHOULD be selected from the Accept-Language header in the request (if present). If no language can be selected, there SHOULD be a fixed fall-back language. The selected language MUST be set in the Content-Language response header.
statuscode (REQUIRED): MUST be the same as the HTTP Status code which is sent with this error. The reason to include this in the JSON as well, is because if you are using the API over JSONP for example, there is no easy way to get the error code. This is to make it more easy to use the API.
code (REQUIRED) : An error code. The error code SHOULD be same as the last part of the help url and SHOULD consist (mostly) out of lower case letters. (Letters allow for easier documentation-lookup then just a numeric code.)
details (optional) : Field by field error messages.
details[*].field or details[*].fields (at least one is REQUIRED) : Name of the field(s) that did not pass validation.
details[*].message (REQUIRED) : A human readable description of the message for the given field in error. Please make sure field contains a full sentence. The language SHOULD be the same as the language used in field message described above.
details[*].code (REQUIRED) : A machine readable code for the error. The code SHOULD consist (mostly) out of lower case letters. (Letters allow for easier documentation-lookup then just a numeric code.)
details[*].value (optional) : An optional value which supports the machine readable code. The actual value and its format depends on the error code.
All fields MUST be string values.
An appropriate status code MUST be used when serving an error resource¶
When serving an error resource an appropriate status code MUST be used. E.g. 4xx for client errors and 5xx for processing errors.
To determine which error code is appropriate, refer to the status codes section of this

(Copied from http://i.stack.imgur.com/whhD1.png.)
Stack traces MUST NOT be included in the error message¶
It may be tempting to include a stack trace for easier support when something goes wrong. Don’t do it! This kind of information is too valuable for hackers and it is therefore not allowed.