Just released: Developer preview of Microsoft Teams bot integration for Now Assistant. Try with your Teams ×

How to design an API

Components such as Cards, often rely on well implemented API's in order to deliver required business logic and avoid bugs. In short, an API is a part of the server that receives and sends responses for data. For example, if you have a Card that displays employee details, you might have an API that queries the server for information, such as the name or id of an employee. This information would then be inserted in your Card's template and the final result would be a Card that can dynamically display information for any employee in the database.

Whilst there are many approaches on how to design an API, we believe that the following list of recommendations capture some of the industry's best practices. The list is not extensive and recommendations can change over time to accommodate the rapid change of technology.

A. General

Use REST

The API should be based on REST principles and return a JSON object. In short, REST is stateless meaning that every request contains all the information required to complete the data transaction. It implements a range of methods (GET, POST, PUT, PATCH, DELETE) that can be used to specify the desired operation e.g. GET a user or DELETE a user.

B. API endpoints

Use GET for read operations

Only use GET method to 'read' the state e.g. get all news articles from a news feed. Therefore, if you want to perform a 'write' operation e.g. create a new article, you should use POST.

Use POST to create data

POST requests should be used to create completely new information.

Use PUT and PATCH to update existing data

If you already have data e.g. a news article on the following path /news/1:

{
    "id": 1,
    "name": "A great article",
    "description": "A description for a great article"
}

Design the PUT request to replace the data fully. For example the following request:
PUT { "id": 1, "name": "A better article", "Description": "A better description" }

Should replace all fields in the article whilst keeping its id.

In contrast, PATCH method should be used to update parts of the data, therefore the following request:
PUT { "name": "A better article" }

Should only update the name of the article without replacing the whole object.

Use DELETE to remove data

As the name of the method suggests it should be used for deletion. For example, to delete an article you could design the API, so that sending a request like this: DELETE /news/1 would delete the article that has an id of 1.

Word the API endpoints well

Use nouns not verbs, when structuring an API endpoint e.g.
Use: /news
Not: /getAllNews/
And prefer plural notation instead of singular:
Use: /employees/
Not: /employee/

Use sub-resources to indicate a relation

If a resource belongs to a group, you should indicate it by using sub-resources similarly to how computers notate folder directories. For example: /employees/1/reports/, could get all the reports by an employee 1.

C. Dates

All dates should be strings in the UTC format. JSON objects do not support Date data type, therefore all dates should be formatted in accordance to the ISO 8601 standard.

D. Returning data

Prefer arrays for collections

If a response contains a collection of items e.g. a list of articles in a news feed, they should be returned as an array e.g. ["article":{..}, "article":{..}, ..]. JSON supports array data structure, which allows for easier and safer data handling by using native Javascript methods.

Sort time-based data

If a response contains collection with time related data e.g. a news article in news feed, the data should be sorted in a descending order (newest items first).

Use HTTP status codes

When sending the response back to the client, ensure that an appropriate HTTP response status code is set to indicate the state of the transaction e.g. 200 (Success) or 500 (Internal server error). A list of HTTP status codes can be found here.

E. Query parameters

Implement ranges for time-based data

It should be possible to retrieve information for a specific time range e.g
/Slack2/GroupFeed?startDate=20170501&endDate=20170601

Split data into pages

If a collection contains a large number of items (more than 50), it should be possible to split the data into "pages" and request a specific page. The bellow example would return results 21-40:
/Slack2/GroupFeed?page=2&pageSize=20

Add search queries

If the server provides the ability to search or filter results it should be possible to provide a search term e.g.
/Slack2/GroupFeed?query=searchTerm

Allow for queries to stack

It should be possible to stack different query parameters e.g.
/Slack2/GroupFeed?startDate=20170501&endDate=20170601&page=2&pageSize=20&query=searchTerm

F. Use OAuth 2.0 for authorization

OAuth 2.0 as defined in RFC6749 is the common standard for securely sharing API's between applications. In short, it works by asking the users to authorize the application that is trying to access the API. If permission is granted the application receives a key that can then be used to retrieve permission-scoped data from the API. The full authorization flow is defined here.

OAuth 2.0 has been widely adopted over the recent years. For example, Slack uses OAuth 2.0 to allow users logging onto other applications using their Slack account. This simplifies the authentication process for the user since the same account can be reused for authentication with the application and Slack.