I want to share what I've learned to be nice to the developer when designing the new API with the best practices.
1. Naming resource
My question was, Should this be singular or plural? I guess it depends on a specific resource. Mostly, we use the noun plural form of the name of a resource.
For example
# To create a customer
POST /customers
GET /customers # To get all customers
# To update the specified customer (#id)
PUT /customers/:id
You will notice that the naming resource is plural.
However, if you need to deal with the relation between resources, let's assume the customer has many orders, so you want to know all the customer's orders.
GET /customers/:id/orders
Or
# Allowing the customer to make a new order.
POST /customers/:id/orders
Unless the resource is singular, then it would be something like
# To get a user profile
GET /profile
GET /me
Here's my suggestion below
Try not to use an abbreviation term like
POST /cust
(customers
). It's hard to forecast. Bear in mind that you should build API to be predictable.Try not to use a verb in URI like
POST /create-customers
because CRUD (Create) helps us create a new record, so it's pretty redundant.
2. Using version
Your API can allow versioning even though you think your API framework is tiny. Often, you don't have a choice because you need to change your response structure and rename the attribute, but versioning lets you escape this situation.
There are a variety of ways to apply to the version.
2.1) Place it in the URI prefix.
Ex:
/v2/customers
But
try not to use URI postfix to say the version like
/customers/api_version2
2.2) Place it in the Accept
Header with a custom.
Ex:
application/vnd.myapp+json;version=2
2.3) Place it in Query.
Ex:
/customers?api_version=2
If you add a new attribute, you don't need to build a new version of the API because you don't interrupt the business transition.
For example
GET /v1/customers/cust_12345
{
"id": "cust_12345",
"name": "jone doe"
"email" "jone@mail" # Add a new `email` attribute. You can add it directly.
}
On the order hand, If you wish to rename the attribute from name
to fullname
you need to re-thinking what happenห if the person who uses your API is attempting to use the name
attribute's gone.
Then you may decide to build a new version of /v2
, or you add more attributes like fullname
into /v1
3. Separation Concern
It's a distinction between concerns that looks like in the Object-Oriented.
Let's assume you have the resource name User
, which has several columns, such as email
, password
, address
, mobile_number
You want the API to be able to change your password.
If it looks simple and generic to modify a user like the below one.
PATCH /v1/users/:id
{
email: "john@mail",
password: "abcdefg",
confirmation_passowrd: "abcdefg"
}
After looking at the name of this endpoint, I should not recognize it immediately. And in my view, the number of comprehensive users would change.
This may not be convenient for the person who uses this API so that the API can be divided into two APIs;
One for modifying the generic user details.
POST /v1/users/:id
{
address: "new address",
mobile_number: "new mobile number"
}
One for just changing a password.
POST /v1/users/:id/password
{
password: "abcdefg",
confirmation_passowrd: "abcdefg"
}
4. Time format
It should return times in UTC formatted to ISO8601.
ISO8601 format: YYYY-MM-DDTHH:MM:SSZ
For example
{
"created_at": "2021-01-21T15:23:38Z"
}
Typically, I describe the name of the field base for the category between Date and DateTime that look like below;
_on
suffixes for Date
_at
suffixes for DateTime
5. camelCase or snake_case
It depends on your preference, but I feel that snake_case
is easier to read than camelCase
for attribute names.
6. Errors
It's similar when you have an error on the website that displays an error with a thorough explanation.
As far as the API is concerned, it should also include a meaningful human-readable error message and support a unique error class for each type of error to the client.
For example
The status code for HTTP should be 404
{
type: "account_not_found",
message: "The account is not existing"
}
7. Using HTTP verbs and status codes correctly
HTTP offers a wonderful mechanism to inform the API to consumers whether the request is successful or not.
You may also refer to a lof of HTTP status code to apply to the API.
HTTP verbs
-
GET
to retrieve a resource. -
POST
to create a resource (Sometime, you might use it without creating any record) -
PATCH
to modify the partial resource -
PUT
to replace a resource or collect of a resource. -
DELETE
to delete a resource.
HTTP status codes
-
2xx Success
Everything's going smoothly. -
200 OK
It's a successful response that everything goes well. -
201 Created
Most of the time, it's used toPOST
that results in a creation. -
204 No content
It is also used forDELETE
, which resource has been removed and the returned body is null. -
400 Bad Request
The request is invalid/unacceptable, or an appropriate parameter is lacking. -
401 Unauthorized
Mostly, It's used for invalid authentication. 404 NotFound
429 Too many requests
-
5xx
Something went wrong with us.
8. Pagination
You might fail to worry about how large the data is since it returns a lot of records at once, so you should have a way to limit the number of records per request.
GET /v1/customers?page=2&per_page=30
9. Rate limiting
You might be surprised if someone attempts to spam your API unreasonably. So you may start implementing a rate-limit early.
You may use Redis with EXPIRE feature to limit the specified person's request.
10. Good Documentation
You should have good API documentation that should be reliable and simple for the developer to understand. I think all developers (including me) enjoy good examples; not only do they have code samples like curl --
but they can cover all test cases like Postman Examples or Swagger Examples.
See Postman Examples and Swagger Examples for more details.
Top comments (0)