Each RESTful API operation is a combination of an HTTP request against a URL and an appropriate HTTP method.
When executed, each operation will return a status code, indicating whether the invocation has been successful or not. Successful invocation is indicated by a HTTP 2XX status code, while operations that are not executed correctly indicate this with erroneous status code—4XX if the error is at client side, or 5xx when the server fails to process a valid request.
Having a well-specified API is vital for its adoption. Such specification should not only completely enumerate the status codes of each operation, but should also specify the expected data format, that is, its supported media types.
The following table defines how the Express.js Router will expose the API operations, and it should serve as a reference specification for it:
| Method | URI | Media type | Description | Status Code |
| GET | /catalog | application/json |
Returns all the items in the catalog.
|
200 OK 500 Internal Server Error |
| GET | /catalog/{categoryId} | application/json | Returns all items for the selected category. If the category does not exist, it returns 404. |
200 OK, 404 NOT FOUND 500 Internal Server Error |
| GET | /item/{itemId} | application/json | Returns a single item for the selected itemId. If there is no such item, it returns 404. |
200 OK, 404 NOT FOUND 500 Internal Server Error |
| POST | /item/ | application/json | Creates a new item; if an item with the same identifier exists, it will be updated. When an item is created, a Location header is returned. It provides the URL where the newly created item can be accessed. |
201 Created 200 OK 500 Internal Server Error |
| PUT | /item/{itemId} | application/json | Updates an existing item; if an item with the provided identifier does not exist, it creates it. When an item is created, a Location header is returned. It provides the URL where the newly created item can be accessed. |
201 Created 200 OK 500 Internal Server Error |
| DELETE | /item/{itemId} | application/json | Deletes an existing item; if an item with the provided identifier does not exist, it returns 404. |
200 OK, 404 NOT FOUND 500 Internal Server Error |
The catalog application handles two types of entities: items and categories. Each item entity contains a collection of categories where it belongs. As you can see, the category is just a logical entity in our application; it will exist as long as there is at least one item referencing it, and will cease to exist when no items refer it. This is why the application exposes routes for exposing data manipulation functions only for resources of type items, while the operations for categories are more or less read only. Looking more carefully into the URLs exposing the data manipulation operations for the items, we can see a clear pattern aligning the URL to the REST fundamental principles—a resource is exposed by a single URL, and it supports resource manipulation actions that are determined by the HTTP method of the request. To sum up, listed here are the generally accepted rules that a well-defined API should follow. They are semantically related to each resource manipulation operation:
- When a new resource is created, the service makes use of the 201 Created status code, followed by a location header that specifies the URL where the newly created resource can be accessed.
- Operation that creates resources may be implemented to gracefully reject creation of resources, which unique identifiers already use; in such cases, the operation should indicate a non-successful invocation with an appropriate status code 409 Conflict, or a more general 400 BAD REQUEST. However, a general status code should always be followed by a meaningful explanation of what has gone wrong. In our implementation, we choose a different approach—we update the resource from the create operation, if it exists, and notify the caller that the resource was updated by returning the 200 OK status code instead of 201 Created.
- The Update operation resembles the create operation; however, it always expects a resource identifier as a parameter, if a resource with this identifier exists—it gets updated with a new state provided in the body of the HTTP PUT request. The 200 OK status code indicates successful invocation. The implementation may decide to reject handling of non-existent resources with the 404 Not Found status code or creating a new resource with the passed identifier. In that case, it would return the 201 Created status code, followed by a location header that specifies the URL where the newly created resource can be accessed. Our API makes use of the second option.
- While successful deletion can be indicated with the 204 No Content status and further payload, most user agents would expect the 2xx HTTP status to be followed by a body. Thus, to stay compatible with most of the agents, our API will indicate successful deletion with the 200 OK status code, followed by a JSON payload:{'Status': 'Successfully deleted'}. Status code 404 Not found will indicate that a resource with the provided identifier does not exist.
- As a general rule, 5XX should not indicate application state errors but more severe errors, such as application server or database failures.
- It is best practice that update and create operations should return as a payload to the entire state of the resource. For instance, if a resource is created with a minimum set of attributes, all non specified attribute will get default values; the response body should contain the full state of the object. The same is valid for updates; even if an update operation updates the resource restate partially, the response should return the complete state. This may save the user-agent an additional GET request if they needed to check the new state.
Now that we have defined some general recommendations on how operations should behave, it's time to implement them in a new version of the API.