Best Practices for API Design


With API Management getting momentum in mainstream business segments, it is important for Organizations to adopt the right design practices upfront to ensure effective implementation of APIs. Let’s have a look at some of the best practices for API Design

  • Capabilities-Resources Mapping
  • Root URL (Entry point for API Consumers)
  • Endpoint standard
  • Effective use of Http verbs
  • Deciding content representation
  • Explicit use of return Media type
  • Specifying partial data for response
  • Rate Limiting
  • Versioning APIs
  • Using Http status codes
  • Schemas for APIs

Capabilities-Resources Mapping
Resources are basically the capabilities Organization (API Provider) wants to expose for collaborative offerings. So API Provider should do proper analysis and derive the logical mapping between capabilities and resources. For example, Product related capabilities-functionalities should be exposed as products resource; similarly Customer related capabilities should be exposed as customers resource. Capabilities-Resources mapping is an important exercise to ensure that resources unambiguously communicate what data/functionalities are being exposed by Organization and this certainly needs governance at respective domain- functional level to avoid duplicate/conflicting resources.

Root URL (Entry point for API Consumers)
API Provider must define a single entry point for APIs it is exposing to external/internal app developer communities. Having a single entry URL or root URL is important from the perspective that API Consumers gets the holistic view (starting point) of various categories of APIs offered by API Provider and consumers can easily browse through these capabilities. Not having the root URL may impact the visibility into various APIs being offered, consumers will only know the URLs of capabilities they are consuming and it will be difficult for them to locate new capabilities delivered over the period of time.

Accessing the API root URL should list some of the useful information such as

  • List of all the available collections
  • List of all the available resources
  • Brief description about API (functionality or data it offers), available versions and status
  • Reference to API documentation for detailed information

Two commonly used styles for API root URL are:

  • To place APIs under the root of the domain (https://abc.com/api/)
  • To have APIs in its own dedicated api domain (https://api.abc.com/)

Endpoint standard
Endpoint is nothing but the URL that represents a collection of resources or a particular resource itself. There are couple of important guidelines API Provider should follow for defining appropriate endpoints.

First guideline is to use noun for endpoint and avoid using verbs to the possible extent. For example, use /products as against /retrieveProduct, /updateProduct etc. Http verbs will anyway be used to specify actions on a resource, use of explicit verb in endpoint defeats the purpose. Use of noun keeps the approach simple and communicates logical domain-functional area from which data/functionalities are being offered. For example, /products signifies functionalities related to product functional area.

Second guideline is to keep endpoint as plural noun and not singular noun. For example, products and not product. This gives space for logically including more functionalities-data under the bigger umbrella of plural noun. For example, getting list of all products, all product types, availability of products and so on.

Effective use of Http verbs
After identifying the resources, API Provider should identify appropriate actions that are applicable to each resource and collection; actions like create, update, retrieve etc. Provider should leverage Http methods to specify actions on a resource. For example, below are some examples of actions on orders resource

GET /orders –For retrieving the list of orders placed (retrieving collection)
GET /orders/2345 – For retrieving a particular order ‘2345’ (retrieving a resource)
PUT /orders/2345 – For updating the order ‘2345’
POST /orders – For creating a new order
DELETE /orders/2345 – For deleting the existing order ‘2345’

The key point to note here is, not all Http actions will be applicable to every resource. For example, on some resources API Provider may only allow GET actions. Additionally, if same capabilities are exposed to both external and internal apps; the actions these apps are allowed to specify may differ based on their role. So resources and role based permissible actions should be clearly defined by the API Provider.

Deciding content representation
JSON and XML are the 2 most common data exchange formats in REST architecture. As a general guideline, JSON should be preferred as resource representation format over XML. JSON is lightweight and easy to parse as compared to nested XML structure. Web apps and mobile apps will have better performance with JSON format. Having said that, there will be use cases where XML may be preferred over JSON.

Explicit use of return Media type
API Provider can support various data interchange formats for the same capability/API. This gives flexibility to various API Consumers to specify media type (specific format) of their choice to be returned in the response while invoking the RESTful API. While API Consumer can always include the media type in the URL explicitly by appending appropriate extension .json or .xml to the URL (making return format explicit), it may be good practice to leverage Http Accept header field instead to specify return media type.

Specifying partial data for response
Sometimes consumers of APIs may not be interested in complete representation of a resource and would be interested in fetching only fields/data which is relevant to their application/processing.

In such scenarios, API Consumers should use fields query parameter in the request to specify what response fields it is interested in.

The request from API Consumer may look like below –

GET /orders?fields=ordernumber,orderdate,status

This will fetch only limited data – order number, order date and status

Supporting such requirement is useful from 2 perspectives

  • Network bandwidth: Partial response will reduce unnecessary network traffic.
  • Performance: Consumer application need not deal with unnecessary data and parsing of it, thus using system resources effectively.

Rate Limiting
Limiting the rate of incoming requests is an important aspect for API Provider when exposing capabilities to numerous third parties and external partners. Not limiting the rate of incoming requests may pose serious risk of bringing down the complete API infrastructure. Additionally, rate limiting is vital from the perspective of preventing threats/abuse and ensuring SLAs are followed.

API Provider should apply rate limits on an individual resource or collection or across all resources (combined) for a given API Consumer depending on the agreement. Rate limits are set against time parameter such as hourly limit, daily limit. However, it is completely up to API Provider how they want to apply limits.

Rate limits will usually be part of standard subscription plans API Provider offers to consumers – Platinum, Gold etc. Depending on the API consumption requirements, consumer can subscribe for the appropriate plan.

To take a simple example, API Provider may allow 1000 POST requests on orders resource per hour for a particular consumer who has subscribed for Gold plan. It may allow 2000 POST request on orders resource for another consumer who has subscribed for Platinum plan.

There are certain best practices to follow for handling rate limits –

  • API Provider should handle the rate limits in an efficient way by keeping consumer informed about its limit upfront, before consumer actually reaches the limit. So this essentially involves API Provider sending well-defined rate limit response header back to API Consumer for each call consumer is making; Http response header should include details such as
    1. Request limit (per hour or per min or per day) (Ex. X-RateLimit-Limit Http response header field)
    2. The number of requests reaming in the current time window (Ex. X-RateLimit-Remaining  Http response header field)
    3. The remaining time window in seconds before the limit resets (Ex. X-RateLimit-Reset Http response header field)
  • If the limit is reached, API Provider should use Http status code ‘429’ for indicating that the consumer has sent too many requests to provider in the current time window. Along with above status code, API Provider can use standard http response header field ‘Retry-After’ to indicate to API Consumer as to when it can re-send the request.

Versioning APIs
Similar to any other Enterprise services, APIs also needs versioning. API Provider should version APIs upfront and communicate the mechanism to request specific version of API to consumers. While the attempt is to shield consumers from interface changes to the possible extent, changes to core capabilities and associated attributes are inevitable in certain scenarios (for example, adding new features, adding fields due to regulatory/compliance requirement etc). APIs exposing these capabilities also need to change/upgrade to offer new functionality or data to consumers.

While new and some existing consumers might use new version of APIs, some consumers may need more time to move to a new version of APIs as per their convenience. Versioning APIs offers flexible/smooth migration path for existing consumers, API Provider can continue to support old version of APIs for some duration after releasing new version of APIs.

Not including version upfront will impact consumer base in case of changes to APIs which are not backward compatible.

There are 2 prevalent ways to specify API version

Header: API version in header. Standard Http Accept header filed can be used to invoke a specific version of API.
For example –
Accept: application/vnd.abc.api+json;version=2
Alternatively, a custom Http header field can be used to indicate version of API

URL: API version in URL path segment.
For example –
https://api.lmn.com/v1/accounts
https://api.abc.com/v2/products

The better practice is to include version in the URL making it explicit. Additionally, sometimes a combination of both the approach (URL + Header) can be implemented to specify major and minor version. Major version in the URL and minor version in the Header. As long as major version of API is same, all upgrade to a minor versions should be backward compatible. The combination approach also works better, it does not clutter URL with too many minor versions for a particular API and keeps it simple.

Using Http status codes
API Provider should use Http status codes efficiently to communicate appropriate response status back to API Consumer. Http status codes anyway covers all possible categories of response (data issues, server error, success).

2xx range is reserved to indicate successful execution of client request
4xx range is reserved to indicate issues with client request.
5xx range is reserved to indicate server side issues.

API Provider can use these standard http codes. For example –

400 – Bad request: To indicate missing mandatory fields or invalid fields in the request.
401 – Unauthorized: To indicate no or invalid API key.
404 – Not found: To indicate that the resource or collection requested by consumer is not found or does not exist.
429 – Too many requests: To indicate that the rate limit is exhausted for the current time window.
500 – Internal server error: To indicate that the server has encountered an issue.
200 – Ok: To indicate that the server has successfully processed the consumer request.

In case of error, API Provider should return meaningful JSON representation of error along with 4xx and 5xx status codes, providing more details about an issue.

For example, the more specific status/error block returned by API Provider to consumer can be as simple as below (in addition to 400 http status code) –

{
“status” : {
“code” : 4001,
“description” : “field 2 and field 7 are mandatory”
}
}

As far as business-functional exceptions are concerned, API Provider should return them under the umbrella of Http 200 status code as the request is anyway executed successfully. For example, the specific status block in the body can be as simple as below –

{
“status” : {
“code” : 2001,
“description” : “item not available in inventory”
}
}

API Provider should clearly publish the status/error block structure and the list of custom status codes (functional and technical) it would return to consumer; these details should be part of API interface specification document produced by API Provider. This will enable consumer to take more appropriate actions based on custom status codes instead of high level Http status code which might be giving generic message.

Schemas for APIs
There are certain API schema related aspects that should be taken care of

Schemas (request-response) should be aligned with resources:
The idea should be to define schemas aligned with resources as against associated actions. There should be single schema per resource and not separate schemas aligning with various actions associated with that particular resource. For example, single schema for orders resource and not separate schemas for create order, delete order, update order or retrieve order.

Schemas (request-response) should be derived from API resource data model:
Data model for resources used in API world should be derived from Enterprise canonical data model. And then the request-response messages for API should be derived from resource data model. However, wherever required, semantic and attributes needs to be aligned with vocabulary commonly used and understood in B2B-partner domain.

Separation of concern between API Schema and underlying implementation:
API schemas should be holistic and should not carry any flavor of underlying implementation details such as proprietary field names used in application, version of capability in underlying application, proprietary function names and so on.

Please refer to ‘Publication Schedule’ page for upcoming articles.

2 thoughts on “Best Practices for API Design

  • Srinivasa Moorte M

    on

    Hi Pravin,

    Came across the best API practices article, the published one is simply superb with self explanatory for all the IT audience.

    My thought on the partial data for response – good to bring the path param instead of query parameter.

    Thanks,
    Srini

Leave a Reply