]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
✨ Add OpenAPI `external_docs` parameter to `FastAPI` (#13713)
authorCarlos Mario Toro <41237977+cmtoro@users.noreply.github.com>
Sat, 20 Sep 2025 17:11:46 +0000 (12:11 -0500)
committerGitHub <noreply@github.com>
Sat, 20 Sep 2025 17:11:46 +0000 (19:11 +0200)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Motov Yurii <109919500+YuriiMotov@users.noreply.github.com>
fastapi/applications.py
fastapi/openapi/utils.py
tests/main.py
tests/test_application.py

index 05c7bd2be71ce3027a4bbf111d50cd940156384f..b3424efcc780a3a5bfac5f59b0f343dbbf01b9dd 100644 (file)
@@ -810,6 +810,32 @@ class FastAPI(Starlette):
                 """
             ),
         ] = True,
+        openapi_external_docs: Annotated[
+            Optional[Dict[str, Any]],
+            Doc(
+                """
+                This field allows you to provide additional external documentation links.
+                If provided, it must be a dictionary containing:
+
+                * `description`: A brief description of the external documentation.
+                * `url`: The URL pointing to the external documentation. The value **MUST**
+                be a valid URL format.
+
+                **Example**:
+
+                ```python
+                from fastapi import FastAPI
+
+                external_docs = {
+                    "description": "Detailed API Reference",
+                    "url": "https://example.com/api-docs",
+                }
+
+                app = FastAPI(openapi_external_docs=external_docs)
+                ```
+                """
+            ),
+        ] = None,
         **extra: Annotated[
             Any,
             Doc(
@@ -838,6 +864,7 @@ class FastAPI(Starlette):
         self.swagger_ui_parameters = swagger_ui_parameters
         self.servers = servers or []
         self.separate_input_output_schemas = separate_input_output_schemas
+        self.openapi_external_docs = openapi_external_docs
         self.extra = extra
         self.openapi_version: Annotated[
             str,
@@ -992,6 +1019,7 @@ class FastAPI(Starlette):
                 tags=self.openapi_tags,
                 servers=self.servers,
                 separate_input_output_schemas=self.separate_input_output_schemas,
+                external_docs=self.openapi_external_docs,
             )
         return self.openapi_schema
 
index eda64a9994ccfc1463db0cc31b76ca3f9026cff1..21105cf654fb92a88081d21ae3530550ec3eb36d 100644 (file)
@@ -488,6 +488,7 @@ def get_openapi(
     contact: Optional[Dict[str, Union[str, Any]]] = None,
     license_info: Optional[Dict[str, Union[str, Any]]] = None,
     separate_input_output_schemas: bool = True,
+    external_docs: Optional[Dict[str, Any]] = None,
 ) -> Dict[str, Any]:
     info: Dict[str, Any] = {"title": title, "version": version}
     if summary:
@@ -565,4 +566,6 @@ def get_openapi(
         output["webhooks"] = webhook_paths
     if tags:
         output["tags"] = tags
+    if external_docs:
+        output["externalDocs"] = external_docs
     return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True)  # type: ignore
index 6927eab61b254b389bdf098eb0d6adec789f9046..2f1d6171155aca526ea2ed160e226d2524f7d1c8 100644 (file)
@@ -3,7 +3,12 @@ from typing import FrozenSet, List, Optional
 
 from fastapi import FastAPI, Path, Query
 
-app = FastAPI()
+external_docs = {
+    "description": "External API documentation.",
+    "url": "https://docs.example.com/api-general",
+}
+
+app = FastAPI(openapi_external_docs=external_docs)
 
 
 @app.api_route("/api_route")
index a7d50ea72afe857ce1a62b6778d2882a1eacbe89..8f1b0a18d37728f1651f328a72a6c09966d464af 100644 (file)
@@ -58,6 +58,10 @@ def test_openapi_schema():
     assert response.json() == {
         "openapi": "3.1.0",
         "info": {"title": "FastAPI", "version": "0.1.0"},
+        "externalDocs": {
+            "description": "External API documentation.",
+            "url": "https://docs.example.com/api-general",
+        },
         "paths": {
             "/api_route": {
                 "get": {