RestAPI Design Best Practices
Design a proper RestAPI is crucial and most of the people end up with poorly designed APIs. In this tutorial we can learn how we can properly design a RestAPI. We will go through the following sections,
- Naming convention
- Versioning
- Query Parameters
- Idempotency
- Proper Status Codes Usage
- Error Handling
- Security
Naming
We need to make sure that we use nouns to represent resources. I have seen that most of the people end up with resources like following,
/getEmployees
/getBooks
/deleteStudent
Usually the action is represented by the HTTP method which can be either GET, PUT, POST, DELETE etc. The good naming convention should be as follows which must be plural.
/employees
/books
/students
Okay, So how we know which action has been performed?
Different HTTP methods represents different actions.
- GET — get resources
- POST — create a new resource
- PUT — update an existing resource
- DELETE — delete an existing resource
Then following RestAPI provide the proper meaning to the reader as well.
GET /employees - get all employees
POST /employees - cretae an employee
PUT /employees/{id} - update a specific employee with id
DELETE /employees/{id} - delete a specific employee with given id
GET /customers/{id}/orders - get all the orders for customer with id
So we can represent the relationship when we design our RestAPI like /customers/{id}/orders
.
Please use hyphens to improve the readability of your url.
Collections is group of resources which has the same name. As an example, GET /orders
, POST /orders
, DELETE /orders/{id}
is a collection of order resource. When we design an API usually we design up to 2 to 3 levels.
Versioning
In RestAPI it is important to versioning your APIs, when we expose our API there can be many consumers for our API and it is not a good practice to change the responce or update the naming. If we are planing to do a change to the existing RestAPI collection then we should go with versioning.
Please understand that changing the API naming and payload depending on the requirement is a sign of a bad design but there are cases where we completely update our system and update our APIs to cater new requirements or relationships which needed the versioning
We can use v1
or v1.1
within the url to mention the version. /v1/orders/{id}
is an example of how we can use versions.
Query Parameters
When we consider GET /orders
that implies to get all the orders. But what if there are 10000s of orders? is it good to get everything and paginate? No.
When we design our APIs we need to consider the following.
- Pagination
- Filtering
- Sorting
- Fetch specific fields
All these details can be added to the API using query parameters.
GET /orders?page=1&limit=100 - we are getting first 100 orders
GET /orders?page=2&limit=100 - we are getting second 100 orders
GET /orders?page=1&limit=100&sort=date - we are getting first 100 order by date
GET /orders?fields=name,amount - only get name and amount
Important — when we design a GET resource it is important to have default limit in our end. As an example eventhough user has not mentioned any limit then the default should be defined number and there should be a maximum number that the user can go for.
If we can get the fields what we want why we need GraphQL? In RestAPI we are considering mostly the flat structure and fields
query parameter is not good for a large set of fields and it cannot solve hierarchy structure projections.
Idempotency
Idempotency essentially means that the effect of a successfully performed request on a server resource is independent of the number of times it is executed.
As an example even we send multiple delete request for the same resource it should not change any states in the server other that deleting the mentioned resource. First delete to /orders/10
will return with 200 success
and second orders/10
will return with 404
not found
but the second call must not cause any additional changes in the server.
Please note that POST
and PATCH
are not idempotent.
Proper Status Code Usage
In RestAPI proper status codes matters similer to traffic lights. Status code provides the high level information of the response. Following are some examples.
- 102 — Processing
- 200 — OK
- 201 — Created
- 302 — Moved Permanently
- 400 — Bad Request
- 401 — Unauthorised
- 403 — Forbidden
- 404 — Not Found
- 500 — Internal Server Error
There are lots of status codes and please note that depending on the first digit it provide some grouping.
- 100–199 — Information processing
- 200–299 — Successful response
- 300–399 — Redirection messages
- 400–499 — Client error messages
- 500–599 — Server error messages
Error Handling
Error handling in RestAPI is crucial. We need to design the RestAPI to provide error information to make sure that,
- Information to recover errors by the endpoint user — As an example if the amount is missing in the payload that should be mentioned.
- Don’t expose too much of internal details — This is one of the most important where hacker can get these to attck the system. As an example direct database errors or any additional information must not pass to the end user
- Using proper status code with the error
Security
Security needs a separate blog to cover and In this section I will pin point what to be done.
- Using proper encryption — Need to use SSL/TLS to secure the data
- Proper Authentication mechanisms
- Proper Authorisation — Using ACLs (Access control list)
- Rate Limits
- Ip blacklisting
- Block XSS attacks
Important — API manager can be used to handle the most of the security aspects and that component will make sure most of the security concerns.
If you have found this helpful please hit that 👏 and share it on social media :).