Creating better endpoint documentation with FastAPI

What is FastAPI

FastAPI is an Asynchronous Python micro-service with self-documenting endpoints using OpenAPI. That is a mouthful if you are not familiar with programming. So in simple terms, asynchronous means it can process more than one request at a time, and return results when available. This is important in the modern web, and with API use. As projects evolve it is important to document how to use them with your end users.

FastAPI borrows a lot from the Flask micro-framework, in that it uses many of the same syntaxes, and does not force you to use a specific way of doing something as other frameworks often do. There are many other advantages to FastAPI over Flask or other python web frameworks too. One of them is that FastAPI is one of the fastest web frameworks out there.

It is a super easy migration from Flask to FastAPI with minimal code changes needed.

One of the other very nice features that are built in, is the use of Pydantic models. These models allow you to define the input and output format that you are willing to accept. This provides a validation check of data before wasting processes or writing custom validation checks. It also lets you create a standard way of returning all data, so your formats are consistent and uniform. Always a good thing when working with API’s.

As FastAPI, like Flask attempt to stay out of the way of you doing something different, these validation checks are not enforced. But….. when you provide them, your documentation takes on a whole new level of professionalism.

FastAPI Documentation

Self-documenting? Yep. Every programmer I ever met hates writing documentation, FastAPI allows you to do it relatively easily by use of pythons DOCSTRING comments. That’s it. I do not think it could get easier or simpler.

async def my_function():
    ''' 
    # Cool Documentation
    This is a doc string... and automatically 
    will be a published documentation 
    '''
    return

To make it more “exciting” FastAPI will handle the docstring as if it is a markdown doc. So you can use markdown to provide formatting, links, embed images, etc.

And for a simple API, we might be done. But as with most projects, they tend to grow, get revisions, and add new features. These things require better documentation as things progress, and documenting inside of the function (which should still be done), can become a little cluttered with different use cases and examples.

I was looking for a better way to provide enhanced documentation for some of our APIs. FastAPI provides a parameter when setting up a route, that lets you provide a “string” with the documentation. Conveniently if this parameter is provided with data, then the function’s docstring is ignored.

This is perfect because it allows us to have simpler documentation in the function of what it does, but provides “published documentation” for end users with examples and instructions. More importantly, we can now easily allow someone to create the documentation independently of the programmer.

Let’s look at a small block of code for an example:

from pathlib import Path
from FastAPI import APIRouter

api = APIRouter()

@api.get("/", description=Path('docs/my_function.md').read_text(), summary="Get MyFunction")
async def my_function():
    '''
    # Cool Documentation
    This is a doc string... and automatically 
    will be a published documentation 
    '''
    return
    

The code starts with the creation of an APIRouter, which if you have used Flask, is basically something like a Flask Blueprint. We also import the Path class from the pathlib module. This is included in Python3. The Path class allows us to pass in a file, and read the text .read_text() this is a nice oneliner that opens a file reads the text, and closed the file.

When we define the route endpoint @api.get("/") we pass in a parameter called documentation=. This only takes a “string” to pass in our markdown document we use them Path('docs/my_function.md').read_text() to read the document. Note that the path does not have a leading /. This is because all calls start in the home directory of your application.

In our example, the documentation is kept in the docs folder at the root of our application. If you wanted sub folders in here you can do so easily. Just add them and update the path in the documentation= parameter.

A few things to consider. You should at least create an empty placeholder file. If you don’t you may receive an error from your application that it can not find the file.

You should also be aware that if an empty string (or file) is provided, FastAPI will default to using the docstring provided in the function. This is convenient from a programming point, where you create a blank placeholder file, perhaps for an existing project, and allow another team member to create updated documentation. Your old documentation will stay in service until the new content is provided. No disruptions. Perfect.

Document with Validation Models

As mentioned earlier FastAPI, provides validation models via Pydantic. When you provide an input validation model you setup structure information of what your incoming payloads are expected to look like. The type of data they should have, and if any fields are optional. If the submitted payload does not match this validation, FastAPI will raise an error and provide an autogenerated response informing the sender of what data type was out of place…. And you did not even need to code it.

The same goes for output validation. You can define the expected data you should receive from your backend services. This can also be used to transform your responses to fit a defined response format wrapper for your presentation to your requester.

The best part is if you view the documentation http://ip.add.re.ss/redoc then you can see a sample of the data input expected, and what should be returned, (if you provided the response model)

fastapi documentation model

The input models also will supplement your docstring/markdown document as well by providing additional documentation details about the individual elements of the model.

fastapi document model

That means that your tech writer updating your markdown documentation does not need to document every single variable in the API. FastAPI will do this for you automatically from the Input model!

Model validation is typical for another time, but it is tied into providing your documentation and it is another excellent feature of FastAPI.

Conclusion

If you have to write any APIs or interface with any APIs to integrate converged services. You should be looking at FastAPI from the start. Ultra-fast asynchronous natively, no funky coding required. Input and Output model validation, and automatic documentation with the ability to provide customizations. Our first APIs at VOICE1 were created using the original Flask framework, but most of those have been migrated to FastAPI due to the auto-documentation, and async support. I encourage you to try it for your next project. You won’t be disappointed.