A utility that automatically generates a pure-Python API client from an OpenAPI specification, optimized for seamless integration with FastAPI applications.
This package uses Ruff to ensure consistent code quality — the generated client is automatically linted and formatted, producing clean and maintainable Python code.
⚠ Note: This project is in early development and may contain bugs. Expect breaking changes until a stable release is published.
- Generates Python API clients directly from OpenAPI specifications
- Designed specifically for compatibility with FastAPI
- Pure Python — no external code-generation tools required
- Ensures consistent style with Ruff (automatic linting + formatting)
- Generates Pydantic models for request and response schemas, including full field validation
- Modular project structure for clean organization and easy extension
ℹ️ Note: The examples below use
ClientAlpha.
Once this package reaches a stable version,Clientwill become the default class name.
UsingClientAlphaavoids breaking existing generated clients in the future.
You can generate a client directly from an in-memory FastAPI application instance.
This is especially useful during development or when your API is defined within Python rather than deployed yet.
from typing import Union
from fastapi import FastAPI
from fastapi_client_generator import FastapiClientGenerator
# 1. Create or import a FastAPI application instance
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
# 2. Provide the FastAPI app to the client generator
FastapiClientGenerator(client_name="demo_client").from_fastapi(fastapi=app)This will generate a new folder named demo_client/ containing the auto-generated API client.
Once generated, you can import and use the client just like any other Python module:
from demo_client import ClientAlpha
client = ClientAlpha(
base_url="http://localhost:4232",
default_headers={}
)
# Calling the root endpoint
root = client.root.get()
# Calling a parameterized endpoint
item = client.items_item_id.get(
item_id=1
)You can also generate a client directly from a remote OpenAPI specification URL.
This is useful when the API documentation is hosted externally or when you want to generate a client without having direct access to the FastAPI application.
In the example below, we generate a client using the public API documentation of a major Dutch retailer, which provides a large and detailed OpenAPI definition:
from fastapi_client_generator import FastapiClientGenerator
api_spec_url="https://api.bol.com/retailer/public/apispec/Retailer%20API%20-%20v10"
FastapiClientGenerator(client_name="bol.com").from_url(api_spec_url)Once generated, you can import and use the client just like any other Python module:
from bol_com import ClientAlpha
dummy_token = "top-secret"
client = ClientAlpha(
base_url="https://api.bol.com",
default_headers={"Authorization": f"Bearer {dummy_token}"}
)
ean_rating = client.retailer_products_ean_ratings.get(ean="1234567")
rating = ean_rating.ratings[0].ratingYou can also generate a client directly from a local OpenAPI document.
This is useful when your API specification is exported as a file (for example, during a CI pipeline, or when the specification is versioned in your project).
The file may be in JSON or YAML format, as long as it contains a valid OpenAPI specification.
from fastapi_client_generator import FastapiClientGenerator
file_path = "./openapi.json"
FastapiClientGenerator(client_name="demo_client").from_file_path(file_path)Once generated, you can import and use the client just like any other Python module:
from demo_client import ClientAlpha
client = ClientAlpha(
base_url="http://localhost:4232",
default_headers={}
)
# Calling the root endpoint
root = client.root.get()
# Calling a parameterized endpoint
item = client.items_item_id.get(
item_id=1
)You can also generate clients using the built-in command-line interface (CLI).
This is convenient for automation, CI pipelines, or working directly with OpenAPI specs without writing Python code.
Two CLI commands are available:
from-url— generate a client from a remote OpenAPI URLfrom-file— generate a client from a local OpenAPI file
Both commands use the same parameters shown in the Python examples above.
This CLI example matches the Python example where the API specification is loaded from the public documentation of a Dutch retailer:
fastapi-client-generator from-url \
--client-name bol.com \
--url "https://api.bol.com/retailer/public/apispec/Retailer%20API%20-%20v10"This creates a folder named bol_com/ containing the generated client.
For how to use that client, see the Python example above in “Generate a Client from a Remote OpenAPI URL”.
This CLI example matches the earlier Python snippet that loads from a local openapi.json file:
fastapi-client-generator from-file \
--client-name demo_client \
--file-path ./openapi.jsonThis creates a folder named demo_client/ containing the generated client.
For how to use that client, see the Python example above in “Generate a Client from an OpenAPI File”.
The generated client raises a custom exception type, HttpExceptionError, whenever the server returns a non-2xx HTTP response.
This ensures that failed API calls are easy to detect, debug, and handle in your application.
Any endpoint method (e.g. client.orders.get(...), client.retailer_products.post(...)) will:
- Return the
requests.Responseobject on success - Raise
HttpExceptionErroron HTTP errors such as:400 Bad Request401 Unauthorized403 Forbidden404 Not Found500 Internal Server Error- …or any other non-successful status code
The HttpExceptionError contains:
status_code— the HTTP status code returned by the APIdetail— the raw response body (text), useful for debugging API-side issues
from bol_com import ClientAlpha, HttpExceptionError
client = ClientAlpha(
base_url="https://api.bol.com",
default_headers={"Authorization": "Bearer YOUR_TOKEN"},
)
try:
client.retailer_invoices.get(period_end_date="2020-10-24")
except HttpExceptionError as error:
print(error.status_code) # e.g. 401
print(error.detail) # e.g. {"error":"Unauthorized"}Contributions are welcome!
If you'd like to improve the generator, fix a bug, enhance the CLI, or add support for additional OpenAPI features, you're more than welcome to contribute.
This project also includes an advanced class diagram located at: mermaid/class-diagram.mmd.
I encourage contributors to review this diagram before making larger architectural changes.
It provides a high-level overview of how the main components interact and can greatly help in understanding the internal structure of the generator.
- Fork the repository
- Create a new branch for your feature or fix
- Commit your changes with clear messages
- Submit a Pull Request describing your update
Before submitting a PR, please:
- Ensure the project builds without errors
- Run linting and formatting (Ruff will handle most of it automatically)
- Add tests when introducing new functionality
- Consult the class diagram when modifying or adding core components
If you have ideas, questions, or want to propose new features, feel free to open an Issue.
I appreciate every contribution that helps make this project better.
This project is licensed under the MIT License.
You’re free to use, modify, distribute, and integrate this package in both open-source and commercial applications, as long as the terms of the MIT License are followed.
You can find the full license text in the LICENSE file included in this repository.
