Skip to main content

Reasoning

FastAPI is an awesome framework that simplifies the process of creating APIs. One of the most exciting features is that it can generate OpenAPI specs out of the box. But what if.. you have an OpenAPI spec and you need to create an API from it?

One day we faced that problem — we had to create an API from multiple OpenAPI specs, and make sure that the incoming requests and the outgoing responses were aligned with the models defined the specs.

⚠️ This library was created to cover only our own needs first. So for now it's not suitable for everyone and has a lot of technical restrictions. Please consider it as experimental stuff

Installation

The package is available on PyPi:

pip install openapi-to-fastapi

Generating FastAPI routes

The main purpose of this library is to generate FastAPI routes from OpenAPI specs. This is done by:

from pathlib import Path
from openapi_to_fastapi.routes import SpecRouter

specs = Path("./specs")

router = SpecRouter(specs).to_fastapi_router()

The code above will create a FastAPI router that can be either included into the main router, or used as the default one.

Imagine you have a following spec (some parts are cut off for brevity):

{
  "openapi": "3.0.2",
  "paths": {
    "/Company/BasicInfo": {
      "post": {
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BasicCompanyInfoRequest",
                "responses": {
                  "200": {
                    "content": {
                      "application/json": {
                        "schema": {
                          "$ref": "#/components/schemas/BasicCompanyInfoResponse"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "components": {
        "schemas": {
          "BasicCompanyInfoRequest": {
            "title": "BasicCompanyInfoRequest",
            "required": ["companyId"],
            "type": "object",
            "properties": {
              "companyId": {
                "title": "Company Id",
                "type": "string",
                "example": "2464491-9"
              }
            }
          },
          "BasicCompanyInfoResponse": {
            "title": "BasicCompanyInfoResponse",
            "required": ["name", "companyId", "companyForm"],
            "type": "object",
            "properties": {
              "name": {
                "title": "Name of the company",
                "type": "string"
              },
              "companyId": {
                "title": "ID of the company",
                "type": "string"
              },
              "companyForm": {
                "title": "The company form of the company",
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}

The FastAPI route equivalent could look like this:

class BasicCompanyInfoRequest(pydantic.BaseModel):
    companyId: str

class BasicCompanyInfoResponse(pydantic.BaseModel):
    name: str
    companyId: str
    companyForm: str


@router.post("/Company/BasicInfo", response_model=BasicCompanyInfoResponse)
def _route(request: BasicCompanyInfoRequest):
    return {}

And openapi-to-fastapi can create it automagically.

Custom routes

In most cases it makes no sense to create an API without any business logic.

Here's how to define it:

from fastapi import Header, HTTPException
from openapi_to_fastapi.routes import SpecRouter

spec_router = SpecRouter("./specs")

# Default handler for all POST endpoints found in the spec
@spec_router.post()
def hello_world(params, x_my_token: str = Header(...)):
    if x_my_token != "my_token":
        raise HTTPException(status_code=403, detail="Sorry")
    return {"Hello": "World"}

# Specific endpoint for a "/pet" route
@spec_router.post("/pet")
def create_pet(params):
    pet = db.make_pet(name=params.name)
    return pet.to_dict()

router = spec_router.to_fastapi_router()

API Documentation

Now after you have a lot of routes, you might want to leverage another great feature of FastAPI — auto documentation.

Request and response models are already handled. But to display documentation nicely, FastAPI needs to assign a name for each endpoint. Here is how you can provide such name:

from openapi_to_fastapi.routes import SpecRouter

spec_router = SpecRouter("./specs")

@spec_router.post(
    "/pet",
    name="Create a pet",
    description="Create a pet",
    response_description="A Pet",
    tags=["pets"],
)
def create_pet(params):
    return {}

# Or you can set the dynamic name based on API path
def name_factory(path: str, **kwargs):
    return path.replace("/", " ")

@spec_router.post(name_factory=name_factory)
def create_pet(params):
    return {}

OpenAPI validation

This package also provides a CLI entrypoint to validate OpenAPI specs. It's especially useful when you need to define you own set of rules for validation.

Imagine your API specs are stored in a separate repository and maintained by another team. You also expect that all OpenAPI specs have only one endpoint defined (some internal agreement).

Now you can set up a CI check and validate them on every push.

Firstly create a file with a custom validator:

# my_validator.py

from openapi_to_fastapi.validator import BaseValidator, OpenApiValidationError

class CustomError(OpenApiValidationError):
    pass

# important: must be inherited from BaseValidator
class MyValidator(BaseValidator):

    # implement this single method
    def validate_spec(self, spec: dict):
        if len(spec["paths"]) != 1:
            raise CustomError("Only one endpoint allowed")

Then run the tool:

openapi-validator --path ./standards -m my_validator.py -v MyValidator

===============================================================================
OpenAPI specs root path: ./standards
Validators: DefaultValidator, MyValidator
===============================================================================
File: ./standards/Current.json
[PASSED]
-------------------------------------------------------------------------------
File: ./standards/Metric.json
[PASSED]
-------------------------------------------------------------------------------
File: ./standards/BasicInfo.json
[PASSED]
-------------------------------------------------------------------------------
===============================================================================
Summary:
Total : 3
Passed: 3
Failed: 0
===============================================================================

This validator can also be reused when generating routes:

router = SpecRouter(specs, validators=[MyValidator])

Development

You will need:

Before working on the project, make sure you run:

pre-commit install

After making changes you can run tests:

poetry run invoke test

License

This code is released under the BSD 3-Clause license. Details in the LICENSE file.

Metadata

Release files for openapi-to-fastapi 0.22.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openapi-to-fastapi 0.22.0
File Size Uploaded
openapi_to_fastapi-0.22.0.tar.gz 26.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openapi-to-fastapi 0.22.0
File Interpreter ABI Platform
openapi_to_fastapi-0.22.0-py3-none-any.whl Python 3 none any Details

Total release size: 78.5 kB

Release files / openapi_to_fastapi-0.22.0.tar.gz

Download URL openapi_to_fastapi-0.22.0.tar.gz
Size 26.5 kB
Tags Source
SHA-256 checksum
How to use checksums
bcac54a93630d88624d8bcfb103fb595178246d5aa2e1c6cc686ec47bd7a6797
BLAKE2b-256 checksum
How to use checksums
2175c30fe30e3670f7b4f8c11a0ddb2d8940844a1df25b77b415a6e854920083
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 10, 2025.

Transparency log

Release files / openapi_to_fastapi-0.22.0-py3-none-any.whl

Download URL openapi_to_fastapi-0.22.0-py3-none-any.whl
Size 51.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dcb50625ac70c35562f445d165ddc39a1700cc71efaf985fcbe9f169b729da6a
BLAKE2b-256 checksum
How to use checksums
f11aac4d7d732a1b19d1848b81b447f4d82d0a588ffdb393fc7e8020601f46d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 10, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.22.0 This release

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.17.0

2 release files

0.16.0

2 release files

0.13.0

2 release files

0.12.1

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page