Tips to Improve Your API Design Skills
Everyone has probably seen a terrible API that eventually turned into a guessing game.
In this article, we will talk about the best practices of REST API development.
Introduction
Any API’s design should follow the Resource-Oriented Design, which means that it should contain:
- a resource, which is a piece of data, e.g., a user;
- a collection, which is a group of resources, e.g., a list of users;
- an URL, which is a resource’s or collection’s location identification.
Tips list
1. Use kebab-case for URLs
If you need to retrieve a list of users, use /system-orders instead of /systemOrders or /system_orders.
2. Use camelCase for parameters
If you want to retrieve some data from a specific list, use /system-orders/{orderId} instead of /system-orders/{order_id} or /system-orders/{OrderId}.
3. Use plural names to identify a collection
If you want to retrieve all collection users, use GET /users instead of GET /user or GET /User.
4. Start an URL with a collection and end it with an identifier
Use GET /shops/:shopId/ or GET /category/:categoryId instead of GET /shops/:shopId/category/:categoryId/price in case you need to keep the concept singular and consistent.
5. Do not use verbs for a resource URL
To describe an operation, use proper HTTP methods instead of verbs: PUT /user/{userId} instead of POST /updateuser/{userId} or GET /getusers.
6. Use verbs for a non-resource URL
If you want to send a notification to a user, use POST /alerts/245743/resend. Remember that resend is not a CRUD operation. It’s a considered function that does a specific job in the system instead.
7. Use camelCase for JSON property
If you build a system where JSON is a request/response body, use camelCase for property names. Thus, use
{
userName: "Mohammad Faisal"
userId: "1"
}
instead of
{
user_name: "Mohammad Faisal"
user_id: "1"
}
8. Condition
/health and /version and /metrics API endpoints implementation is a must for RESTful HTTP services. Those provide the following data:
/healthresponse is a200 OKstatus code;/versionresponse is the current version number;/metricsresponse is various metrics (e.g. average response time).- Using
/debugand/statusis also recommended.
9. Use REST API design tools
There are numerous reasonable solutions for that, e.g., API Blueprint or Swagger.
These tools help provide a great user experience for your API customers.
10. Use simple ordinal numbers as versions
And always put it to the highest level—for instance, http://api.domain.com/v1/shops/3/products, where v1 is the version number.
11. Add the total number of resources in a response
This feature can be called total. Thus, use
{
users: [
...
] offset: 0,
total: 34
}
instead of
{
users: [
...
], offset: 0
}
12. Use limit and offset parameters
Use the parameters in GET operations:
GET /shops?offset=5&limit=5
That is necessary due to the need for pagination on the front end.
13. Use fields query parameter
Returned data amount is also important. Add the parameter to expose the required fields from the API only.
Example:
Return the name, address, and contacts only:
GET /shops?fields=id,name,address,contacts
This may also help reduce the response size.
14. Do not pass authentication tokens in URL
Often the authentication token would be logged with the logged URLs, which is unnecessary.
Thus, use the header:
Authorization: Bearer xxxxxx, Extra yyyyy,
instead of using just this:
GET /shops/123?token=some_kind_of_authenticaiton_token.
Remember that tokens should be short-lived.
15. Verify the Content-Type
For instance, if you accept application/x-www-form-urlencoded, an attacker is free to create a form and trigger a simple POST request. Instead, you can use the default content-type: application/json.
16. Use HTTP methods for CRUD functions
HTTP methods aim to explain CRUD functionality:
- use
GETto retrieve a representation of a resource; - use
POSTto create new resources and sub-resources; - use
PUTto update existing resources; - use
PATCHto update existing resources. It only updates the fields that were supplied, leaving the others alone; - use
DELETEto delete existing resources.
17. For nested resources, use the relation in a URL
Examples:
GET /shops/2/productsis used to get the list of all products from shop 2;GET /shops/2/products/31is used to get the details of product 31, which belongs to shop 2;DELETE /shops/2/products/31is used to remove product 31, which belongs to shop 2;PUT /shops/2/products/31is used to update the info of product 31. Use PUT on resource-URL only, not the collection;POST /shopsis used to create a new shop and return the details of the new shop created. Use POST on collection-URLs.
18. Cross-Origin Resource Sharing (CORS)
Use CORS for all APIs that are publicly accessible. Consider supporting CORS-allowed “*” source and enforcing authorization via OAuth tokens.
Do not combine user credentials with origin validation.
19. Security
Use HTTPS (TLS-encrypted) protocol for all end-points, resources, and services. In addition to that, make HTTPS obligatory for all callback URLs, push notifications, and webhooks.
20. Errors
Service errors occur when a client makes an invalid request to a service or passes invalid data to a service. After those, the server rejects the requests, which results in a failure.
Try resolving those by:
- returning
4xxHTTP error codes when rejecting a client request due to one or more Service Errors, - processing all attributes and then returning multiple validation problems in a single response.
The Golden Rules
These rules are to help you make the right decisions while developing REST API:
- Do not use excessive nesting.
- Simple is better than complex.
- Strings are better than numbers.
- Consistency is better than customization.