API отвечает, но интеграция сломалась: как проверить контракт

HTTP 200 ещё не означает, что интеграция работает. Разбираем, как сравнить реальный ответ API с контрактом и найти несовместимое изменение.

API может вернуть HTTP 200, хотя интеграция уже сломана: успешный статус подтверждает, что сервер обработал запрос, но не гарантирует прежнюю структуру и смысл данных. Сначала сравните фактический ответ с согласованным контрактом, затем воспроизведите запрос тем же способом, каким его делает приложение.

Проверять нужно не только наличие JSON. Важны обязательные поля, типы, допустимые значения, вложенность и бизнес-смысл данных; после этого проверку стоит закрепить контрактным тестом.

Как выглядит нарушение контракта API

Обычно проблема проявляется после релиза одной из сторон. Запрос завершается без сетевой ошибки, но интерфейс показывает пустой блок, заказ не меняет статус, импорт пропускает записи или обработчик падает на неожиданном значении.

Признаки, которые помогают отличить такой сбой от обычной недоступности:

  • endpoint отвечает стабильно, но потребитель не может разобрать тело;
  • поле исчезло, переименовано или переместилось во вложенный объект;
  • число стало строкой, объект — массивом или значение впервые стало null;
  • появилось новое значение перечисления, которое клиент не умеет обрабатывать;
  • формат даты, единица измерения или смысл поля изменились без смены имени;
  • пагинация возвращает другой набор метаданных или иначе трактует границы страницы.

Диагностика по порядку

1. Зафиксируйте один неработающий обмен

Сохраните метод и публичный адрес endpoint, код ответа, Content-Type, обезличенное тело запроса и ответа, время с часовым поясом и версии релизов обеих сторон. Удалите токены, Cookie, персональные данные и другие секреты до передачи примера коллегам.

Важно получить ответ тем же клиентом и с теми же безопасными параметрами, при которых возникает ошибка. Проверка другого endpoint или запрос без нужного заголовка может дать корректный ответ и увести диагностику в сторону.

2. Отделите транспорт от данных

Сначала проверьте DNS, TLS, соединение, тайм-аут, HTTP-статус, редиректы и тип содержимого. Если ожидается JSON, убедитесь, что сервер действительно вернул application/json, а не HTML-страницу прокси, форму входа или текст ошибки с кодом 200.

Затем разберите тело стандартным JSON-парсером. Успешный разбор говорит только о корректном синтаксисе: совместимость с приложением ещё не доказана.

3. Сравните ответ со схемой

Источником контракта может быть утверждённое описание OpenAPI, JSON Schema или явно зафиксированная модель потребителя. Сравнивайте реальный ответ не со случайным старым примером из документации, а с версией схемы, на которую рассчитан работающий клиент.

| Изменение | Почему это важно | |---|---| | Удалено или переименовано обязательное поле | Потребитель больше не найдёт ожидаемое значение | | Изменён тип поля | Десериализация или последующая операция может завершиться ошибкой | | Допущен null вместо значения | Клиенту нужна отдельная ветка обработки | | Добавлено новое значение статуса | Закрытый список значений в клиенте может не распознать его | | Изменена вложенность | Прежний путь к данным перестаёт существовать | | Добавлено необязательное поле | Обычно совместимо, если потребитель игнорирует неизвестные поля |

Последняя строка не универсальна: строгий десериализатор может отклонить даже дополнительное поле. Поэтому правила о допустимых свойствах должны быть частью контракта, а не устной договорённостью.

4. Проверьте смысл, а не только тип

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

Полезен условный пример. Клиент ожидает {"status":"paid","currency":"RUB"}, а получает {"state":"paid","currency":null}. Ответ синтаксически корректен, но одно поле переименовано, а второе перестало соответствовать ожиданию клиента.

5. Воспроизведите сценарий потребителя

После проверки отдельного ответа запустите тот же путь, который выполняет сайт или сервис: получение данных, преобразование, сохранение и отображение результата. Так можно отличить несовместимый ответ провайдера от ошибки в маппинге, кэше или локальной бизнес-логике.

Если интеграция имеет несколько потребителей, проверьте каждый поддерживаемый вариант. Исправление, подходящее новому приложению, может оставить старый клиент неработоспособным.

Как не пропустить несовместимое изменение при релизе

Контрактная проверка должна выполняться до выкладки и на стороне поставщика, и в тестах потребителя. Практический минимум:

  1. Хранить версионируемую схему рядом с кодом, который ею управляет.
  2. Проверять примеры и тестовые ответы провайдера по этой схеме.
  3. Запускать тесты потребителя на обязательные поля, типы и известные бизнес-инварианты.
  4. Сравнивать новую и действующую версии контракта и отдельно разбирать потенциально несовместимые изменения.
  5. Для намеренного разрыва выпускать новую версию API и заранее переводить потребителей.

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

Контракт, создаваемый требованиями конкретного потребителя, можно проверять на стороне провайдера перед релизом. Такой подход особенно полезен, когда общая схема слишком широкая и не показывает, какие поля действительно критичны для работающего клиента.

Что контролировать после выкладки

Для production-проверки выбирайте безопасный read-only endpoint или отдельный диагностический сценарий без создания заказов, платежей и заявок. Контроль должен отвечать на разные вопросы:

  • доступен ли endpoint и укладывается ли ответ в допустимое время;
  • вернулся ли ожидаемый HTTP-статус и тип содержимого;
  • соответствует ли тело минимальной схеме;
  • сохраняются ли ключевые бизнес-инварианты;
  • можно ли связать ошибку с конкретной версией и журналом запроса.

Одна успешная проверка показывает состояние только в данный момент. Регулярный мониторинг помогает заметить недоступность и резкое изменение времени ответа, а контрактные тесты объясняют, совместимы ли данные.

Web-Puls можно использовать для регулярной проверки доступности URL и времени ответа; проверку полной схемы и бизнес-смысла ответа лучше оставить в CI и специализированных интеграционных тестах. О выборе адресов для контроля подробнее рассказано в статье «Мониторинг API: какие endpoint проверять».

Что делать сейчас

Возьмите один сломавшийся запрос, очистите его от секретов и сравните ответ с действующей схемой по порядку: транспорт, синтаксис, структура, типы, допустимые значения и смысл. Затем добавьте найденное расхождение в автоматический тест, чтобы следующий релиз остановился до production.

Если нужно разобрать несовместимость между сайтом и внешним API или подготовить безопасную проверку после релиза, отправьте описание ситуации и обезличенный пример ответа через форму профессиональной поддержки.

Проверьте свой сайт прямо сейчас

Введите адрес сайта: Web-Puls покажет HTTP-код, время ответа и базовую диагностику. Для постоянного контроля можно подключить мониторинг.

Нужна помощь с диагностикой ошибки?

Опишите симптомы в короткой заявке: URL, код ответа, время появления и что менялось перед сбоем. Специалист поддержки оценит задачу и предложит формат работ.