FastAPI simple endpoint versioning

Lise Smith
CSIS TechBlog
Published in
3 min readOct 10, 2023

API and endpoint versioning is crucial for developers to consider when developing new APIs.

We quickly grew quite happy with using the FastAPI framework for developing APIs, and in the following, we will share a way to do endpoint versioning in a simple way that might be useful for others as well.

In our FastAPI versioning journey, we first tried using the fastapi-versioning library (https://pypi.org/project/fastapi-versioning/), which creates sub-apps for each endpoint version you specify. For that, we also needed to attach the exception handlers similar to the approach here: https://medium.com/geoblinktech/fastapi-with-api-versioning-for-data-applications-2b178b0f843f.

We didn’t think the sub-app approach was exactly what we were looking for — we were looking for something simpler.

In the following, we’ll share a way to do simple FastAPI endpoint versioning with code examples. It’s a combination of defining a decorator for the app routes and defining a custom route_class when initializing an APIRouter. Let’s illustrate it 🎨

First, we’ll define a decorator — this is strongly inspired by the source code of the decorator in fastapi-versioning. The decorator can be used for the route functions and basically sets the _api_version property on the function.

The idea is now to use the route_class attribute on the APIRouterclass to add additional behavior when an APIRouter is created.

We’ll define a format for the prefix of the API routes that includes the endpoint version: /api/{major}.{minor} . In the code snippet below, the VersionedRoute class extends the FastAPI APIRoute class and can be passed in the creation of a FastAPI APIRouter. VersionedRouter does exactly this together with combining the version prefix with the normal prefix attribute.

With this, all you need to do is to create a VersionedRouter in place of the FastAPI APIRouter with your wanted version_prefix (or keep the default). Decorating the route functions with the version decorator will take care of your endpoint versioning. For convenience, we have defined endpoints without the decorator to have version default_version.

Let’s look at an example. Suppose you are running an API for Halloween inspiration 🎃. You have created your API with FastAPI and versioning as described above, and you already have the version 1.0 endpoint that returns a list of costumes. A friend is eagerly using your API, and it’s crucial that the format of the returned data does not change.

Another friend wants to use your API, but would like the costumes to be categorized with tags.
Changing the endpoint directly would most likely make the first friend’s usage of the endpoint break. Furthermore, the first friend is happy with version 1.0 of the customer endpoint and doesn’t want to use time and energy to switch to a more fancy format.
You can now add the new version 1.1 endpoint by defining your next version of the costume endpoint — making your users happy:

In that way, the user can, in their own time, switch to the new version of the costume endpoint — if they want to and need it. To query the first version, they will query /api/1.0/costume (since we defined the default version as 1.0) and the second version /api/1.1/costume.

Now you’re all set up to not give your users an unnecessary scare 👻

--

--