Design Best Practices

Organize the API around resources

  • Focus on the business entities that the web API exposes
  • A resource does not have to be based on a single physical data item
  • Adopt a consistent naming convention in URIs.
  • avoid "chatty" web APIs that expose a large number of small resources. The more requests, the bigger the load.
  • Avoid introducing dependencies between the web API and the underlying data sources

Define operations in terms of HTTP methods

  • GET retrieves a representation of the resource at the specified URI. The body of the response message contains the details of the requested resource.
  • POST creates a new resource at the specified URI. The body of the request message provides the details of the new resource. Note that POST can also be used to trigger operations that don't actually create resources.
  • PUT either creates or replaces the resource at the specified URI. The body of the request message specifies the resource to be created or updated.
  • PATCH performs a partial update of a resource. The request body specifies the set of changes to apply to the resource.
  • DELETE removes the resource at the specified URI.

Conform to HTTP semantics

  • Media types
  • GET methods
  • POST methods
  • PUT methods
  • PATCH methods
  • DELETE methods
  • Asynchronous operations

Filter and paginate data

Exposing a collection of resources through a single URI can lead to applications fetching large amounts of data when only a subset of the information is required

Instead, the API can allow passing a filter in the query string of the URI, such as /orders?minCost=n.

You can use a similar strategy to sort data as it is fetched, by providing a sort parameter that takes a field name as the value, such as /orders?sort=ProductID.

Limit the fields returned for each item, if each item contains a large amount of data.

Support partial responses for large binary resources

A resource may contain large binary fields, such as files or images. To overcome problems caused by unreliable and intermittent connections and to improve response times, consider enabling such resources to be retrieved in chunks. To do this, the web API should support the Accept-Ranges header for GET requests for large resources. This header indicates that the GET operation supports partial requests. The client application can submit GET requests that return a subset of a resource, specified as a range of bytes.

Also, consider implementing HTTP HEAD requests for these resources. A HEAD request is similar to a GET request, except that it only returns the HTTP headers that describe the resource, with an empty message body. A client application can issue a HEAD request to determine whether to fetch a resource by using partial GET requests.

Use HATEOAS to enable navigation to related resources

Hypertext(HyperMedia) as the Engine of Application State.

Possibility to navigate the entire set of resources without requiring prior knowledge of the URI scheme. Each HTTP GET request should return the information necessary to find the resources related directly to the requested object through hyperlinks included in the response, and it should also be provided with information that describes the operations available on each of these resources. This principle is known as HATEOAS

Versioning a RESTful web API

Versioning enables a web API to indicate the features and resources that it exposes, and a client application can submit requests that are directed to a specific version of a feature or resource.

The primary imperative is to enable existing client applications to continue functioning unchanged while allowing new client applications to take advantage of new features and resources.

Types of Versioning:

Open API Initiative

  • The OpenAPI Specification comes with a set of opinionated guidelines on how a REST API should be designed. That has advantages for interoperability, but requires more care when designing your API to conform to the specification.
  • OpenAPI promotes a contract-first approach, rather than an implementation-first approach. Contract-first means you design the API contract (the interface) first and then write code that implements the contract.
  • Tools like Swagger can generate client libraries or documentation from API contracts. For example, see ASP.NET Web API Help Pages using Swagger.


What is Swagger / OpenAPI?

Swagger is a language-agnostic specification for describing REST APIs. The Swagger project was donated to the OpenAPI Initiative, where it's now referred to as OpenAPI. Both names are used interchangeably; however, OpenAPI is preferred. It allows both computers and humans to understand the capabilities of a service without any direct access to the implementation (source code, network access, documentation). One goal is to minimize the amount of work needed to connect disassociated services. Another goal is to reduce the amount of time needed to accurately document a service.

Use nouns but no verbs

For naming URI use nouns.

Do not use verbs:

/getAllCars
/createNewCar
/deleteAllRedCars

GET method and query parameters should not alter the state

Use PUT, POST and DELETE methods instead of the GET method to alter the state.

Do not use GET for state changes:

Use plural nouns

Do not mix up singular and plural nouns. Keep it simple and use only plural nouns for all resources.

Use sub-resources for relations

If a resource is related to another resource use subresources.

GET /cars/711/drivers/ Returns a list of drivers for car 711
GET /cars/711/drivers/4 Returns driver #4 for car 711

Use HTTP headers for serialization formats

Both, client and server, need to know which format is used for the communication. The format has to be specified in the HTTP-Header.

Handle Errors with HTTP status codes

  • 200 – OK – Eyerything is working
  • 201 – OK – New resource has been created
  • 204 – OK – The resource was successfully deleted
  • 304 – Not Modified – The client can use cached data
  • 400 – Bad Request – The request was invalid or cannot be served. The exact error should be explained in the error payload. E.g. „The JSON is not valid“
  • 401 – Unauthorized – The request requires an user authentication
  • 403 – Forbidden – The server understood the request, but is refusing it or the access is not allowed.
  • 404 – Not found – There is no resource behind the URI.
  • 422 – Unprocessable Entity – Should be used if the server cannot process the enitity, e.g. if an image cannot be formatted or mandatory fields are missing in the payload.
  • 500 – Internal Server Error – API developers should avoid this error. If an error occurs in the global catch blog, the stracktrace should be logged and not returned as response.