Best Practices for rest APIs
This article is composed of a summary of the Stack Overflow blog article “Best practices for REST API design” by John Au-Yeung
Accept and Respond with JSON
JSON is the standard for transferring data. The reason is that most networking technologies have tools to process it: JavaScript has built-in methods to encode and decode JSON either through the Fetch API or another HTTP client. Server-side technologies have libraries that can decode JSON without doing much work.
XML isn’t widely supported as it requires prior conversion to a form which may be used by network frameworks, i.e. JSON. Further, client side manipulation is hard
To inform the client that an app responds with JSON data, set Content-Type
in the response HTTP header to application/json
. Certain frameworks rely on this header to parse received data
Use nouns instead of verbs in endpoint paths
We should use the nouns which represent the entity that the endpoint that we’re retrieving or manipulating as the path-name. This is because our HTTP request method already has the verb
GET retrieves resources. POST submits new data to the server. PUT updates existing data. DELETE removes data. The verbs map to the CRUD operations
With the two principles we discussed above in mind, we should create routes like GET /articles/
for getting news articles. Likewise, POST /articles/
is for adding a new article , PUT /articles/:id
is for updating the article with the given id
. DELETE /articles/:id
is for deleting an existing article with the given ID.
Name collections with plural nouns
To deal with collections instead of a single entity, the noun representing the collection of entities/resources should be in the plural form. Tables usually have more than one entry and are named to reflect that, so to be consistent with them, we should use the same language as the table the API accesses.
With the /articles
endpoint, we have the plural form for all endpoints, so we don’t have to change it to be plural
Nesting resources for hierarchical objects
The path of the endpoints that deal with nested resources should be done by appending the nested resource as the name of the path that comes after the parent resource.
For instance, if we want an endpoint to get the comments for a news article, we should append the /comments
path to the end of the /articles
path. This is assuming that we have comments
as a child of an article
in our database. Thus the resulting endpoint would look like: '/articles/:articleId/comments'
Handle errors gracefully and return standard error codes
We should be throwing errors that correspond to the problem that our app has encountered
Allow filtering, sorting, and pagination
Sometimes, there’s so much data that it shouldn’t be returned all at once because it’s way too slow or will bring down our systems. Therefore, we need ways to filter items
We also need ways to paginate data so that we only return a few results at a time. We don’t want to tie up resources for too long by trying to get all the requested data at once
Filtering and pagination both increase performance by reducing the usage of server resources.
For filtering, the fields to be filtered are passed via the URL’s parameters as follows /employees?lastName=Smith&age=30
For sorting by certain fields, pass the fields to be sorted are passed as URL parameters under a “sort” field name as follows: /articles?sort=+author,-datepublished
Where +
means ascending and -
means descending. So we sort by author’s name in alphabetical order and datepublished
from most recent to least recent.
Maintain Good Security Practices
Using SSL/TLS for security is a must. To enforce the principle of least privilege, we need to add role checks either for a single role, or have more granular roles for each user.
Cache data to improve performance
We can add caching to return data from the local memory cache instead of querying the database to get the data every time we want to retrieve some data that users request.
There are many kinds of caching solutions like Redis, in-memory caching, and more. We can change the way data is cached as our needs change.
Versioning our APIs
We should have different versions of API if we’re making any changes to them that may break clients. The versioning can be done according to semantic version (for example, 2.0.6 to indicate major version 2 and the sixth patch) like most apps do nowadays.
Versioning is usually done with /v1/
, /v2/
, etc. added at the start of the API path.