Auto-generating API specifications as OpenAPI, WSDL and Sphinx

This article presents a workflow for auto-generation of API specifications for your Zato services - if you need to share your APIs with partners, external or internal, this is how it can be done.

Sample services

Let's consider the services below - they represent a subset of a hypothetical API of a telecommunication company. In this case, they are to do with pre-paid cards. Deploy them on your servers in a module called api.py.

Note that their implementation is omitted, we only deal with their I/O, as it is expressed using SimpleIO.

What we would like to have, and what we will achieve here, is a website with static HTML describing the services in terms of a formal API specification.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Int, Service

# #####################################################################

class RechargeCard(Service):
    """ Recharges a pre-paid card.
    Amount must not be less than 1 and it cannot be greater than 10000.
    """
    class SimpleIO:
        input_required = 'number', Int('amount')
        output_required = Int('status')

    def handle(self):
        pass

# #####################################################################

class GetCurrentBalance(Service):
    """ Returns current balance of a pre-paid card.
    """
    class SimpleIO:
        input_required = Int('number')
        output_required = Int('status')
        output_optional = 'balance'

    def handle(self):
        pass

# #####################################################################

Docstrings and SimpleIO

In the sample services, observe that:

  • Documentation is added as docstrings - this is something that services, being simply Python classes, will have anyway

  • One of the services has a multi-line docstring whereas the other one's is single-line, this will be of significance later on

  • SimpleIO definitions use both string types and integers

Command line usage

To generate API specifications, command zato apispec is used. This is part of the CLI that Zato ships with.

Typically, only well-chosen services should be documented publicly, and the main two options the command has are --include and --exclude.

Both accept a comma-separated list of shell-like glob patterns that indicate which services should or should not be documented.

For instance, if the code above is saved in api.py, the command to output their API specification is:

zato apispec /path/to/server        \
    --dir /path/to/output/directory \
    --include api.*

Next, we can navigate to the directory just created and type the command below to build HTML.

cd /path/to/output/directory
make html

OpenAPI, WSDL and Sphinx

The result of the commands is as below - OpenAPI and WSDL files are in the menu column to the left.

Also, note that in the main index only the very first line of a docstring is used but upon opening a sub-page for each service its full docstring is used.

Branding and customization

While the result is self-contained and it can be already used as-is, there is still room for more.

Given that the output is generated using Sphinx, it is possible to customize it as needed, for instance, by applying custom CSS or other branding information, such as the logo of a company exposing a given API.

All of the files used for generation of HTML are stored in config directories of each server - if the path to a server is /path/to/server then the full path to Sphinx templates is in /path/to/server/config/repo/static/sphinxdoc/apispec.

Summary

That is everything - generating static documentation is a matter of just a single command. The output can be fully customized while the resulting OpenAPI and WSDL artifacts can be given to partners to let third-parties automatically generate API clients for your Zato services.