diff --git a/fastapi/applications.py b/fastapi/applications.py index 05c7bd2be..5373185d4 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -810,6 +810,47 @@ class FastAPI(Starlette): """ ), ] = True, + openapi_external_docs: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + This field allows you to provide additional external documentation links + for an API operation or component. It’s an optional field and can be added + to an operation or a tag. If provided, it must be a dictionary containing: + + * `description`: A brief description of the external documentation, which may use + [CommonMark syntax](https://commonmark.org/) for rich text formatting. + * `url`: The URL pointing to the external documentation. The value **MUST** + be a valid URL format. + + **Example**: + + ```python + from fastapi import FastAPI + from typing import Dict, Any + from typing import Optional + from fastapi.openapi.models import Doc + from typing_extensions import Annotated + + external_docs: Annotated[Optional[Dict[str, Any]], Doc()] = { + "description": "Detailed API Reference", + "url": "https://example.com/api-docs", + } + + app = FastAPI(openapi_external_docs=external_docs) + + ``` + + ### Explanation: + - `description`: Provides a short description explaining what this external documentation covers. + - `url`: Points to the full external documentation. + + **Notes**: + - This field is **optional**; if not included, no external documentation will be linked. + - You can use this feature to link to full API documentation, tutorials, or any other + """ + ), + ] = None, **extra: Annotated[ Any, Doc( @@ -838,6 +879,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 +1034,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 diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..b2913963e 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -489,6 +489,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: @@ -566,4 +567,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 diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index b3f83ae23..85b74aa43 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -5,7 +5,12 @@ from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient from pydantic import BaseModel -app = FastAPI() +external_docs = { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general", +} + +app = FastAPI(openapi_external_docs=external_docs) class Item(BaseModel): @@ -468,4 +473,8 @@ def test_openapi_schema(): }, } }, + "externalDocs": { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general", + }, }