lenec ru

← все посты

Документация внутренних API: минимальный жизненный набор

14K

Внутренний сервис, к которому ходят два-три соседних сервиса в той же команде. Документации нет — «и так все знают, что туда писать». Через год команда вырастает, ходоков становится десять, половина — из других команд. Каждая интеграция начинается с переписки в чате, ответов в стиле «посмотри в коде вот тут», и через пару итераций кто-то ломает прод, потому что никто не знал про обязательное поле tenant_id.

Внутренние API часто документируют по принципу «мы сами знаем, потом расскажем». Это работает, пока команда из трёх человек, и проваливается, как только проект перерастает чат. Разберу минимально жизнеспособный набор документации для внутреннего API — что обязательно, что необязательно, и почему «полный гайд как у публичного» здесь не нужен.

Чем внутренний API отличается от публичного

Не тем, что про него можно меньше знать. А тем, что у него другая аудитория и другие тратные точки.

  • Аудитория — коллеги. Они могут зайти в код, написать в чат, спросить голосом. Внешний клиент — нет.
  • Скорость изменений выше. Публичный API — 1-2 крупных релиза в год. Внутренний — еженедельно, иногда чаще.
  • Контракт менее формальный. Поломал — починили вместе. С внешними клиентами так не получится.
  • Бюджет на документацию ниже. Никто не выделит технического писателя на каждую внутреннюю кишку.

Из этого следует: документация должна быть минимальной по объёму, максимально близкой к коду, и обновляться сама, насколько возможно.

Минимальный жизненный набор

То, без чего внутренний API превращается в чёрный ящик:

  1. Список endpoint-ов с методами, путями, кратким описанием.
  2. Схемы запросов и ответов в машиночитаемом виде (OpenAPI, gRPC proto, GraphQL schema).
  3. Пример вызова с реальными данными — curl, Postman, скрипт на питоне.
  4. Описание аутентификации: где взять токен, как его подсовывать.
  5. Список ошибок с кодами и что они означают.
  6. Контакты команды-владельца и ссылка на канал саппорта.

Всё. Если есть это — потребитель API сможет интегрироваться без личного коучинга. Если нет — каждое внедрение становится тикетом «помогите подключиться».

Список endpoint-ов

Самый частый вопрос потребителя: «у вас есть метод для X?». Если отвечать на него можно только чтением кода, документации нет.

Минимум — таблица или список с одной строкой на endpoint:

## Endpoints

- `GET /v1/users/{id}` — получить пользователя.
- `POST /v1/users` — создать пользователя.
- `PATCH /v1/users/{id}` — обновить поля пользователя.
- `DELETE /v1/users/{id}` — soft-delete, восстановление через `/users/{id}/restore`.
- `GET /v1/users` — список с пагинацией. Фильтры: `tenant_id`, `email`, `created_after`.
- `POST /v1/users/{id}/restore` — восстановить soft-deleted.

Если их сорок и больше — генерируй из OpenAPI или из аннотаций в коде. Руками поддерживать такой список — путь к расхождению с реальностью.

Схемы — обязательно машиночитаемые

Внутренний API без схемы — это «угадай, что прилетит в этом поле». Схема нужна не ради красивых страниц, а ради:

  • Генерации клиентов на стороне потребителей.
  • Автоматической проверки контракта в CI.
  • Mock-сервера для разработки.
  • Базы для рендера документации.

OpenAPI или gRPC proto хранятся в репозитории сервиса, рендерятся через Redoc/Swagger UI на простом сайте, в идеале — публикуются на внутренний хостинг. Не отдельный «документ для людей», а тот же файл, который читают тулзы.

Я обычно делаю так: /openapi.json отдаёт сам сервис на отдельном эндпоинте, /docs рендерит его в HTML. Внутри компании такого «приколочено гвоздём к сервису» оказывается достаточно.

Аутентификация: один абзац, без воды

Внутренние API часто используют что-то простое: service-to-service токен, mTLS, JWT от внутреннего OIDC. Описание занимает абзац:

## Auth

Все запросы требуют заголовок `Authorization: Bearer <token>`.

Токены выдаёт внутренний service-to-service auth (`auth.internal/v1/token`).
Время жизни 1 час, перевыпуск через client_credentials.
В deploy-конфигах — variable `INTERNAL_AUTH_TOKEN`, обновляется sidecar-ом.

Без токена — 401. Истёк — 401, нужен retry с новым токеном.

Не пиши длинные эссе про OAuth flows для внутреннего API. Скажи, где взять, как использовать, что будет, если нет.

Пример запроса с реальными данными

Описание endpoint-а в OpenAPI — это спецификация. Пример — это шпаргалка для копирования. Они нужны оба.

curl -X POST https://users.internal/v1/users \
  -H 'Authorization: Bearer eyJhbGc...' \
  -H 'Content-Type: application/json' \
  -H 'X-Tenant-Id: acme' \
  -d '{
    "email": "alice@acme.com",
    "name": "Alice",
    "role": "admin"
  }'

Был случай: у нас внутренний сервис требовал заголовок X-Tenant-Id на каждый запрос. В OpenAPI он был описан как обязательный, но в примерах его не было. Все потребители забывали его поставить, и каждое подключение начиналось с «у нас 400, что не так?». Поправили примеры — поток вопросов исчез за неделю.

Ошибки: коды и расшифровка

Не «400 Bad Request — что-то не так». Список конкретных кодов с расшифровкой и что делать клиенту:

## Errors

- `email_taken` (409) — email уже зарегистрирован.
  Клиент: предложить вход или восстановление пароля.
- `tenant_not_found` (404) — `X-Tenant-Id` не существует или нет доступа.
  Клиент: проверить заголовок и права.
- `quota_exceeded` (429) — превышена квота на создание пользователей.
  Клиент: показать сообщение, повторить через час.
- `internal_error` (500) — серверная ошибка. См. `request_id` в теле.
  Клиент: ретрай через 5 секунд, эскалация на 3-й попытке.

Это та же таблица, что для публичного API, но короче — внутренние клиенты обычно знают одно-двух разработчиков, и могут спросить уточнение в чате.

Идемпотентность, ретраи, тайм-ауты

Внутренний API работает в среде, где сетевые ошибки — норма. Если потребитель не знает, что метод POST /transfer идемпотентен по заголовку Idempotency-Key, он либо вообще не делает ретрай (теряет запрос), либо делает (создаёт дубль).

## Reliability

- POST `/transfer` принимает заголовок `Idempotency-Key` (UUID).
  Повторный запрос с тем же ключом возвращает первый ответ.
  Ключ хранится 24 часа.
- GET-эндпоинты можно ретраить свободно, они всегда идемпотентны.
- Тайм-аут на запрос — 30 секунд серверный, 60 секунд рекомендуем клиенту.
- При 5xx — exponential backoff с jitter, минимум 1 секунда между попытками.

Этот раздел экономит часы разбора инцидентов «почему у нас N дублей в базе».

Версионирование внутри компании

Семантика «v1 / v2 / breaking changes» во внутреннем API проще, чем в публичном, но всё равно нужна. Минимум:

  • Версия в URL (/v1/) или в заголовке (API-Version: 1) — выбери одно.
  • Поддержка одной предыдущей major-версии минимум 3-6 месяцев после релиза новой.
  • Анонс breaking changes в общий канал минимум за 2 недели.
  • В CHANGELOG — список потребителей, которые потенциально пострадают.

Без этого «обновили API, два сервиса слегли» становится регулярным.

Контакты и канал поддержки

Самое часто забываемое поле. На странице документации обязательно — две строки:

## Owners

- Team: `users-platform`
- Slack: `#users-platform`
- On-call: см. PagerDuty schedule `users-platform-oncall`

Без этого потребитель пишет в общий чат, его пинают по двум-трём командам, и время на инцидент растёт. С таким блоком — он сразу попадает к нужным людям.

Что НЕ нужно класть во внутреннюю документацию

  • Tutorials в стиле «getting started». Внутренний потребитель — это не новичок, ему не нужны 10 шагов «установите curl и сделайте свой первый запрос». Хватит примера.
  • Ребрендинг и маркетинг. «Сервис Users — мощное решение для управления учётными записями». Никто не читает.
  • FAQ из десяти вопросов. Один-два частых вопроса можно вынести в самый верх как «known issues», но не больше.
  • Полный API reference как для публичного. OpenAPI и Redoc этого закрывают. Не дублируй вручную.
  • Глубокую архитектурную документацию. Это другой жанр (ADR, design docs), её ищут отдельно.

Где документация живёт

Три рабочих варианта, которые видела:

  1. Markdown в репозитории сервиса. Просто, версионируется с кодом, читается прямо в GitHub/GitLab. Минус — найти трудно, если репозиториев много.
  2. Внутренний docs-сайт (Backstage TechDocs, MkDocs на корп. поддомене). Удобный поиск, единый стиль. Минус — нужна инфраструктура и регулярное обновление.
  3. Wiki (Confluence, Notion). Знакомо нетехническим коллегам. Минус — отрыв от кода, быстро устаревает, версии путаются.

Лично для документации API я выбираю первый или второй: Markdown в репо как источник правды, рендер на сайт через CI. Confluence-овые страницы про API устаревают быстрее, чем команда пишет следующую правку.

Что автоматизировать

Внутренний API меняется часто, документация «руками» отстаёт. Автоматизировать как минимум:

  • Генерацию OpenAPI из кода (FastAPI, NestJS Swagger plugin, drf-spectacular для DRF, springdoc для Spring).
  • Генерацию страницы reference из OpenAPI (Redoc CLI в CI).
  • Проверку, что схемы коммитятся вместе с кодом (CI fail, если openapi.json отличается от того, что генерируется).
  • Генерацию клиентов для основных потребителей (TypeScript, Python, Go) — закидываем в их репозитории через CI.

Если потребители получают типизированный клиент — половина вопросов «что в этом поле» отпадает сама.

Чек-лист минимальной документации внутреннего API

  • Список endpoints с описанием, генерируется из кода или коммитится.
  • Схема (OpenAPI / proto / GraphQL), доступная как файл и как рендер.
  • Пример curl-запроса, копируется и работает.
  • Раздел про аутентификацию: один абзац, конкретно.
  • Список ошибок с кодами и инструкцией клиенту.
  • Раздел про надёжность: идемпотентность, ретраи, тайм-ауты.
  • Версионирование: где смотреть, как анонсируются изменения.
  • Контакты команды: канал, on-call, owners.
  • CHANGELOG, обновляется при релизе.

Если этот лист закрыт — внутренний API готов к тому, чтобы к нему подключались без помощи команды-владельца. Дальше можно усложнять (туториалы, расширенные сценарии, гайды по типичным интеграциям), но это уже доп., а не базовый минимум. Пока базовый минимум не закрыт — никакие красивые странички про «как мы построили платформу» не помогут.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.