Интеграции: API, вебхуки, CRM/сайт и события пользователя
Как эта тема связывает данные, доставку и контент
В предыдущих статьях мы подготовили основу:
архитектуру Unisendr как слоя между продуктом и каналами доставки
домены и доставляемость (SPF/DKIM/DMARC, статусы)
управление контактами (поля, теги, сегменты, согласия)
шаблоны и персонализациюТеперь собираем всё в рабочую систему: как именно данные попадают в Unisendr и как результаты рассылок возвращаются обратно.
Ключевая идея: интеграция должна обеспечивать актуальные профили, корректные события и надёжную обратную связь (отписки, ошибки, статусы), иначе сегменты, триггеры и персонализация будут работать непредсказуемо.
!Общая схема потоков данных: кто и куда отправляет API-запросы и webhooks
Базовые понятия интеграций
Источник данных
Источник данных — система, где возникает факт или хранится состояние пользователя. Типичные источники:
backend продукта (основной профиль, тариф, безопасность)
сайт и формы (подписки, лиды)
CRM (статусы лидов/сделок, менеджер, сегментация продаж)
биллинг (оплаты, чеки, возвраты)API-интеграция
API-интеграция — вы инициируете HTTP-запросы в Unisendr, чтобы создать/обновить контакт, отправить событие или запустить сценарий.
Вебхук
Вебхук — HTTP-запрос в вашу систему, который отправляет Unisendr или провайдер доставки, чтобы сообщить о факте: доставка, ошибка, отписка, жалоба.
Событие пользователя
Событие — запись о действии пользователя или изменении состояния, которое важно для триггера, персонализации или аналитики.
Примеры:
user_registered
email_confirmed
order_paid
trial_expiringПаттерны интеграций: как выбрать комбинацию
На практике почти всегда используется комбинация из трёх потоков.
Онлайн API: контакт и события отправляются в момент действия.
Пакетная синхронизация: периодические выгрузки из CRM/хранилища.
Вебхуки обратно: статусы доставки и изменения согласий возвращаются в ваш контур.Когда достаточно только пакетной синхронизации
Unisendr используется для редких маркетинговых рассылок
нет триггеров, критичных к минутам
CRM является единственным источником правды по аудиторииМинусы: сложно сделать welcome-цепочки, брошенную корзину и точные окна актуальности.
Когда нужен онлайн API
триггеры должны стартовать быстро (регистрация, оплата)
персонализация зависит от последнего действия
важно минимизировать рассинхронизацию сегментовПочему вебхуки обычно обязательны
Без вебхуков вы теряете управление качеством базы и согласиями:
отписка может не попасть в вашу базу
hard bounce не остановит дальнейшие отправки
жалоба это спам не приведёт к немедленному исключениюAPI-интеграция: контакты
Основная операция: upsert контакта
Upsert означает: если контакт уже есть — обновить, если нет — создать. Это базовый режим, чтобы интеграция была устойчивой к повторным попыткам и частичным сбоям.
Рекомендации к контракту данных:
один стабильный основной ключ (часто user_id)
email и телефон как изменяемые поля
согласия и их метаданные (дата, источник)Пример полезной структуры данных контакта (псевдоформат):
Политика обновления: не затирать хорошее пустым
Определите правило для каждого поля:
если поле пришло пустым, это удаление или нет данных?
какие поля можно затирать пустым (например, city), а какие нельзя (например, email_marketing_opt_in_at)Это напрямую влияет на корректность сегментов и персонализации.
Конфликты: один email у разных user_id
Это частый операционный инцидент (ошибка ввода, семейный ящик, перенос аккаунта).
Рекомендуемая практика:
не сливать автоматически без аудита
логировать конфликт (кто, когда, из какого источника)
решать бизнес-правилом (например, приоритет подтверждённого email)API-интеграция: события пользователя
Зачем события, если есть поля профиля
Поля профиля описывают состояние, а события — историю и момент.
состояние: plan = pro
событие: plan_upgraded с датой и контекстомСобытия особенно важны для:
триггеров (запуск цепочки)
окон актуальности (например, “оплата 15 минут назад”)
персонализации контекстом (последний заказ, последняя корзина)Минимальная схема события
Чтобы события были пригодны для триггеров и дебага, удобно иметь следующий минимум.
| Поле | Что это | Пример | Зачем нужно |
|---|---|---|---|
| event_name | тип события | order_paid | правила сценариев |
| event_id | уникальный идентификатор | a3f2... | дедупликация |
| occurred_at | время события | 2026-02-03T12:00:00Z | окна актуальности |
| user_id | связь с контактом | 842193 | склейка |
| properties | контекст события | { "order_total": 1990 } | персонализация |
Именование событий: как не утонуть в хаосе
Правила, которые упрощают поддержку:
используйте единый стиль (например, snake_case)
делайте названия событий действиями (order_paid, а не payment)
фиксируйте словарь событий как договор команды (продукт, маркетинг, разработка)Пример “каркаса” словаря:
онбординг: user_registered, email_confirmed, profile_completed
покупки: checkout_started, order_paid, refund_issued
удержание: last_seen (если вы реально его отправляете событием), trial_expiringНадёжность API: идемпотентность, ретраи и лимиты
Идемпотентность: как не отправить одно и то же дважды
Идемпотентность — свойство операции, при котором повтор запроса не меняет итоговый результат.
В рассылках это критично в двух местах:
upsert контакта
приём событийПрактика:
генерируйте event_id на вашей стороне
храните у себя журнал отправленных event_id хотя бы на окно ретраев
если ваш воркер отправил событие повторно, оно не должно создавать второй триггерСправка про семантику идемпотентности в HTTP: RFC 9110: HTTP Semantics.
!Как ретраи не должны превращаться в дубли событий и повторные триггеры
Ретраи: какие ошибки повторять
Типичная стратегия:
повторять временные сбои сети и ответы вида 429 или 5xx
не повторять “логические” ошибки вида 400 (невалидные данные)Важно: ретраи должны быть ограничены и с паузой, иначе вы создадите шип нагрузки.
Корреляция: как связывать логи между системами
Чтобы расследовать инциденты, полезно передавать технический идентификатор запроса, например:
correlation_id в теле запроса или заголовкеТогда вы сможете связать:
запись в ваших логах
запись в логах Unisendr
событие доставки/ошибки через вебхукВебхуки: обратная связь по доставке и согласиям
Какие вебхуки нужны в первую очередь
Минимальный список типов обратной связи:
доставка и ошибки: delivered, soft_bounce, hard_bounce
жалобы: complaint
отписки: unsubscribeТочные названия зависят от Unisendr и подключённого провайдера, но смысл один: изменить профиль и согласия так, чтобы следующий сегмент не включал контакт.
Обработчик вебхуков: требования к реализации
Обработчик вебхуков должен быть:
быстрым (принять запрос и подтвердить)
идемпотентным (одно и то же событие может прийти повторно)
безопасным (проверять подпись или секрет)Практическая схема обработки:
проверить подпись запроса (если поддерживается)
распарсить payload
проверить, что event_id или аналог ещё не обработан
записать факт в журнал
обновить профиль пользователя в вашей базе (например, выставить email_marketing_opt_in = false при отписке)Что именно менять в данных при статусах
Полезно заранее зафиксировать таблицу соответствий.
| Входящий статус | Что это означает | Что делать в вашей базе |
|---|---|---|
| unsubscribe | пользователь отписался | выключить маркетинг по каналу, сохранить unsubscribed_at |
| complaint | жалоба это спам | выключить маркетинг по каналу немедленно, пометить как высокорисковый |
| hard_bounce | адрес не существует или запрещён | пометить адрес недействительным, остановить отправку |
| soft_bounce | временная ошибка | считать и мониторить, не отключать сразу |
Безопасность вебхуков
Рекомендуемый минимум:
отдельный публичный endpoint только для вебхуков
проверка секрета/подписи (если Unisendr предоставляет)
ограничение по IP (если возможно и уместно)
защита от повторов через дедупликациюИнтеграции с сайтом: формы, лиды, подписки
Подписка через форму: что важно передавать
В форме подписки обычно рождается маркетинговое согласие, поэтому важно сразу собрать метаданные:
факт согласия (email_marketing_opt_in = true)
время (opt_in_at)
источник (opt_in_source = signup_form, landing_pricing, webinar)Если вы используете double opt-in, то первая запись может быть как “ожидает подтверждения”, а финальный opt-in — после клика в письме подтверждения.
Сайт как источник событий
С сайта часто отправляют события верхней воронки:
просмотр ключевых страниц
начало оформления
заполнение формыПрактический принцип: отправляйте только те события, которые вы реально будете использовать в сегментах, триггерах или аналитике, иначе события превращаются в шум.
Интеграции с CRM: синхронизация аудитории и статусов
Два типовых сценария
CRM как источник для маркетинговой сегментации (индустрия, менеджер, стадия сделки)
CRM как источник для триггеров продаж (например, “встреча назначена” → письмо с материалами)Почему CRM почти всегда пакетная
CRM-данные часто меняются не каждую секунду, и бизнесу обычно достаточно синхронизации:
раз в час
раз в ночьГлавное — договориться о том, какие поля CRM являются источником правды и не будут перетираться данными из продукта.
Маппинг CRM в профиль контакта
Пример, какие поля удобно синхронизировать.
| Поле CRM | Поле контакта | Пример | Использование |
|---|---|---|---|
| lead_stage | crm_stage | proposal | сегменты по стадии |
| account_manager | crm_manager | ivan.petrov | персонализация |
| industry | industry | retail | контент по отрасли |
Как связать события и контент: триггеры без дублей
Окно актуальности
Окно актуальности — период, в течение которого событие имеет смысл для отправки.
Пример:
“брошенная корзина” актуальна 1–24 часа
“подтвердите email” актуально до подтверждения или ограниченное времяОкна актуальности снижают риск отправки нерелевантных писем при задержках синхронизации.
Защита от повторов на уровне сценария
Даже при идемпотентных событиях полезны дополнительные предохранители:
хранить флаг “письмо N сценария уже отправлено” в вашей базе или в атрибутах контакта
учитывать этот флаг в сегменте или в логике сценарияНабор практических чеклистов
Чеклист API для контактов
выбран основной ключ (user_id)
определены правила обновления полей (что можно затирать)
нормализация email и телефона сделана до отправки
согласия передаются с датой и источникомЧеклист API для событий
у каждого события есть event_id для дедупликации
фиксирован словарь событий и их properties
occurred_at передаётся в едином формате
события отправляются только из источника, который является “истиной” для этого фактаЧеклист вебхуков
обработчик идемпотентен
настроена проверка подписи/секрета
статусы меняют согласия и валидность адреса
есть журнал входящих событий для расследованийЧто дальше по курсу
После того как контакты и события стабильно “ходят” через API, а вебхуки возвращают статусы и отписки, можно уверенно переходить к планированию запусков:
триггерные сценарии и их окна актуальности
расписания с учётом timezone
ограничения частоты и приоритеты кампанийИменно там становится видно качество интеграций: хороший контент и правильный момент запуска работают только тогда, когда данные и обратная связь надёжны.