HubSpot + Notion: почему нативная интеграция устаревает раньше чем данные синхронизируются

HubSpot + Notion: почему нативная интеграция устаревает раньше чем данные синхронизируются

Нативной интеграции между HubSpot и Notion не существует. В HubSpot Marketplace нет официального Notion-коннектора. Для связки используют Zapier, Make или n8n — и именно здесь начинаются проблемы. Данные в Notion устаревают раньше чем команда ими пользуется, типы полей не совпадают, а обновления из Notion никогда не попадают обратно в HubSpot. Ниже — конкретный разбор что ломается и как это исправить.

Что происходит: симптомы

Типичный сценарий: команда хочет видеть данные о клиентах из HubSpot в Notion — для client portal, операционного трекинга, onboarding checklist или базы знаний. Подключают через Zapier и через неделю замечают:

  • Данные в Notion расходятся с HubSpot — обновление владельца сделки или суммы не синхронизировалось
  • Новые контакты появляются в Notion с задержкой 15–60 минут (polling-интервал Zapier на бесплатном тарифе)
  • Кастомные поля HubSpot с типом enumeration (dropdown) превращаются в сырой internal value в Notion, а не в читаемую метку
  • Команда начинает редактировать Notion напрямую — изменения не идут обратно в HubSpot
  • CRM-данные деградируют: реальность — в Notion, актуальность — в HubSpot, правда — непонятно где

Почему Zapier/Make не решают задачу

Задержки: Zapier на платном Business-тарифе ($49+/мес) обновляет каждые 1–2 минуты. На бесплатном — каждые 15 минут. Make — от 15 минут на минимальном тарифе. Для операционных данных (смена ответственного, обновление статуса) это неприемлемо.

Маппинг типов полей: HubSpot и Notion имеют принципиально разные модели данных:

HubSpot типЧто приходит в NotionПроблема
enumeration (dropdown)internal value: "new_business"В Notion нужно читать "Новый бизнес"
datetimeISO timestampNotion принимает только дату без времени в date-полях
multi_checkboxмассив internal valuesNotion multi-select ждёт массив строк с нужными именами
rich_text (Notes)HTML-строкаNotion RichText — отдельный формат с блоками
Ассоциации (Deal -> Contact -> Company)ID числомВ Notion нет связей между базами через внешние ID

Нет обратной синхронизации: Zapier и Make работают в одну сторону — HubSpot -> Notion. Любые изменения в Notion (добавили заметку, обновили статус) не попадают в HubSpot. Два источника истины — классическая причина деградации CRM.

Ограничения HubSpot Webhook через Zapier: Zapier использует polling, а не real-time webhook. Настоящий HubSpot webhook (мгновенный) недоступен через стандартные Zapier-триггеры.

Что теряет бизнес

Операционные потери:
— CS-менеджер обновляет статус клиента в Notion — менеджер по продажам видит старый статус в HubSpot
— Ответственный за сделку меняется в HubSpot — в Notion по-прежнему указан прежний менеджер
— Клиент переходит на другой тариф — обновление синхронизируется через 40 минут или не синхронизируется вовсе

Архивные потери:
— HubSpot Activity log (звонки, письма) не синхронизируется в Notion вообще — Zapier не умеет реплицировать активности
— Notes из HubSpot приходят как raw HTML — <strong>важно</strong> вместо читаемого форматирования
— Ассоциации (сделка -> контакт -> компания) теряются — Notion не поддерживает реляционные связи между разными базами через внешние ID

Правильный подход: HubSpot Webhook -> кастомный backend -> Notion API

Правильная архитектура: HubSpot Webhook App (native) -> ваш backend -> Notion API. Это даёт мгновенную синхронизацию без polling и полный контроль над маппингом.

HubSpot Webhook: deal.propertyChange (amount, owner, stage)
  ↓ Backend (FastAPI / Flask)
  1. Получить полные данные сделки: GET /crm/v3/objects/deals/{id}?properties=...
  2. Разрезолвить ассоциации: GET /crm/v3/objects/deals/{id}/associations/contacts
  3. Трансформировать данные: enumeration -> label, datetime -> date, HTML -> Notion blocks
  4. Найти страницу в Notion: POST /databases/{db_id}/query (filter by hubspot_deal_id)
     -> если найдена: PATCH /pages/{page_id} с обновлёнными properties
     -> если не найдена: POST /pages с hubspot_deal_id как идентификатором

Notion API: создать/обновить страницу в базе:

import requests
from datetime import datetime

NOTION_TOKEN = "secret_your_integration_token"
NOTION_VERSION = "2022-06-28"
NOTION_DB_ID = "your_database_id"

headers = {
    "Authorization": f"Bearer {NOTION_TOKEN}",
    "Notion-Version": NOTION_VERSION,
    "Content-Type": "application/json",
}

# Маппинг HubSpot enumeration -> читаемое имя
STAGE_LABELS = {
    "appointmentscheduled": "Встреча назначена",
    "qualifiedtobuy":       "Квалифицирован",
    "presentationscheduled":"Презентация",
    "decisionmakerboughtin":"ЛПР вовлечён",
    "contractsent":         "Контракт отправлен",
    "closedwon":            "Выигран",
    "closedlost":           "Потерян",
}

def find_notion_page(hubspot_deal_id: str) -> str | None:
    resp = requests.post(
        f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query",
        headers=headers,
        json={
            "filter": {
                "property": "HubSpot Deal ID",
                "rich_text": {"equals": hubspot_deal_id}
            }
        }
    )
    resp.raise_for_status()
    results = resp.json().get("results", [])
    return results[0]["id"] if results else None

def sync_deal_to_notion(deal: dict, contact_name: str = "", company_name: str = "") -> None:
    deal_id = str(deal["id"])
    props = deal.get("properties", {})

    amount = props.get("amount", "") or ""
    stage_key = props.get("dealstage", "")
    stage_label = STAGE_LABELS.get(stage_key, stage_key)

    # Дата closedate: HubSpot -> ISO date string для Notion
    closedate_raw = props.get("closedate", "")
    closedate = closedate_raw[:10] if closedate_raw else None  # "2026-06-15T..."->"2026-06-15"

    notion_props = {
        "Name": {"title": [{"text": {"content": props.get("dealname", f"Deal {deal_id}")}}]},
        "HubSpot Deal ID": {"rich_text": [{"text": {"content": deal_id}}]},
        "Stage": {"select": {"name": stage_label}},
        "Owner": {"rich_text": [{"text": {"content": props.get("hubspot_owner_id", "")}}]},
        "Contact": {"rich_text": [{"text": {"content": contact_name}}]},
        "Company": {"rich_text": [{"text": {"content": company_name}}]},
    }

    if amount:
        notion_props["Amount"] = {"number": float(amount)}

    if closedate:
        notion_props["Close Date"] = {"date": {"start": closedate}}

    existing_page_id = find_notion_page(deal_id)
    if existing_page_id:
        requests.patch(
            f"https://api.notion.com/v1/pages/{existing_page_id}",
            headers=headers,
            json={"properties": notion_props}
        ).raise_for_status()
    else:
        requests.post(
            "https://api.notion.com/v1/pages",
            headers=headers,
            json={
                "parent": {"database_id": NOTION_DB_ID},
                "properties": notion_props
            }
        ).raise_for_status()

HubSpot Webhook настройка: HubSpot -> Settings -> Integrations -> Private Apps -> Create private app -> Webhooks. Подписаться на deal.propertyChange для нужных полей (amount, dealstage, hubspot_owner_id). Или использовать HubSpot Workflow -> Webhook action для триггеров по этапам.

Зачем вообще синхронизировать HubSpot с Notion

Это законный вопрос. Типовые сценарии где это оправдано:

  • Client portal в Notion: клиент видит статус своего проекта/onboarding — данные из HubSpot, интерфейс в Notion через Notion Pages
  • Операционный трекинг: CS-команда ведёт онбординг в Notion, хочет видеть CRM-контекст без доступа к HubSpot
  • Еженедельный revenue report: автоматически обновляемая таблица Won-сделок в Notion для борда

Если цель — аналитика, лучше рассмотреть Prooflytics или BI-инструменты. Если цель — операционный трекинг, кастомная интеграция через Notion API решает задачу правильно.

Для кого актуально

  • Команды, где HubSpot — CRM для продаж, Notion — операционная база для CS/delivery
  • Client portal сценарии: клиент читает статус в Notion, данные берутся из HubSpot
  • Компании, которые уже пробовали Zapier и столкнулись с перечисленными проблемами

Часто задаваемые вопросы

Есть ли официальная интеграция HubSpot + Notion?

По состоянию на Q2 2026 — нет. В HubSpot App Marketplace нет официального Notion-коннектора. Существуют интеграции через Zapier, Make и n8n, но все они работают через polling, а не native webhook.

Notion API поддерживает ассоциации между базами данных?

Да, через Relation property. POST /pages с {"relation": [{"id": "{other_page_id}"}]} создаёт связь между страницами в разных базах. Для HubSpot-интеграции: при синхронизации Deal -> также синхронизировать Contact и Company как отдельные страницы, затем связать через Relation.

Как обработать удалённую сделку в HubSpot?

HubSpot Webhook присылает deal.deletion событие. Соответствующую страницу в Notion — архивировать (PATCH /pages/{id} с {"archived": true}) или обновить статус-поле. Физическое удаление страниц в Notion через API не рекомендуется — лучше архивирование.

HubSpot Notes — как синхронизировать в Notion?

Через отдельный endpoint: GET /crm/v3/objects/notes?associations.objectId={deal_id}&associations.objectType=deals. Notes приходят с полем hs_note_body в HTML. Для Notion нужно конвертировать HTML -> Notion Blocks (paragraph, heading, bulleted_list). Библиотека notion-block-renderer или ручной парсер.

Итого

  • Нативной HubSpot + Notion интеграции нет — Zapier/Make дают polling с задержками и неполным маппингом
  • Ключевые проблемы: задержки, несовместимость типов, нет обратной синхронизации
  • Правильный подход: HubSpot Private App Webhook -> backend -> Notion API (2022-06-28)
  • Notion Auth: Bearer token в заголовке Authorization, заголовок Notion-Version: 2022-06-28
  • Идентификатор связи: hubspot_deal_id как rich_text поле в Notion для поиска при обновлениях
  • Типы полей требуют трансформации: enumeration -> label, datetime -> date string, HTML -> Notion blocks

Если вам нужна надёжная синхронизация HubSpot с Notion — опишите сценарий: что должно отображаться в Notion и при каких событиях обновляться. Exceltic.dev разработает правильную архитектуру.

Ещё статьи

Все →