Skip to main content

Azure Functions OpenAPI

Part of the Azure Functions Python DX Toolkit — dogfood-tested by azure-functions-cookbook-python.

PyPI Downloads Python Version CI Release Security Scans codecov pre-commit Docs License: MIT

Read this in: 한국어 | 日本語 | 简体中文

OpenAPI (Swagger) documentation and Swagger UI for the Azure Functions Python v2 programming model.

Why this exists

Azure Functions Python v2 has no built-in API documentation story:

  • No auto-generated docs — you maintain OpenAPI specs by hand or not at all
  • No Swagger UI — no browser-based API explorer for testing endpoints
  • Hard to test — consumers rely on tribal knowledge or external tools to discover your API
  • Spec drift — hand-written docs diverge from actual handler behavior over time

Before / After

❌ Without azure-functions-openapi — maintain specs by hand

# openapi_spec.json — manually written, manually updated
{
    "paths": {
        "/api/users": {
            "post": {
                "summary": "Create user",
                "requestBody": { "...": "..." },
                "responses": { "200": { "...": "..." } }
            }
        }
    }
}

# function_app.py — no connection to the spec above
@app.route(route="users", methods=["POST"])
def create_user(req):
    ...

Spec drifts. Consumers guess. No Swagger UI.

✅ With azure-functions-openapi — spec lives next to the handler

from pydantic import BaseModel


class CreateUserRequest(BaseModel):
    name: str


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


@openapi(
    summary="Create user",
    requests=CreateUserRequest,
    responses=UserResponse,
)
@app.route(route="users", methods=["POST"])
def create_user(req):
    ...

# Auto-generated endpoints:
# GET /api/openapi.json  — always in sync
# GET /api/docs          — Swagger UI included

Spec matches code. Always. Swagger UI out of the box.

What it does

  • @openapi decorator — attach operation metadata directly to your handler
  • Auto-generated spec/openapi.json and /openapi.yaml endpoints from decorated handlers
  • Swagger UI — built-in /docs endpoint with security defaults
  • CLI tooling — generate specs at build time for CI validation
  • Schema support — query, path, header, body, and response schemas
  • Metadata inference — infer the 200 response from a handler's return type (always on), and opt into summary/description inference from its docstring with infer_docstring=True; both are gap-fill-only and explicit-always-wins (see Usage Guide)
  • auth_level security inference — opt-in infer_auth_level=True derives OpenAPI security from a route's Azure Functions auth_level (see Usage Guide)

How it fits together

flowchart LR
    DEC["@openapi decorator"] --> REG["_openapi_registry"]
    REG --> GEN["spec.generate_openapi_spec()"]
    GEN --> EP["GET /api/openapi.json | .yaml"]
    UI["render_swagger_ui()<br/>GET /api/docs"] -.->|browser fetches spec| EP

FastAPI comparison

Feature FastAPI azure-functions-openapi
API docs generation Built-in from type hints @openapi decorator on handlers
Swagger UI /docs auto-served render_swagger_ui() endpoint
OpenAPI spec Auto-generated /openapi.json get_openapi_json() endpoint
CLI spec export N/A azure-functions-openapi generate
Pydantic integration Native requests= / responses=

Scope

  • Azure Functions Python v2 programming model
  • Decorator-based func.FunctionApp() applications
  • HTTP-triggered functions documented with @openapi
  • Pydantic schema generation (requires Pydantic v2)

This package does not support the legacy function.json-based v1 programming model.

What this package does not do

This package does not own:

CLI Quick Start

Generate an OpenAPI spec from your decorated function app:

# Install
pip install azure-functions-openapi

# Generate spec from a function app module (registers @openapi routes)
azure-functions-openapi generate --app function_app --title "My API" --format json

# Write to file with pretty-printing
azure-functions-openapi generate --app function_app --title "My API" --pretty --output openapi.json

# YAML output
azure-functions-openapi generate --app function_app --format yaml --output openapi.yaml

Pass module:variable to resolve the FunctionApp instance and also discover endpoint-metadata routes — those registered by producers like @validate_http or azure-functions-langgraph — merging them with your @openapi routes into a single spec. With module alone the CLI imports the module (firing @openapi decorators) but does not scan for endpoint metadata:

azure-functions-openapi generate --app function_app:app --title "My API"

See the CLI Guide for all options and CI integration examples.

Installation

pip install azure-functions-openapi

Your Function App dependencies should include:

azure-functions
azure-functions-openapi

SDK Compatibility

This package discovers routes, methods, and handlers from the azure-functions SDK through a single isolated adapter (azure_functions_openapi.adapters). Discovery is public-API-first: it enumerates via the public, idempotent FunctionBuilder.build() and reads everything else through public Function accessors (get_function_name / get_user_function / get_bindings / is_http_function). The adapter never calls the non-idempotent FunctionApp.get_functions(). The one unavoidable private token — app._function_builders, which has no public substitute for enumeration — lives exclusively in the adapter and is covered by a mandatory guard test. We validate the package against an explicit matrix in CI. See issue #258 and issue #327 for background.

azure-functions Python 3.10 Python 3.11 Python 3.12 Python 3.13 Python 3.14
1.21.0 (floor) ✅ tested
1.24.0 ✅ tested
latest 1.x ✅ tested ✅ tested ✅ tested
2.x (>=2,<3) ✅ tested ✅ tested

The version pin in pyproject.toml is interpreter-aware: azure-functions>=1.21.0,<2.0.0 on Python < 3.13, and azure-functions>=1.21.0,<3.0.0 on Python 3.13+. The <3.0.0 ceiling keeps an uncertified azure-functions 3.x out. The floor is 1.21.0 because earlier releases return None from FunctionBuilder.__call__ (breaking direct invocation of decorated handlers in tests and CLI extraction). The split exists because azure-functions 2.x drops support for Python < 3.13, so the 2.x line is only installable — and only offered — on Python 3.13+. The 2.x path is proven by a dedicated wheel-based compatibility matrix in CI (real Python 3.13 and 3.14 interpreters) and certified against real Azure — a Python 3.13 Function App deployed on a Flex Consumption plan in koreacentral. See issue #528 and issue #488 for the cap-lift work.

Quick Start

import json

import azure.functions as func
from pydantic import BaseModel

from azure_functions_openapi import (
    get_openapi_json,
    get_openapi_yaml,
    openapi,
    render_swagger_ui,
)

app = func.FunctionApp()


# Describe your API with plain Pydantic models.
class GreetRequest(BaseModel):
    name: str


class GreetResponse(BaseModel):
    message: str


# @openapi infers the route and method from the @app.route below —
# no need to repeat them here.
@openapi(
    summary="Greet user",
    tags=["Example"],
    requests=GreetRequest,
    responses=GreetResponse,
)
@app.route(route="http_trigger", auth_level=func.AuthLevel.ANONYMOUS, methods=["POST"])
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
    # @openapi documents the request/response contract — it does not validate.
    # For runtime validation, see azure-functions-validation.
    data = req.get_json()
    name = data.get("name", "world")
    return func.HttpResponse(
        json.dumps({"message": f"Hello, {name}!"}),
        mimetype="application/json",
    )

Pydantic v2 is optional. requests= / responses= are the recommended path, but you can pass raw JSON Schema dicts instead (see below) if you'd rather not add a dependency.

Want runtime validation too? (optional) @openapi documents your Pydantic models — it does not parse or validate requests at runtime. If you also want automatic request parsing, consistent 400/422 error responses, and response-model enforcement, layer azure-functions-validation's @validate_http on the same Pydantic models. It is an optional companion, not a dependency — this package works fully on its own. See the validation README for details, or a full runnable example that pairs both on one resource: Full Stack CRUD API.

Want structured logging too? (optional) Pair your documented endpoints with azure-functions-logging for structured, correlation-aware logs and observability. It attaches request/response context to every log line without changing your @openapi contracts. Like validation, it is an optional companion, not a dependency — this package works fully on its own. See the logging README for details.

Wire up the spec + Swagger UI endpoints (openapi.json / openapi.yaml / docs)
# Serve the generated spec and Swagger UI as ordinary HTTP routes.
@app.route(route="openapi.json", auth_level=func.AuthLevel.ANONYMOUS, methods=["GET"])
def openapi_json(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse(
        get_openapi_json(
            title="Sample API",
            description="OpenAPI document for the Sample API.",
        ),
        mimetype="application/json",
    )


@app.route(route="openapi.yaml", auth_level=func.AuthLevel.ANONYMOUS, methods=["GET"])
def openapi_yaml(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse(
        get_openapi_yaml(
            title="Sample API",
            description="OpenAPI document for the Sample API.",
        ),
        mimetype="application/x-yaml",
    )


@app.route(route="docs", auth_level=func.AuthLevel.ANONYMOUS, methods=["GET"])
def swagger_ui(req: func.HttpRequest) -> func.HttpResponse:
    return render_swagger_ui()
Advanced: describe the schema with raw JSON Schema instead of Pydantic
@openapi(
    summary="Greet user",
    tags=["Example"],
    requests={
        "type": "object",
        "properties": {"name": {"type": "string"}},
        "required": ["name"],
    },
    responses={
        200: {
            "description": "Successful greeting",
            "content": {
                "application/json": {
                    "schema": {
                        "type": "object",
                        "properties": {"message": {"type": "string"}},
                    }
                }
            },
        }
    },
)
@app.route(route="http_trigger", auth_level=func.AuthLevel.ANONYMOUS, methods=["POST"])
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
    ...

Run locally with Azure Functions Core Tools:

func start

Verify locally and on Azure

After deploying (see docs/deployment.md), the same request produces the same response in both environments.

Local

curl -s http://localhost:7071/api/http_trigger \
  -H "Content-Type: application/json" \
  -d '{"name": "World"}'
{"message": "Hello, World!"}

Azure

curl -s "https://<your-app>.azurewebsites.net/api/http_trigger" \
  -H "Content-Type: application/json" \
  -d '{"name": "World"}'
{"message": "Hello, World!"}

The /api/openapi.json, /api/openapi.yaml, and /api/docs endpoints are also available in both environments.

Verified against a temporary Azure Functions deployment in koreacentral on a Flex Consumption plan (certified on Python 3.13). Response captured and URL anonymized.

Demo

The representative webhook_receiver example shows the full outcome of adopting this library:

  • You annotate an Azure Functions v2 HTTP handler with @openapi.
  • The package generates a real OpenAPI document for that route.
  • The same route is rendered in Swagger UI for browser-based inspection.

Generated Spec Result

The generated OpenAPI file is captured as a static preview from the same example run, so the README shows the actual document produced by the representative function.

OpenAPI spec preview

Swagger UI Result

The web preview below is generated from the same representative example and captured automatically from the rendered Swagger UI page produced by that example flow.

OpenAPI Swagger UI preview

When to use

  • You have HTTP-triggered Azure Functions and need API documentation
  • You want Swagger UI for browser-based API testing
  • You need OpenAPI specs for client code generation or CI validation
  • You want to keep docs in sync with handler code automatically

Documentation

Ecosystem

This package is part of the Azure Functions Python DX Toolkit.

Design principle: azure-functions-openapi owns API documentation and spec generation. azure-functions-validation owns request/response validation and serialization. azure-functions-langgraph owns LangGraph runtime exposure.

Package Role
azure-functions-openapi-python OpenAPI spec generation and Swagger UI
azure-functions-validation-python Request/response validation and serialization
azure-functions-db-python SQLAlchemy-powered DB integration helpers (poll-based pseudo trigger, input/output/client injection)
azure-functions-langgraph-python LangGraph deployment adapter for Azure Functions
azure-functions-scaffold-python Project scaffolding CLI
azure-functions-logging-python Structured logging and observability
azure-functions-doctor-python Pre-deploy diagnostic CLI
azure-functions-durable-graph-python Manifest-first graph runtime with Durable Functions (experimental)
azure-functions-knowledge-python Knowledge retrieval (RAG) decorators
azure-functions-cookbook-python Dogfood examples — runnable recipes that exercise the full toolkit

For AI Coding Assistants

This repository includes llms.txt and llms-full.txt in the root directory. These files provide comprehensive package and API information optimized for LLM context windows.

  • llms.txt — Quick reference with core API, installation, and quick-start example
  • llms-full.txt — Complete reference with full signatures, patterns, design principles, and ecosystem context

Use these files to get better context when working with this package in AI-assisted coding environments.

Disclaimer

This project is an independent community project and is not affiliated with, endorsed by, or maintained by Microsoft.

Azure and Azure Functions are trademarks of Microsoft Corporation.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

azure_functions_openapi-0.25.0.tar.gz (1.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

azure_functions_openapi-0.25.0-py3-none-any.whl (82.8 kB view details)

Uploaded Python 3

File details

Details for the file azure_functions_openapi-0.25.0.tar.gz.

File metadata

  • Download URL: azure_functions_openapi-0.25.0.tar.gz
  • Upload date:
  • Size: 1.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for azure_functions_openapi-0.25.0.tar.gz
Algorithm Hash digest
SHA256 a746da50dadd4e0997ab54e3590279ceab783461f209922ce08db137d50bf066
MD5 9ad03b2f171217266ba14f5fdc6e1984
BLAKE2b-256 84865c6a515beaa97f1c83f125438edcf521e1b304f6345c22591e931886ab3b

See more details on using hashes here.

Provenance

The following attestation bundles were made for azure_functions_openapi-0.25.0.tar.gz:

Publisher: publish-pypi.yml on yeongseon/azure-functions-openapi-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file azure_functions_openapi-0.25.0-py3-none-any.whl.

File metadata

File hashes

Hashes for azure_functions_openapi-0.25.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1c5f3038d18acd4c555204526e4b225ef8c06bd35e3d58f745f202d67e2d6bcb
MD5 91f2fdf0f0ba0a22f019b352f1bafefd
BLAKE2b-256 b802d7036c3e236f97deb851cac92566499708b2ffbbfb9b80b56b0ff9647347

See more details on using hashes here.

Provenance

The following attestation bundles were made for azure_functions_openapi-0.25.0-py3-none-any.whl:

Publisher: publish-pypi.yml on yeongseon/azure-functions-openapi-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.25.0 This release

2 files

0.24.0

2 files

0.23.0

2 files

0.22.0

2 files

0.21.2

2 files

0.21.1

2 files

0.21.0

2 files

0.20.0

2 files

0.19.1

2 files

0.19.0

2 files

0.18.2

2 files

0.18.1

2 files

0.18.0

2 files

0.17.1

2 files

0.17.0

2 files

0.16.0

2 files

0.15.1

2 files

0.15.0

2 files

0.14.0

2 files

0.13.1

2 files

0.12.1

2 files

0.12.0

2 files

0.11.0

2 files

0.10.1

2 files

0.10.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.1

2 files

0.6.0

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 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