This post contains some notes about REST and best practices that I follow to design RESTful APIs, it will focus mainly on Uniform interface constraint.
REST
REST (REpresentational State Transfer) is an architectural approach to design web services presented by Roy Fielding in 2000 in his dissertation. A RESTful API is an API that satisfies the REST constraints.
Constraints
Client-server - Separate client application and server application, It’s about separation of concerns, by doing this we improve portability and scalability because it allows those components to evolve independently.
Stateless - Each request from a client to server must contain all necessary information, including authentication details, the server cannot store anything about requests, sessions, history, etc.
Cache - When possible responses data have to be cacheable, clients have the right to reuse responses data later. This will improve efficiency and scalability, the trade-off, however, is that it can decrease reliability if the cached data differs significantly from the data in the server.
Uniform interface - Define the standards of the API interface and follow it, for example, identification of resources and response messages. If it was decided to pluralize resources name on URI, follow this standard in all URIs, it will improve the readability and maintainability.
Layered system - The system has to be composed of components in hierarchical layers, each component is only aware of the immediate layer with which they are interacting. For example, a system can have a data layer, cache layer, security layer, etc. And all those layers should not affect the communication between the server and client.
Code-on-demand - This is the only optional constraint, the server will provide static representations of resources, but when requested it can send executable code.
In this post, I will show some best practices to achieve a uniform interface, the constraints 1 and 2 are pretty straightforward, while the other constraints have many ways to satisfy and cover them is out of the scope of this post.
Best practices to design an API uniform interface
REST is not limited to but is frequently applied on web applications and leverages HTTP protocol. A RESTful API will expose your system’s resources via a collection of Uniform Resource Identifiers (URIs). Responses will be in JSON or XML, you can provide both formats if you want, in that case, the client will choose using the content-type header. Once defined the system resources, it's time to choose a resource naming strategy and combine it with HTTP Methods to represent operations on those resources.
Moreover is wise to define standards for responses: what will be the response body in case of failure? Will it have a message describing the error, only a code for reference, or both? And in case of success, what data of resources will be presented? What HTTP Response Codes will be used in each response? These questions have to be addressed in the API design phase.
Let’s use a music streaming service as an example, among other resources it has Artists, Albums, and tracks, let’s see some practices to define the URIs:
Use nouns to represent resource, not actions
HTTP Methods will indicate the action.
/** Do **/
api.example.com/artists
/** Don't **/
api.example.com/get-artists
Pluralize resources
The rationale here is that we are dealing with collections of resources.
/** Do **/
api.example.com/albums
/** Don't **/
api.example.com/album
Demonstrate the hierarchical relationship between resources
This strategy improves comprehension.
api.example.com/artists/{id}/albums
api.example.com/artists/{id}/albums/{id}/tracks
Those URIs indicate that artists have a collection of albums that in turn have a collection of tracks. This is not required, often you will find APIs that don’t use this format, for example:
api.example.com/albums
api.example.com/albums/{id}/tracks
You may find APIs that provide both formats. Also note that we are not using trailing forward slash, because it doesn’t add semantic value, for example:
api.example.com/artists/{id}/albums/
Other tips to improve readability
- Use hyphens ( - ) instead of underscores ( _ )
- Use only lowercase letters
- Don’t use file extensions
Use HTTP methods to indicate operations on resources
Most common HTTP Methods
- POST - Create resources
- GET - Read resources
- PUT - Update or replace resources
- PATCH - Modify resources
- DELETE - Delete resource
Examples:
/** Get artists **/
GET api.example.com/artists
/** Get a particular artist **/
GET api.example.com/artists/{id}
/** Create a track **/
POST api.example.com/artists/{id}/albums/{id}/tracks
/** Update an album **/
PUT api.example.com/artists/{id}/albums/{id}
/** Delete a track **/
DELETE api.example.com/artists/{id}/albums/{id}/tracks/{id}
Use appropriate HTTP Response Codes on responses
Most common HTTP Response Codes
- 200 OK - Indicate success
- 201 Created - Successful creation occurred (via POST or PUT)
- 204 No Content - Indicate success without a response but, commonly used for DELETE and PUT requests
- 400 Bad Request - Indicate something is not right with the request, for example, missing information or invalid data.
- 401 Unauthorized - Indicates invalid authentication credentials.
- 403 Forbidden - User not authorized to perform the operation
- 404 Not found - Resource not found
- 405 Method not allowed - Indicates URL exists, but HTTP method is not applicable
- 500 Internal error - Indicates the server encountered an error and don’t know how to handle
Conclusion
Many of those practices described here came from reading about, developing, integrating with, and reading APIs documentations. I think that following them is a good way to create a concise and coherent API interface.
This post just scratched the surface, there other related topics worth taking a look at, such as caching, compression, security, versioning, and a lot more. For a more in-depth study I recommend reading the following:
- Architectural Styles and the Design of Network-based Software Architectures
- Learn REST
- RESTful web API design
- REST API Tutorial
Also is useful to look at how other APIs was designed, such as:
Top comments (1)
Nice piece.