RESTful API
Rules ¶
Use nouns to represent resources [Mandatory] ¶
RESTful URI should refer to a resource that is a thing (noun) instead of referring to an action (verb) because nouns have properties that verbs do not have – similarly, resources have attributes.
We should not use URIs to indicate a CRUD function. URIs should only be used to uniquely identify the resources and not any action upon them.
We should use HTTP request methods to indicate which CRUD function is performed.
Some examples of a resource are:
- Users of the system
- User Accounts
- Network Devices etc.
Above resource URIs can be designed as below:
HTTP GET http://api.example.com/device-management/managed-devices //Get all devices HTTP GET http://api.example.com/device-management/managed-devices/{id} //Get device for given Id HTTP GET http://api.example.com/user-management/users //Get all users HTTP GET http://api.example.com/user-management/users/{id} //Get one user for given Id HTTP POST http://api.example.com/device-management/managed-devices //Create new Device HTTP PUT http://api.example.com/device-management/managed-devices/{id} //Update device for given Id HTTP DELETE http://api.example.com/device-management/managed-devices/{id} //Delete device for given Id
Divide the resource archetypes into four categories into Document, Collection, Store and Controller [Mandatory] ¶
For more clarity, let’s divide the resource archetypes into four categories (document, collection, store, and controller). Then it would be best if you always targeted to put a resource into one archetype and then use its naming convention consistently.
For uniformity’s sake, resist the temptation to design resources that are hybrids of more than one archetype.
1) Document
A document resource is a singular concept that is akin to an object instance or database record.
In REST, you can view it as a single resource inside resource collection. A document’s state representation typically includes both fields with values and links to other related resources.
Use "singular" name to denote document resource archetype.
http://api.example.com/device-management/managed-devices/{device-id} http://api.example.com/user-management/users/{id} http://api.example.com/user-management/users/admin
2) Collection
A collection resource is a server-managed directory of resources.
Clients may propose new resources to be added to a collection. However, it is up to the collection resource to choose to create a new resource or not.
A collection resource chooses what it wants to contain and also decides the URIs of each contained resource.
Use the "plural" name to denote the collection resource archetype.
http://api.example.com/device-management/managed-devices http://api.example.com/user-management/users http://api.example.com/user-management/users/{id}/accounts
3) Store
A store is a client-managed resource repository. A store resource lets an API client put resources in, get them back out, and decide when to delete them.
A store never generates new URIs. Instead, each stored resource has a URI. The URI was chosen by a client when the resource initially put it into the store.
Use "plural" name to denote store resource archetype.
http://api.example.com/song-management/users/{id}/playlists
4) Controller
A controller resource models a procedural concept. Controller resources are like executable functions, with parameters and return values, inputs, and outputs.
Use "verb" to denote controller archetype.
http://api.example.com/cart-management/users/{id}/cart/checkout http://api.example.com/song-management/users/{id}/playlist/play
Indicate hierarchical relationships and have much better readability [Mandatory] ¶
1) The forward-slash (/) character is used in the path portion of the URI to indicate a hierarchical relationship between resources. e.g.
http://api.example.com/device-management/managed-devices/{id}
http://api.example.com/device-management/managed-devices/{id}/scripts/{id}
http://api.example.com/device-management/managed-devices/scripts/{device-id}/{script-id} //Bad hierarchical relationships
2) As the last character within a URI's path, a forward slash (/) adds no semantic value and may confuse. It’s better to drop it from the URI.
http://api.example.com/device-management/managed-devices
http://api.example.com/device-management/managed-devices/ //Trailing forward slash
3) To make your URIs easy for people to scan and interpret, use the hyphen (-) character to improve the readability of names in long path segments.
4) It’s possible to use an underscore in place of a hyphen to be used as a separator – But depending on the application’s font, it is possible that the underscore (_) character can either get partially obscured or completely hidden in some browsers or screens.
To avoid this confusion, use hyphens (-) instead of underscores ( _ ).
http://api.example.com/inventory-management/managed-entities/{id}/install-script-location //More readable
http://api.example.com/inventory-management/managedEntities/{id}/installScriptLocation //Less readable
5) When convenient, lowercase letters should be consistently preferred in URI paths.
http://api.example.org/my-folder/my-doc
HTTP://API.EXAMPLE.ORG/my-folder/my-doc //Capital letters are there
http://api.example.org/My-Folder/my-doc //Capital letters are there
Do not use file extensions [Mandatory] ¶
File extensions look bad and do not add any advantage. Removing them decreases the length of URIs as well. No reason to keep them.
Apart from the above reason, if you want to highlight the media type of API using file extension, then you should rely on the media type, as communicated through the Content-Type header, to determine how to process the body’s content.
http://api.example.com/device-management/managed-devices /This is correct URI/
http://api.example.com/device-management/managed-devices.xml /Do not use it/
Use query component to filter URI collection [Mandatory] ¶
Often, you will encounter requirements where you will need a collection of resources sorted, filtered, or limited based on some specific resource attribute.
For this requirement, do not create new APIs – instead, enable sorting, filtering, and pagination capabilities in resource collection API and pass the input parameters as query parameters. e.g.
http://api.example.com/device-management/managed-devices http://api.example.com/device-management/managed-devices?region=USA http://api.example.com/device-management/managed-devices?region=USA&brand=XYZ http://api.example.com/device-management/managed-devices?region=USA&brand=XYZ&sort=installation-date
Accept and respond with JSON [Recommend] ¶
REST APIs should accept JSON for request payload and also send responses to JSON. JSON is the standard for transferring data. Almost every networked technology can use 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.
There are other ways to transfer data. XML isn’t widely supported by frameworks without transforming the data ourselves to something that can be used, and that’s usually JSON. We can’t manipulate this data as easily on the client-side, especially in browsers. It ends up being a lot of extra work just to do normal data transfer.
Form data is good for sending data, especially if we want to send files. But for text and numbers, we don’t need form data to transfer those since—with most frameworks—we can transfer JSON by just getting the data from it directly on the client side. It’s by far the most straightforward to do so.
To make sure that when our REST API app responds with JSON that clients interpret it as such, we should set Content-Type in the response header to application/json after the request is made. Many server-side app frameworks set the response header automatically. Some HTTP clients look at the Content-Type response header and parse the data according to that format.
The only exception is if we’re trying to send and receive files between the client and server. Then we need to handle file responses and send form data from client to server. But that is a topic for another time.
We should also make sure that our endpoints return JSON as a response. Many server-side frameworks have this as a built-in feature.
Handle errors gracefully and return standard error codes [Mandatory] ¶
To eliminate confusion for API users when an error occurs, we should handle errors gracefully and return HTTP response codes that indicate what kind of error occurred. This gives maintainers of the API enough information to understand the problem that’s occurred. We don’t want errors to bring down our system, so we can leave them unhandled, which means that the API consumer has to handle them.
Common error HTTP status codes include:
- 400 Bad Request – This means that client-side input fails validation.
- 401 Unauthorized – This means the user isn’t 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.).
Use version to control API, such as /v1/, /v2/ [Mandatory] ¶
Just two examples are as below:
https://atlas-a.wbx2.com/admin/api/v1/commerce/orders/search?service-id=Sub147431 https://atlas-a.wbx2.com/admin/api/v2/commerce/orders/search?service-id=Sub147431
Use the HTTP methods accurately [Mandatory] ¶
- Only use HTTP GET to query records.
- Only use HTTP POST to create new records or explain one action (Such as checkout cart, play playlist and so on).
- Only use HTTP PUT to modify records.
- Only use HTTP DELETE to delete records.