Effortless OpenAPI (Swagger) documentation & Swagger‑UI for Python Azure Functions.
@openapi
decorator — annotate once, generate full spec- Serves
/openapi.json
,/openapi.yaml
, and/docs
(Swagger UI) - Supports query/path/header parameters, requestBody, responses, tags
- Optional Pydantic integration (supports both v1 and v2)
- Zero hard dependency on Pydantic
pip install azure-functions-openapi
For local development:
git clone https://github.com/yeongseon/azure-functions-openapi.git
cd azure-functions-openapi
pip install -e .[dev]
Create a minimal HTTP-triggered Azure Function with auto Swagger documentation.
- Set up environment
python -m venv .venv
source .venv/bin/activate
pip install azure-functions azure-functions-worker azure-functions-openapi
- Initialize Azure Functions project
func init hello_openapi --python
cd hello_openapi
- Add
function_app.py
with OpenAPI-decorated function and endpoints:
# hello_openapi/function_app.py
import json
import azure.functions as func
from azure_functions_openapi.decorator import openapi
from azure_functions_openapi.openapi import get_openapi_json, get_openapi_yaml
from azure_functions_openapi.swagger_ui import render_swagger_ui
app = func.FunctionApp()
@openapi(
summary="Greet user",
route="/api/http_trigger",
request_model={"name": "string"},
response_model={"message": "string"},
tags=["Example"]
)
@app.function_name(name="http_trigger")
@app.route(route="/api/http_trigger", auth_level=func.AuthLevel.ANONYMOUS, methods=["POST"])
def main(req: func.HttpRequest) -> func.HttpResponse:
try:
data = req.get_json()
name = data.get("name", "world")
return func.HttpResponse(
json.dumps({"message": f"Hello, {name}!"}),
mimetype="application/json"
)
except Exception as e:
return func.HttpResponse(f"Error: {str(e)}", status_code=400)
@app.function_name(name="openapi_json")
@app.route(route="/api/openapi.json", auth_level=func.AuthLevel.ANONYMOUS, methods=["GET"])
def openapi_json(req: func.HttpRequest) -> func.HttpResponse:
return get_openapi_json()
@app.function_name(name="openapi_yaml")
@app.route(route="/api/openapi.yaml", auth_level=func.AuthLevel.ANONYMOUS, methods=["GET"])
def openapi_yaml(req: func.HttpRequest) -> func.HttpResponse:
return get_openapi_yaml()
@app.function_name(name="swagger_ui")
@app.route(route="/api/docs", auth_level=func.AuthLevel.ANONYMOUS, methods=["GET"])
def swagger_ui(req: func.HttpRequest) -> func.HttpResponse:
return render_swagger_ui()
Swagger UI (
/docs
) is now supported viarender_swagger_ui()
helper.
- Run locally:
func start
- OpenAPI JSON: http://localhost:7071/api/openapi.json
- Swagger UI: http://localhost:7071/api/docs
- Deploy:
func azure functionapp publish <FUNCTION-APP-NAME> --python
- OpenAPI JSON: https://.azurewebsites.net/api/openapi.json
A partial example of the generated /api/openapi.json
:
{
"openapi": "3.0.0",
"info": {
"title": "API",
"version": "1.0.0",
"description": "Auto-generated OpenAPI documentation. Markdown supported in descriptions (CommonMark)."
},
"paths": {
"/api/http_trigger": {
"get": {
"summary": "HTTP Trigger with name parameter",
"description": "Returns a greeting using the **name** from query or body.",
"parameters": [
{
"name": "name",
"in": "query",
"required": true,
"schema": { "type": "string" },
"description": "Name to greet"
}
],
"responses": {
"200": {
"description": "Successful response with greeting",
"content": {
"application/json": {
"examples": {
"sample": {
"summary": "Example greeting",
"value": {
"message": "Hello, Azure!"
}
}
}
}
}
},
"400": { "description": "Invalid request" }
}
}
}
}
}
- Swagger UI: https://.azurewebsites.net/api/docs
Swagger UI will look once you set up the routes:
from pydantic import BaseModel
from azure_functions_openapi.decorator import openapi
class RequestModel(BaseModel):
name: str
class ResponseModel(BaseModel):
message: str
@openapi(
summary="Greet user (Pydantic)",
route="/api/http_trigger",
request_model=RequestModel,
response_model=ResponseModel,
tags=["Example"]
)
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
...
Supports both Pydantic v1 and v2. Schema inference will work automatically with either version.
- Full docs: yeongseon.github.io/azure-functions-openapi
- Quickstart
- Development Guide
- Contribution Guide
MIT © 2025 Yeongseon Choe