This page documents the public runtime API exposed by azure-functions-openapi.
!!! info "Import from package root"
All symbols below are exported from azure_functions_openapi.__init__, so you can import from azure_functions_openapi directly.
from azure_functions_openapi import (
OPENAPI_VERSION_3_0,
OPENAPI_VERSION_3_1,
OPENAPI_VERSION_3_2,
DocsRoutes,
OpenAPIOperationMetadata,
OpenAPIRegistry,
OpenAPISpecConfigError,
SDKIncompatibleError,
SpecReport,
SpecWarning,
WarningCode,
clear_openapi_registry,
generate_openapi_report,
generate_openapi_spec,
get_openapi_json,
get_openapi_yaml,
openapi,
register_openapi_metadata,
register_openapi_routes,
render_swagger_ui,
scan_endpoint_metadata,
scan_validation_metadata,
)| Symbol | Kind | Purpose |
|---|---|---|
openapi |
decorator | Attach operation metadata to function handlers |
register_openapi_metadata |
function | Register metadata for dynamically-created endpoints |
register_openapi_routes |
function | Explicitly register JSON, YAML, and Swagger UI routes on a supplied app |
clear_openapi_registry |
function | Remove all entries from the registry |
scan_endpoint_metadata |
function | Auto-discover validation metadata from @validate_http handlers |
scan_validation_metadata |
function | Deprecated alias for scan_endpoint_metadata (emits DeprecationWarning; removed in a future minor release) |
generate_openapi_spec |
function | Build OpenAPI dictionary from decorator registry |
generate_openapi_report |
function | Build the spec plus a deterministic tuple of structured warnings (returns SpecReport) |
get_openapi_json |
function | Build OpenAPI and serialize to JSON string |
get_openapi_yaml |
function | Build OpenAPI and serialize to YAML string |
render_swagger_ui |
function | Return Swagger UI HttpResponse |
OpenAPIOperationMetadata |
dataclass | Frozen dataclass for operation metadata |
OpenAPIRegistry |
class | Thread-safe registry backing the decorator; pass an instance for isolated (test-friendly) registration |
SpecReport |
dataclass | Result of generate_openapi_report: the spec dict plus a warnings tuple |
SpecWarning |
dataclass | A single structured warning (code, message, function_name, and optional operation path, method, location) emitted during generation |
WarningCode |
enum | Stable string identifiers for warning categories (e.g. version-skew, ambiguous-namespace) |
OpenAPISpecConfigError |
exception | Raised for configuration errors |
SDKIncompatibleError |
exception | Subclass of OpenAPISpecConfigError; raised when the installed Functions SDK is incompatible |
OPENAPI_VERSION_3_0 |
constant | OpenAPI version string "3.0.0" |
OPENAPI_VERSION_3_1 |
constant | OpenAPI version string "3.1.0" |
OPENAPI_VERSION_3_2 |
constant | OpenAPI version string "3.2.0" |
routes = register_openapi_routes(
app,
title="Orders API",
version="1.0.0",
route_prefix="/api",
auth_level=func.AuthLevel.ANONYMOUS,
)register_openapi_routes() is an explicit, opt-in convenience over three
ordinary app.route(...) registrations. It does not replace Azure Functions
routing and performs no import-time registration. The returned frozen
DocsRoutes exposes the JSON, YAML, and docs handlers for tests and
introspection; all three fields are None when enabled=False.
Customize json_route, yaml_route, docs_route, and name_prefix when the
defaults conflict with existing functions. route_prefix controls both the
generated spec paths and the URL fetched by Swagger UI. Additional generation
arguments such as description, strict, or servers can be supplied through
spec_options.
The keyword-only docs_key_forwarding: Literal["header", "query", "none"] | None = None
controls protected documentation keys:
| Value | Behavior |
|---|---|
"header" |
Recommended: no server-side key echo; the browser removes code from its page URL and sends x-functions-key only on the exact same-origin spec download, never Try-it-out |
"query" |
Legacy: copies the page request's code into the served spec URL |
"none" |
No forwarding; suitable for edge authentication or an anonymous spec |
None (default) |
Legacy query behavior with a caller-facing DeprecationWarning for protected registrations |
Anonymous routes never forward keys or warn. Explicit values suppress the warning.
The default will become "header" no earlier than the minor release after the one
that first warns, and before 1.0; see the
migration boundary. The
initial page navigation can still expose the key in access logs before browser
URL replacement. A function-scoped key authorizes only its own function; the
key must authorize both the docs and JSON functions. Prefer production edge auth.
See the protected-docs threat model.
The low-level render_swagger_ui(..., *, forward_page_key_header=False) preserves
existing output by default. Opting in reads the page query in the browser, not
on the server. Only root-relative spec URLs are eligible for header forwarding;
absolute HTTPS URLs remain supported but never receive the key, and
protocol-relative URLs are rejected. Custom CSP policies need {nonce} in
script-src for the inline scripts.
@openapi stores metadata in a thread-safe registry and the spec functions read from that registry to generate output.
@openapi metadata ---------> internal registry --> generate_openapi_spec --> JSON/YAML endpoint
@validate_http metadata --> scan_endpoint_metadata(app) --^ `--> render_swagger_ui (docs)
!!! note
get_openapi_json() and get_openapi_yaml() return strings, not HttpResponse. Wrap the returned value in func.HttpResponse in your Azure Function route.
!!! warning
If @openapi is the innermost decorator (below @app.route), it runs before
the route binding exists. Pass the completed app to the package-root
generate_openapi_spec(app=app), get_openapi_json(app=app),
get_openapi_yaml(app=app), or generate_openapi_report(app=app). Without
binding evidence, generation emits a non-fatal unresolved-route warning
before falling back to the function name. The warning remains non-fatal
under strict=True, because the fallback can be Azure's correct default
route. The low-level functions in
azure_functions_openapi.spec intentionally remain SDK-free registry compilers.
@openapi(summary="Ping", description="Health check endpoint")
@app.route(route="ping", methods=["GET"])
def ping(req: func.HttpRequest) -> func.HttpResponse:
return func.HttpResponse("ok", status_code=200)class CreateItemRequest(BaseModel):
name: str
class ItemResponse(BaseModel):
id: int
name: str
@openapi(
summary="Create item",
method="post",
route="/api/items",
requests=CreateItemRequest,
responses={
201: {
"description": "Created",
"content": {"application/json": {"schema": ItemResponse}},
},
},
)
@app.route(route="items", methods=["POST"])
def create_item(req: func.HttpRequest) -> func.HttpResponse: ...!!! note
Here the 201 entry carries the model schema in content.schema while also
setting the status description, so a single unified responses= map puts a
model schema on a non-200 success status. The request side uses the
requests= parameter.
@openapi(
summary="Raw schema example",
method="post",
requests={
"type": "object",
"properties": {"value": {"type": "string"}},
"required": ["value"],
},
responses={
200: {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {"accepted": {"type": "boolean"}},
}
}
},
}
},
)
@app.route(route="raw", methods=["POST"])
def raw(req: func.HttpRequest) -> func.HttpResponse: ...OpenAPI 3.2 adds a querystring parameter location that describes the entire
query string with a single schema. Pass a Pydantic model or raw JSON Schema via
querystring=; it is emitted only when generating a 3.2.0 document.
class SearchQuery(BaseModel):
q: str
limit: int = 10
@openapi(
summary="Search",
method="get",
querystring=SearchQuery,
# querystring_media_type defaults to "application/x-www-form-urlencoded"
)
@app.route(route="search", methods=["GET"])
def search(req: func.HttpRequest) -> func.HttpResponse: ...!!! note
querystring requires openapi_version="3.2.0" (raises
OpenAPISpecConfigError under 3.0/3.1). At most one querystring parameter is
allowed per operation, and it cannot coexist with any in: query parameter.
See Configuration for
details.
@app.route(route="openapi.json", methods=["GET"])
def openapi_json(req: func.HttpRequest) -> func.HttpResponse:
return func.HttpResponse(
get_openapi_json(title="My API", version="1.0.0", app=app), mimetype="application/json"
)
@app.route(route="openapi.yaml", methods=["GET"])
def openapi_yaml(req: func.HttpRequest) -> func.HttpResponse:
return func.HttpResponse(
get_openapi_yaml(title="My API", version="1.0.0", app=app), mimetype="application/x-yaml"
)
@app.route(route="docs", methods=["GET"])
def docs(req: func.HttpRequest) -> func.HttpResponse:
return render_swagger_ui(title="My API Docs", openapi_url="/api/openapi.json")The sections below are generated directly from source docstrings.
::: azure_functions_openapi.decorator.openapi
::: azure_functions_openapi.generate_openapi_spec
::: azure_functions_openapi.get_openapi_json
::: azure_functions_openapi.get_openapi_yaml
::: azure_functions_openapi.render_swagger_ui
::: azure_functions_openapi.scan_endpoint_metadata
Scans a FunctionApp for HTTP-triggered functions decorated with @validate_http
and auto-registers their Pydantic models in the OpenAPI registry.
from azure_functions_openapi import scan_endpoint_metadata
# Call after all routes are registered
scan_endpoint_metadata(app)!!! info "No extra dependencies required"
scan_endpoint_metadata() reads the convention-based metadata attribute
written by @validate_http. No import from azure-functions-validation is needed —
just install both packages in your project.
| Scenario | Behavior |
|---|---|
Only @validate_http |
Auto-registers discovered models |
Only @openapi |
Existing behavior unchanged |
| Both with same models | Merges additional OpenAPI fields |
| Both with different models | Raises OpenAPISpecConfigError |
Explicit @openapi |
Always takes precedence |
Response compatibility is determined from resolved JSON Schema, so a Pydantic
model in @openapi is equivalent to the same schema emitted by
@validate_http. For an equivalent status, the merged operation contains one
response entry and keeps the explicit summary and description (a blank
discovered description never replaces explicit text). Different schemas for a
shared status, request body, or parameter raise OpenAPISpecConfigError with
the method, route or function name, conflicting item, and the @openapi and
@validate_http source names.
!!! warning "scan_validation_metadata is deprecated"
scan_validation_metadata() is a deprecated alias for scan_endpoint_metadata().
The scanner now consumes the namespace-neutral "endpoint" contract (the
"validation" namespace is only a fallback), so the old name is a misnomer.
Calling it forwards unchanged but emits a DeprecationWarning, and it will be
removed in a future minor release. Switch to scan_endpoint_metadata().
generate_openapi_report() mirrors generate_openapi_spec() but returns a
SpecReport — the identical spec mapping plus a deterministic warnings tuple.
This lets CI gate a build on API drift without parsing log output.
It accepts the same document options as generate_openapi_spec(), including
infer_auth_level, servers, contact, license, external_docs, and
top-level tags:
report = generate_openapi_report(
title="My API",
servers=[{"url": "https://api.example.com"}],
tags=[{"name": "users"}],
)from azure_functions_openapi import generate_openapi_report
report = generate_openapi_report(title="My API", version="1.0.0")
if report.warnings:
for w in report.warnings:
print(w.code, w.message, w.function_name, w.method, w.path, w.location)
raise SystemExit(1) # fail the build on any warning
spec = report.spec| Symbol | Purpose |
|---|---|
SpecReport |
Dataclass with spec: dict and warnings: tuple[SpecWarning, ...] |
SpecWarning |
Frozen dataclass: code: WarningCode, message: str, function_name: str | None, plus optional path, method, and location; to_dict() includes every field for JSON |
WarningCode |
str-based enum of stable codes: version-skew, ambiguous-namespace, duplicate-operation, spec-validation, discovery-skipped, empty-discovery, method-binding-mismatch |
When conversion of an explicit request or response model fails, strict generation
raises an error naming the HTTP method, normalized emitted path, function or
registry identity, and failure location (request body or response <status>).
Non-strict generation preserves the fallback behavior and emits a
schema-substitution warning with the same context in its structured fields.
While not part of the top-level runtime import list for app code, these internals are useful when debugging:
- Registry accessor:
azure_functions_openapi.decorator.get_openapi_registry - Route sanitizer:
azure_functions_openapi.utils.validate_route_path - Operation ID sanitizer:
azure_functions_openapi.utils.sanitize_operation_id
Use these constants for explicit version selection:
from azure_functions_openapi import OPENAPI_VERSION_3_0, OPENAPI_VERSION_3_1
spec_30 = get_openapi_json(openapi_version=OPENAPI_VERSION_3_0)
spec_31 = get_openapi_json(openapi_version=OPENAPI_VERSION_3_1)!!! tip Prefer constants over hardcoded strings to avoid typos and keep version intent explicit in code review.