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:
/health
response is a200 OK
status code;/version
response is the current version number;/metrics
response is various metrics (e.g. average response time).- Using
/debug
and/status
is 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
GET
to retrieve a representation of a resource; - use
POST
to create new resources and sub-resources; - use
PUT
to update existing resources; - use
PATCH
to update existing resources. It only updates the fields that were supplied, leaving the others alone; - use
DELETE
to delete existing resources.
17. For nested resources, use the relation in a URL
Examples:
GET /shops/2/products
is used to get the list of all products from shop 2;GET /shops/2/products/31
is used to get the details of product 31, which belongs to shop 2;DELETE /shops/2/products/31
is used to remove product 31, which belongs to shop 2;PUT /shops/2/products/31
is used to update the info of product 31. Use PUT on resource-URL only, not the collection;POST /shops
is 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
4xx
HTTP 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.