API Docs with OpenAPI & Swagger

Reviewed & published by Brayan K

OpenAPI is a standard, machine-readable way to describe a REST API — every path, parameter, request body, and response — so that both humans and tools understand exactly how your API behaves.

Part of the free Flask course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

In this lesson you'll document a Flask API with flask-smorest, define marshmallow schemas, validate input with @blp.arguments, serialize output with @blp.response, and get an interactive Swagger UI for free.

What You'll Learn in This Lesson

1 The OpenAPI / Swagger Standard

OpenAPI is a standard format — usually written as JSON or YAML — that describes a REST API in a way machines can read. It lists every path, the parameters each one accepts, the shape of request bodies, and the responses they return. It used to be called Swagger, and that name still appears in tools like Swagger UI.

Why bother? Because one document becomes a single source of truth. From it, tools can auto-generate client libraries, mock servers, contract tests, and interactive docs. Hand-written documentation drifts out of date; a generated spec stays accurate.

# A tiny slice of an OpenAPI document (YAML)
paths:
  /pets:
    get:
      summary: List all pets
      responses:
        "200":
          description: A list of pets

2 Building an API with flask-smorest

flask-smorest is an extension that builds REST APIs and documents them at the same time. You define marshmallow schemas for your data, register routes on a special Blueprint with @blp.route, and decorate them with @blp.arguments (to validate input) and @blp.response (to serialize output). flask-smorest reads all of this and produces the OpenAPI document for you.

# app.py - a documented API with flask-smorest
from flask import Flask
from flask.views import MethodView   # class-based views need this base
from flask_smorest import Api, Blueprint
from marshmallow import Schema, fields

app = Flask(__name__)
app.config["API_TITLE"] = "Pet API"
app.config["API_VERSION"] = "v1"
app.config["OPENAPI_VERSION"] = "3.0.2"
app.config["OPENAPI_URL_PREFIX"] = "/"
app.config["OPENAPI_SWAGGER_UI_PATH"] = "/swagger-ui"
app.config["OPENAPI_SWAGGER_UI_URL"] = "https://cdn.jsdelivr.net/npm/swagger-ui-dist/"

api = Api(app)

# A marshmallow schema describes the data shape.
class PetSchema(Schema):
    id = fields.Int(dump_only=True)
    name = fields.Str(required=True)
    species = fields.Str(required=True)

# flask-smorest's Blueprint records metadata for the docs.
blp = Blueprint("pets", __name__, url_prefix="/pets", description="Operations on pets")

@blp.route("/")
class Pets(MethodView):
    @blp.response(200, PetSchema(many=True))
    def get(self):
        # Returns a list serialized by PetSchema.
        return [{"id": 1, "name": "Rex", "species": "dog"}]

    @blp.arguments(PetSchema)            # validates the request body
    @blp.response(201, PetSchema)        # documents and serializes the reply
    def post(self, new_pet):
        new_pet["id"] = 2
        return new_pet

api.register_blueprint(blp)
print("Swagger UI would be served at /swagger-ui")

# The test client exercises both methods without a server, so you can see
# exactly what the documented routes return:
with app.test_client() as client:
    print(client.get("/pets/").get_json())
    print(client.post("/pets/", json={"name": "Ada", "species": "cat"}).get_json())

# ✅ Expected output:
# Swagger UI would be served at /swagger-ui
# [{'id': 1, 'name': 'Rex', 'species': 'dog'}]
# {'id': 2, 'name': 'Ada', 'species': 'cat'}

3 The /swagger-ui Endpoint

Once your app runs, flask-smorest serves an interactive documentation page at the path you configured — here /swagger-ui. Open it in a browser and you'll see every endpoint, its parameters, the schemas, and a "Try it out" button that sends real requests to your running API. The raw machine-readable OpenAPI JSON is available at its own URL so other tools can consume it.

# Run the app, then visit these in your browser:
#   http://127.0.0.1:5000/swagger-ui      -> interactive Swagger UI
#   http://127.0.0.1:5000/openapi.json    -> raw OpenAPI document

# Other tools can read that JSON to generate, for example:
#   - a Python or JavaScript client library
#   - a mock server for front-end work
#   - automated contract tests

A second popular option is flasgger, which builds Swagger UI from docstrings and YAML (often via the apispec library). It is handy for adding docs to an existing app without restructuring it around schemas.

🎯 Your Turn: Fill in the Blanks

Complete the documented route below. Replace each ___ so it validates the body and serializes the response.

# YOUR TURN: replace each ___ to finish the documented route
from flask.views import MethodView
from flask_smorest import Blueprint
from marshmallow import Schema, fields

class BookSchema(Schema):
    id = fields.Int(dump_only=True)
    title = fields.Str(required=True)

blp = Blueprint("books", __name__, url_prefix="/books")

@blp.route("/")
class Books(MethodView):
    @blp.___(BookSchema)          # validate the incoming request body
    @blp.___(201, BookSchema)     # document and serialize the reply
    def post(self, new_book):
        new_book["id"] = 1
        return new_book

print("Books route ready")

Common Errors & Quick Reference

The request body failed schema validation. flask-smorest returns this automatically when a required field is missing or has the wrong type — check the JSON you sent against your schema.

❌ Swagger UI page is blank or 404

Make sure OPENAPI_VERSION and the Swagger UI config keys are set, and that you visit the configured path such as /swagger-ui.

TaskCode
Install toolspip install flask-smorest marshmallow
Define a schemaclass PetSchema(Schema): ...
Validate input@blp.arguments(PetSchema)
Serialize output@blp.response(200, PetSchema)
View docs/swagger-ui

🏆 Mini Challenge: Document a GET-by-id Route

Add a route that fetches one item by its id and documents the response.

# Mini Challenge: document a GET-by-id route
from flask.views import MethodView
from flask_smorest import Blueprint, abort
from marshmallow import Schema, fields

class PetSchema(Schema):
    id = fields.Int(dump_only=True)
    name = fields.Str(required=True)

blp = Blueprint("pets", __name__, url_prefix="/pets")

PETS = {1: {"id": 1, "name": "Rex"}}

@blp.route("/<int:pet_id>")
class PetById(MethodView):
    @blp.response(200, PetSchema)        # documents the single-pet response
    def get(self, pet_id):
        pet = PETS.get(pet_id)
        if pet is None:
            abort(404, message="Pet not found")
        return pet

print("GET /pets/<id> is documented and ready")

❓ Frequently Asked Questions

Lesson complete — your API documents itself!

You can describe an API with the OpenAPI standard, build documented endpoints with flask-smorest and marshmallow schemas, and serve an interactive Swagger UI. Your docs now stay in lockstep with your code.

Practice quiz

What is OpenAPI?

  • A standard format for describing REST APIs
  • A database driver
  • A testing framework
  • A Flask extension only

Answer: A standard format for describing REST APIs. OpenAPI is a language-agnostic standard for describing REST APIs in a machine-readable document.

What was OpenAPI formerly called?

  • RAML
  • API Blueprint
  • Swagger
  • WSDL

Answer: Swagger. The OpenAPI Specification grew out of the Swagger spec, and the Swagger name still lives on in tools like Swagger UI.

Which Flask extension builds APIs with auto-generated OpenAPI docs using marshmallow?

  • flask-cors
  • flask-smorest
  • flask-login
  • flask-migrate

Answer: flask-smorest. flask-smorest pairs Flask with marshmallow schemas and produces an OpenAPI document plus Swagger UI automatically.

In flask-smorest, what do you use instead of Flask's plain Blueprint?

  • app.route
  • a class-based view
  • render_template
  • flask_smorest.Blueprint

Answer: flask_smorest.Blueprint. flask-smorest provides its own Blueprint class that records route and schema metadata for the docs.

Which decorator declares the request body schema in flask-smorest?

  • @blp.arguments
  • @blp.payload
  • @blp.body
  • @blp.input

Answer: @blp.arguments. @blp.arguments(SomeSchema) validates and deserializes the incoming request using a marshmallow schema.

Which decorator declares the response schema and status code?

  • @blp.send
  • @blp.response
  • @blp.returns
  • @blp.output

Answer: @blp.response. @blp.response(200, SomeSchema) serializes the return value and documents the response shape.

What library defines the schemas flask-smorest validates against?

  • pydantic
  • cerberus
  • voluptuous
  • marshmallow

Answer: marshmallow. flask-smorest uses marshmallow Schema classes to validate input and serialize output.

What interactive documentation page does flask-smorest generate by default?

  • A plain text file
  • A GraphQL playground
  • Swagger UI
  • A Postman collection

Answer: Swagger UI. flask-smorest serves Swagger UI (and ReDoc) so users can read and try the API in the browser.

Why do machine-readable API docs matter?

  • They encrypt requests
  • Tools can generate clients, tests, and docs from one source of truth
  • They make code run faster
  • They replace the need for a database

Answer: Tools can generate clients, tests, and docs from one source of truth. A standard spec lets tools auto-generate client SDKs, mock servers, and tests, keeping everything in sync.

Which other extension generates Swagger docs from docstrings and YAML?

  • flasgger
  • flask-wtf
  • flask-caching
  • flask-sqlalchemy

Answer: flasgger. flasgger reads docstrings and YAML (often via apispec) to build a Swagger UI for an existing Flask app.

Continue this course

Frequently asked questions

What is OpenAPI and how does it relate to Swagger?

OpenAPI is a standard, machine-readable format for describing a REST API — its paths, parameters, request bodies, and responses. It used to be called Swagger, and the Swagger name still lives on in tools like Swagger UI that render an OpenAPI document into interactive documentation.

What is flask-smorest?

flask-smorest is a Flask extension for building REST APIs. You define marshmallow schemas, register routes on its Blueprint with @blp.route, and use @blp.arguments and @blp.response to validate input and serialize output. It then generates an OpenAPI document and a Swagger UI page for you automatically.

Why are machine-readable API docs worth the effort?

Because one spec becomes the single source of truth. Tools can auto-generate client SDKs in many languages, build mock servers, run contract tests, and render interactive docs. Hand-written docs drift out of date; a generated spec stays accurate.

How do I view the interactive docs?

With flask-smorest the Swagger UI is served at a configured path such as /swagger-ui, and the raw OpenAPI JSON is available at its own endpoint. Open the page in a browser and you can read every endpoint and even send test requests.