/
RESTful API - Best Practices v1

RESTful API - Best Practices v1

Introduction

This is the initial draft of recommended best practices for API development and consumption at Columbia.

Overview

The central feature of REST architecture is the emphasis on a uniform interface between components

REST is defined by four interface constraints:

  • Identification of resources;

  • Manipulation of resources through representations;

  • Self-descriptive messages; and,

  • Hypermedia as the engine of application state

RESTful Application URL and methods

The Key principle of REST involves separating API into logical resources. These resources are manipulated using HTTP requests where the method (GET,POST,PUT,PATCH,DELETE) has specific meaning.

REST API resources are plural nouns (not verbs!) from the consumer perspective.

Versioning

Always version the API. There are two widely accepted approaches to versioning

  1. Version as part of URL

  2. Version as part of header

We at Columbia choose version to be part of URL:

Version should be kept to the right of the app name. We choose to prefix 'v' as part of version and use only the ordinal numbers, like “v1”, “v2”, etc.

API Pattern

Use the following example patterns as a guide. Implementing every HTTP method and complex search query parameters is not required but should follow these patterns when used.

Note that the above definitions have use the following query parameter names:

  • filter

  • sort

  • fields

For more complete details, see the JSON API Architecture Pattern.

API Pattern Example

Basic Operation APIs are shown with examples (for the directory app, version 1):

Application Metadata Resources (DRAFT)

The following metadata and special resources should be available for every application:

Enterprise Metadata Resources (DRAFT)

A top-level Columbia University enterprise metadata directory will contain the list of available types (schemas) and resource types (item, collection, etc.) that are used by the various applications:

SSL Everywhere

Always use SSL, no exceptions. This is enforced at the f5 load balancer (https://<domain-app>.api.columbia.edu) which terminates SSL sessions.

Documentation

Always provide good API documentation. The document should be easy to find and publicly accessible to the consumers. Documentation should consist of:

  • OpenAPI Specification (OAS) 3.0 definition that documents the API in general, the specific resources and the methods that operate on them, Meanings of OAuth 2.0 scopes, etc.

  • An example walkthrough of using the API, perhaps using a Jupyter Notebook.

JSON only responses

At Columbia JSON responses are preferred responses from API

Pagination

For APIs which returns large number of records, links should be used for pagination into the previous and next pages. For example:

{
  "links": {
    "first": "https://app.api.columbia.edu/v1/things/?page[number]=1",
    "last": "https://app.api.columbia.edu/v1/things/?page[number]=448",
    "next": "https://app.api.columbia.edu/v1/things/?page[number]=2",
    "prev": null
  },
  "data": [ ... ]
}

Rate Limiting

It is good practice to add rate limiting to an API, use HTTP status code 429 Too Many Requests

Some good example of rate limiting can be found here

Authentication

REST APIs are stateless. API request authentication shouldn't depend cookies and sessions. Instead each request should use some sort of token for authorization.

Tokens can be associated with two types of resources i.e. Applications and/or users of applications

oAuth2 will be used in Columbia to provide the secure token for API authorization.

oAuth2 Protocol


Caching

Use HTTP's inbuilt capability for caching, following can be used as part inbound request header

ETag : An ETag is an opaque identifier assigned by a web server to a specific version of a resource found at a URL. If the resource representation at that URL ever changes, a new and different ETag is assigned. Used in this manner ETags are similar to fingerprints, and they can be quickly compared to determine whether two representations of a resource are the same.

In typical usage, when a URL is retrieved the web server will return the resource's current representation along with its corresponding ETag value, which is placed in an HTTP response header “ETag” field:

   ETag: "686897696a7c876b7e"

The client may then decide to cache the representation, along with its ETag. Later, if the client wants to retrieve the same URL again, it will send its previously saved copy of the ETag along with the request in a “If-None-Match” field.

   If-None-Match: "686897696a7c876b7e"

On this subsequent request, the server may now compare the client's ETag with the ETag for the current version of the resource. If the ETag values match, meaning that the resource has not changed, then the server may send back a very short response with a HTTP 304 Not Modified status. The 304 status tells the client that its cached version is still good and that it should use that.

Last-Modified : This basically works like to ETag, except that it uses timestamps. The response header Last-Modified contains a timestamp, which is validated against If-Modified-Since.

Errors

An API should provide a useful error message in a known consumable format like JSON. The error message should contain its own set of fields, for example:

{
    "errors": [
        {
            "detail": "Authentication credentials were not provided.",
            "status": "401",
            "source": {
                "pointer": "/data"
            },
            "code": "not_authenticated"
        }
    ]
}

N.B. See JSON API error objects.

HTTP Codes

API should return HTTP defined status codes, which helps consumer of API route their responses accordingly, see below for the list (HTTP Status code)

  • 200 OK: Successful response. (Use for POST that doesn't result in a creation)

  • 201 Created: Response to POST that results in a creation

  • 400 Bad Request: The request that is malformed, such as if the body doesn't parse

  • 401 Unauthorized: When no or invalid authentication details are provided.

  • 403 Forbidden: When authentication succeeded but authenticated user doesn't have access to the resource.

  • 404 Not Found: When an non-existent resource is requested

  • 405 Method Not Allowed: When an HTTP method is being requested that isn't allowed for the authenticated user

  • 410 Gone: Indicates that the resource at this end point is no longer available, deprecated API

  • 415 Unsupported Media Type: If incorrect content type was provided as part of the request

  • 422 Unprocessable Entity: Used for validation errors

  • 429 Too Many Requests: When a request is rejected due to rate limiting

References

Related content

Using the Django REST Framework and DRF-JSONAPI
Using the Django REST Framework and DRF-JSONAPI
More like this
JSON Schema Standard
JSON Schema Standard
More like this
Welcome and Caveat
Welcome and Caveat
More like this
OAuth 2.0 Protection Standard
OAuth 2.0 Protection Standard
More like this
API Contract Specifications
API Contract Specifications
More like this
API - Integration Domain Names
API - Integration Domain Names
More like this