# apispec: generate an OpenAPI document from your Python objects

> apispec is a pluggable API specification generator for Python that turns marshmallow schemas, and optionally Flask views, into an OpenAPI 2 or 3 document, with a plugin system so other frameworks can be supported. It suits a Python team that already has validation schemas and wants the API description derived from them rather than written twice.

**marshmallow-code/apispec** — A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification)..

- Repository: https://github.com/marshmallow-code/apispec
- Website: https://apispec.readthedocs.io/
- Stars: 1,220 · Forks: 210
- Language: Python
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/marshmallow-code-apispec

## What the library is and what it is not

apispec is a pluggable API specification generator that currently supports the OpenAPI Specification, formerly the Swagger specification. The four features it lists are the whole of the scope, and they are worth reading in order because they tell you what the library is for. It supports the OpenAPI Specification versions 2 and 3. It is framework-agnostic. It has built-in support for marshmallow. And it provides utilities for parsing docstrings. What it is not is a server, a documentation renderer or a schema validator, and it does not define your API for you. The primary language is Python, the licence is MIT, the version is 6.10.0, and the last push was on 2026-10-08 with the default branch being `dev`. The project is not archived, and the repository has no GitHub releases because the distribution is on PyPI rather than through GitHub. The upstream documentation is at apispec.readthedocs.io, and the package is classified as Production/Stable and requires Python 3.10 or newer, with classifiers for 3.10 through 3.14.

## Installation, and the extra that matters

The install is a pip command:

```bash
$ pip install -U apispec
```

And when you are using the marshmallow plugin, the documentation says to ensure a compatible marshmallow version is used, which is done by installing the extra:

```bash
$ pip install -U apispec[marshmallow]
```

The extra matters because the core library's own dependency list is tiny. The project declares only `packaging>=21.3` as a runtime dependency, which tells you that the generator itself does almost nothing on its own, and everything it produces comes from the plugins you attach. The optional dependencies are `yaml` for PyYAML, which is what makes `to_yaml` available, and `marshmallow` for marshmallow 3.18.0 or newer. That is a deliberate design rather than an accident of packaging, since a specification generator with no opinion about your framework is the only way to support several of them.

## The plugin system, and the two plugins in the example

The example application wires two plugins into a single APISpec object:

```python
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from apispec_webframeworks.flask import FlaskPlugin
from flask import Flask
from marshmallow import Schema, fields


# Create an APISpec
spec = APISpec(
    title="Swagger Petstore",
    version="1.0.0",
    openapi_version="3.0.2",
    plugins=[FlaskPlugin(), MarshmallowPlugin()],
)
```

Two things are visible in that call. The `openapi_version` is set explicitly, and the plugins are a list, so the order is the order in which they contribute. The MarshmallowPlugin comes from the apispec package itself, under `apispec.ext.marshmallow`, while the FlaskPlugin comes from a different distribution entirely, `apispec_webframeworks.flask`. That split is the design made concrete. apispec ships the marshmallow integration because marshmallow is its sibling project, and the framework integrations live in a separate webframeworks package so that a Flask user does not have to install a Django or a Bottle dependency.

## Schemas, security schemes and view registration

The rest of the example shows the three kinds of thing you register with the spec. Schemas come from marshmallow and are declared as ordinary Schema classes:

```python
class CategorySchema(Schema):
    id = fields.Int()
    name = fields.Str(required=True)


class PetSchema(Schema):
    category = fields.List(fields.Nested(CategorySchema))
    name = fields.Str()
```

A security scheme is added through the components helper, here an API key in a header:

```python
api_key_scheme = {"type": "apiKey", "in": "header", "name": "X-API-Key"}
spec.components.security_scheme("ApiKeyAuth", api_key_scheme)
```

And a view is registered inside a test request context, which is what the Flask plugin needs in order to read the route's metadata:

```python
with app.test_request_context():
    spec.path(view=random_pet)
```

The test request context is a detail worth noting. The Flask plugin inspects the view function and the routing rules, and doing that outside a request context raises errors, so the context manager is not optional ceremony.

## Docstrings as the source of the operation description

The view in the example carries its own documentation, and it is YAML in the docstring, using the reStructuredText field list style with a `---` separator:

```python
@app.route("/random")
def random_pet():
    """A cute furry animal endpoint.
    ---
    get:
      description: Get a random pet
      security:
        - ApiKeyAuth: []
      responses:
        200:
          content:
            application/json:
              schema: PetSchema
    """
    pet = get_random_pet()
    return PetSchema().dump(pet)
```

So the operation description, the security requirement and the response schema all live next to the code that implements the endpoint, and the schema reference points at the marshmallow class by name. The description in the generated document comes from the `description` key in the YAML block below the `---`, which is parsed and merged into the operation. The utilities for parsing docstrings are the fourth feature in the list, and this is where they earn their place, since the alternative is a parallel file of YAML fragments that nobody remembers to update.

## What comes out, and in which formats

The generated document is available in two shapes, and the example prints both:

```python
import json

print(json.dumps(spec.to_dict(), indent=2))
```

and `spec.to_yaml()` for the YAML form. The JSON output shows the structure the plugin has assembled. Under `paths` there is `/random` with a `get` operation carrying the `description`, the `security` list with the `ApiKeyAuth` entry, and a `200` response whose content maps `application/json` to a `$ref` of `#/components/schemas/Pet`. Under `components` there are the `schemas` with `Category` and `Pet`, where `Category` carries a `required` array naming `name` because the marshmallow field was declared with `required=True`, and a `securitySchemes` block with the `ApiKeyAuth` entry. The `info` block holds the title and version you passed to the constructor, and `openapi` holds the version string. The YAML output is the same document, and it is the one that reads more cleanly because of how the schema references nest.

## Project structure, tests and the wider ecosystem

The repository is a standard modern Python layout, with `src/`, `tests/`, `docs/`, a `pyproject.toml`, a `tox.ini` and a `uv.lock`, plus a `.readthedocs.yml` for the documentation build, a `.pre-commit-config.yaml`, a `renovate.json` for dependency updates, a `CHANGELOG.rst`, a `RELEASING.md` and a `SECURITY.md`. The project uses uv with `exclude-newer = "1 week"`, which is a supply chain practice that keeps newly published upstream releases out of a build until they have been out for a week. The dependency groups are informative. The `docs` group pulls marshmallow 4.0.0 or newer alongside Sphinx and the furo theme, the `tests` group has pytest and `openapi-spec-validator`, which is how the generated documents are checked against the specification, and the `lint` group is pre-commit. There is also an ecosystem wiki page listing apispec-related libraries, which is where third-party plugins live, and the project is maintained by a group of volunteers with an Open Collective, plus a Tidelift subscription for professional support.

## Conclusion

Adopt apispec if your Python API already uses marshmallow schemas and you want the OpenAPI document generated from them instead of maintained by hand, since the two then cannot drift. Skip it if you do not use marshmallow, because the built-in support is the path of least resistance and the core library without a plugin is thin. Before you start, note that the core install is `pip install -U apispec` and the marshmallow extra is `pip install -U apispec[marshmallow]`, that the marshmallow extra requires marshmallow 3.18.0 or newer, and that the framework plugin such as FlaskPlugin lives in a separate package.

## FAQ

### How do I install apispec with marshmallow support?

Run `pip install -U apispec` for the core library, and `pip install -U apispec[marshmallow]` when using the marshmallow plugin, which ensures a compatible marshmallow version is used. The marshmallow extra requires marshmallow 3.18.0 or newer.

### Which OpenAPI versions does apispec support?

Both version 2 and version 3 of the OpenAPI Specification, formerly the Swagger specification. The version is set on the APISpec constructor with the openapi_version argument, and the example uses 3.0.2.

### Where does the FlaskPlugin come from?

It is in a separate distribution and is imported as apispec_webframeworks.flask. The marshmallow plugin ships inside apispec itself under apispec.ext.marshmallow, which is why the two imports in the example come from different places.

### Why does registering a view in apispec need a test request context?

The Flask plugin reads the view function and the routing rules, and that inspection needs a request context. The example registers the path with `with app.test_request_context(): spec.path(view=random_pet)`.

## Sources

- [Issues](https://github.com/marshmallow-code/apispec/issues)
- [License: MIT](https://github.com/marshmallow-code/apispec/blob/dev/LICENSE)
- [marshmallow-code/apispec on GitHub](https://github.com/marshmallow-code/apispec)
- [Project website](https://apispec.readthedocs.io/)
- [README](https://github.com/marshmallow-code/apispec/blob/dev/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/marshmallow-code-apispec
