Exabit Logo

Проектирование API для системного аналитика: как не превратить интеграцию в дорогой проект

06 ноября 2025 · 4 мин чтения ·
Проектирование API для системного аналитика: как не превратить интеграцию в дорогой проект
  • «Нам нужна простая интеграция: сайт передает заказы в CRM и ERP по API».
  • «Какие именно события: создание, резерв, оплата, отмена, возврат, смена адреса?»
  • «Ну... заказ».

Обычно именно в этот момент проект и начинает ползти по срокам. Короче, API для интеграции - это не набор POST и GET, а договоренность между системами: кто меняет состояние заказа, где итоговая правда по оплате, что считать сбоем связи, а что бизнес-ошибкой.

Сначала сценарии, потом endpoint'ы

Самая частая ошибка - сразу рисовать Swagger. На практике первым документом должна быть карта сценариев: кто инициирует событие, какая система источник по каждой сущности, какие статусы вообще существуют и кто имеет право их менять.

У заказа почти никогда нет состояния «просто есть». Обычно это «создан», «подтвержден», «оплачен», «в резерве», «собран», «частично отгружен», «отменен», «возвращен». Если это не проговорить заранее, API потом растет рывками, а каждая доработка тянет пересогласование с CRM, ERP, складом и бухгалтерией.

У нас был интернет-магазин на Laravel 11. На старте описали только создание заказа и оплату. После запуска приехали 7 новых статусов и split shipment. В итоге получили 30-40% доработок к уже согласованному контракту. Код был нормальный, проблема оказалась в аналитике.

Я бы перед endpoint'ами закрыл вот что:

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

Когда поля «и так понятны», люди начинают чинить руками

В маленьких проектах это любимая ловушка. Все смотрят на поле status и думают, что уже договорились. Потом на сайте оказывается 5 статусов, в CRM - 12, в ERP - 8, и менеджер руками правит заказы, чтобы документы хоть как-то сходились.

Мы это проходили в связке сайт + CRM + 1С. Пока не сделали каноническую модель данных и таблицу маппинга, ручная обработка держалась на уровне 15-20% операций. У бухгалтера своя логика плательщика, у склада - своя логика получателя, а в интерфейсе это выглядело почти одинаково.

Swagger показывает форму данных. Интеграцию держит смысл полей и правила переходов.

Вопрос: Достаточно ли согласовать названия полей в OpenAPI?
Ответ: Нет. Нужны обязательность, справочники, ограничения, правила маппинга и понятный словарь терминов. Иначе через месяц команда будет «временно» править руками то, что стоило договорить на старте.

Хороший контракт проверяется на дублях и таймаутах

По основному сценарию обычно все выглядит аккуратно. Запрос пришел, заказ создался, статус вернулся. Настоящие расходы начинаются позже - когда ERP подвисла, клиент нажал кнопку еще раз, а система создала второй документ.

В одном B2B-проекте на Node.js 20 + NestJS счета дублировались после сетевого таймаута. Причина была простая: мы не договорились про Idempotency-Key. Потом добавили ключ, хранение результата в Redis на 24 часа, и за 2 недели инциденты этого класса почти исчезли.

Тут полезна очень простая матрица:

Ситуация Код Смысл
Объект создан сразу 201 Created операция завершена
Приняли в обработку 202 Accepted результат будет позже
Конфликт состояния 409 Conflict объект есть, но статус другой
Бизнес-правило нарушено 422 Unprocessable Entity формат верный, смысл нет

Когда команда валит все в 500, первая линия поддержки потом разбирает бизнес-ошибки как аварии инфраструктуры. Это дорогая привычка.

Иногда лучший ответ API - «принято»

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

В прошлом году мы переделывали интеграцию оптового кабинета. До этого фронт ждал ERP по 8-12 секунд, пользователи кликали повторно, а в системе росли дубли.

До: фронт ждет финальный ответ от ERP, таймауты, повторы, ручные разборы.
После: API валидирует минимум, отвечает 202 Accepted за 300-500 мс, дальше заказ уходит в RabbitMQ, итоговый статус приходит позже. На пике число ошибок просело больше чем на 40%.

Я бы в таких задачах фиксировал не только REST-контракт, но и события: что ушло в очередь, когда операция считается принятой, где проверять финальный результат. Если интеграция событийная, AsyncAPI тоже полезен, но только после сценариев, а не вместо них.

Плохой знак - когда вторую интеграцию API уже не переживает

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

Расширить контракт не получилось, пришлось его ломать и пересобирать. Рефакторинг занял 6 недель. Мы тогда сэкономили на старте пару обсуждений и сильно переплатили позже. Это была наша ошибка, вполне приземленная и дорогая.

Если хотите быстро понять, насколько API вообще спроектирован, попросите у команды не список методов, а набор артефактов:

  • карта событий и критичных сценариев;
  • каноническая модель данных и маппинги;
  • правила ошибок, повторов и идемпотентности;
  • политика версий;
  • тестовые сценарии в Postman или Insomnia.

Перед согласованием API я бы задал один вопрос: если завтра добавится еще один канал продаж, вы будете расширять контракт или переписывать его с нуля? Вот там обычно и лежит реальная цена интеграции.

Нужна помощь с реализацией?

Расскажите о задаче - предложим решение и дадим оценку сроков.