2 minute read

Introduction

“Application Programming Interface,” or API, refers to a communication channel between various software services[1].

In this post, I am going to talk about

  1. How to design REST API
  2. Some examples from my project, cmpnyinfo.

What is REST?

REST stands for representational state transfer. It is an architectural style that uses stateless client-server communication, meaning no client information is stored between get requests and each request is separate and unconnected[2]. It uses URIs to identify resources and applies HTTP methods for CRUD operations on these resources.

Good Practices

1. Use nouns for endpoint paths, not verbs.

For example, here’s a code from my project

def cmpny(request, cmpnyname):
	basic_info = requests.post("http://localhost:8000/api/basicInfo", data={"cmpnyname":cmpnyname})

The server is sending a http POST request to the url of /api/basicInfo, with the name of the company, (cmpnyname) as POST data

2. Don’t use _

When you desing the urls, don’t design them like api/basic_info. Instead, design them using (-), or capital letters, like api/basic-info or api/basicInfo

3. Use plurals

/employee/:id/ -> /employees/:id/

4. Use proper status codes

Here are some examples of commonly used status codes and their meaning

This way, it is easier to handle exceptions and errors, since you can identify what went wrong. Here’s an example code from my project.

In the API side, I am going to return a 404 NOT FOUND status code when the company is not one of the keys in the name_code dictionary; meaning that our website doesn’t provide any information regarding that company.

from rest_framework import status
@api_view(['POST'])
def get_basic_info(request):
    try:
        cmpnycode = name_code[cmpnyname]
    except KeyError:
        return Response({"error": "Bad Request: cmpnyname not in list"},    
        status=status.HTTP_404_NOT_FOUND)

Here’s a documentation for all the status codes in djangorestframework. Click Here or copy-paste this url

https://www.django-rest-framework.org/api-guide/status-codes/

Then, in the client’s side, I can handle the errors. If I don’t handle the errors like this, every error would return 500 internal server error, making it impossible to identify the problem

#Calling API
basic_info = requests.post(api url, post data)
finstate_sum = requests.post(api url, post data)
graph_data = requests.post(api url, post data)

if basic_info.status_code != 200 or finstate_sum.status_code != 200 orgraph_data.status_code != 200:
    return redirect("error_page")

5. Don’t return plain text

REST APIs should accept JSON for request payload and respond with JSON because it is a standard for transferring data[1].

The response should not only be formatted in JSON, but the content-type in the response header should be set as application/JSON.

I only have to make sure that the response is properly formatted as JSON since the Response module would set the header accordingly.

Import like this

from rest_framework.response import Response

Use like this

    return Response(dictionary_object_here)

6. Security

  1. always use SSL/TLS, with no exceptions[1]
  2. allow authentication via API keys, which should be passed using a custom HTTP header with an expiration date[1]

7. Versioning

Our future APIs should not affect the current users using our API. Different users use different versions and we should seperate them and support them. API versions can be passed through HTTP headers or query/path params.[1] For example, /products/v1/4

8. Documenting

Of course, you have to document what your API provides and how others can use it.

References.

This post contains a lot of quotes from this great post from medium, written by Dr. Milan Milanovic.

1. https://medium.com/@techworldwithmilan/rest-api-design-best-practices-2eb5e749d428

And a quote from this website.

2. https://www.redhat.com/en/topics/api/what-is-a-rest-api

Written by

Roger Kim
GitHub LinkedIn