What is a REST API?
A REST API is an application programming interface
architecture style that conforms to specific architectural constraints, like
stateless communication and cacheable data. It is not a protocol or standard.
While REST APIs can be accessed through a number of communication protocols,
most commonly, they are called over HTTPS, so the guidelines below apply to
REST API endpoints that will be called over the internet.
REST API Best Practices :-
- Follow Resource naming guidelines – Use nouns instead of verbs in endpoint paths.
We shouldn't use verbs in our endpoint paths. Instead, we
should use the nouns which represent the entity that the endpoint that we're
retrieving or manipulating as the pathname.
Examples –
- GET /users
- POST /users
- GET /users/{id}
- PUT /users/{id}
- DELETE /users/{id}
Here /users represents a REST API resource.
Don't use verbs, like GET /getUsers or /save or /update
Use logical nesting on endpoints –
Example:-
if we want an endpoint to get the comments for a blog post,
we should append the /comments path to the end of
the /posts path
/posts/{postId}/comments
Get particular comment from the post,
/posts/{postId}/comments/{commentId}
- Use the Appropriate HTTP Method
After you’ve named an endpoint, determine which HTTP methods to use based on the nature of the operation being performed. For context:
- GET - requests are used to retrieve resources.
- PUT - requests are typically employed for resource creation or replacement.
- POST - requests are suitable for resource creation when the server assigns a unique identifier.
- PATCH - requests allow for partial resource updates.
- DELETE - requests, as the name implies, deletes the specified resource.
Scenarios Where POST Might Be Used to Retrieve Data:-
- Complex Queries:
- Sensitive Data:
- GraphQL:
- Rate Limiting or Quota Management:
Below are the HTTP status codes,
- 400 Bad Request - This means that client-side input fails validation.
- 401 Unauthorized - This means the user isn't not authorized to access a resource. It usually returns when the user isn't authenticated.
- 403 Forbidden - This means the user is authenticated, but it's not allowed to access a resource.
- 404 Not Found - This indicates that a resource is not found.
- 500 Internal server error - This is a generic server error. It probably shouldn't be thrown explicitly.
- 502 Bad Gateway - This indicates an invalid response from an upstream server.
- 503 Service Unavailable - This indicates that something unexpected happened on server side (It can be anything like server overload, some parts of the system failed, etc.).
- 204 No Content - Indicates that the request was successful, and the server has fulfilled the request, but there is no additional content to send in the response body. This is the most used status code for successful DELETE operations.
- 422 Unprocessable Entity - This status code is used to indicate that the server understands the content type of the request entity, and the syntax of the request entity is correct, but was unable to process the contained instructions. It’s often used for validation errors that are not syntax errors.
- 409 Conflict - Indicates that the request could not be processed because of a conflict with the current state of the resource.
some common scenarios where a 409 Conflict might be used,
- Resource Version Conflict (Optimistic Locking:-
Example – mongo db version lock at db level
The code will throw OptimisticLockException so need to provide status code as 409 and proper error message to the API.
- Duplicate Resource Creation
- Concurrent Modification
Below are the scenario's,
- /products - returns List of Products
Status Code if No Products Exist: 200 OK.
Returning an empty list is a valid response when there are no products. A 404 Not Found would imply that the endpoint itself does not exist or that the resource could not be found at the endpoint, which is not the case here.
- /products?page=0&size=10
Status Code if No Products Exist: 200 OK.
Like the previous case, an empty list is a valid response for this query. The request was successful, and the endpoint exists; it’s just that there are no products to return.
- /products/{productId} - To Get Product Based on Product ID
Status Code if Product ID Doesn’t Exist: 404 Not Found
If the productId provided in the path variable does not exist, the resource cannot be found, so a 404 status code is appropriate. It indicates that the resource was not found at the given endpoint.
- /products - POST method - Create a Product
Status Code for Invalid Request Body Field: 400 Bad Request or 422 - Unprocessable Entity
- 400 Bad Request: This is commonly used when there is a syntax or validation error in the request body. It indicates that the server cannot process the request due to client-side issues.
- 422 Unprocessable Entity: This status code is used to indicate that the server understands the content type of the request entity, and the syntax of the request entity is correct, but was unable to process the contained instructions. It’s often used for validation errors that are not syntax errors.
Choosing Between 400 and 422
- Use
400 if the request body is malformed or if there’s an error with the
structure or syntax.
- Use
422 if the request body is well-formed but fails business logic or
validation rules (e.g., invalid data format or logical inconsistencies).
- Use Query Parameters for Filtering, Sorting, and Pagination:
The databases behind a REST API can get very large. 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. As more data accumulates in the database, the more important these features become.
/products?sort=price&limit=10&page=2
- Versioning
Versioning a REST API is essential to maintain backward compatibility while evolving your API. Here are some common strategies for versioning REST APIs:
- URI Versioning:
Include
the version number in the URI path.
Example:
https://api.example.com/api/v1/users
- Query Parameter Versioning:
Include the version
number as a query parameter.
Example:
https://api.example.com/users?version=1
- Header Versioning:
Use
custom headers to specify the API version.
Example:
GET /users with header Accept: application/vnd.example.v1+json
- Content Negotiation:
Use the
Accept header to specify the version.
Example:
GET /users with header Accept: application/vnd.example.v1+json
- Embedded Versioning:
Include
the version number in the payload.
Example:
{ "version": "1.0", "data": { ... } }
- Document Your API:
Use tools like Swagger/OpenAPI for clear documentation.
- Security Best Practices:
- Implement authentication and authorization mechanisms (e.g., JWT, Spring Security).
- Validate and sanitize user input to prevent common web vulnerabilities (XSS, SQL injection).
- Secure communication using HTTPS.