DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Secure API Design With OpenAPI Specification
  • From APIs to Actions: Rethinking Back-End Design for Agents
  • The Bill You Didn't See Coming
  • When Events Move Faster Than Your Database: A Resilient Design Pattern

Trending

  • Detecting Advanced Persistent Threats Using Behavioral Analytics and Log Correlation
  • Navigating the Complexities of AI-Driven Integration in Multi-Cloud Environments: A Veteran’s Insights
  • Modernization Is Not Migration
  • Setting Up a Data Catalog With Azure Purview and Collibra: What Three Attempts Taught Me
  1. DZone
  2. Data Engineering
  3. Databases
  4. API Design Principle

API Design Principle

In this article, I will only talk about WEB API in the microservice scenario, which is usually implemented by RESTFUL, RPC, etc.

By 
Eason YIN user avatar
Eason YIN
·
Oct. 12, 20 · Opinion
Likes (3)
Comment
Save
Tweet
Share
12.7K Views

Join the DZone community and get the full member experience.

Join For Free

Although API has more various definitions in a different scenario, in this blog, I will only talk about WEB API in micro-service scenario, which is usually implemented by RESTFUL, RPC, etc. API represents a capability of an instance of micro-service, hence the format of transition (like XML, JSON) has little impact in the design APIs

However, API design is crucial in the design of micro-service representing the method of communication between services and impacts the integration of services. Generally, a good API design should meet below 2 requirement

  • Platform Independency. Each client can consume API without knowing how it is implemented. API should follow standard protocol and message format to provide service. Transition protocol and format should NOT invade the business logic, which means system should be able to support different transition protocol and message format. 
  • System Reliability. In the circumstance that API has been delivered and non-API version changes, API should be responsible to API contract,  no any changes which might cause destructive data. When API needs tremendous update, the version update should reserve timeframe for older version. 

In practice, API design is not an easy effort. Meanwhile, it is also difficult to evaluate the design. From system design and consumer perspective,  here we list some simple design principle.  

Use a Proven RESTful API 

RESTful style API design has some nature advantage, for example, by using HTTP to reduce the coupling of clients and has very good openness. So more and more developers use RESTful style API. But RESTful is only an design idea rather than a principle due to lacking of constraints. 

Hence, when we design RESTful API, we should refer to maturity model of RESTful. 

Maturity Grade Explanation Example
Level 0 Define a root API to finish all actions POST /?action=changePassword
Level 1 Create isolated resource address and API scope POST /user?action=update
Level 2 Use HTTP verb to define the action for resource GET /users/001
Level 3 Use API HATEOAS (Hypermedia as the Engine of Application State) to provide information dynamically

"links": {

            "deposit": "/accounts/12345/deposit",

            "withdraw": "/accounts/12345/withdraw",

            "transfer": "/accounts/12345/transfer",

            "close": "/accounts/12345/close"

  }

According to scenario, we should choose suitable maturity grade of model. 

Avoid Simple Encapsulation 

API should be encapsulated for business, we should avoid to simply encapsulated API to became API for database throughout. For example, if an order status has been updated as "paid", we should provide the API like POST /orders/1/pay, not the API PATH /ORDERS/1 and update the order by param. 

Because order payment has its detail business logic, and might involve large number of complicate actions, so using simple update method might leak the business logic out of system, and external system also needs to know internal "order status" field.

More importantly, it also destroys encapsulation of business logic and also impacts other functionality requirement such as privilege control, logs or notification. 

 Separation Concern

A good API should be neither more nor less. For example, user password change and user info change look very similar. However if we design a generic API /users/1/update URI, and define an "User" object

JSON
 




xxxxxxxxxx
1


 
1
{
2
   "username": "xxxx"
3
   "password": "xxxx"
4
}



When we use this object to change the user information, password is not necessary. But in action of changing password, one "password" filed is not enough, and "confirmPassword" might also be needed. 

Then the API becomes 

JSON
 




xxxxxxxxxx
1


 
1
{
2
   "username": "xxxx"
3
   "password": "xxxxx"
4
   "confirmPassword":  "xxxxx"
5
}



Such reuse will confuse the maintenance developers and is also not friendly to consumers. A reasonable design of API should break it into 2 separate API:

JSON
 




xxxxxxxxxx
1
10


 
1
//POST /users/{userId}/password
2
{
3
   "password": "xxxxx"
4
   "confirmPassword":  "xxxxx"
5
}
6
//PATCH /users/{userId}
7
{
8
   "username": "xxxx"
9
   "other info":  "xxxxx"
10
}



Accordingly, 2 DTO are created to handle them. It also shows separation of concern idea in Object-oriented.

MECE Principle 

API should follow MECE principle (mutually exclusive and collective exhaustive", APIs should not be override for each other. Taking order and order item 2 resources as examples, If API: PUT orders/1/order-item/1 is designed to modify the order item, then API: PUT /orders/1 should not be capable to modify one order-item. 

The benefit of the design is there are no overlay API which might cause complex on maintenance and understanding. But how to follow MECE principle?

The simple way is to design a table listing APIs and business capability. 

Resource URI design coming from Domain Driven Design is very simple, aggregation root is root URL and entity is second URI. And Each aggregation root should have no any relation, responsibility for entity and aggregation root should also be clear. 

Version

A service serving outside probably is changing all the time. Any business change might also change API parameters, response structure  and relations among resources. Generally,  new fields will not impact legacy client running. But if there are some destructive modification, then new version will be used to lead data to new resource address. 

Version information could be transferred in below ways

  • URI prefix
  • Header
  • Query

URI prefix is most suggested way, like /v1/users/ means the API fetching users list in version 1. 

Common anti-pattern way is to use URI postfix to tell version like /users/1/updatev2. The drawback of this way is version is embedded into business logic, and cause inconvenient management of router. 

Using Header and Using Query are similar. The difference is in MVC framework, using URI prefix is easier to be implemented by routing. But addition implementation of interceptor is needed to support Header or Query solution. 

Naming

Naming in API design involves some aspects such as, URI, request parameter, response data, etc. Usually it is most difficult and most important to have a global consistent naming mechanism. 

Secondly,  naming needs cover below consideration:

  • Try best to keep consistence of domain naming, for example aggregate root, entity, event, etc. 
  • Noun plurals should be used in URI in RESTful design
  • Try not to use abbreviation like calling user to usr. 
  • Try to use character which needn't encoding 

If multiple words existing in URI, "-" could be used to separate them like /orders/1/order-items

Security

Security is always most critical in any software design. From API design perspective, internal API is slight different with external API exposed to outside. 

As an internal system, what to consider more should be whether API is robust enough. It should have enough ability to verify the receiving data and provide corresponding error message rather than receiving any data. 

However there are more challenge for external APIs.

  • Wrong call
  • Interface abuse
  • Illegal visit caused by browsers' security breach

Therefore,  measures should be considered in API design. To handle those wrong call, API should respond error message before business flow; To handle interface abuse, some throttle limitation plans are needed; To handle browsers' security breach, some security related header should be added in response like: X-XSS-Protection, Content-Security-Policy, etc. 

Reviewing List of API Design

  • Whether URI naming is consistent via aggregate root and entity. 
  • Whether URI naming uses noun plural and dash
  • Whether URI naming uses lower case word
  • Whether URI expose unnecessary information like /cgi-bin
  • Whether URI rule is consistent
  • Whether the capabilities resources provide are independent. 
  • Whether there are characters which need encoding
  •  Whether the parameters in request and response are no more and no less
  • Whether IDs in resources are passed by PATH
  • Whether authentication and authorization information is exposed in Query parameters
  • Whether parameters contain rare abbreviation
  • Whether field naming is consistent between request and response
  • Whether there is meaningless object like {" data":{ }}
  • Whether data structure agreed is broken when exception
  • Whether status codes are suitable
  • Whether type of media is suitable
  • Whether singular and plural is consistent with data content
  • Whether cache data are in the response header
  • Whether there is version management
  • Whether version information exists as URI prefix
  • Whether API provides expiration time
  • Whether API index is provided
  • Whether authentication and authorization are executed
  • Whether HTTPS is used
  • Whether illegal parameters are verified
  • Whether security headers are added
  • Whether there is throttling limitation strategy
  • Whether CORS is supported
  • Whether ISO 8601 standard is applied in date format
  • Whether there is unauthorized access
API Design Database

Opinions expressed by DZone contributors are their own.

Related

  • Secure API Design With OpenAPI Specification
  • From APIs to Actions: Rethinking Back-End Design for Agents
  • The Bill You Didn't See Coming
  • When Events Move Faster Than Your Database: A Resilient Design Pattern

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook