Интеграции без API: когда письмо становится контрактом
Что делать, когда у контрагента нет API: письмо как источник данных, адаптеры по каналам, идемпотентность и границы браузерной автоматизации.
TL;DR. Половина процессов в малом и среднем бизнесе завязана на контрагента, который интеграции не даёт: у площадки нет партнёрского API, у поставщика — только личный кабинет, у перевозчика — письма. Данные при этом всё равно приходят машиночитаемо — письмом. На нём можно построить надёжную интеграцию, если сразу заложить три вещи: адаптер на каждый канал, устойчивый идентификатор события и обработку отмен наравне с подтверждениями.
Когда API нет и не будет
Обычный сценарий: занятость, заказы или отгрузки ведутся сразу на нескольких площадках, каждая знает только про себя. Пока данные не сведены в одном месте, один и тот же слот, товар или машина уходят дважды.
Стандартный ответ — интеграция по API. Он упирается в то, что партнёрского API у части контрагентов просто нет: ни выгрузки событий, ни управления доступностью. Остаётся ручной обход личных кабинетов после каждого события — то есть работа, которую невозможно делать без пропусков.
Но машиночитаемый выход у такой площадки обычно всё-таки есть. Это письмо-уведомление, которое она присылает на каждое событие. Оно приходит в предсказуемый ящик, содержит все нужные поля и появляется в момент события, а не по расписанию опроса.
Письмо в такой схеме — не костыль, а осознанно выбранный источник данных. Разница принципиальная: костыль пишут наспех и не сопровождают, а источник данных проектируют.
Что заложить с самого начала
Адаптер на каждый канал. Формат у всех разный: одна площадка кладёт вложение в формате ICS, другая присылает HTML, где данные лежат в вёрстке шаблона, третья отличает отмену от подтверждения только темой письма. Общего парсера здесь быть не может. Зато при разделении по каналам смена шаблона у одной площадки ломает один адаптер, а не весь сбор — и это видно сразу, а не через неделю.
Устойчивый идентификатор события. Самая дорогая ошибка в такой интеграции — дубли. Письмо может прийти дважды, обработка может упасть на середине и повториться. Поэтому у каждого события должен быть ключ, который не меняется между попытками: идентификатор письма, UID из вложенного календарного файла или их комбинация. Идемпотентность здесь не украшение — без неё календарь заполняется призрачными записями, и доверие к системе теряется на первой же неделе.
Отметка на обработанном. Разобранное письмо помечается ярлыком прямо в почте. Это одновременно защита от повторной обработки и способ увидеть глазами, что система вообще видела, а что прошло мимо неё.
Отмены — полноценный сценарий, а не исключение. Пропущенное подтверждение заметят сразу. Пропущенную отмену не заметит никто: даты останутся закрытыми, слот не продастся, и потерю обнаружат в конце месяца по выручке. Обработка отмен закладывается в каждый адаптер с первого дня, а не добавляется потом.
Обратная запись: где заканчивается почта
Собрать данные в одном месте — половина задачи. Вторая половина — закрыть занятые даты или позиции в остальных каналах. Письмом это не сделать: письмо приходит от площадки, а не уходит к ней.
Здесь остаётся браузерная автоматизация — сценарий, который заходит в личный кабинет и выполняет действие руками пользователя. И вот тут важно разделить две части:
- Очередь заданий, повторные попытки и обнаружение конфликтов — обычная инфраструктура. Пишется один раз, работает для всех площадок, тестируется без единого браузера.
- Сам сценарий для конкретной площадки — хрупкая часть. Интерфейс меняется без предупреждения, сценарий ломается.
Развязка этих двух частей даёт полезное свойство: задания копятся в очереди независимо от того, готов ли сценарий для конкретного канала. Появился сценарий — накопленное выполняется без переделки логики. И статус готовности имеет смысл вести по каждому каналу отдельно: где-то работает полный цикл, где-то только приём событий. Сведение их в один общий статус «интеграция работает» — надёжный способ незаметно потерять часть данных.
Чего эта схема не даёт
- Гарантий по формату. Шаблон письма принадлежит площадке, и она меняет его когда захочет, никого не спрашивая. Нужен мониторинг: письмо пришло, а адаптер не смог его разобрать — это событие, о котором надо узнать сразу, а не из отчёта.
- Полноты данных. В письме есть то, что площадка решила в него положить. Если нужного поля там нет, взять его неоткуда.
- Мгновенности в обе стороны. Приём событий работает почти в реальном времени, а обратная запись через браузер медленнее и надёжна ровно настолько, насколько стабилен чужой интерфейс.
- Юридической беспечности. Разбор писем в собственном почтовом ящике — обычная работа с собственными данными. А вот автоматизация чужого личного кабинета часто упирается в условия использования площадки, и это стоит прочитать до разработки, а не после. Иногда правильный вывод — оставить этот шаг человеку.
Где ещё это применимо
Схема «письмо как источник данных → нормализация → единая база или календарь» переносится на любой процесс, где контрагент не даёт интеграции:
- уведомления маркетплейсов о заказах и возвратах;
- подтверждения перевозчиков и статусы отгрузок;
- выгрузки от поставщиков, которые приходят вложением по расписанию;
- заявки с чужих форм и агрегаторов, падающие на общий ящик.
Признак задачи один и тот же: событие происходит у контрагента, приходит письмом, а дальше кто-то переносит его руками.
Как мы это делали
- Синхронизация календарей занятости с каналами без API — адаптеры по каналам (ICS-вложение, HTML-шаблон, отмена по теме письма), нормализация в общий формат, единый календарь как источник правды, очередь обратной записи с повторными попытками.
- Автораспределение обращений — соседняя задача: что делать с событиями после того, как они собраны в одном месте.
Если процесс завязан на контрагента, который не даёт интеграции, — обсудим за 30 минут.