diff --git a/fastapi/routing.py b/fastapi/routing.py
index e2c83aa7..ffb22446 100644
--- a/fastapi/routing.py
+++ b/fastapi/routing.py
@@ -1,5 +1,6 @@
 import contextlib
 import email.message
+import email.utils
 import functools
 import inspect
 import json
@@ -21,6 +22,7 @@ from contextlib import (
     AsyncExitStack,
     asynccontextmanager,
 )
+from datetime import datetime, timezone
 from enum import Enum, IntEnum
 from typing import (
     Annotated,
@@ -344,6 +346,70 @@ def _build_response_args(
     return response_args
 
 
+def _first_not_none(*values: _T | None) -> _T | None:
+    """
+    Return the first value that is not `None`, or `None` if all are `None`.
+
+    Used to resolve the precedence of the deprecation related configuration
+    (`deprecated`, `sunset`, `deprecation_date` and `successor_url`) between a
+    *path operation*, the routers it belongs to and the app.
+    """
+    for value in values:
+        if value is not None:
+            return value
+    return None
+
+
+def _format_http_date(value: datetime) -> str:
+    """
+    Format a datetime as an RFC 7231 HTTP-date (IMF-fixdate), e.g.
+    `Sun, 06 Nov 1994 08:49:37 GMT`.
+
+    Naive datetimes are assumed to be in UTC.
+    """
+    if value.tzinfo is None:
+        value = value.replace(tzinfo=timezone.utc)
+    return email.utils.format_datetime(value.astimezone(timezone.utc), usegmt=True)
+
+
+def _apply_deprecation_headers(
+    response: Response,
+    *,
+    deprecated: bool | None,
+    deprecation_date: datetime | None,
+    sunset: datetime | None,
+    successor_url: str | None,
+) -> None:
+    """
+    Add the deprecation related HTTP headers to a response:
+
+    * `Deprecation` (RFC 8898): the deprecation date if `deprecation_date` is
+        set, otherwise `true` if the route is marked as deprecated.
+    * `Sunset` (RFC 8594): the sunset date if `sunset` is set.
+    * `Link` (RFC 8288): a link with `rel="successor-version"` pointing to
+        `successor_url`, if set.
+
+    Existing `Deprecation` and `Sunset` headers are preserved (checked
+    case-insensitively). An existing `Link` header is merged with the
+    successor link, following RFC 8288 list semantics.
+    """
+    headers = response.headers
+    if "deprecation" not in headers:
+        if deprecation_date is not None:
+            headers["Deprecation"] = _format_http_date(deprecation_date)
+        elif deprecated:
+            headers["Deprecation"] = "true"
+    if sunset is not None and "sunset" not in headers:
+        headers["Sunset"] = _format_http_date(sunset)
+    if successor_url is not None:
+        successor_link = f'<{successor_url}>; rel="successor-version"'
+        existing_link = headers.get("link")
+        if existing_link:
+            headers["Link"] = f"{existing_link}, {successor_link}"
+        else:
+            headers["Link"] = successor_link
+
+
 def get_request_handler(
     dependant: Dependant,
     body_field: ModelField | None = None,
@@ -819,6 +885,9 @@ class APIRoute(routing.Route):
         response_description: str = "Successful Response",
         responses: dict[int | str, dict[str, Any]] | None = None,
         deprecated: bool | None = None,
+        sunset: datetime | None = None,
+        deprecation_date: datetime | None = None,
+        successor_url: str | None = None,
         name: str | None = None,
         methods: set[str] | list[str] | None = None,
         operation_id: str | None = None,
@@ -865,6 +934,17 @@ class APIRoute(routing.Route):
         self.summary = summary
         self.response_description = response_description
         self.deprecated = deprecated
+        self.sunset = sunset
+        self.deprecation_date = deprecation_date
+        self.successor_url = successor_url
+        # The values explicitly set for this route, before router-level
+        # defaults are applied. APIRouter.add_api_route() overrides these with
+        # the original per-route values, so that include_router() can tell
+        # apart route-level values from values inherited from router defaults.
+        self._explicit_deprecated = deprecated
+        self._explicit_sunset = sunset
+        self._explicit_deprecation_date = deprecation_date
+        self._explicit_successor_url = successor_url
         self.operation_id = operation_id
         self.response_model_include = response_model_include
         self.response_model_exclude = response_model_exclude
@@ -972,7 +1052,7 @@ class APIRoute(routing.Route):
         self.app = request_response(self.get_route_handler())
 
     def get_route_handler(self) -> Callable[[Request], Coroutine[Any, Any, Response]]:
-        return get_request_handler(
+        handler = get_request_handler(
             dependant=self.dependant,
             body_field=self.body_field,
             status_code=self.status_code,
@@ -990,6 +1070,26 @@ class APIRoute(routing.Route):
             stream_item_field=self.stream_item_field,
             is_json_stream=self.is_json_stream,
         )
+        if (
+            not self.deprecated
+            and self.deprecation_date is None
+            and self.sunset is None
+            and self.successor_url is None
+        ):
+            return handler
+
+        async def deprecation_headers_handler(request: Request) -> Response:
+            response = await handler(request)
+            _apply_deprecation_headers(
+                response,
+                deprecated=self.deprecated,
+                deprecation_date=self.deprecation_date,
+                sunset=self.sunset,
+                successor_url=self.successor_url,
+            )
+            return response
+
+        return deprecation_headers_handler
 
     def matches(self, scope: Scope) -> tuple[Match, Scope]:
         match, child_scope = super().matches(scope)
@@ -1210,6 +1310,45 @@ class APIRouter(routing.Router):
                 """
             ),
         ] = None,
+        sunset: Annotated[
+            datetime | None,
+            Doc(
+                """
+                Declare a date and time when all *path operations* in this
+                router are planned to stop being available (their
+                "sunset" moment).
+
+                Responses will include a `Sunset` header (RFC 8594) and the
+                generated OpenAPI will include `x-sunset`.
+                """
+            ),
+        ] = None,
+        deprecation_date: Annotated[
+            datetime | None,
+            Doc(
+                """
+                Declare the date and time when all *path operations* in this
+                router became (or will become) deprecated.
+
+                Responses will include a `Deprecation` header with this date
+                (instead of `Deprecation: true`) and the generated OpenAPI will
+                include `x-deprecation-date`.
+                """
+            ),
+        ] = None,
+        successor_url: Annotated[
+            str | None,
+            Doc(
+                """
+                URL (relative or absolute) of the successor version of the
+                *path operations* in this router.
+
+                Responses will include a `Link` header with
+                `rel="successor-version"` (RFC 8288) and the generated OpenAPI
+                will include `x-successor-url`.
+                """
+            ),
+        ] = None,
         include_in_schema: Annotated[
             bool,
             Doc(
@@ -1301,6 +1440,9 @@ class APIRouter(routing.Router):
         self.tags: list[str | Enum] = tags or []
         self.dependencies = list(dependencies or [])
         self.deprecated = deprecated
+        self.sunset = sunset
+        self.deprecation_date = deprecation_date
+        self.successor_url = successor_url
         self.include_in_schema = include_in_schema
         self.responses = responses or {}
         self.callbacks = callbacks or []
@@ -1343,6 +1485,9 @@ class APIRouter(routing.Router):
         response_description: str = "Successful Response",
         responses: dict[int | str, dict[str, Any]] | None = None,
         deprecated: bool | None = None,
+        sunset: datetime | None = None,
+        deprecation_date: datetime | None = None,
+        successor_url: str | None = None,
         methods: set[str] | list[str] | None = None,
         operation_id: str | None = None,
         response_model_include: IncEx | None = None,
@@ -1379,6 +1524,14 @@ class APIRouter(routing.Router):
         current_generate_unique_id = get_value_or_default(
             generate_unique_id_function, self.generate_unique_id_function
         )
+        current_deprecated = deprecated if deprecated is not None else self.deprecated
+        current_sunset = sunset if sunset is not None else self.sunset
+        current_deprecation_date = (
+            deprecation_date if deprecation_date is not None else self.deprecation_date
+        )
+        current_successor_url = (
+            successor_url if successor_url is not None else self.successor_url
+        )
         route = route_class(
             self.prefix + path,
             endpoint=endpoint,
@@ -1390,7 +1543,10 @@ class APIRouter(routing.Router):
             description=description,
             response_description=response_description,
             responses=combined_responses,
-            deprecated=deprecated or self.deprecated,
+            deprecated=current_deprecated,
+            sunset=current_sunset,
+            deprecation_date=current_deprecation_date,
+            successor_url=current_successor_url,
             methods=methods,
             operation_id=operation_id,
             response_model_include=response_model_include,
@@ -1410,6 +1566,14 @@ class APIRouter(routing.Router):
                 strict_content_type, self.strict_content_type
             ),
         )
+        # Keep the values explicitly passed for this route (before applying
+        # this router's defaults) so that include_router() can apply its own
+        # parameters to routes that didn't set a value, overriding the
+        # included router's defaults without overriding route-level values.
+        route._explicit_deprecated = deprecated
+        route._explicit_sunset = sunset
+        route._explicit_deprecation_date = deprecation_date
+        route._explicit_successor_url = successor_url
         self.routes.append(route)
