NEW: Fenrir v4.1.2 — 56 Bug Fixes, Performance Optimizations, 1331 Tests, 5-Framework Benchmark! Read the changelog
openapi-customization.md
docs openapi-customization.md

OpenAPI & Docs Customization

Fenrir auto-generates OpenAPI 3.0.3 schemas from your route definitions and Pydantic models, powering the built-in Swagger UI and ReDoc endpoints.

Default Setup

1
2
3
4
5
6
7
8
9
from fenrir import Fenrir

app = Fenrir(
    title="My API",
    version="1.0.0",
    docs_url="/docs",        # Swagger UI (default)
    redoc_url="/redoc",      # ReDoc (default)
    openapi_url="/openapi.json"  # OpenAPI schema (default)
)
  • Swagger UI: GET /docs
  • ReDoc: GET /redoc
  • OpenAPI JSON: GET /openapi.json

Disabling Docs

1
2
3
4
5
app = Fenrir(
    docs_url=None,       # Disable Swagger UI
    redoc_url=None,      # Disable ReDoc
    openapi_url=None     # Disable schema endpoint
)

Customizing the Schema

Access and modify the OpenAPI schema programmatically:

1
2
3
@app.get("/items", tags=["items"], summary="List all items")
async def list_items():
    return [{"id": 1}]

Route Metadata

Add OpenAPI metadata to routes via decorator kwargs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@app.get(
    "/users/<user_id:int>",
    tags=["users"],
    summary="Get a user by ID",
    description="Retrieve detailed information about a specific user.",
    response_model=UserResponse,
    responses={
        404: {"description": "User not found"}
    }
)
async def get_user(user_id: int):
    return {"id": user_id, "name": "John"}

Route Tags

Organize endpoints in Swagger UI using tags:

1
2
3
4
5
6
7
8
@app.get("/items", tags=["items"])
async def list_items(): ...

@app.post("/items", tags=["items"])
async def create_item(): ...

@app.get("/users", tags=["users"])
async def list_users(): ...

Deprecated Routes

Mark routes as deprecated:

1
2
3
@app.get("/old-endpoint", deprecated=True, summary="Deprecated endpoint")
async def old_endpoint():
    return {"message": "Use /new-endpoint instead"}

Response Models

Use Pydantic models for automatic response validation and documentation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from pydantic import BaseModel

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

@app.get("/users/<user_id:int>", response_model=UserResponse)
async def get_user(user_id: int):
    return {"id": user_id, "name": "John", "email": "john@example.com"}

Multiple Response Models per Status

Apply different models based on HTTP status code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class ErrorResponse(BaseModel):
    detail: str

@app.get(
    "/items/<item_id:int>",
    response_models={
        200: ItemResponse,
        404: ErrorResponse
    }
)
async def get_item(item_id: int):
    if item_id < 0:
        return JSONResponse(status_code=404, content={"detail": "Not found"})
    return {"id": item_id, "name": "Item"}

Response Model Filtering

Control which fields are included in the response:

1
2
3
4
5
6
7
@app.get(
    "/users/<user_id:int>",
    response_model=User,
    response_model_exclude={"password", "secret_token"}
)
async def get_user(user_id: int):
    return User(id=user_id, name="John", password="hidden")

Generating the Schema Programmatically

1
2
3
4
5
6
7
from fenrir.openapi import get_openapi

schema = get_openapi(
    title="My API",
    version="1.0.0",
    routes=app.router.routes
)
Edit on GitHub Last Updated: Oct 20, 2018
© 2026 Fenrir Project.
main*
v4.1.2
Ln 1, Col 1
UTF-8
Prettier
Light Mode
Markdown