REST APIs — Tips and Best Practices
By: Richard Mahler
Tags: Rest Api, Development, API, Web Development, Software Development

Writing a REST API for any software developer can be a daunting task as there are a plethora of considerations in designing and developing for the long term. One should consider the needs of the consumer in terms of simplicity and a clean implementation, as well as planning for the long term with goals such as scalability and maintenance. Consumers can be either end users or developers working with your API.

Whether the aim is to develop an API for a consumer facing web application or mobile app you will find that there are best practices that fit the solution. Questions concerning how many users expect to consume your API is a good place to start but perhaps it is best to first explain what REST is.

REST is…

Representational State Transfer, an architectural approach for designing web services. Typically, it is a client — server model where clients interact with the server exchanging HTTP requests which will request the necessary resources and the operation to perform. It is also stateless in that each request is treated on its own and does not affect the result of future requests. REST is most often associated with HTTP however REST is not strictly tied to this protocol.

The most common methods in REST are:

GET — retrieving a resource

POST — create a resource

PUT — create or replace a resource

PATCH — update a resource

DELETE — delete a resource

An endpoint is putting together a URL with a method, such as:

POST http://localhost:8080/users/1

With a basic understanding of what REST is we can dive into the best practices.

Name your API endpoints wisely

REST operations already imply an action, such as GET or DELETE, so it is not necessary to name your API with actions such as fetchUsers when simply users will suffice. Always go with nouns over verbs. For example:

POST /users

GET /users/12

DELETE /users/12

Also, notice using plurals instead of single naming, which is important because more often than not, you are working with multiple resources. Occasionally you can use a single word to describe your scenario if you are truly operating on a single resource or performing a task such as kicking off a background thread. The best recommendation is still to name your resources in plural.

Status codes aren’t just for show

HTTP has developed their own standards when it comes to response codes. It is best to return the status code that is the most meaningful and descriptive.

100–199: Information responses — Basic information returned to the user such as when a request is received but not yet processed

200–299: Successful responses — What you would expect to return to the user if the request succeeded.

300–399: Redirection — Messages should be returned when the resource has moved in most cases.

400–499: Client error responses — Errors on behalf of the user, such as invalid syntax or requesting an object not found or is unauthorized.

500–599: Server error responses — These errors should be returned when the server experiences a problem or has a limitation.

Do not confuse users with improper error codes. Sometimes it can get dicey when it comes to the finer details such as 401 (Unauthorized) and 403 (Forbidden) since these seem similar, but ultimately it is good to be consistent with the standard.

Versioning is your best friend

APIs will undergo healthy change and evolution, but when push comes to shove, there can be times where breaking changes are needed and implementations are replaced. For this, it is recommended to version your APIs ahead of time to communicate this point. This can be done simply with including a version number in the URL: www.myapi/v1/getUsers

Filtering, searching, sorting, pagination

When dealing with possibly thousands of resources you may find filtering, searching, sorting and pagination to be useful. A benefit through REST is that you don’t need separate endpoints for these features. Many API frameworks have this built in, but you can design your API on your own as well. Quite often they can be specified as query parameters in the request.

Here are a few examples of each:

Filtering: GET /users?status=online

Filtering is narrowing the results to a specific field and value. Here, keeping it simple with retrieving only the users whose status is set to online.

Sorting: GET /users?sort=username

This specifies the results to be sorted by username, often lexicographically or from A — Z.

Searching: GET/users?status=online&search=bob

Combining a filter with an exact text search is a way to narrow the resources more specifically. ElasticSearch is one example that tends to use the power of full text searching.

Pagination: GET/users?limit=50&offset=100

Pagination is segmenting the data by requesting a certain amount of the data (the limit in this case) and how far into the search (the offset).

Rate Limiting — Everything in moderation

Rate limiting controls the amount of data that your server can return. This is very useful in preventing bottlenecks with millions of clients simultaneously hitting your APIs. One way is to include in your request headers the following:

X-Rate-Limit-Limit — The number of requests a client can send within a particular time interval.

X-Rate Limit-Remaining — The number of requests left over that the client can send within the interval.

X-Rate-Limit-Reset — The time stamp when the rate limit will reset.

Simplicity is the ultimate sophistication

Taking a page out of the SOLID principles, it is best to keep your API simple by having each endpoint perform one single responsibility, and doing it well. This means not having one API do the work of multiple. This also means keeping a simple data model for all objects, and consistently representing them. An example is expressing a hierarchy with a simple Employee-Person relationship rather than writing a dozen different types of employee types.

Other tips to keeping it simple is using only a small set of status codes, throwing one or two different types of exceptions and only exposing the properties that are absolutely essential to the user. It is not useful to return data that will not be used by the developer or consumer.

To err is human, to document is divine

Documenting code is essential, and APIs are no exception. Creating a documentation page makes your API accessible and should not be hidden behind a PDF or signin page as that almost defeats the purpose. Docs should explain the request and expected responses and include an example of each operation. While documenting can seem tedious, there are tools out there that will make documentation a lot easier.

One such tool is Swagger, which lets you document via annotations that describe your API so clients can understand the behavior. The Swagger framework will create the documentation in a URL where clients can also try out your API as a demonstration.

Conclusion

Developing a RESTful API can be a complicated task. However, following a few basic principles is a good start as is reading the specifications and checking out tools and frameworks that simplify the job will make life easier for you and for your consumers and developers. Happy coding!