Обратная совместимость API
Меняем API, не ломаем клиентов
Обратная совместимость API — это когда клиенты, написанные под предыдущую версию, продолжают работать после изменений на сервере и не требуют доработки. Ниже — таблица изменений с примерами: что можно менять спокойно, а что ломает клиентов.
Выпуск новой версии API — это всегда головная боль:
- 1Нужно уведомить всех клиентов
- 2Поддерживать две версии параллельно
- 3Дождаться перехода всех на новую версию API
- 4И только потом выводить старую версию API из эксплуатации
Поэтому, если у вас планируется несовместимое изменение для существующих API-методов, сначала попробуйте сделать его обратно совместимым в текущей версии API.
Как это сделать? Смотрите рекомендации в нашем гайде.
Как пользоваться
Прежде чем вносить изменение в действующий API-метод, пройдитесь по таблице. Нашли своё предполагаемое изменение? Смотрите, что делать, чтобы избежать головной боли.
Таблица изменений API: что совместимо, а что ломает клиентов
| Изменение в API-методе | Пример | Обратная совместимость | Как реализовать |
|---|---|---|---|
| 1 Изменение в API-методе Новое необязательное поле или вложенный объект |
Пример Было POST /orders
{ "items": [ … ] }Стало POST /orders
{ "items": [ … ],
"comment": "Позвонить" } |
Обратная совместимостьВсё ок Старые клиенты продолжают работать как раньше. |
Как реализовать
|
| 2 Изменение в API-методе Новое значение enum в ответе |
Пример Было GET /orders/17
{ "status": "SHIPPED" }Стало GET /orders/17
{ "status": "REFUNDED" }
|
Обратная совместимостьЗависит Ок при условии, что все клиенты умеют обрабатывать незнакомые значения. |
Как реализовать
|
| 3 Изменение в API-методе Переименование значения enum |
Пример Было "status": "CANCELED" Стало "status": "CANCELLED" Безопасно enum: - CANCELED # deprecated - CANCELLED |
Обратная совместимостьЛомает Клиенты, которые ждут старое значение, не узнают новое. |
Как реализовать
|
| 4 Изменение в API-методе Смена типа полячисло → строка |
Пример Было "userId": 1001 Стало "userId": "1001" Безопасно "userId": 1001, "userIdStr": "1001" Так сделал Twitter: числовой |
Обратная совместимостьЛомает Клиент ждёт число, а получает строку: ошибка разбора или неверное сравнение. |
Как реализовать
|
| 5 Изменение в API-методе Новый обязательный параметр или более строгая валидация |
Пример Было POST /orders
{ "items": [ … ] }Стало POST /orders
{ "items": [ … ],
"deliveryType": "COURIER" }Безопасно deliveryType: type: string default: COURIER
|
Обратная совместимостьЛомает Старые клиенты не знают про параметр и получают ошибку 400. Особенно для мобильных приложений: старые версии живут у пользователей месяцами. |
Как реализовать
|
| 6 Изменение в API-методе Переименование или удаление поля |
Пример Было { "name": "Анна" }Стало { "firstname": "Анна" }Безопасно { "name": "Анна",
"firstname": "Анна" } |
Обратная совместимостьЛомает Клиент читает |
Как реализовать
|
| 7 Изменение в API-методе Смена формата даты |
Пример Было "createdAt": "25.12.2026" Стало "createdAt": "2026-12-25" Безопасно "createdAt": "25.12.2026", "createdDate": "2026-12-25" |
Обратная совместимостьЛомает Клиентский парсер ждёт ДД.ММ.ГГГГ и не разберёт новую строку. |
Как реализовать
|
| 8 Изменение в API-методе Смена уровня иерархииполя переехали во вложенный объект |
Пример Было { "id": 42,
"city": "Казань",
"country": "RU" }Стало { "id": 42,
"address": {
"city": "Казань",
"country": "RU" } }Безопасно { "id": 42,
"city": "Казань",
"country": "RU",
"address": {
"city": "Казань",
"country": "RU" } } |
Обратная совместимостьЛомает Клиент ищет |
Как реализовать
|
Где хранить версию API
Версия должна где-то жить. Выберите один способ и зафиксируйте его в требованиях.
В URL
/v2/ordersВерсия видна в любой ссылке, логе и документации. Минус: у всех методов меняется адрес.
В заголовке
X-GitHub-Api-Version: 2022-11-28Stripe-Version: 2026-09-30.endiveАдреса методов не меняются. Так делают GitHub и Stripe: версия обозначена датой.
Что записать в требованиях
- Где передаётся версия: в URL или в заголовке.
- Какая версия применяется, если клиент её не передал. У GitHub это 2022-11-28.
- Сколько версий поддерживаем параллельно. GitHub держит предыдущую версию не меньше 24 месяцев после выхода новой.
Как выводить старую версию из эксплуатации
Старую версию не выключают в один день. Объявите, назначьте дату, проверьте по логам и только потом отключайте.
- 1
Объявили
Deprecation: @1798761600Link: <https://api.example.com/migrate-v2>; rel="deprecation"Версия устарела с 1 января 2027 (RFC 9745). В ссылке — инструкция по миграции. Напишите клиентам и добавьте запись в changelog.
- 2
Назначили дату
Sunset: Thu, 01 Jul 2027 00:00:00 GMTПлановое отключение (RFC 8594). Дата Sunset не раньше даты Deprecation.
- 3
Проверили по логам
Посмотрите, кто ещё вызывает старую версию, и напишите этим клиентам лично до даты отключения.
- 4
Отключили
410 GoneПосле Sunset старая версия отвечает 410 Gone со ссылкой на новую.
Частые вопросы про обратную совместимость API
Что такое обратная совместимость API?
Это свойство API, при котором клиенты, написанные под предыдущую версию, продолжают работать после изменений на сервере и не требуют доработки. Например, добавление необязательного поля в ответ обычно совместимо, а переименование поля — нет.
Какие изменения API обратно совместимы?
Безопасно добавлять необязательные поля, вложенные объекты и параметры со значением по умолчанию. Новое значение enum в ответе совместимо, если все клиенты умеют обрабатывать неизвестные значения. При этом клиенты должны игнорировать незнакомые поля.
Какие изменения API ломают клиентов?
Переименование значения enum, смена типа поля, новый обязательный параметр или более строгая валидация, переименование или удаление поля, смена формата даты и смена уровня иерархии, например перенос полей во вложенный объект.
Как переименовать поле в API и не сломать клиентов?
Отдавайте оба поля с одним значением: старое name и новое firstname. В запросах принимайте оба. Старое поле пометьте как deprecated, по логам смотрите, кто его ещё читает, и удалите после даты Sunset.
Где хранить версию API: в URL или в заголовке?
Подходят оба способа. В URL версия видна в любой ссылке, но у всех методов меняется адрес (/v2/orders). В заголовке адреса не меняются: так делают GitHub (X-GitHub-Api-Version) и Stripe (Stripe-Version). Выберите один способ и зафиксируйте его в требованиях.
Как объявить, что версия API устарела?
Отправляйте заголовок Deprecation (RFC 9745), добавьте в Link ссылку на инструкцию по миграции с rel="deprecation" и назначьте дату отключения заголовком Sunset (RFC 8594). После даты Sunset старая версия отвечает 410 Gone.
Гайд «Обратная совместимость API»
4 страницы A4: таблица изменений с примерами, хранение версии и вывод старой версии из эксплуатации. Откройте на следующем API-review.
Разборы по API и архитектуре — в Telegram-канале @getanalysts


