OpenAPI Customisation¶
FasterAPI generates an OpenAPI 3.x schema automatically. This page covers how to conditionally show it, extend it, and override generated metadata.
Disable docs in production¶
import os
from FasterAPI import Faster
is_prod = os.environ.get("ENV") == "production"
app = Faster(
docs_url=None if is_prod else "/docs",
redoc_url=None if is_prod else "/redoc",
openapi_url=None if is_prod else "/openapi.json",
)
Change the docs URLs¶
Add tags metadata¶
Provide descriptions and external documentation links for each tag:
from FasterAPI import Faster
tags_metadata = [
{
"name": "items",
"description": "Operations on inventory items.",
},
{
"name": "users",
"description": "User management. See the [docs](https://example.com).",
"externalDocs": {
"description": "External docs",
"url": "https://example.com/users",
},
},
]
app = Faster(
title="Inventory API",
description="Full inventory management system.",
version="1.0.0",
)
Route-level OpenAPI fields¶
@app.get(
"/items/{item_id}",
summary="Get item by ID",
tags=["items"],
deprecated=False,
status_code=200,
)
async def get_item(item_id: int):
"""Retrieve a single inventory item.
Returns 404 if the item does not exist.
"""
...
The docstring becomes the route description in Swagger UI.
Extending the generated schema¶
The schema is generated by FasterAPI.openapi.generator.generate_openapi. To add
custom fields (e.g. servers, x-internal), intercept the /openapi.json endpoint:
import copy
from FasterAPI import Faster, JSONResponse
from FasterAPI.openapi.generator import generate_openapi
app = Faster(openapi_url=None) # disable default endpoint
def _custom_openapi():
schema = generate_openapi(app, title=app.title, version=app.version)
schema = copy.deepcopy(schema)
schema["servers"] = [
{"url": "https://api.example.com", "description": "Production"},
{"url": "http://localhost:8000", "description": "Development"},
]
schema["info"]["x-logo"] = {"url": "https://example.com/logo.png"}
return schema
@app.get("/openapi.json", include_in_schema=False)
async def openapi_schema():
return JSONResponse(_custom_openapi())
Adding security schemes¶
_openapi_cache = None
def get_openapi_schema():
global _openapi_cache
if _openapi_cache is None:
schema = generate_openapi(app, title=app.title, version=app.version)
schema.setdefault("components", {}).setdefault("securitySchemes", {}).update({
"BearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
}
})
schema["security"] = [{"BearerAuth": []}]
_openapi_cache = schema
return _openapi_cache
Hiding internal routes¶
Set include_in_schema=False (currently achieved by using the openapi tag and
filtering, or simply by not declaring the route through the public decorator):
# Internal health probe — not shown in API docs
async def _internal_health():
return {"ok": True}
app._add_route(
"GET",
"/_health",
_internal_health,
tags=["internal"],
summary="",
response_model=None,
status_code=200,
deprecated=False,
)
Next steps¶
- Metadata & Docs — per-route tags and descriptions.
- Bigger Applications — organise routes and schemas at scale.