The objective of this document is to provide guidelines and design standards to be followed for building a RESTful API. These standards will help to design APIs that are intuitive and can be easily understood and consumed by developers consuming them.
This document in intended for a technical audience already familiar with the REST protocol and APIs. For an introduction to the topic of RESTful APIs please refer to https://medium.com/extend/what-is-rest-a-simple-explanation-for-beginners-part-1-introduction-b4a072f8740f
How this document is organized
This document is organized in four sections:
1. Resource Design
The first section provides standards and guidelines for URI Resource Modelling and Naming. This section also addresses HTTP Methods and Service Versioning for REST APIs
2. Request Structures
The second section focuses on Request Message structures by guidelines for Request Content Format, Request Headers, Query Parameters and Pagination requests.
3. Response Handling
The third section focuses on Response Handling by providing guidelines for Response Content Format, HTTP Errors, Combining Responses from multiple API calls and handling Asynchronous callbacks.
4. HATEOAS
The final section focuses on the specialized topic of Hypermedia as the Engine of Application State (HATEOAS) which allows an API to be discoverable
Guidelines and Examples
After identification of the resources, the next question is about the action to be performed on these resources. A HTTP verb is normally used to specify the action to be performed. It forms an important part of RESTful API design. The primary and most commonly used HTTP verb are POST, GET, PUT and DELETE. These verbs help to perform the CRUD operations on the resource. As a guideline, these verbs should be used as follows:
· GET – Used to retrieve or read the information about the requested resource entity identified by the request-URI
· POST – Used to create a new resource, which is subordinate to the parent resource identified by the request URI
· PUT – Used to update an existing resource entity identified by the request URI
· DELETE – Used to delete the resource represented by the request URI
Other HTTP verbs like PATCH, OPTIONS and HEAD can be used for specific usage requirements:
· PATCH – Modify based on the differences in a resource rather than the full resource.
· OPTIONS – Solicit the server for the list of other methods that are permitted for this Resource
· HEAD– Identical to GET except the server must not return the message body in the response
Guidelines and Examples
API URLs must follow a naming convention that meets the following criteria:
· It must provide the address or location of the server hosting the API
· It must specify the service name of the API
· It must specify the version of the API service
· It must specify the resource on which the service operation is being performed
E.g. http[s]://[<server-name>]/api/[<service-name>]/[<version>]/[<resource>]
E.g. https://api.<companyname>.com/api/amenities/v1/flights
Guidelines and Examples
Versioning is an important aspect of API design. Every API must have a version number associated with it. The following guidelines should be used to version APIs and determine backward compatibility:
· The version should consist of a major version and an optional minor version
· There are various methods for versioning (using the URI, a query parameter or a custom header) But to keep things simple, it is recommended to use the URI method with an integer number prefixed with a ‘v’ to denote the major version of the API.
E.g. http://api.foo.com/api/amenities/v1
· A major version shall be regarded as incompatible with the prior major version. Major version changes include the following:
o Change of optional request field to mandatory
o Addition of mandatory request field
o Type and constraints of values are constrained:
§ Max length is decreased
§ Min length is increased
§ Decimal or floating-point primitive changed to integer
· The Resources published as a REST API must remain compatible across minor versions. API Clients and Service Consumers must tolerate the following changes as compatible:
o Change of mandatory request field to optional
o Addition of optional request field
o Addition of response field
o Relaxing of field data types and constraints
§ Max length of a request field or array is increased
§ Min length of a request field or array is decreased
§ Request integer changed to decimal or floating-point primitive
o Addition to the list of possible error codes
Guidelines and Examples
Every resource of an RESTful API must have a meaningful name to identify itself. Following are some of the recommended naming conventions for resources:
· Name collection resource with plural noun
E.g. http://api.foo.com/api/amenities/v1/flights
·
Name singular resource with singular
noun
E.g. http://api.foo.com/api/amenities/v1/flights/v1/UA123
· Name a controller resource using a verb
E.g. http://api.foo.com/api/amenities/v1/flights/UA123/book
·
A URI consists of segments
separated by forward slashes (‘/’). Each segment must identify a resource. If a
resource has sub-resources, the URI must specify the path to the sub-resource
in a hierarchical manner as follows:
/api/servicename/v1/{ResourceCollectionName}/{ResourceId}/{SubResourceCollectionName}/<{SubResourceId}>
E.g. /api/amenities/v1/flights/UA123/snacks/sku456
What to Avoid
· Avoid using CRUD operation names in the URIs. For example, do not use URIs like http://api.foo.com/api/amenities/v1/getflights
· Avoid mixed and upper cases in URIs. Use lowercase for naming URIs. Mixed case is harder to type in and read.
· Avoid using characters that require URL encoding. Use hyphen instead of space or underline. They are aesthetic and easier to read. Spaces in URL will get transformed into URL encoded %20s, degrading readability further.
Guidelines and Examples
The API request or response body content is referred to as the API payload. There are many options for exposing the API payload. But in the RESTful world there are 2 well adopted formats – viz. JSON and XML. JSON is the preferred of the two due to the following benefits that it offers over XML:
· JSON is a more compact format, meaning it weighs far less on the wire than the more verbose XML. It is a good benefit for mobile devices with a limited bandwidth to save costs and improve loading speed.
· JSON parsing is generally faster than XML parsing.
· JSON is easier to work with in some languages (such as JavaScript, python, and php)
· Formatted JSON is generally easier to read than formatted XML.
· JSON specifies how to represent complex datatypes, there is no single best way to represent a data structure in XML.
Guidelines and Examples
· The following is a list of HTTP headers that are commonly supported by service endpoints when clients require them:
o Accept
o Authorization
o Content-Type
o X-HTTP-Method-Override
· REST APIs use either the "application/json" or the "application/xml" media type in the ‘Content-Type’ and ‘Accept’ headers of an HTTP/1.1 request or response.
· ‘Accept’ header is a way for a client to specify the media type of the response content it is expecting and ‘Content-Type’ is a way to specify the media type of request being sent from the client to the server. ‘Content-Type’ is also used in the response to specify the type of response being sent by the server.
· The request header should also include some information for diagnosis, routing, and monitoring purposes. Some common examples of headers that can be used for this are:
o RequestorId
o ApplicationId
o Environment
o UserId
o TransactionId /UUID
o TransactionSequence
o SendTimeStamp
What to Avoid
The header should not include elements of the Resource itself. For example, the service provider shall not require a client to POST an update with the Airline Code in the header for flight booking purposes. This is considered an improvisation and should be avoided.
Guidelines and Examples
Clients may accomplish the filtering and sorting of responses by passing query parameters in a GET request. The guidelines are as follows:
· The filter criteria should depend on the specific Resources fields, and not on some other object.
E.g. HTTP GET http://api.foo.com/api/amenities/v1/flights?airlineCode=’UA’®ion=’Europe’
· Filter by association can be used when a relationship between two Resources produces the desired set of results. This may be combined with query parameters as shown:
E.g. HTTP GET http:// api.foo.com/api /hotels/v1/locations/{locationId}/landmarks
E.g. HTTP GET http:// api.foo.com/api /hotels/v1/locations/{locationId}/landmarks?type=’airport’
· The ‘orderBy’ query parameter should be used for sorting the response.
Alternative to Consider
The Resource may support a POST operation that includes the query in the request body in cases when the query to a Resource is extensive. A service provider or business service may also publish a Resource specifically to perform complex searches.
Guidelines and EXAMPLES
When a client requests an API that represents a set of resources, the results can be broken into subsets, or paginated. Some guidelines for pagination are as follows:
· The size of the subsets, or pages, should be indicated by a default limit.
· The default limit should be identified during service or API design. There should not be a defined universal default limit.
· The client should be able to override the limit by passing a ‘limit’ request parameter equal to the preferred page size.
· The specific subset or page of results returned should be indicated by an offset parameter. The client should be able to indicate the desired page by passing the ‘offset’ request parameter. The first page should be the default (offset = 0).
· A paginated representation should include the following metadata in the response:
o A link to the previous page, if there is one
o A link to the next page, if there is one
o A link to the first page, if there is one
o A link to the last page, if there is one
o A link to the current page
o The total number of records
E.g.
{
"links": {
"first": "/hotels/v1/profiles?offset=0,limit=10",
"prev": "/hotels/v1/profiles?offset=0,limit=10",
"self": "/hotels/v1/profiles?offset=1,limit=10",
"next": "/hotels/v1/profiles?offset=2,limit=10",
"last": "/hotels/v1/profiles?offset=520,limit=10",
"related": "/articles/1/tags"
}
}
Guidelines and Examples
It is possible that an API client only needs a few specific fields from the larger response normally provided. These are the guidelines for supporting this requirement:
· The ‘fieldset’ query parameter should be used by the client if supported by the resource:
E.g. ?fieldset=name,description,addresses.count
· The value is a comma-separated list of fields. The fields use periods to indicate a field within a structure (the count field under the addresses section of the response for example).
· API designers should support fieldsets when an API client requests a subset of information from an API. APIs may not support field sets if it is deemed unnecessary.
· The client can also have a default fieldset by identity (i.e., API Key). This is so that the request parameters do not have to explicitly include them.
Guidelines and Examples
· The response body should be returned in JSON format, except when another format is requested by the client and agreed upon during the design of the API.
· If supported, clients may request an API response in a format other than JSON. The Client should indicate the preference as an extension to the resource name (.pdf, .xml, .csv, etc.) or in the ‘Accept’ header of the HTTP request.
· The Resource may return an HTTP 406 if the request content type cannot be generated.
Communicating error information properly to the API consumer is critical for the success of the REST API. API consumers and app developers using APIs learn to write code through errors. Well defined error messages are helpful for troubleshooting and resolving issues after the applications built using the APIs are in the hands of the end users.
Guidelines and Examples
RESTful APIs must communicate error information using proper HTTP response status code. There are different types of HTTP response status codes to communicate the different success and error information as follows:
· 2xx: Success – Used to communicate that the request from the client was successfully received, understood, and accepted
· 3xx: Redirection – Used to communicate that additional action needs to be taken by the user agent like browser to fulfil the request
· 4xx: Client Error - Used to indicate errors caused by the client
· 5xx: Server Error – Used to indicate that server is aware that an error occurred while processing the request and cannot process it further
The following table summarizes the common HTTP error response codes that may be returned by the API under different error scenarios
400 |
Bad Request |
Indicates that the request had some mal-formed syntax error due to which it could not be understood by the server. Probable reason could be missing mandatory parameters or syntax error |
401 |
Unauthorized |
Indicates that the request could not be authorized possibly due to missing or incorrect authentication token information |
403 |
Forbidden |
Indicates that the request was understood by the server but it could not be processed due to some policy violation or the client does not have access to the requested resource |
404 |
Not Found |
Indicates that the server did not find anything matching the Request-URI |
405 |
Method Not Allowed |
Indicates that the method specified in the Request-Line is not allowed for the resource identified by the Request-URI |
409 |
Conflict |
Indicates that the request could not be processed due to a conflict with the current state of the resource |
414 |
Request URI Too Long |
Indicates that the Request URI length is longer than the allowed limit for the sever |
415 |
Unsupported Media Type |
Indicates that the request format is not supported by the server |
429 |
Too Many Request |
Indicates that the client has submitted the request too often and needs to slow down |
500 |
Internal Server Error |
Indicates that the request could not be processed due to an unexpected error in the server. |
501 |
Not Implemented |
Indicates that the server does not support the functionality required to fulfil the request |
502 |
Bad Gateway |
Indicates that the server while acting as a gateway or proxy received an invalid response from the backend server |
503 |
Service Unavailable |
Indicates that the server is currently unable to process the request due to temporary overloading or maintenance of the server. Trying the request at a later point of time might result in success |
504 |
Gateway Timeout |
Indicates that the server while active as a gateway or proxy did not receive a timely response from the backend server |
Along with the Http status code, the response message must also provide additional information to clarify the error such as error codes and error messages as shown below. The errors array will often be used when the service captures multiple errors to return to the consumer.
{ “status_code” : {status},
“status_message”: “status message”,
"errors":
[ { "error_code": {error code},
"error_message": "Error message"
} ]
}
E.g.
{
“status_code” : 400,
“status_message”: “Incorrect Request”
"errors": [
{ "error_code": 123, "message": "SMS message body is required" } ,
{ "error_code": 456, "message": "SMS recipient is required" }
]
}
Guidelines and Examples
· APIs that orchestrate multiple calls to other APIs or systems should return a single status code representing the outcome of the combined execution of calls.
· A successful outcome of the multiple calls should result in an HTTP 200 status.
· A failure of any one call should result in an error status code (except when business requirements allow for partial success). The API should report the most severe error status of the orchestrated calls.
· HTTP 207 should not be returned, except in cases where the Service Provider requires this approach, or the API is built for a domain-specific purpose that requires the client to handle partial successes and failures.
o Example of valid partial success: An API is designed to return both an account balance and transaction history. Internally the API does a mashup of two different systems to get the data. If the account balance is available but the transaction history call fails, then the business requirements may make it acceptable to return just the account balance information.
o For additional examples and syntax for returning partial success refer to "A response containing responses" section of https://apihandyman.io/api-design-tips-and-tricks-getting-creating-updating-or-deleting-multiple-resources-in-one-api-call/
An API Client may require a variation in the HTTP status code. The variation should be managed as part of the client’s profile. For example, at the API Gateway, a policy should be added to the Client’s profile to adjust the response of API calls made by an exception approved client.
Guidelines and Examples
Two options are standard for following up with a client asynchronously after an API call i.e. either a Callback URL or a Push notification. The guidelines for these are as follows:
· Clients may provide a Callback URL for the API results to be returned to, in cases where the API or resource supports this function.
o The Callback should be a POST with a request body matching the response body that would be provided in a synchronous call.
o Custom callback message bodies should be avoided.
o Webhooks can be used to implement Callbacks. See https://webhooks.pbworks.com/w/page/13385124/FrontPage for more information.
· If supported by the API product implementation, follow-up may be provided by Push notification.
o A good use case for push notifications is to allow web applications to receive messages from the server, even if the web app is not currently open in the browser or not running on the device. See https://flaviocopes.com/push-api/ for more information.
Guidelines and Examples
HATEOS (Hypermedia as the Engine of Application State) allows an API to be discoverable i.e. .by querying a resource, links are provided to related resources and endpoints. This means no prior knowledge of the data model or schema is required to navigate and interact with the API
HATEOS can be handled via a query parameter such as include-links=true. When links are requested, they should be included in the response as a separate element as follows:
{ "links":
{ "flights": "/amenities/v1/flights" }
}
A client can choose to begin from the primary URL or begin with knowledge of a specific set of API resources. Actions or state transitions that the client can perform are included in the response as hyperlinks. Links are only available for allowable actions based on the current state. Information influencing the state includes the identity of the client, the status of the resource, values of information within the resource, and status of the systems behind the API implementation.
Additional Information:
What is HATEOAS and why is it important for my REST API?
Resource Specification
Use below table for documenting all resources and operations supported by the REST resources defined in the REST API
Resource Name |
Name of the resource exposed by this API |
Resource URL |
Define relative URI for the resource exposed as API. The URL should be designed to be able to traverse through the resource and sub resource. Explain variables in URL template if URL contains variables in curly braces. |
Request Verb |
POST/GET/PUT/DELETE/OPTIONS/HEAD/PATCH |
Request Headers |
List and explain all mandatory and optional headers needed for calling the service. |
Request Query Parameters |
List down all the mandatory and optional query parameters that are passed in request. |
Request Body Schema |
Specify the schema (JSON schema or XML schema) for the inputs sent in the request body. |
Request Body Example |
How exactly the request data look like, if applicable. Generally GET requests do not have request body. Requests for POST, PUT,PATCH will have an request body mostly in either JSON or XML format |
Response Headers |
Provide the response header Information |
Response Body Schema |
Specify the schema (JSON schema or XML schema) for the output message expected in the response |
Response Body Example |
How Exactly the response body look like. Sample response from the API during positive scenarios (i.e user input is good and server does not encounter any errors). |
Input Data validations performed |
Explain any validation done on the mandatory and optional input parameters (i,e URL template params, Query Params, Request Headers or Params in request body like form params etc). |
Success/Error Response HTTP Status Codes returned by Service/API |
2xx or 3xx codes used for successful responses. 4xx or 5xx series error HTTP status codes returned by the API. 4xx codes are used for validating input in the request and returning error to client. 5xx codes are used for any errors generated due to error conditions in the server. |
Error Response Format |
{"errors": [ { "message": "Message to be displayed to user", "reason": "Reason which might help App Developer to correct the input errors or understand errors on server side", "type": "Classification of error" } ]} |