Skip to main content

Automate SDK generation for Flask APIs

Supported SDK languages:

TypeScript /
Javascript
Java /
Kotlin
PythonC#GoPHP

tip
  1. Before getting started make sure you have a liblab account and the liblab CLI installed.
  2. If you don't have an existing project but want to try out liblab then check out our standalone tutorials.

Providing an SDK for your API can significantly ease the development process for users, ensuring quicker integration and encouraging wider adoption due to the streamlined development experience.

In this doc you'll learn how to take your existing Flask API and generate user-friendly SDKs for most major programming languages using the liblab SDK generator. After a short bit of setup you'll have a pipeline that will automatically generate SDKs for your API whenever you make changes.

Initializing the SDK

First, create a new directory to store your SDK. This directory should be separate from your existing project directory:

mkdir Flask-sdk cd Flask-sdk

And initialize your project to create a liblab.config.json file:

liblab init -y

Getting an OpenAPI Spec File

In order to auto-generate SDKs from a Flask project you need an OpenAPI Spec File. This file contains information that describes your API like servers, paths, operations, parameters, responses, and security schemas.

To get the OpenAPI spec file from your Flask project you'll need to do the following:

This guide will walk you through the step-by-step process of creating your OpenAPI spec file using Flask-Smorest, configuring it, and annotating your project.

Installing flask-smorest

To start, navigate to your project to install flask-smorest and marshmallow.

pip install flask-smorest marshmallow

Configuring flask-smorest

After installing flask-smorest, you need to integrate it into your Flask application to generate the OpenAPI spec. Flask-Smorest automatically generates the OpenAPI spec based on your API's structure and annotations.

When setting the configuration, you can specify:

  • API_TITLE: The title of your API.
  • API_VERSION: The version of your API.
  • OPENAPI_VERSION: The version of the OpenAPI spec (e.g., 3.0.4).
  • OPENAPI_URL_PREFIX: The URL prefix for serving the OpenAPI spec.
  • API_SPEC_OPTIONS: Used to define the server URL.

The following code snippet shows how to add flask-smorest to your project and configure it to add the basic information of your API:

app.py
...
from flask import Flask
from flask_smorest import Api

app = Flask(__name__)

# Configure Flask-Smorest
app.config["API_TITLE"] = "Your API Title"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.4"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["API_SPEC_OPTIONS"] = {
"servers": [{"url": "https://your-api-domain.com"}]
}

api = Api(app)

Annotating Your Project

info

In most cases your Flask project will now be able to produce an OpenAPI spec that you can use to automatically generate SDKs and Documentation for your API and you could jump ahead to the next step of copying your spec. However the generated SDK may be missing important annotations such as descriptions of endpoints, possible responses, parameters, and example values.

To improve the readability and maintainability of your OpenAPI spec, you can annotate your Flask API using different approaches. The most common methods include:

  • Flask-Smorest Decorators: Add annotations directly in your code, empower you to define API routes and generate comprehensive OpenAPI documentation.

  • Marshmallow schemas: Utilizes marshmallow for data validation and OpenAPI spec generation.

Choosing the right method depends on your project's structure and maintainability requirements. However, the most commons is using Flask-Smorest Decorators.

Beyond the Basics

Flask-Smorest's documentation covers all the options available. Check it further customizing your OpenAPI spec.

If you're interested in learning more about OpenAPI specs in general, then Swagger's OpenAPI documentation is a great starting point for common annotations.

Using Flask-Smorest Decorators

Flask-Smorest uses a combination of decorators and docstrings to annotate your API endpoints, which are then used to generate the OpenAPI spec. They include the following:

While it may seem like a lot it's actually quite straightforward to use. Here's an example of a simple GET endpoint for /hello/{name} that accepts a name parameter in the URL path and returns a greeting message.

app.py
#...

from flask_smorest import Api, Blueprint
from flask.views import MethodView
from marshmallow import Schema, fields

#...

# Create a Blueprint for the Hello endpoint
hello_blp = Blueprint(
"hello", __name__, url_prefix="/hello", description="Operations that returns a greeting message"
)

# Define a schema for the URL parameters
class HelloQuerySchema(Schema):
name = fields.String(
required=True,
metadata={
"description": "The name of the person to greet"
}
)

@hello_blp.route("/")
class HelloResource(MethodView):
@hello_blp.arguments(HelloQuerySchema, location="query")
@hello_blp.doc(summary="Get a greeting message", tags=["Greetings"])
@hello_blp.response(
200,
example={"message": "Hello John"},
description="Successfully returned a greeting"
)

def get(self, name):
"""Return a greeting message"""
name = args["name"]
return {"message": f"Hello {name}"}

# Register the Blueprint with the API
api.register_blueprint(hello_blp)
Take it one step at a time

You don't need to annotate every view at once. You can start with annotating a single view, or even just part of it (e.g., the 200 response) to get the hang of the annotations.

Complete Example

Putting the above steps together produces a complete example of generating an Openapi spec in a Flask project using flask-smorest.

app.py
from flask import Flask
from flask_smorest import Api, Blueprint
from flask.views import MethodView
from marshmallow import Schema, fields

app = Flask(__name__)

# Configure Flask-Smorest for OpenAPI
app.config["API_TITLE"] = "Hello API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.4"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["API_SPEC_OPTIONS"] = {
"servers": [{"url": "https://your-api-domain.com"}]
}

api = Api(app)

# Create a Blueprint for the Hello endpoint
hello_blp = Blueprint("hello", __name__, url_prefix="/hello")

# Define a schema for query parameters
class HelloQuerySchema(Schema):
name = fields.String(required=True, metadata={"description": "The name of the person to greet"})

@hello_blp.route("/")
class HelloResource(MethodView):
@hello_blp.arguments(HelloQuerySchema, location="query")
@hello_blp.doc(summary="Get a greeting message", tags=["Greetings"])
@hello_blp.response(200, example={"message": "Hello John"}, description="Successfully returned a greeting")
@hello_blp.alt_response(400, example={"error": "Missing required parameter 'name'"}, description="Bad request due to missing parameter")
def get(self, args):
"""Return a greeting message"""
name = args["name"]
return {"message": f"Hello {name}"}

# Register the Blueprint with the API
api.register_blueprint(hello_blp)

if __name__ == "__main__":
app.run(debug=True)
Click to see the OpenAPI spec example
  {
"servers": [
{
"url": "https://your-api-domain.com"
}
],
"paths": {
"/hello/": {
"get": {
"responses": {
"400": {
"description": "Bad request due to missing parameter",
"content": {
"application/json": {
"example": {
"error": "Missing required parameter 'name'"
}
}
}
},
"200": {
"description": "Successfully returned a greeting",
"content": {
"application/json": {
"example": {
"message": "Hello John"
}
}
}
},
"default": {
"$ref": "#/components/responses/DEFAULT_ERROR"
}
},
"summary": "Get a greeting message",
"tags": [
"Greetings"
],
"parameters": [
{
"name": "name",
"in": "query",
"required": true,
"schema": {
"type": "string"
},
"description": "The name of the person to greet"
}
]
}
}
},
"info": {
"title": "Hello API",
"version": "v1"
},
"tags": [
{
"name": "hello",
"description": ""
}
],
"openapi": "3.0.4",
"components": {
"schemas": {
"Error": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "Error code"
},
"status": {
"type": "string",
"description": "Error name"
},
"message": {
"type": "string",
"description": "Error message"
},
"errors": {
"type": "object",
"description": "Errors",
"additionalProperties": {}
}
}
},
"PaginationMetadata": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"total_pages": {
"type": "integer"
},
"first_page": {
"type": "integer"
},
"last_page": {
"type": "integer"
},
"page": {
"type": "integer"
},
"previous_page": {
"type": "integer"
},
"next_page": {
"type": "integer"
}
}
}
},
"responses": {
"DEFAULT_ERROR": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}

Copy Your Spec

Once the configuration is complete, you can generate the OpenAPI spec. Start your Flask development server running:

python app.py

To view your OpenAPI spec, navigate to the /openapi.json endpoint on your server (e.g., http://localhost:5000/openapi.json).

Now that your openapi.json file is generated, you're ready to proceed. Save your openapi.json file to the liblab project directory you created during the initializing step. This is typically something like:

cd ../Flask-sdk curl -o openapi.json http://localhost:5000/openapi.json

Configuring liblab

Now you'll need to make some minor updates to your liblab.config.json file in your Flask-sdk folder:

  1. Point the specFilePath parameter to the location of your OpenAPI spec file (ex. ./openapi.json).
  2. Specify the baseUrl of your API. This is the URL that the SDK will use to make requests to your API.

The top of the file should then looks something like this:

{
"sdkName": "Flask-sdk",
"apiVersion": "1.0.0",
"apiName": "Flask-api",
"specFilePath": "./openapi.json",
"baseUrl": "http://localhost:PORT",
"languages": [
"go",
"java",
"python",
"typescript",
"csharp",
"php"
],
"auth": [
"bearer"
]
}
note

liblab's SDK generator supports many more advanced URL and environment configuration options than the basic configuration shown here.

Explore the configuration documentation to discover all the available settings and enhancements or review the SDK customization options for tailored adjustments.

Generate the SDK

info

During build you might see warnings about the OpenAPI spec. These are often minor issues that can be fixed later.

Now that you have an OpenAPI spec file and have finished setting the liblab.config.json file, it's time to generate our SDK:

liblab build -y

The CLI will validate the OpenAPI spec and notify you about any issues with it or the liblab.config.json.

The output will look something like this:

✓ No issues detected in the liblab config file.

No hooks found, SDKs will be generated without hooks.

⚠ Validation succeeded with warnings

Created /Users/username/projects/Flask-sdk/output/api-schema-validation.json with the full linting results

Next you'll see the builds started and once they're done you'll see a message like this:

Your SDKs are being generated. Visit the liblab portal (https://app.liblab.com/apis/Flask-sdk/builds/1234) to view more details on your build(s). ✓ C# built ✓ Go built ✓ Java built ✓ PHP built ✓ Python built ✓ TypeScript built ✓ Generate package-lock.json for TypeScript Successfully generated SDKs for Python, Java, Go, TypeScript, C#, PHP. ♡ You can find them inside: /Users/username/projects/Flask-sdk/output

If we go inside the output directory, we will see a directory for each of our SDKs:

ls output/     api-schema-validation.json go php typescript     csharp java python

Try out your SDK

Environment Setup

The following instructions assume you have already set up the respective development environment for the language you are testing. If necessary refer to each language's official documentation before proceeding.

Learn more about the language versions liblab generated SDKs support.

note

The generated SDKs are intended to be deployed to package managers for end users. The instructions below to test your SDK locally will differ from user-facing instructions.

cd output/typescript/examples
npm run setup
npm run start

Next Steps

Now that you've packaged your SDKs you can learn how to integrate them with your CI/CD pipeline and publish them to their respective package manager repositories.

We currently have guides for: