This document is not a presentation of REST.
It presents guidelines for designing REST API. Guidelines shall provide consistency accross services.
The guidelines are based on various sources all listed below in the section References.
-
[Microsoft] Microsoft REST API Guidelines https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md
-
[rfc6750] RFC6750, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", https://tools.ietf.org/html/rfc6750
-
[rfc7231] RFC7231, "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", https://tools.ietf.org/html/rfc7231
-
[IANA-headers] Message Headers, http://www.iana.org/assignments/message-headers/message-headers.xhtml
-
[Octo] How to design a REST API, https://blog.octo.com/en/design-a-rest-api/
-
[rfc3986] RFC3986, Uniform Resource Identifier (URI): Generic Syntax, https://tools.ietf.org/html/rfc3986
-
[rfc7807] RFC7807, Problem Details for HTTP APIs, https://tools.ietf.org/html/rfc7807
-
[restcase] 5 Basic REST API Design Guidelines, https://blog.restcase.com/5-basic-rest-api-design-guidelines/
-
[OpenAPI] The OpenAPI Specification, https://github.com/OAI/OpenAPI-Specification
-
[Zalando] Zalando RESTful API and Event Scheme Guidelines, https://opensource.zalando.com/restful-api-guidelines/
Humans SHOULD be able to easily read and construct URLs.
The API should be published under a base URL.
The base URL should distinguishely show its purpose by including either the term ``api"" in the FQDN or the path of the URL.
Any API will have to evolve over time. There are several ways of versioning an API:
With a timestamp, a release number… In the path, at the beginning or at the end of the URI As a parameter of the request In a HTTP Header With an optional or mandatory versioning.
The API SHOULD include a version in the path.
The version can be on:
-
one digit (recommended)
-
2 digits
-
a date
According to [rfc3986], URLs are "case sensitive" (except for the scheme and the host).
Regarding the URIs, spinal-case (which is highlighted by [rfc3986]) is recommended with lowercase letters.
Example:
POST /v1/specific-orders
The case of parameters SHOULD follow Body case convention
The HTTP 1.1 message format, defined in RFC 7230, in section 3.1.1, defines no length limit on the Request Line, which includes the target URL. From the RFC:
HTTP does not place a predefined limit on the length of a request-line. […] A server that receives a request-target longer than any URI it wishes to parse MUST respond with a 414 (URI Too Long) status code.
Services that can generate URLs longer than 2,083 characters MUST make accommodations for the clients they wish to support. Here are some sources for determining what target clients support:
Also note that some technology stacks have hard and adjustable url limits, so keep this in mind as you design your services.
Authentication should rely on OAuth2.0 and follow [rfc6750].
Operations MUST use the proper HTTP methods whenever possible, and operation idempotency MUST be respected. HTTP methods are frequently referred to as the HTTP verbs. The terms are synonymous in this context, however the HTTP specification uses the term method.
Below is a list of methods that Microsoft REST services SHOULD support. Not all resources will support all methods, but all resources using the methods below MUST conform to their usage.
Method | Description | Is Idempotent |
---|---|---|
GET |
Return the current value of an object or a collection of object |
True |
PUT |
Replace an object |
True |
DELETE |
Delete an object |
True |
POST |
Create a new object based on the data, or submit a command |
False |
HEAD |
Return metadata of an object for a GET response. Resources that support the GET method MAY support the HEAD method as well |
True |
PATCH |
Apply a partial update to an object |
False |
OPTIONS |
Get information about a request; see below for details. |
True |
POST operations SHOULD support the Location response header to specify the location of any created resource that was not explicitly named, via the Location header.
As an example, imagine a service that allows creation of hosted servers, which will be named by the service:
POST http://api.contoso.com/account1/servers
The response would be something like:
201 Created
Location: http://api.contoso.com/account1/servers/server321
Where "server321" is the service-allocated server name.
Services MAY also return the full metadata for the created item in the response.
The table of request headers below SHOULD be used. Using these headers is not mandated, but if used they MUST be used consistently.
All header values MUST follow the syntax rules set forth in the specification where the header field is defined. Many HTTP headers are defined in [rfc7231] however a complete list of approved headers can be found in the IANA Header Registry.
Header | Type | Description |
---|---|---|
|
String |
Authorization header for the request |
|
Content type |
The requested content type for the response such as:
Per the HTTP guidelines, this is just a hint and responses MAY have a different content type, such as a blob fetch where a successful response will just be the blob stream as the payload. For services following OData, the preference order specified in OData SHOULD be followed. |
|
Gzip, deflate |
REST endpoints SHOULD support GZIP and DEFLATE encoding, when applicable. For very large resources, services MAY ignore and return uncompressed data. |
|
"en", "es", etc. |
Specifies the preferred language for the response. Services are not required to support this, but if a service supports localization it MUST do so through the Accept-Language header. |
|
Charset type like "UTF-8" |
Default is UTF-8, but services SHOULD be able to handle ISO-8859-1. |
|
Content type |
Mime type of request body (PUT/POST/PATCH) |
|
return=minimal, return=representation |
If the return=minimal preference is specified, services SHOULD return an empty body in response to a successful insert or update. If return=representation is specified, services SHOULD return the created or updated resource in the response. Services SHOULD support this header if they have scenarios where clients would sometimes benefit from responses, but sometimes the response would impose too much of a hit on bandwidth. |
|
String |
Services that support updates to resources using optimistic concurrency control MUST support the If-Match header to do so. Services MAY also use other headers related to ETags as long as they follow the HTTP specification. |
Services SHOULD return the following response headers, except where noted in the "required" column.
Response Header | Required | Description |
---|---|---|
|
All responses |
The content type |
|
All responses |
GZIP or DEFLATE, as appropriate |
|
When specified in request |
Whether a preference indicated in the Prefer request header was applied |
|
When the requested resource has an entity tag |
The ETag response-header field provides the current value of the entity tag for the requested variant. Used with |
Consistent with their organization’s privacy policy, clients SHOULD NOT transmit personally identifiable information (PII) parameters in the URL (as part of path or query string) because this information can be inadvertently exposed via client, network, and server logs and other mechanisms.
For organizations to have a successful platform, they must serve data in formats developers are accustomed to using, and in consistent ways that allow developers to handle responses with common code.
Web-based communication, especially when a mobile or other low-bandwidth client is involved, has moved quickly in the direction of JSON for a variety of reasons, including its tendency to be lighter weight and its ease of consumption with JavaScript-based clients.
snake_case seems adopted by most Web Giants, especially those relying on Ruby. However, the convention in JavaScript is the camelCased.
JSON property names SHOULD be camelCased, with first letter in lower case.
In HTTP, response format SHOULD be requested by the client using the Accept header. This is a hint, and the server MAY ignore it if it chooses to, even if this isn’t typical of well-behaved servers. Clients MAY send multiple Accept headers and the service MAY choose one of them.
The default response format (no Accept
header provided) SHOULD be application/json
, and all services MUST support application/json
.
HTTP Status | Description |
---|---|
|
Indicates that a resource has been created. Typical answer to PUT and POST requests, including a HTTP Header “Location” which points toward the new resource URL. |
|
The request has been accepted and will be processed later. It is a classic answer to asynchronous calls (for better UX or performances). |
|
The request has been successfully processed, but there is nothing to return. It is often returned to a DELETE request. |
|
Content returned is incomplete. Mostly returned by paginated answers. |
|
Commonly used for calling errors if no other status matches. |
|
The request MUST be authenticated |
|
Not enough rights |
|
The resource does not exist |
|
Either calling a method on this resource has no meaning, or the user is not authorized to make this call. |
|
Nothing matches the Accept-* Header of the request. As an example, you ask for an XML formatted resource but it is only available as JSON |
|
Execution problem has been encountered. |
Warning
|
Should 206 implemented?? |
The RFC 7807 should be used as a standardized format for returning machine readable error responses from HTTP APIs.
RFC 7807 provides a standard format for returning problem details from HTTP APIs. In particular, it specifies the following:
-
Error responses MUST use standard HTTP status codes in the 400 or 500 range to detail the general category of error.
-
Error responses will be of the Content-Type application/problem, appending a serialization format of either json or xml: application/problem+json, application/problem+xml.
-
Error responses will have each of the following keys:
-
detail (string) - A human-readable description of the specific error.
-
type (string) - a URL to a document describing the error condition (optional, and "about:blank" is assumed if none is provided; should resolve to a human-readable document).
-
title (string) - A short, human-readable title for the general error type; the title should not change for given types.
-
status (number) - Conveying the HTTP status code; this is so that all information is in one place, but also to correct for changes in the status code due to the usage of proxy servers. The status member, if present, is only advisory as generators MUST use the same status code in the actual HTTP response to assure that generic HTTP software that does not understand this format still behaves correctly. ( instance (string) - This optional key may be present, with a unique URI for the specific error; this will often point to an error log for that specific response.
Example:
{ "type": "https://example.net/validation-error", "title": "Your request parameters didn't validate.", "invalid-params": [ { "name": "age", "reason": "must be a positive integer" }, { "name": "color", "reason": "must be 'green', 'red' or 'blue'"} ] }
Filtering, paginating, sorting and searching will be done based on query parameters.
Parameters and results will follow OData specification
It is necessary to anticipate the paging of your resources in the early design phase of your API. It is indeed difficult to foresee precisely the progression of the amount of data that will be returned. Therefore, we recommend paginating your resources with default values when they are not provided by the calling client, for example with a range of values [0-25].
Filtering consists in restricting the number of queried resources by specifying some attributes and their expected values. It is possible to filter a collection on several attributes at the same time and to allow several values for one filtered attribute.
Sorting the result of a query on a collection of resources. A sort parameter should contain the names of the attributes on which the sorting is performed, separated by a comma.
A search is a sub-resource of a collection. As such, its results will have a different format than the resources and the collection itself. This allows us to add suggestions, corrections, and information related to the search. Parameters are provided the same way as for a filter, through the query-string, but they are not necessarily exact values, and their syntax permits approximate matching.
Services MAY support durable identifiers for each item in the collection, and that identifier SHOULD be represented in JSON as "id". These durable identifiers are often used as item keys.
Collections that support durable identifiers MAY support delta queries.
The API should be documented following OpenAPI