.. index:: URLs and URIs .. _url-and-uris: URLs and URIs ============= Base URL -------- Examples of good base URLs: .. code-block:: http https://api.platform.com/v1 https://api.platform.com/subsystem/v1.1 Not so good example (see rules below why): .. code-block:: http http://open.prod.platform.com/api/subsystem/services/1.2.4 Base URL should be short ^^^^^^^^^^^^^^^^^^^^^^^^ The base URL SHOULD be short and easy to remember. The longer the domain name and path, the harder it is to use. Https MUST be used ^^^^^^^^^^^^^^^^^^ Https MUST be used. This solves a great deal of otherwise hard to tackle security problems. Base URL MUST end in a version number ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The version in the URL is the escape route to introduce breaking changes to the API. This should not be taken lightly and therefore a single digit should be enough for a long time. For clarity, the version MUST be preceded by a ``v``. Base URL's version number MAY include a minor version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ See :ref:`versioning` for more information on when to use a minor version. URL and URI naming ------------------ Collection names SHOULD be a plural noun ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A URI identifying a collection of resources SHOULD be named with a plural noun, or noun phrase, as its path segment. For example, the URI for a collection of categories may use the plural noun form as follows: .. code-block:: http https://api.platform.com/v1/categories Document names SHOULD be a singular noun ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A URI representing a document resource SHOULD be named with a singular noun or noun phrase path segment. For example, the URI for a single seller profile document would have the singular form: .. code-block:: http https://api.platform.com/v1/users/1/profile Forward slash separator (``/``) MUST be used to indicate a hierarchical relationship ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The forward slash (``/``) character MUST be used in the path portion of the URI to indicate a hierarchical relationship between resources. For example: .. code-block:: http https://api.platform.com/v1/categories/91/advertisements URIs SHOULD NOT have a trailing forward slash (``/``) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As the last character within a URI’s path, a forward slash (``/``) adds no semantic value and may cause confusion. REST APIs should not expect a trailing slash and SHOULD NOT include them in the links that they provide to clients. Many web components and frameworks will treat the following two URIs equally: .. code-block:: http https://api.platform.com/v1/categories/ https://api.platform.com/v1/categories However, every character within a URI counts toward a resource’s unique identity. Two different URIs must map to two different resources. If the URIs differ, then so do the resources, and vice versa. Therefore, a REST API must generate and communicate clean URIs and SHOULD be intolerant of any client’s attempts to identify a resource imprecisely. Redirects (e.g. 301 Moved Permanently) from one version to the other MUST NOT be used. Some clients don't support redirects and we need to keep this consistent over our separate APIs. Hyphens (``-``) SHOULD be used to improve the readability of URIs, not underscores (``_``) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To make your URIs easy for people to scan and interpret, use the hyphen (``-``) character to improve the readability of names in long path segments. Anywhere you would use a space or hyphen in English, you should use a hyphen in a URI. For example: .. code-block:: http https://api.platform.com/v1/this-is-an-endpoint-with-a-large-name URI paths MUST use lowercase letters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Lowercase letters are preferred in URI paths since capital letters can sometimes cause problems. RFC 3986 defines URIs as case-sensitive except for the scheme and host components. For example: .. code-block:: http https://api.example.restapi.org/my-folder/my-doc HTTPS://API.EXAMPLE.RESTAPI.ORG/my-folder/my-doc https://api.example.restapi.org/My-Folder/my-doc The first URL is fine and RFC3986 considers the second url to be identical to URL #1. But the third URL is not the same as URIs one and two, which may give unnecessary confusion. Parameters inside the URI path are excluded from this rule. Actions ^^^^^^^ Though it SHOULD be avoided, in some cases it is simply not possible to mold an action into REST's resource model. In those cases an action can be made available on a resource. To clearly indicate that a URL indicates an action instead of a sub-resource, action URLs MUST contain the path segment ``/actions/`` in front of the action name. For example: .. code-block:: http https://api.example.restapi.org/v1/message/1234/actions/mark-as-read Query parameters ---------------- The query component of a URI SHOULD be used to filter collections ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A URI’s query component is a natural fit for supplying search criteria to a collection. Example : .. code-block:: javascript GET /v1/users?casUser=true HTTP/1.1 Host: api.platform.com HTTP/1.1 200 OK Content-Type: application/json { "_links": { "self": { "href": "/v1/users?casUser=true" }, "curies": [ { "href": "/v1/docs/rels/{rel}.html", "templated": true, "name": "ec" } ] }, "_embedded": { "ec:user": [{ "_links": { "self": { "href": "/v1/users/2" }, }, "id": 2, "name": "Richard", "email": "2@platform.com", "casUser": true }] }, "totalResults": 10 } .. _pagination-parameters: Query parameters ``offset`` and ``limit`` SHOULD be used to paginate collections results ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A REST API client SHOULD use query parameters ``offset`` and ``limit`` to paginate collections. The ``offset`` parameter specifies the 0 based index of the first element to return in the response. The ``limit`` parameter specifies the maximum number of contained elements to return in the response. Example: .. code-block:: javascript GET /v1/users?offset=0&limit=2 HTTP/1.1 Host: api.platform.com HTTP/1.1 200 OK Content-Type: application/json { /* See section `resource representation format` for an example. */ } Note that ``offset`` and ``limit`` are only used for collection resources. Pagination of embedded (linked) collections is done with the ``_expand`` query parameter. .. _expand-parameter: The ``_expand`` parameter MAY be used for zooming ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Zooming is an optional technique that allows linked resources to be embedded. The embedded resources are serialized as described by HAL. The full syntax for the ``_expand`` parameter is: .. code-block:: javascript = [::][({,})] = {/} _expand = {,} Where ``[...]`` indicates an optional clause and ``{s...}`` indicates an optional repeating clause with ``s`` as separator. Here are some examples: .. code-block:: javascript _expand=ec:parent-category _expand=ec:parent-category/ec:parent-category _expand=ec:parent-category,ec:child-categories:0:10 _expand=ec:parent-category/ec:parent-category,ec:child-categories:0:10/ec:child-categories:0:10 _expand=ec:parent-category(name,shortName) *Relation name* The relation name can be quite long, for example ``https://api.platform.com/v1/docs/rels/users`` and can contain many separator characters. Therefor the relation name MUST be shortened with HAL's `curie syntax `_. Clients can obtain the correct prefix by getting the non-expanded resource first and inspect the ``curies`` section inside the ``_links`` section. Implementations are RECOMMENDED to verify the prefix but are free to ignore it. *Offset and limit* When the relation refers to a collection, the ``offset`` and ``limit`` parameters SHOULD be used for pagination. Offset specifies the 0 based index of the first element to return in the response. Limit specifies the maximum number of contained elements to return in the response. *Nesting expansion* An embedded resource can be further expanded by adding a slash (``/``) and another expand clause. *Multiple expansions* Multiple embedded resources can be expanded by adding a comma (``,``) and another expand clause. It is not possible to expand multiple embedded resources in an embedded resource. *Implementation considerations* Documentation MUST specify exactly what parts of the ``_expand`` parameter are supported. It is not expected that implementations support expansion in a generic way. *Example* Full example for a simple expansion (expand parent category in a category resource): .. code-block:: javascript GET /v1/categories/92?_expand=ec:parent-category HTTP/1.1 Host: api.platform.com HTTP/1.1 200 OK Content-Type: application/json { "_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" }, }, "id": 91, "name": "Auto's, motors en andere voertuigen", "shortName": "Auto's" } }, "id": 92, "parentCategoryId": 91, "name": "Alpha romeo", "shortName": "Alpha romeo" } An example for a linked collection resource (expand messages in a conversation resource). See `chapter 20 `_ for the full representation. .. code-block:: javascript GET /v1/conversations/1234?_expand=ec:messages:0:10 Host: api.platform.com HTTP/1.1 200 OK Content-Type: application/json { "_links": { ... }, "_embedded": { "ec:messages": { "_embedded": { "ec:message": [ { ... message fields ... }, { ... message fields ... } ], "offset": 0, "limit": 10, "totalCount": 25 } } }, "id": "1234", ... more conversation fields ... } .. _include-and-exclude-parameters: The ``_include`` and ``_exclude`` query parameters MAY be used for selecting fields ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``_include`` and ``_exclude`` parameters MAY be used to select fields. If both parameters are present, only the ``_include`` parameter MUST be used. Both fields have a similar format. A list of comma separated field names are valid arguments for both ``_include`` and ``_exclude``. Nested fields may be specified with a ``/`` character. E.g. ``seller/name`` identifies the ``name`` field inside the ``seller`` field. Note that ``_include`` and ``_exclude`` only work on the fields of the requested resource, and not on embedded resources. .. _body-parameter: The ``_body`` query parameter SHOULD be used to include/exclude a response body ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default responses contain a body, even if it is mostly the same as what was posted. The ``_body`` parameter SHOULD be used to change this behavior. Parameter ``_body`` takes values ``true`` (the default) or ``false``. Example: .. code-block:: javascript POST https://api.platform.com/v1/users?_body=false HTTP/1.1 Host: api.platform.com { "username": "testUser", "zipcode": "1097DN", "email": "test@platform.com" } HTTP/1.1 201 Created Location: /v1/users/95 Note: the ``_body`` parameter SHOULD be supported by each method on each resource. The ``_links`` query parameter SHOULD be used to exclude HAL's ``_links`` field ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default responses contain one or more ``_links`` sections. The information in the ``_links`` section is normally only used for discovery purposes and could be discarded for automated clients. The ``_links`` query parameter SHOULD be used to exclude the ``_links`` fields. Parameter ``_links`` takes values ``true`` (the default) or ``false``. HAL's ``_links`` fields are exclude when the parameter is present and has value false. For example the representation .. code-block:: javascript { "_links": { "self": { "href": "/v1/users" }, "curies": [ { "href": "/v1/docs/rels/{rel}.html", "templated": true, "name": "ec" } ] }, "_embedded": { "ec:user": [{ "_links": { "self": { "href": "/v1/users/2" }, }, "id": 2, "name": "Richard", "email": "2@platform.com", "casUser": true }] }, "totalResults": 10 } will be shortened to: .. code-block:: javascript { "_embedded": { "ec:user": [{ "id": 2, "name": "Richard", "email": "2@platform.com", "casUser": true }] }, "totalResults": 10 } Note: the ``_links`` parameter SHOULD be supported by each method on each resource. Note that curie syntax may be used inside the representation (``ec:user`` in the example), even though the curie definition is no longer present. .. _method-parameter: Mimicking request methods ^^^^^^^^^^^^^^^^^^^^^^^^^ Some clients do not support all methods. Therefore we support other ways to mimic any request method: 1. The value of ``_method`` URL parameter MUST be interpreted as the intended request method. 2. The value of request header ``X-HTTP-METHOD-OVERRIDE`` MUST be interpreted as the intended request method. 3. The value of request header ``X-HTTP-METHOD`` MAY be interpreted as the intended request method. 4. The value of request header ``X-METHOD-OVERRIDE`` MAY be interpreted as the intended request method. These ways MUST be evaluated in the given order; the first found value overrides all following. When during evaluation of a parameter or header value an unknown or illegal method is encountered, an ``400`` error response MUST be given, independent of the correctness of other available values. Example: .. code-block:: javascript POST /v1/advertisements/95?_method=PATCH HTTP/1.1 Host: api.platform.com Content-Type: application/json-patch+json If-Match: "abc123" [ { "op": "replace", "path": "/title", "value": "new advertisement title" }, { "op": "replace", "path": "/price", "value": 9000 } ] is interpreted as a ``PATCH`` request. A failure example: .. code-block:: javascript POST /v1/advertisements/95?_method=BLABLA HTTP/1.1 Host: api.platform.com X-HTTP-METHOD-OVERRIDE: PATCH Content-Type: application/json-patch+json If-Match: "abc123" [ { "op": "replace", "path": "/title", "value": "new advertisement title" }, { "op": "replace", "path": "/price", "value": 9000 } ] results in an ``400`` error response because the ``_method`` parameter contains an illegal method, even though the ``X-HTTP-METHOD-OVERRIDE`` header does contain a correct value. The ``_callback`` parameter MAY be used to return a JSONP response ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ A ``_callback`` parameter MAY be used in any ``GET`` call to have the results wrapped in a javascript function. This is typically used when browsers want to embed content in web pages by getting around cross domain issues. The response includes the same data output as the regular API, plus the relevant HTTP Header information. The content type of the response MUST be ``application/javascript``. Example: .. code-block:: javascript GET /v1/users/2?_callback=foo HTTP/1.1 Host: api.platform.com HTTP/1.1 200 OK Content-Type: application/javascript foo( { "_links": { "self": { "href": "/v1/users/2" }, ... }, "name": "Richard", "email": "r2@hotmail.com" } ) .. _prettyprint-parameter: The ``_prettyprint`` parameter MAY be used to pretty print the response ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Implementation MAY support the ``?_prettyprint`` parameter to make it easier for people to view, read and understand resources. Formatting SHOULD be enabled when the parameter is present and does not have the value ``false``. Consider enabling pretty printing by default for documentation resources only (e.g. the ``/`` resource). Example : .. code-block:: javascript GET /v1/categories/95?_prettyprint HTTP/1.1 Host: api.platform.com HTTP/1.1 200 OK Content-Type: application/json { "_links": { "self": { "href": "/v1/categories/95" }, ... }, "id": 95, "parentCategoryId": 91, "name": "BMW", "shortName": "BMW" } Use of underscore character ^^^^^^^^^^^^^^^^^^^^^^^^^^^ The underscore character is used to clearly identify shared URL parameters. The underscore is nicely consistent with how it is used in HAL resource representations. Parameter names MUST NOT start with an underscore unless they are described in these guidelines.