Версионирование API: чек-лист безболезненных изменений
Версия API нужна не для красоты в URL, а чтобы выпускать изменения без внезапных поломок клиентов. Чек-лист поможет выбрать схему, проверить совместимость, объявить устаревание и не потерять миграцию из виду.

Изменение поля в ответе API может сломать мобильное приложение, интеграцию партнёра и старый клиент, который никто уже не помнит. Версионирование не устраняет этот риск автоматически: оно лишь создаёт управляемый контракт между командами. Ниже — практический чек-лист для REST/HTTP API, подготовленный с учётом HTTP Semantics RFC 9110 и OpenAPI 3.1.0.
Сначала определите, что именно вы версионируете
Версия API — это версия публичного контракта: структуры запросов, ответов, кодов состояния, правил авторизации и поведения ошибок. Версия сервера, контейнера или базы данных сюда не входит. Вы можете выкатывать новую сборку без смены версии API, если внешний контракт остаётся совместимым.
Начните с инвентаризации клиентов. В список входят ваши веб-приложения и мобильные приложения, SDK, фоновые задания, интеграции партнёров, публичная документация и примеры запросов. Для каждого клиента зафиксируйте владельца, способ обновления, текущую версию контракта и дату последнего запроса.
Версия нужна там, где вы не можете одновременно обновить всех потребителей API.
Сноска. Обратно совместимое изменение — изменение, после которого корректный старый клиент продолжает работать с новым сервером. Добавление необязательного поля обычно относится к этой категории, а переименование обязательного поля — нет.
Выберите одну схему адресации
У REST API есть несколько распространённых способов сообщить серверу нужную версию. Они решают одну задачу, но по-разному ведут себя в кэшах, логах, документации и клиентских библиотеках. Не смешивайте схемы без причины: клиенту будет сложнее понять, какой контракт он вызывает.
| Подход | Пример | Плюсы | Цена и риск |
|---|---|---|---|
| Версия в пути | /api/v1/orders | Видна в логах, проста для ручной проверки и маршрутизации, легко описывается в OpenAPI. | Путь размножается; после долгой поддержки приходится обслуживать несколько наборов маршрутов. |
| Версия в заголовке | Accept: application/vnd.example.orders.v2+json | URL остаётся стабильным, можно выбирать представление ресурса через HTTP-механику. | Версию легко не заметить в браузере и логах; нужно аккуратно настроить кэширование и документацию. |
| Версия в параметре | /orders?version=2 | Просто добавить к существующему маршруту, удобно для отдельных внутренних клиентов. | Параметр могут потерять при проксировании или сборке URL; легко получить разные правила для одного ресурса. |
| Версия по дате | API-Version: 2025-01-15 | Подходит для частых изменений и долгоживущих интеграций: контракт фиксируется на дату. | Сложнее тестировать и объяснять пользователям; число вариантов контракта быстро растёт. |
Для публичного REST API с ограниченным числом крупных релизов чаще всего выбирают версию в пути: её проще увидеть в мониторинге и передать команде интеграции. Заголовки и версии по датам полезны, когда один ресурс должен иметь много представлений или контракт меняется регулярно. Универсального стандарта, который был бы обязательным для всех REST API, нет.
Чек-лист перед выпуском новой версии
- Опишите границу изменения. Составьте список затронутых маршрутов, методов, полей, кодов ответа, заголовков, ограничений и ошибок. Проверьте не только успешный ответ, но и случаи 400, 401, 403, 404, 409 и 429, если они используются вашим сервисом. Результат — diff контракта, а не только задача в трекере.
- Классифицируйте изменение. Добавление необязательного поля обычно можно выпустить в текущей версии. Удаление поля, изменение его типа, переименование, изменение смысла значения, обязательности или кода ошибки требуют отдельного решения. Если сомневаетесь, считайте изменение несовместимым до проверки реальных клиентов.
- Зафиксируйте контракт в OpenAPI. Для каждой поддерживаемой версии держите отдельное описание или явно обозначенные группы маршрутов. В OpenAPI 3.1.0 проверьте схемы запросов, ответов, параметры, security schemes и примеры. Документация должна описывать именно то, что принимает и возвращает сервер.
- Составьте матрицу совместимости. В строках разместите версии клиентов, в столбцах — версии API. Отдельно отметьте, какие мобильные приложения невозможно быстро обновить и какие партнёры требуют уведомления. Так обнаруживаются клиенты, которых не видно в репозитории.
- Добавьте контрактные проверки. Проверяйте обязательные поля, типы, допустимые значения, коды ответа и формат ошибок. Запускайте проверки против обеих версий. Если тесты ловят только серверные исключения, они не доказывают совместимость с клиентом.
- Подготовьте маршрутизацию и наблюдаемость. В логах и метриках должна присутствовать версия API, а также идентификатор клиента или приложения, если он доступен. Считайте запросы по версии, endpoint и коду ответа. Иначе вы не узнаете, остались ли пользователи старого контракта.
- Опишите миграцию. Укажите новый маршрут или заголовок, отличия схем, дату запуска, срок поддержки и пример перехода. У каждой версии должен быть владелец. Формулировка «старая версия скоро исчезнет» без даты и канала связи не является планом.
- Запустите новую версию рядом со старой. Сначала проверьте её на тестовом трафике или ограниченной группе клиентов. Перед переключением убедитесь, что старый контракт всё ещё отвечает ожидаемыми кодами, а ошибки новой версии не растут.
Что считать совместимым изменением
Обычно безопасно
- добавить необязательное поле в ответ;
- добавить новый endpoint, не меняя существующий;
- добавить новый необязательный параметр запроса с прежним поведением по умолчанию;
- расширить список значений только если старые клиенты умеют обрабатывать неизвестные значения;
- добавить новый код ошибки, если клиент корректно обрабатывает неизвестные ответы.
Последний пункт часто ошибочно считают безопасным. Клиент, который обрабатывает только 200 и 404, может показать пользователю пустой экран после появления 409 или 429. Поэтому «новый код ошибки» нужно проверять на реальных клиентах, а не только на серверных тестах.
Почти всегда требует новой версии
- переименование или удаление поля;
- смена типа: например, числа на строку или одиночного значения на массив;
- изменение часового пояса, точности, единиц измерения или семантики статуса;
- изменение обязательности параметра;
- изменение порядка или правил пагинации, если клиент рассчитывает на прежнее поведение;
- замена формата ошибок или схемы авторизации.
Что ломается на практике
Версию добавили только в документацию. Клиент продолжает обращаться к старому маршруту, а команда считает миграцию завершённой. Версия должна быть частью маршрутизации или явно передаваться в запросе, а не жить только в заголовке страницы с описанием API.
Одна схема OpenAPI описывает две версии. В результате документация показывает поля, которых нет у старого endpoint, или скрывает обязательное различие между ответами. Разделяйте схемы и запускайте проверку документации в CI.
Старую версию отключили по календарю. Публикация даты не означает, что все клиенты обновились. Перед отключением смотрите фактические запросы за период, достаточный для редких интеграций, и связывайтесь с владельцами оставшихся клиентов.
Кэш не учитывает версию. Если ответ зависит от заголовка, прокси должен различать варианты по этому заголовку. Иначе клиент может получить представление, предназначенное для другой версии. Для версии в URL проблема обычно заметнее, потому что разные адреса образуют разные ключи кэша.
Логи не содержат версию. Ошибки смешиваются, и невозможно понять, какой контракт сломался. Добавьте версию в структурированные поля логов, трассировку и дашборды, а не только в текст сообщения.
Когда какую схему выбирать
Выбирайте версию в пути, если API публичный, клиентов много, а команда хочет видеть контракт прямо в URL. Это хороший вариант для крупных несовместимых релизов вроде v1 и v2.
Выбирайте заголовок или media type, если URL должен оставаться стабильным, а инфраструктура уже умеет корректно логировать, кэшировать и маршрутизировать такие запросы. До запуска проверьте работу CDN, reverse proxy и клиентских SDK.
Выбирайте дату, если API развивается часто и каждому клиенту нужен зафиксированный срез поведения. Цена — больше вариантов для тестирования и более строгий процесс удаления старых контрактов.
Параметр запроса оставляйте для ограниченных внутренних сценариев или совместимости с уже работающей платформой. Для публичного API он редко даёт преимущества, которые компенсируют риск непоследовательной маршрутизации.
Что делать после публикации
Через неделю после выпуска сравните долю запросов по версиям, долю ошибок и задержку по каждому endpoint. Затем проверьте, какие клиенты не начали миграцию, и отправьте им адрес нового контракта с конкретным сроком и перечнем отличий. Следующий полезный шаг — автоматизировать проверку обратной совместимости в CI и завести отдельный календарь окончания поддержки для каждой версии.
Тендерный специалист 44-ФЗ / 223-ФЗ: Разбор PDF-документации закупки, поиск «заточек» под поставщика, чек-лист заявки.
Спросить за 20 ₽Источники: HTTP Semantics, RFC 9110, OpenAPI Specification 3.1.0
Частые вопросы
Нужно ли выпускать новую версию API при добавлении поля в JSON?
Что лучше для публичного API: версия в URL или заголовке?
Можно ли удалить старую версию API, если объявлен срок миграции?
Как понять, что изменение действительно несовместимое?
Нужно ли держать отдельный файл OpenAPI для каждой версии?
Что делать, если после выпуска новой версии выросли ошибки?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.