All good things must come to an api endpoint
Most of the real world application these days work by calling some sort of API to display or process data. API led connectivity has increased the pace of development. It is very similar to putting lego blocks together to build something useful.
With the evolution of API, there are 2 major principles which drives the success
Platform Agnostic: A client should be able to call the API, regardless of how the API is implemented internally. The complexity should be hidden and the contract between the API and the client should define the mechanism of data exchange.
Scalability: An API should be able to scale without independent of client application dependency. The new functionality should be exposed and easily discoverable to the client.
Representational State Transfer API (REST API)
In 2000, Roy Fielding in his dissertation laid the foundation for REST architecture. REST is independent of any underlying protocol and is not necessarily tied to HTTP. However, most common REST implementations use HTTP as the application protocol, and this guide focuses on designing REST APIs for HTTP.
The following outlines designing a REST API for Web Services Architecture.
- [API Endpoint] (#api-endpoint)
- [Authentication] (#authentication)
- [Caching] (#caching)
- [HTTP Methods (verbs)] (#http-verbs)
- [HTTP Response Codes] (#response-codes)
- [Query Parameters] (#query-params)
- [Versioning] (#versioning)
- [Checklist] (#checklist)
API Endpoint
The endpoint should have following features:
- It should be friendly to developer and be explored via browser / rest client address bar
- It should be simple, consistent and intuitive to make adoption easy
- It should provide flexibility for getting the data as required
- It should be concrete names because Cool URIs never change.
Authentication
The endpoint should be always authenticated to prevent from automated attacks. There are multiple ways of authenticating an endpoint.
- Token Based Authorization:
In token based authorization, a token should be given to the given along with the call to the endpoint. The token can have the client signature and the expiry time. The service should first validate the token before doing the processing. If the token configuration is invalid, the service should return the error with response code as
401. - Key Based Authorization:
A key is provided with the request by the client. The key can be unique to each client. This also helps in doing rate-limiting and statistics on the api calls. The key should be validated for the correct client and the expiration before the processing. If invalidated, the service should return the error with response code as
401.
Caching
A parameter should be given with the API definition to set / unset cache. The response for subsequent calls to the same resource should be based on the cache parameter. Default value for the parameter to be set as true. This helps in reducing the response time and also results in better performance.
The table below describes the expiry for cache.
| Expiry | Description |
|---|---|
| x mins | If external or third-party services is used |
| < x mins | If the values fetched doesn’t change frequently |
| (where x is defined as per requirement) |
HTTP Methods (verbs)
The following table explains the usage of HTTP verbs
| HTTP Verb | Description | Example | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| get | For retrieval | /test-service/test-resource/<resourceId> | ||||||||
| post | For persistance |
| ||||||||
| put | For updating {For updating the complete object} | /test-service/test-resource/<resourceID>
| ||||||||
| patch | For partial updating | /test-service/test-resource/<resourceID>
| ||||||||
| delete | For deleting | /test-service/test-resource/<resourceID>
|
HTTP Response Codes
Only standard response codes should be used for the services. The list below defines the allowed status codes
| Response Code | Description |
|---|---|
| 200 | For successful execution of request |
| 201 | For successful creation of the new instance of object as in the request |
| 204 | For successful processing of request. Should be used for delete requests |
| 400 | Bad request. Because of invalid body or headers |
| 401 | Unauthorized. Invalid authorization token |
| 404 | Not Found. Resource not found |
| 500 | Internal Server Error |
Query Parameters
Query parameters can be used for following operations.
| Operation | Description |
|---|---|
| Paging | Required if the data returned by the service is more than 25 records at a time |
| Filtering | Required if data is to be filtered based on arguments. Example: /test-service/test-resource?resourceFilter=test1 |
| Sorting | Required if data is to be sorted in a particular order. Example: /test-service/test-resource?startDate=2016-01-1&endDate=2017-01-01 |
| Searching | Required if data is to be retrieved based on query parameters but supports approximate matching |
Versioning
It’s always advisable to version the APIs. This helps in maintaining code independence and new changes are introduced without breaking current functionality. There are various approaches to version the API.
In URL:
API can be versioned by appending the version number in the resource URL.
Example: /v1.0/ test-serviceIn Header:
Some users prefer version number to be passed in the headers when calling the API
Example: /test-service HEADER: version: 1.0As query parameter: API are also versioned by passing version number in the resource URL but as query parameter.
Example: /test-service?version=1.0
Checklist
This is a personal checklist which I use to review the code for APIs.
HTTP Verbs are used for what they are defined as above. For example: A
POSTrequest should not do a partial update on the resource.URI formatting
Use plurals when returning collections in response.
Example: test-service/test-resources will return all resources related to the account.URI should not have trailing slash at the end of it
Example:URI Structure Allowed /test-service/test-resource/<resourceID>/ wrong /test-service/test-resource/<resourceID> correct URI for every endpoint uses nouns instead of verbs.
Example:URI Structure Allowed get
/test-service/gettestResource/<resourceID>wrong post
/saveDocumentswrong get
/test-service/test-resource/<resourceID>correct post
/documentscorrect
All messages are defined for HTTP response codes associated with the request.
Example: Always define200,400and500responses.Always define
Content-Typeheader to explicit say about the responses.Cache is used if possible
Don’t expose underlying data model in response. Only return what is required or is business need.
### References:
For further reading I would like to suggest an article in Microsoft’s technical documentation. Microsoft API Guidelines