Автодокументация API в FastAPI: настройка, кастомизация, подводные камни
FastAPI генерирует интерактивную документацию автоматически — Swagger UI и ReDoc доступны сразу после запуска. Но дефолтная схема редко устраивает: описания пустые, модели названы невнятно, а часть эндпоинтов лучше скрыть. Разбираем, как довести автодокументацию до рабочего состояния.

Что FastAPI даёт из коробки
FastAPI (версии 0.100+) строит OpenAPI-схему на лету: каждый маршрут, каждая Pydantic-модель, каждый query-параметр попадают в JSON-схему, которую рендерят два встроенных интерфейса — Swagger UI по адресу /docs и ReDoc по адресу /redoc. Схема доступна в сыром виде по /openapi.json.
Звучит просто, но «из коробки» документация выглядит так: десятки эндпоинтов без группировки, модели с именами вроде ItemCreate и ItemCreate1, ответы описаны только для кода 200, а авторизация не отображается вовсе. Для внутренней команды это терпимо. Для внешних потребителей API — нет.
Минимальная настройка приложения
Начнём с параметров самого объекта FastAPI. Они задают метаданные, которые видит каждый, кто откроет /docs.
# main.py — FastAPI 0.110+, Pydantic v2
from fastapi import FastAPI
app = FastAPI(
title="Каталог товаров",
summary="API для управления товарами и категориями",
description=(
"Сервис предоставляет CRUD-операции над каталогом. "
"Авторизация — Bearer-токен в заголовке Authorization."
),
version="1.2.0",
docs_url="/docs", # None — отключить Swagger UI
redoc_url="/redoc", # None — отключить ReDoc
openapi_url="/openapi.json",
)
Параметры title, summary и description попадают в шапку документации. version показывает потребителю, с какой ревизией он работает. Если API не предназначен для внешних глаз, docs_url=None скрывает интерфейс целиком.
Группировка через теги
Без тегов все маршруты сваливаются в один список. Теги задают логические группы и их порядок.
from fastapi import FastAPI
tags_metadata = [
{
"name": "Товары",
"description": "Создание, обновление и удаление товаров",
},
{
"name": "Категории",
"description": "Управление деревом категорий",
},
{
"name": "Служебные",
"description": "Health-check и метрики",
},
]
app = FastAPI(
title="Каталог товаров",
version="1.2.0",
openapi_tags=tags_metadata,
)
Каждый маршрут привязывается к тегу через аргумент tags:
@app.get("/items/{item_id}", tags=["Товары"])
async def get_item(item_id: int):
...
Порядок групп в tags_metadata — это порядок в документации. Swagger UI и ReDoc оба его уважают.
Скрытие служебных маршрутов
Эндпоинт, который не нужен потребителю (например, внутренний health-check для Kubernetes), можно убрать из схемы, не удаляя сам маршрут:
@app.get("/healthz", include_in_schema=False)
async def healthz():
return {"status": "ok"}
Описание запросов и ответов
Самая частая проблема — голые модели без описаний полей и пустые секции ответов. Pydantic v2 и декораторы FastAPI закрывают обе.
from pydantic import BaseModel, Field
from fastapi import Query, Path
class ItemOut(BaseModel):
"""Карточка товара, возвращаемая клиенту."""
id: int = Field(examples=[42])
name: str = Field(
min_length=1,
max_length=200,
description="Название товара на русском",
examples=["Кроссовки беговые"],
)
price_rub: float = Field(
gt=0,
description="Цена в рублях, включая НДС",
examples=[4999.0],
)
@app.get(
"/items/{item_id}",
response_model=ItemOut,
summary="Получить товар по ID",
description="Возвращает полную карточку. Если товар не найден — 404.",
responses={
404: {"description": "Товар с таким ID отсутствует"},
},
tags=["Товары"],
)
async def get_item(
item_id: int = Path(description="Уникальный идентификатор товара", ge=1),
):
...
Обратите внимание на examples в Field — Swagger UI подставит эти значения в форму «Try it out», и потребителю не придётся угадывать формат. В Pydantic v2 параметр examples принимает список; единичный пример через устаревший example всё ещё работает, но будет удалён в будущих версиях.
Документирование нескольких кодов ответа
По умолчанию FastAPI документирует только 200 (или 201, если указан status_code). Всё остальное — responses.
| Ситуация | Что добавить |
|---|---|
| Валидация не прошла | 422 — FastAPI добавляет сам, с описанием ValidationError |
| Объект не найден | 404 — добавлять вручную через responses |
| Нет прав | 403 — добавлять вручную |
| Внутренняя ошибка | 500 — обычно не документируют, но для внешних API стоит |
Авторизация в документации
Если API защищён токеном, Swagger UI должен показывать кнопку «Authorize» и отправлять заголовок. Иначе «Try it out» бесполезен.
from fastapi.security import HTTPBearer
security = HTTPBearer()
@app.get("/items/", dependencies=[Depends(security)], tags=["Товары"])
async def list_items():
...
HTTPBearer добавляет в OpenAPI-схему секцию securitySchemes. Swagger UI рисует замок рядом с защищёнными эндпоинтами и предлагает ввести токен. Для OAuth2 используется OAuth2PasswordBearer — механизм тот же, но схема описывает ещё и tokenUrl.
Документация, в которой нельзя нажать «Try it out» и получить ответ, — это PDF с красивой вёрсткой, а не инструмент. Если потребитель не может протестировать запрос прямо из браузера, вы потеряли половину ценности автодокументации.
Кастомизация интерфейса
Иногда нужно подключить корпоративный CSS, заменить логотип или раздать Swagger UI из собственных статических файлов (например, в закрытой сети без доступа к CDN). FastAPI позволяет переопределить HTML-страницу документации целиком через get_swagger_ui_html:
from fastapi import FastAPI
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.staticfiles import StaticFiles
app = FastAPI(docs_url=None) # отключаем дефолтный /docs
app.mount("/static", StaticFiles(directory="static"), name="static")
@app.get("/docs", include_in_schema=False)
async def custom_docs():
return get_swagger_ui_html(
openapi_url=app.openapi_url,
title=app.title,
swagger_js_url="/static/swagger-ui-bundle.js",
swagger_css_url="/static/swagger-ui.css",
)
Файлы swagger-ui-bundle.js и swagger-ui.css скачиваются из официального репозитория swagger-api/swagger-ui и кладутся в директорию static/. Версию Swagger UI стоит зафиксировать: обновления иногда ломают рендер кастомных расширений.
Подводные камни
Дубликаты имён моделей
Если в разных модулях есть class Item(BaseModel), OpenAPI-схема получит конфликт. FastAPI добавит суффикс, и потребитель увидит Item и Item1 — без намёка на разницу. Решение: давайте моделям уникальные имена или используйте вложенные модели.
Документация расходится с реальностью
Автодокументация генерируется из кода, но есть сценарии, когда она врёт:
- Middleware меняет тело ответа после обработчика — схема этого не знает.
- Зависимость (
Depends) добавляет заголовки или меняет статус-код — в схему это не попадает автоматически. - Ответ формируется через
JSONResponseнапрямую, а не черезresponse_model— FastAPI не может вывести тип.
Каждый из этих случаев требует ручного описания через responses или кастомизации схемы.
Тяжёлая схема на больших проектах
На API в 300+ эндпоинтов /openapi.json может весить несколько мегабайт. Swagger UI при этом ощутимо тормозит. Два способа облегчить:
- Разнести API на несколько
FastAPI-приложений и подключить черезapp.mount— у каждого будет своя схема. - Генерировать схему при старте и кешировать, а не пересобирать на каждый запрос к
/openapi.json. Для этого достаточно переопределить методapp.openapi().
Что делать дальше
Автодокументация — отправная точка, а не финальный продукт. После настройки стоит:
- Экспортировать
/openapi.jsonи сгенерировать клиент для фронтенда черезopenapi-generatorилиopenapi-typescript-codegen— схема, которую вы уже написали, становится контрактом. - Добавить тест, который сравнивает текущую схему с эталонной: так вы узнаете о случайном изменении контракта до того, как узнает потребитель.
- Проверить, что
/docsи/redocзакрыты авторизацией на проде, если API не публичный.
Документация, которая обновляется вместе с кодом и позволяет сделать запрос из браузера, — это не бонус, а минимальный стандарт для любого HTTP API в 2024–2025 годах. FastAPI даёт инструменты для этого бесплатно — нужно только не оставлять дефолты как есть.
Сноска. OpenAPI (ранее Swagger) — спецификация для описания HTTP API в машиночитаемом формате (JSON или YAML). На её основе генерируются интерактивные интерфейсы, клиентские библиотеки и серверные заглушки. Текущая версия — OpenAPI 3.1, которую FastAPI поддерживает начиная с версии 0.100.
Генератор изображений: Иллюстрация, обложка, баннер, схема — по текстовому описанию, без исходного фото.
Спросить за 20 ₽Источники: FastAPI — официальная документация: Metadata and Docs URLs, OpenAPI Specification 3.1.0
Частые вопросы
Можно ли отключить документацию на проде?
Чем Swagger UI отличается от ReDoc в FastAPI?
Как описать загрузку файла, чтобы это отобразилось в документации?
У меня другая версия FastAPI (ниже 0.100). Будет ли всё работать?
Документация показывает модель Item и Item1 — как исправить?
Как добавить markdown-форматирование в описания эндпоинтов?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.