PHP
Article

Writing API Documentation with Slate

By Lukas White

So you’ve built yourself an API. Perhaps it’s RESTful, RESTlike or something else entirely. You’ve implemented authentication – be it using OAuth, HTTP Basic Auth or JSON Web Tokens. You’ve fashioned your responses using JSON, maybe XML, or even something else. Your unit and integration tests are passing, you may have a third-party service such a Runscope testing it periodically, or using JSON or XML schemas to validate your responses.

There’s one more thing, however.

Thing is, an API is only as good as its documentation. That applies if it’s for internal use only – perhaps it’s for a JavaScript-based one-page app, or a mobile application – but even more so if it’s for public consumption.

There are a number of ways in which you can put together your documentation. For the purposes of this article I’ll assume it’s web-based, whether it’s publicly available over the internet or privately held on a company intranet.

You could of course hand-code it in HTML. You could use a paid service such as Readme.io. There are even tools to help automatically generate API documentation from source-code such as Doxygen and API Blueprint, or for creating dynamic docs; such as Swagger.

Another option is Slate. Slate allows you to write your API documentation by hand using markdown, which it will then package up as a pre-styled static HTML site for you. Because it generates static HTML, hosting is straightforward – in particular, it’s a breeze to host with Github Pages. Let’s take a look at how it works, and go through an example from installation through to deployment.

What to Expect

A picture speaks a thousand words; here’s an example, straight out-of-the-box:

API documentation created by Slate, straight out-of-the-box

To see Slate-generated documentation in the wild, check out the Travis documentation, or Mozilla’s localForage or recroom docs. You’ll find even more examples in the project’s README.

Essentially, what you’ll get by default is the following:

  • a one-page static site with JS-based documentation (using jquery.tocify.js)
  • automatic Markdown parsing
  • a customizable three-columned layout
  • in-page search
  • tabbed, language-specific code samples
  • syntax highlighting

Getting Started

Pre-requisites

You’re going to need Ruby, at version 1.9.3 or newer. Head over to the documentation if you don’t already have it.

You’ll also need the Bundler gem, which you can install from the command-line with the following:

gem install bundler

You can skip this, and some of the installation steps if you use Docker; Slate ships with a Dockerfile you can use to get up-and-running quickly and easily.

Installation

Next, fork the Github repository.

Clone your fork of the repository to your machine:

git clone git@github.com:[YOUR-USERNAME]/slate.git

If you take a look in the newly created slate folder, you should see the following structure:

The default Slate folder structure

Next, cd into the slate directory and install the necessary libraries:

bundle install

Finally, enter the following command to launch Middleman, a lightweight web server, which will listen on port 4567:

bundle exec middleman server

If you now browse to http://localhost:4567, you should see the site in all its glory. You can also view the Middleman configuration by browsing to http://localhost:4567/__middleman/.

As well as serving up the site locally, Middleman will watch for changes and rebuild the site as required. We’ll try that out by modifying the site’s meta-data.

Meta-Data and Configuration

Let’s start by modifying your documentation site’s title. Open up slate/index.md, and change the first line of the (YAML-based) configuration at the top of the file:

---
title: API Reference

For example:

---
title: MusicApp API Docs

Now go back to your browser, hit refresh and you should see the changes take effect straight away.

Now let’s look at the other configuration variables. If you look at the default site, you’ll find it includes three tabs sitting at the top of the right-hand column, which allow you to browse language-specific example code.

Out-of-the-box, those tabs are Shell, Ruby and Python:

language_tabs:
  - shell
  - ruby
  - python

Let’s get rid of Python (no disrespect intended!) and change it to PHP:

language_tabs:
  - shell
  - ruby  
  - php

You’ll notice we’ve added PHP using lowercase letters. This is important, because the language name must exactly match the corresponding format which Rouge – the syntax highlighter used by Slate – expects. However, you’ll probably want to display it in uppercase. While we’re at it, let’s change “shell” so that it displays “cURL”, and correctly capitalize Ruby. To provide an alternative “display name” for a language, simply append it after a colon, as follows:

language_tabs:
  - shell: cURL
  - ruby: Ruby  
  - php: PHP

Again, by going to your broswer and hitting refresh you should see the changes straight away.

The configuration section also allows you to add links below the menu in the left-hand column. To add a link to your client libraries, for example, modify the toc_footers section as follows:

toc_footers:
  - <a href='#'>Sign Up for a Developer Key</a>
  - <a href='https://github.com/acme'>Client libraries</a>
  - <a href='http://github.com/tripit/slate'>Documentation Powered by Slate</a>

We’ll look at the includes section shortly.

Now that we’ve configured our documentation site, it’s time to get writing.

Writing your Documentation

Out-of-the-box, Slate provides a bunch of dummy content. The easiest way to get started is probably to modify that, as it will help familiarize you with Slate’s structure and style of markdown.

You’ll notice there are four sections, which the left-hand menu automatically picks up on. Using the JQuery TOC (Table of Contents) plugin, which will already be installed for you, it allows you to navigate between them, and will also expand the current item to show the second-level navigation.

The four sections are as follows:

  • Introduction
  • Authentication
  • Kittens
  • Errors

The introduction, authentication and errors section are generic enough that we probably want to keep them, albeit modified to suit our API.

“Kittens” reflects the example entity for the dummy documentation. It’s common practice to split up your API documentation into the various entities your API supports, so let’s change “Kittens” to “Albums”, since for the purposes of this article we’re going to document a music-related API. To do so, find the following (around line 61):

# Kittens

Change it to:

# Albums

You should find that simply by renaming this level-one header, the left-hand menu and the name of the auto-generated anchor should change with it.

You can also modify, remove or add the second level headings, which again update the menu in its expanded form accordingly.

Here’s an example for our music API:

## Get All Albums
	
	```ruby
	require 'music'
	
	api = Music::APIClient.authorize!('your-api-key')
	api.albums.get
	```
	
	```shell
	curl "http://example.com/api/albums"
	  -H "Authorization: your-api-key"
	```
	
	```php
	$client = new Acme\Music\Client('your-api-key');
	$client->authorize();
	$albums = $client->getAlbums();
	```
	
	
	The above command returns JSON structured like this:
	
	```json
	[
	  {
	    "id": 1,
	    "title": "Dubnobasswithmyheadman",
	    "artist": "Underworld",
	    "year": 1994
	  },
	  {
	    "id": 2,
	    "title": "ISDN",
	    "artist": "Future Sound of London",
	    "year": 1994
	  }
	]
	```
	
	This endpoint retrieves all albums.

Feel free to use third-level headings and above as normal, although note that the menu only goes two-levels deep.

As far as the body of your documentation goes, it’s largely just plain old Markdown. Take a look at the default introduction as an example, and modify it accordingly. Things get a little more complex when we start using notices and code samples, as we’ll see shortly.

Using Includes

If your API documentation is going to get quite long or quite complex, keeping all of it in one file will quickly become unmanageable. However, it’s very easy to split it into multiple files.

You’ll notice that the example errors section is already situated in a separate file – you’ll find it in includes/_errors.md.

Let’s create a new section, “Artists” and place it in a separate file. First, create that file as includes/_artists.html:

# Artists

In addition to album and track information, you can also request information about the artists.

## Getting all Artists

Retrieve information about all artists using the following URL:

`GET http://example.com/api/artists`

## Getting an Artist

Retrieve a specific artist using the following URL:

`GET http://example.com/api/artists/[ID]`

<aside class="notice">
Replace [ID] with the numeric ID of the artist
</aside>

Now we need to tell Slate about our new section. In the configuration section at the top of slate\index.md, inserting the name of the file – minus the preceding underscore – placing it right before the Errors section as follows:

includes:
  - artists
  - errors

You should find that the contents of includes/_artists.md has been inserted just before the errors section, and that the menu has automatically been adjusted to match.

Alerts

Slate comes with three “alert” styles out-of-the-box; notices, success messages and warnings. These are pictured below, in that order:

Notices

To display these, insert an <aside> with the relevant class:

<aside class="notice">...</aside>

<aside class="success">...</aside>

<aside class="warning">...</aside>

Tables

Tables lend themselves well to API documentation. The out-of-the-box errors section uses a table to list HTTP response codes; chances are, you can simply modify this to suit.

You’ll probably also want to use them to list an endpoint’s available parameters; again, the dummy content provides examples which you can simply modify.

Otherwise, in addition to writing out by hand – which is relatively simple, yet fiddly – then you could use this online tool.

The sidebar on the right hand side is largely made up of three separate elements:

  • callouts
  • language-specific example code
  • sample output

A sample callout is illustrated below:

An example Callout

To include one, which will appear in the right-hand column, use the Markdown for a blockquote:

> A sample of the JSON you can expect is displayed below

To include code samples use Github-flavored markup, ensuring the language name matches one of the ones we configured earlier; if you’ve been following along, you’ll remember that for this example those keys are shell, ruby and php. If you try and use the “display” name, for example cURL or PHP, the tabs won’t render properly.

For example, to display some sample PHP:

```php
	<?php
	$client = new Acme\Music\Client($apiKey);
	$client->authorize();
	$albums = $client->getAlbums();
	?>
	```

Notice that we’re including the opening and closing PHP tags; without this, the syntax highlighter doesn’t do its magic.

Typically you’ll want to create samples for each of your chosen languages for each endpoint:

```shell
	curl "http://example.com/api/albums"
	  -H "Authorization: your-api-key"
	```

	```ruby
	require 'music'
	
	api = Music::APIClient.authorize!('your-api-key')
	api.albums.get
	```

Provided you place your code in the relevant section, it should appear in the correct place. When users select their preferred language using the tabs, only the specified language should be displayed.

You can also embed example responses from your API. For example, to provide an example JSON response:

```json
	[
	  {
	    "id": 1,
	    "title": "Dubnobasswithmyheadman",
	    "artist": "Underworld",
	    "year": 1994
	  },
	  {
	    "id": 2,
	    "title": "ISDN",
	    "artist": "Future Sound of London",
	    "year": 1994
	  }
	]
	```

Because the json key doesn’t match one of the configured languages, it will be displayed on whichever tab is selected – this, of course, is what we want since the output should be the same whichever language is used to query the API.

Other Markdown

You’ll find a comprehensive guide to the Markdown used in Slate on the wiki; but as you’ll see, it’s pretty much standard Markdown, so there’s little else to learn if you’re already familiar with it.

Customizing

The first and simplest thing you’ll probably want to tweak is the site logo. Slate comes with a placeholder image; all you need do is replace it.

You’ll find it in slate\source\images\logo.png. The default image is 230 x 52 pixels; the default site uses a fixed width left-hand column to match, so unless you’re planning to modify that, it’s probably best to keep your image at roughly the same dimensions.

Beyond changing the logo image, customizing is really quite simple. Everything in the source directory – bar the layouts directory – everything will get copied over to the “built” version of the site. If you wish to add additional stylesheets, fonts, images or JS files, just pop them in the relevant directory.

You can modify the stylesheets as you wish; do note that they are in .scss format, so it’s probably easiest to stick to that – don’t worry about compiling them, since that’s taken care of for you. The “main” styles are in source\stylesheets\screen.css.scss, and you’ll find that it’s pretty well documented.

If you want to modify the layout, you’ll find it in source\layouts\layout.erb. Don’t worry if you’re not too familiar with the ERB templating system; in the most part the template tags – denoted by <%= ... => can be left in place; and in any case, you’ll quickly pick it up.

You can even rename the assets directories, should you prefer – you’ll find the appropriate configuration in config.rb.

Building

Once you’ve modified the content, reworked the dummy content and added in your additional content, you’re ready to build.

So far we’ve used Middleman to serve the site, watch the file system and rebuild the site on demand. When it comes to building the site ready for deployment, we can use the following command:

rake build

You should find this creates a new folder – build – comprising a complete, self-contained site. The markdown gets compiled into a single index.html file, the SASS styles get compiled, and your assets – for example the contents of the fonts, images, javascripts and stylesheets folders – get copied over from the source folder.

At this stage, you can simply upload the contents of the build folder to a webhost, use Githooks to publish it when pushed to a particular remote, or create a Grunt or Gulp task to do it automatically.

If you’d like to use Github Pages, read on because that’s made really easy for you.

Hosting with Github Pages

Github Pages is optimized for use with Jekyll, but Slate works in much the same way.

Slate comes with the Middleman Github Pages plugin pre-installed. Deploying is simple:

  1. Commit your changes to the source
  2. Push those changes to Github
  3. Create a gh-pages branch
  4. Run rake publish from the command-line

There is further information on creating Github pages in Github’s documentation as well as the Slate wiki.

You can also use your own custom domain; refer to the relevant documentation for details.

Just remember you’ll need to create a CNAME file; for example, suppose you plan to publish your documentation at http://docs.example.com. Create a file named CNAME with the following contents:

docs.example.com

Place this file in the source directory. Remember that anything you put in here will automatically be copied over to your build folder, so it will get uploaded to Github pages for you.

Of course by publishing your documentation to a public Github repository, you could even turn your documentation into a community effort, allowing users to modify your documentation via direct access or pull requests. This is entirely optional, but it’s always worth bearing in mind who’ll actually be using your API.

Summary

In this article we’ve looked at Slate, which is just one tool to help you document your API. It might not be to everyone’s taste, but it provides a quickstart for anyone who wishes to create HTML-based documentation and write in Markdown.

How do you write your API documentation? Let me know in the comments.

Comments
TaylorRen

Looks quite straightforward. Will try later.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in PHP, once a week, for free.