unokay.com

For when things are just not quite right.

How to Design Rest APIs

Thu, 25 Jul 2019 12:10 BST article Dominic Francocci

We may work in a development environment where we are designing applications which need to access information through web services.

As part of the development process, we may be asked to design the interfaces – or APIs – to new web services.

This article gives an approach to designing logical APIs using the REST approach which is suitable for designers who don’t need to understand how the API will be technically implemented.

Background

People have been wanting to create web services that worked across the internet using HTTP.

The problem is that there was no standard for how to do this – early development saw no consistency in the use of HTTP operations (GET, POST, etc.), responses, and structure of URLs.

The REST API approach is an attempt to apply a standard for web services over HTTP.

Thinking about resources

The first step in designing a REST API, is to think about the ‘resources’ that the web service will need access to.

This step is essentially an exercise in data analysis, in which we work out the entities - termed ‘resources’ or ‘endpoints’ in the REST API approach - which the web service will need to access.

Let’s use the example of a bank or building society which needs to design some APIs to provide public access to its information. It may be that it needs to provide:

  • A directory of all its branches
  • The locations of all its ATMs
  • A list of the products that it provides

Tip. When determining the resources that we need to give access to, name each resource as a plural noun.

Using this approach, we might come up with the following resources:

  • branches
  • ATMs
  • products

The way that HTTP gets access to a resource is using a ‘uniform resource locator’, or URL. You will be familiar with a URL, as that’s what you use to access a website.

When your API is implemented, you can think of it as having a base URL - say:

apis.finstitute.co.uk

Then each of the resources can be implemented as a continuation of this URL:

apis.finstitute.co.uk/branches

apis.finstitute.co.uk/ATMs

apis.finstitute.co.uk/products

Web service operations

The web service we’re designing may have many functions or operations, but using the REST approach, we can think of the user of our web service wanting to operate on a resource, or number of resources.

If we imagine a resource to be a database, then the operations that we want our web service to perform can be summarised as:

  • Adding an item to a database
  • Reading items from a database
  • Updating an item on a database, and
  • Deleting an item from a database

This analysis of operations, also known as Create, Read, Update, Delete, or CRUD, can be mapped to existing HTTP methods:

  • Create maps to POST
  • Read maps to GET
  • Update maps to PUT
  • Delete maps to DELETE

Putting the operation and resource together

Putting together the operation and resource, you can create a catalogue of APIs, for example:

GET apis.finstitute.co.uk/ATMs

might get you a list of all the institution’s ATMs.

Assuming each resource has a unique identifier, then this can be added to the URL to specify an individual resource. So, for example:

GET apis.finstitute.co.uk/ATMs/AB461881

could get you the details of the ATM with the unique identifier “AB461881”.

Sub-resources

It could be that the information that you get back from a resource lends itself to specifying a ‘sub-resource’. For example, each ATM may have a list of services available on that ATM. This could be specified using a sub-resource as follows:

GET apis.finstitute.co.uk/ATMs/AB461881/ATMservices

In this example, the user is asking for the list of ATM services for the ATM with the unique identifier “AB461881”.

Filtering

Rather than getting the whole list, a query string can be used to imply a filter, for example:

GET apis.finstitute.co.uk/ATMs?postcode="SA36"

could be used to show all ATMs which are in the SA36 postcode area.

Ordering

A query string could also specify an order, for example:

GET apis.finstitute.co.uk/ATMs?order=postcode

could be used to show all ATMs in postcode order.

Transfer of data

So far, we’ve talked about how to determine the resources that your users need access to, and the operations that they’ll need to perform.

The next element of API design concerns the transfer of data across the API boundary.

This data is known as the ‘payload’, and it’s used for:

  • Specifying the response that the user when they issue a GET
  • Sending data when creating a new record, as part of a POST
  • Or sending data when updating a record, as part of a PUT

The preferred method of specifying the data in the payload is using JSON. This has won the battle over XML, as JSON is generally more consumable by the JavaScript applications using REST APIs.

JSON is a way of specifying a series of key and value pairs in a structured way.

Let’s look at the example again, where we got the details for a specific ATM.

GET apis.finstitute.co.uk/ATMs/AB461881

The sort of response that we get back might include:

  • The unique identifier of the ATM
  • Languages supported by the ATM
  • ATM services offered
  • Location of the ATM

In JSON, this might look like:

[
    {
        "ID": "AB461881",
        "supportedLanguages": [
            "en",
            "cy"
        ],
        "ATMservices": [
            "CashWithdrawal",
            "PINChange",
            "MobilePhoneTopUp",
            "Balance",
            "MiniStatement",
            "CharityDonation"
        ],
        "postcode": "SA36 0ED"
    }   
]                           

Putting together the operations and payload to do transactions

The same data as we get in the GET response could be used to create a record for a new ATM. If we imagine an administrator, who has permission to add new ATMs, they might issue a call to the web service as follows:

POST apis.finstitute.co.uk/ATMs/CZ312516

and in this case, the user would send a payload with the call containing the details of the new ATM:

[
    {
        "ID": "CZ312516",
        "supportedLanguages": [
            "en"
        ],
        "ATMservices": [
            "CashWithdrawal",
            "PINChange",
            "MobilePhoneTopUp",
            "Balance",
            "CharityDonation"
        ],
        "postcode": "SN12 9DN"
    }   
]                           

Let’s say the administrator made a mistake with the postcode, and needs to update it. Then they could issue a PUTrequest:

PUT apis.finstitute.co.uk/ATMs/CZ312516

this time just sending the data that needs to be updated:

[
    {
        "postcode": "SN12 9DM"
    }   
]                           

Status responses

The REST API approach also standardises the way that the web service responds to say whether the call has been successful, or there was an error.

HTTP has a standard set of status codes, and subset of these can be used in your API design. For example:

  • 200 - OK. Can be used for a successful response
  • 404 - Not found. Say you specify a unique identifier, and it doesn’t exist
  • 500 - Error. Some sort of technical error has occurred. This could be accompanied by an error message, or messages, in the payload.

Conclusion

So in this article, we’ve looked at:

  • How to think about the resources you access to, and how to specify these in a URL
  • Designing the operations on the web service, using standard HTTP methods
  • Structuring the data in the payload using JSON
  • Using standard HTTP status codes for successful and failure responses

Here are some useful links and references which I found when putting this article together.

How to Connect to an API with JavaScript - A practical example of how to use a set of APIs published by Studio Ghibli, by web developer Tania Rascia. Her site is a great resource in general for demystifying some of the concepts in web development

ATM API Specification - v2.2.0 - The actual Open Banking API spec for ATMs, in case you’re interested

JSON.org - The reference site for JSON

comments powered by Disqus