Documenting RESTful APIs

Welcome to Documenting RESTful API guide. This document is meant to serve as an introduction to the technical writing world of documenting RESTful APIs.

This guide includes the following topics:

In this guide, we will revisit our delivery robot API as mentioned in previous technical writing guides that I have written.

Written by Brian Immel

What are APIs?

API stands for Application Programming Interface and they define how two different software packages talk to each other. In this document, we are going to focus on REST. Other types of web API include JSON and XML. If you haven't had a chance to view my guides on those, please visit Documenting APIs Via JSON and Documenting APIs Via XML.

If you don't have access to an API or know how to build one, Programmable Web is a great resource to access many publich APIs.

REST stands for REpresentational State Transfer. REST relies on a stateless communication protocol. Lets say you are using a social media service on an electronic (client) device. When you open up that service, the application sends an API request to the social media's server to get the latest social media updates. The server then responses with some data that represents the state of your social media feed.

Another important topic of API documentation is security. This is handled through the authentication and authorization aspects of the API itself. When a client device requests a feed update, the device must provide it's identity to the server to receive and/or modify data. Typically, authentication is handled by the user providing username and password information. Authorization makes use of a token and grants authority to make a request. In this document, we will cover OAuth which is a popular authorization platform.

What is REST?

Design Pattern

There are two pattern types to consider when transferring data: Design pattern and protocol pattern. A protocol is a pattern that you need to match exactly. One way to think of a protocol to compare it to a wall outlet and an electrical cord. These two only work together because of how they are designed to accommodate the shape, size, and configuration of the pins of the plug and outlet.

A design pattern is a set of guidelines. For example, in Lego, the bricks are designed to connect to one another because of their inter-lockable format. The bricks can be connected in a multitude of ways.

REST uses the design pattern. That is, REST uses guidelines but they are not strict. Some APIs require that the guidelines followed more closely than others. Because REST uses a design pattern, the API often referred to as "RESTful APIs". You will hear about both of these terms, so don't get too caught up in semantics.

REST is a relatively new API. There are several other methods for transferring data back and forth but some of those tend to require more information to be transferred than what REST does. REST is a simpler and more flexible API and in its pure form is highly flexible. However, most REST APIs do not follow pure design patterns which makes them a little more difficult to use.

HTTP

REST uses standard web protocols like HTTP or HTTPS to send data. HTTP stands for HyperText Transfer Protocol. HTTPS is just the more secure version of HTTP.

REST APIs send data to an HTTP address (URL) just like a regular web page. The HTTP protocol has select actions (methods) that can use when receiving or send data. Those actions include OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, and CONNECT (as defined by HTTP/1.1 methods). The GET and HEAD methods do nothing but retrieve data and are considered "safe" because they do nothing but ask to receive data from the server. Methods like POST, PUT, and DELETE are considered "unsafe" because the actions they perform modifies the data on the server.

Resources

A resource is a data item that represents something. For example, if you are making a request about robot, then the URL should have the resource name robot in it like this one:

http://api.website.com/robot

This particular call will return information on all robots. However, if you wish to return data on just one robot, you can use IDs in your URL to filter this information.

http://api.website.com/robot/9000

Format

One thing that is nice about REST is that it is completely independent of format. The data that is sent and received can be any format with JSON and XML being the most popular formats. Sometimes, the media types that are transferred are images, videos, sound files, and so on.

Stateless

Inventory Request and Updated List

REST is stateless meaning that the server does not keep track of the state of the client device. For example, lets say you want to get an inventory list of what our robot is carrying. You load a web page and it displays the first five items in the robot's inventory. At the bottom of this list is a "Load More" button. When you click this button, it sends a request to the server asking for the next five items in the list. The server returns the data for the next five items. The server does not know how many items it has returned. The client device keeps track of how many items it has listed (via any number of methods) and when you request for the next set of items, the page then sends the correct request data to the server.

Comparison to SOAP

Before there was REST, there was SOAP: Simple Object Access Protocol. SOAP was not very easy to use because of it's strict nature and it only supported the XML format. Because this protocol is falling out of favor with developers, this document who go into any more details about it.

Requests

What is an HTTP Request

Just a quick refresher, an API request is data being sent to the server and an API response is data being sent from the server. When data is sent to the server, that data is packaged up in an HTTP request. Various pieces of data are stored in different parts of the request depending on what type of data it is.

Anatomy of a Request

Here is a sample HTTP request:

POST http:/api.website.com/robot?source=android&device=robot

In this example, POST is a method or an action of the request. The URL (http://api.website.com/robot) is what the action is acting on. And source=android&device=robot is the query parameters.

Next up is an example of a header which is used to store information about the request:

Accept: application/json
Content-type: application/json

And here we have the body which stores additional data that is typically used when creating or modify data objects.

{
  "id": "9000",
  "status": "active"
}

Method

Methods are the actions that you take (by requesting). These are standard HTTP requests like:

  • GET: returns data from server,
  • POST: Create a new resource on the server,
  • DELETE: Delete a resource from the server

URL

URL stands for Uniform Resource Locator. An URL is what one types in the address section of a browser and can start with HTTP or HTTPS. After the HTTP part of the URL, you have the server domain (api.website.com). Finally, you have the information on the resource (/robot). Here is a full URL:

http://api.website.com/robot

Query Parameters

Query parameters usually contains information about the data returned. The data is returned in key/value pairs like JSON. In our robot API, if it allows for searches, you will often see the query parameters in the URL.

http://api.website.com/robot?sort=id&location=ascend

In this example, sort and location are the keys and id and ascend are the values. In this particular URL, the query parameters are asking for data on ids of every robot and return that list in ascending order.

Headers

Headers are used for specific types of data. There are standard headers to use for HTTP and REST requests and other header formats used to handle a multitude of other requests. Headers commonly use data formats such as JSON and XML. Headers are also used for authorization (security) but we will get into that later on.

Body

The body of a request is used to send significant amount of data to the server. The body can be any format but it's usually formatted as JSON or XML or can be any media file. Only POST and PUT request have bodies while GET and DELETE requests to not.

Resources

What is a Resource?

A resource is an object with a type, associate data, possibly a relationship to other resources, and a set of methods that can operate on it. In our robot API, a resource can be the operator, designer, programming, and task. Basically, anything that is assignable.

The resource is defined in the URL. A standard convention for URLs is using singular nouns.

http://api.website.com/operator
http://api.website.com/programming/9000
http://api.website.com/operator/0010/task

In these three URLs, the first one uses the operator resource and the third one uses two resources (operator and task).

Existing resource objects have an unique id. You use ids in the URL to specify a particular resource object.

http://api.website.com/operator

This particular URL doesn't have an id. So, it would return all operators. The following URL uses and id and the data returned would be just for that one particular object.

http://api.website.com/operator/0010

In the following example, we are assigning operator 0010 with the task of 0042 (whatever that is).

http://api.website.com/operator/0010/task/0042

Endpoints

An endpoint refers to an URL for a resource. The following URLs show ids used in a general way:

http://api.website.com/operator
http://api.website.com/programming/{programming-id}
http://api.website.com/operator/{operator-id}/task

For a given endpoint, you can use retrieve (GET), create (POST), update (PUT), or delete (DELETE) from one endpoint.

Resources Within Other Resources

Like most programming objects, you can have a resource nested within another resource. If we wanted to get data on all programming for modes of transportation, we would use this URL:

GET http://api.website.com/programming/1234/transportation_types

If we wanted to get information just for one particular type of mode of transportation, we would use this URL:

GET http://api.website.com/programming/1234/transportation_types/004
Methods

What is an HTTP Method

As part of the HyperText Transfer Protocol, there are different types of requests (methods). The common Internet probably does not know this but they use the GET method every time they submit an address (URL) into the browser. If you're filling out a form on a web page to order new parts for your robot, you are using the POST method to send your data to a server. And when that same user updates their list of videos he has watched RoboTube, he's use a PUT method to modify which videos has watched or not on the RoboTube server.

CRUD

You can use resources to Create, Retrieve, Update, and Delete (CRUD). For each CRUD operation, there is a HTTP method associated with it:

  • Create - POST
  • Retrieve - GET
  • Update - PUT
  • Delete - DELETE

Note: Not all requests fall nicely into this model. Some requests nothing to do with a resource. For example, you could turn off your robot remotely. In this case, this is not a CRUD operation.

GET

The GET method retrieves data and do not use bodies in the request. GET methods allows for the use of ids in the URL to get a specific object.

To get data on all robots, your API request should look like this:

GET http://api.website.com/robot

To get data on a particular robot, put the id in the URL like this:

GET http://api.website.com/robot/9000

POST

The POST method is used to create a new resource object. The data to create the new object is contained in the body of the request. To create a new robot object, we would use this request:

POST http://api.website.com/robot
{
  ...data for new object...
}

PUT

The PUT method is used to modify an existing resource object. The data to modify an existing object is contained in the body of the request. You should use ids in the URL to specify which object to modify.

PUT http://api.website.com/robot/9000
{
  ...data for updated object...
}

DELETE

The DELETE method is used to remove an existing resource object. DELETE methods do not use bodies and you must specify which object to delete by it's id in the URL.

DELETE http://api.website.com/robot/9000

Documentation in Action

Lets put all this knowledge we have learned so far to use. The following is an example of what a RESTful document may look like for our robot API. This robot has an inventory resource that needs to documented and it has the following methods: retrieving data about a particular item in it's inventory, creating new inventory objects, updating and deleting a particular inventory item, getting a list of all inventory items, and finally a method to tell a particular robot to return to home.

Retrieving Item

Returns data about a specific item.

GET http://api.website.com/robot/9000/inventory/{item id}
Create New inventory

Creates a new collection of inventory items

POST http://api.website.com/robot/9000/inventory
Update Inventory Item

Updates an existing inventory item.

PUT http://api.website.com/robot/9000/inventory/{item id}
Delete Inventory Item

Deletes an inventory item.

DELETE http://api.website.com/robot/9000/inventory/{item id}
Retrieve All Inventory Items

Returns a list of all inventory items.

GET http://api.website.com/robot/9000/inventory
Return Home

Instructs a particular robot to return to home base.

POST http://api.website.com/robot/9000/home
Query Parameters

What Are Query Parameters

Query parameters are a way for the API request to provide additional information to the server. A common use of query parameters is modify or filter the data that is returned.

Some consider the query parameter as part of the URL. Query parameters comes after the URL which is followed by a question mark in a series of key/value pairs separated by an equals sign. If you wish to use more than one query parameter, you can use as many key/value pairs that are available to the API as long as you separate each key/value pair with an ampersand.

Here is a example of two query parameters in action that asks for information from robot #9000's inventory item called tire:

http://api.website.com/robot?id=9000&inventory=tire

Pagination

One generic method used to speed up transfer of data is pagination. Pagination breaks up the data into several smaller pieces which allows for faster delivery. This method is used frequently when requesting data from a server. In the following example, we are going to ask for the first five items first and then the next five items later.

GET http://api.website.com/robot?limit=5&offset=0

Here, limit is set to 5 which will restrict the data returned to just five items and offset is the value used to indicate the start of returned values. In the next call, we want to pull down data for the next five items.

GET http://api.website.com/robot?limit=5&offset=5

Since this query could potentially return too much data, you can filter this returned data even further by using a type query.

GET http://api.website.com/robot?limit=5&offset=0&type=roller

Data can be requested in a particular format via query parameters though this is not a common practice anymore. The format data type is usually specified in the header.

GET http://api.website.com/robot?format=json

There is a third, and less common, way to specify the data format and that is using a suffix.

GET http://api.website.com/robot.json

Sometimes, query parameters are used for authorization. This authorization comes in the form of a token or "apikey" which is usually a string of numbers and letters. It's more common to use headers to pass this information.

GET http://api.website.com/robot?toekn=234235fe23512a332

How to Document Query Parameters

As noted above and in my previous guides on documenting JSON and XML, query parameters are key/value pairs. To document query parameters, you may want to consider using a table with at least the following columns:

  • Parameter
  • Description
  • Type
  • Required
  • Notes

Quick note on query parameter types: all values are technically strings but you may want to specify your types regardless in your documentation using terms like Integer, Date, URL, and so on. If there is a limit on a set, put that information in the Notes column.

Parameter Description Type Required Notes
date Date which the robot left base. Date Required Format is YYYY-MM-DD-HH-MM-SS
last_updated Time elapsed since the robot last checked in. Integer Optional Default is 0.00
id Id of robot Integer Required
status Activity status of robot Boolean Optional active/inactive; Default is active.
Headers

HTTP Headers

Headers are part of the HTTP protocol and uses key/value pairs. The key of a header is typically a standard HTTP header and are often used for specifying a format and/or authorization.

Formats

HTTP defines special headers to specify data formats. These formats can change depending on whether or not the data is being sent or received. The sending format refers to the data used in POST or PUT in the body which uses a header key of Content-Type. If you are sending JSON or XML, your header will include a header value of application/jsonor application/xml respectively. The header value can also specify formats for media like images, videos, and audio files.

This is what a typical header might include:

Content-Type: application/json

A difference between sending and receiving data is that the header key will use Accept.

Accept: application/json

Some APIs not only specify which format to use but also the format of the resource. Below is an example of a resource being requested:

application/json;website.robot.json+v1

In this case, the request is expecting our website to return the robot resource in a JSON format (in particular, the first version of this JSON format).

Headers will be similar for all API requests. GET and DELETE don't need Content-Type headers as they do not use bodies unless they use a different format type for each resource.

Documenting Headers

Documenting a header is pretty straight forward. You should use a table with the following columns:

  • Header Name
  • Description
  • Values
Header Name Description Required Values
Bearer Access token Required See Authorization section
Content-Type Format of request data Optional application/json, application/xml. Default is application/json
Accept Format of response data Optional application/json, application/xml. Default is application/json

Sample Request

This request uploads and downloads information and accepts JSON data by default.

POST http://api.website.com/robot/9000/inventory
Content-Type: application/json
Accept: application/json

POST body is the data to update the robot's inventory.

Authentication and Authorization

Why is Security Important

There are two general areas where security is important: APIs are only called by registered developers and the user data it works with.

Why is this important? Often companies have a business model that involves API access. Other times, API access may be limited to certain number of requester per time period. Also, APIs help companies collect important data on how their product is used.

User data can be very sensitive and their data should only be accessible to those with the proper credentials.

Authentication Versus Authorization

Authentication is the process of a user providing a valid username and password. Sometimes this process may be augmented with other authenticating systems like Google Authenticator. This process usually results in an access token.

Authorization means that when you make an API request, you pass the server the access token thus allowing you access. This token determines what API requests you can make.

App Keys

App key, also known as API keys, must be registered with the company's developer portal (website for developers). The portal then returns a temporary app key which is usually a string of numbers and characters. Sometimes, this key is sent to the server in exchange for the access token so that each API request is associated with the registered app. After some time, your app key will expire and you will need to refresh it.

OAuth

OAuth is a popular open protocol that is both very flexible and complex used for authentication and authorization systems. To better understand OAuth, we can use the metaphor of valet keys. Older cars use to come with two sets of keys: one that grants the driver access to all areas of the car (door, ignition system, trunk, etc.) and the valet key only grants the driver access to the door and ignition system. When you use a valet service at a restaurant, you would hand the parking attendant your valet key. Basically, this means that different users have different privileges.

OAuth has several ways to handle authorization with the most common types being "one-legged" and "three-legged". One-legged is when no sensitive data is involved. Three-legged is used when there is a need to protect user data.

Information flows differently depending on how authorization is granted thus the need for grant types. The two most common grant types are authorization code and implicit.

Authorization code is used with server-side applications while implicit is used with mobile and web applications.

An example of one-legged OAuth is data that can be accessed by anyone like social media feeds. A typical data flow might act like this when requesting a social media feed update: Your device sends an app key to the server and the server returns with an access token. Once your device has the access token, it sends an API request with the access token back to the server and the server responds with the requested API data.

Three-legged OAuth is used when user data needs to be protected like updating a status on a social media feed. No one but the owner of that feed should be granted access to it. This type of authentication is called three-legged because there are three pathways of data involved: There are connections between the client device, an authentication server, and the API server.

Headers and Access Tokens

As mentioned earlier, it is a more common practice to pass the access token via the header rather than an query parameter. Here is an example header line passing the key/value pair of Bearer and the value:

Bearer: 234234ea356793e32a3f33

How to Document Authentication and Authorization

Documenting authentication and authorization various widely from application to application. You will need to write a section just for Authorization with a step by step process to get an access token, the URL of the authentication server, and how to get the access token from the server's redirect URL. Then, write up how to pass that token to the server, how often it expires, and how to get a new token. Also include how to use the token in an appropriate table or header or query parameter.

Request Bodies and Responses

Structured Data in REST

Structured data is data that is organized in objects and lists (like JSON and XML). Structured data is only found in request bodies (with methods such as POST and PUT) and response bodies. To document those structures, please review my guides on Documenting APIs Via JSON and Documenting APIs Via XML.

Note: if a response has no body (like a DELETE request), you will not need to document this in a table. You can write the valid response code confirming that the action has been successfully executed and that the response has no body.

Often, you will encounter an API request that returns the same type of data. You should create a document that lists all the objects that also contain their response bodies in a simple table with links to any other objects.

Documenting Errors

Errors are handled in one of two ways: HTTP status codes or elements in the response body. A status code is part of the HTTP protocol and is always returned with the response.

As part of the HTTP protocol, each status code has a standardized code and description like these:

  • 200 - OK
  • 201 - Created
  • 204 - No Content
  • 206 - Partial Content
  • 301 - Moved Permanently
  • 401 - Unauthorized
  • 404 - Not Found

The 200 codes are successful returns with varying levels of data. 300s usually means that something else needs to happen to make the request successful. And 400s means there was an error on the client side. Here is a list of examples applied to APIs:

  • 200 - OK: Successfully used GET, PUT, or DELETE
  • 201 - Created: Successful POST
  • 401 - Unauthorized: Bad access token
  • 404 - Not Found: Bad URL

Documenting HTTP status codes is pretty straight forward and only needs to be done once. Use a table with Code, Description, and Notes columns. However, sometimes you may need to create more than one table if the API has different requests. Here is an sample table you might find:

Code Description Notes
200 OK API successful request
201 Created Successful POST
401 Unauthorized Invalid access token

As mentioned earlier, error message can appear in bodies and will need to be documented just like response elements. You can generate a table similar to HTTP status codes.

Sample error code in a body:

{
  "errorCode": 02,
  "errorMessage": Inventory limit reached"
}
Sample Documentation

It's highly advised that you should create templates for each type of document that you will be producing and maintaining. You will creating multiple pages with the same layout and style of your API documentation and investing a little time in creating a template per type of document that you will be producing will save hours, if not days, of going back and forth with your documentation set making sure everything looks and reads the same throughout.

The following is a sample of getting the inventory of one of our robots out on a delivery run:

GET http://api.website.com/robot?id=9000&inventory=update&status=update

Bearer: 234234ea356793e32a3f33
Accept: application/json
  • id is required
  • inventory is required
  • status is optional. Default is to return active.
  • You can get a list of inventory by GETting on the /robot/{type} call.
  • You can also use pagination. Use offset for the start index and limit is the number of items to return.
  • For Accept, you can have either application/json or application/xml. JSON is the default.

Here is what a sample page could like:

Retrieve inventory update for a robot

Retrieves the inventory of a particular robot.

URL

GET http://api.website.com/robot

Query Parameters

Parameter Description Type Required Notes
id Id of robot Integer Required
index Number of results to return Integer Optional Defaults to 10
inventory Returns a list of items in robot's hold String Optional Defaults to a comma separated list. See Notes below.
offset Index to start at Integer Optional Defaults to 0
status Returns the activity status Boolean Optional active/inactive. Defaults to active.

Note: To get a list of inventory items, make a inventory type request.

Headers

Header Name Description Required Values
Bearer Access token. Required See Authorization section.
Accept Format of the data to be returned Optional application/json, application/xlm. Default is application/json.

Sample Request

GET http://api.website.com/robot?id=9000&inventory=update&status=update

Bearer: 234234ea356793e32a3f33
Accept: application/json

Response

Element Description Type Notes
id Id of robot Integer
inventory Items in robot's hold Array of item data If inventory isn't specified, then there is no response with inventory.
name Name of item String
id Id of item Integer
quantity Quantity of item in robot's hold Integer
status Returns the activity status Boolean

Sample response:

{
  "id": "9000"
  inventory: [
    {
      "name": "tire",
      "id": 00104,
      "quantity": 4
    },
    {
      "name": "rim",
      "id": 00105,
      "quantity": 4
    }
  ],
  "status": "active"
}

Status Codes and Errors

Code Description Notes
200 OK Success
401 Unauthorized Invalid access token
404 Not found Invalid inventory type
REST Documentation Tools

Helpful tools

You want to choose a tool, or a few of tools, that makes it easy for all interested individuals to collaborate, generates web-based documentation, is easy to keep in sync with the constantly changing and updating API. There are several tools on the market that can help but because this documentation field is relatively new and every company has a different preference for what and how to document, this guide will not get into the particulars of this subject.

Single source tools

A single source tool is an application that you would use to write document and has the capability to generate several formats such as HTML, PDF, Word, and so on and have the feature set to create templates. I cannot stress how important it is to use a tool that allows for the creation of templates. These tools are typically used for end-user documentation which tends to have a nice appearance but when crunched for time, you don't want to worry too much about the appearance of the content but rather just getting the correct information out there.

Content management systems

Content management systems are web-based and are typically viewed, and edited, through a browser. Such systems may include wikis which can range in basic to very rich features sets. Wikis are also great for collaboration. Some of these wiki systems may include features that allow for each multi-page and/or scripting base updates as well as integration options into developer portals.

Auto-docs (auto-generated documentation)

Auto-generated documentation takes data files (such as JSON and XML) and automatically generate documentation from them. However, you cannot always generate REST documentation from code comments. In which case, you will need to work with your developer team to create a comment file which then can be parsed into the auto-generated documentation.

Markdown

Markdown is a simple mark-up language similar to HTML but without styling and has some limits. It is much easier to read than HTML and be learned very quickly if you already know HTML.

Tools for REST request

Part of your job as an API writer, it would be best if you were able to make REST requests on your own as well. This ability will often give you answers without having to ask for questions and in some cases, troubleshoot errors or bugs in the responses. You can make these requests and view their responses using a REST client. Once such example is an add-on for Chrome called Advanced REST Client.