БлогУслугиКарьера
Обсудить проект
БлогУслугиКарьераОбсудить проект
Автоматизация

Автоматизация Notion с помощью API и Python: полный гайд

Как автоматизировать Notion через API: создание страниц, обновление баз данных, синхронизация с CRM. Примеры на Python и готовые сценарии.

Редакция Feature
Редакция Feature·
31 мар
·
14 мин
·
Автоматизация Notion с помощью API и Python: полный гайд

Почему Notion нуждается в автоматизации

Notion стал стандартом для управления знаниями, проектами и документацией в IT-компаниях и стартапах. Но чем больше данных в Notion, тем больше ручной работы: обновление статусов, перенос данных из CRM, создание отчётов, актуализация контент-плана.

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

В этом гайде мы разберём всё — от получения API-ключа до продакшн-деплоя. Если вас интересует автоматизация бизнес-процессов в целом, Notion API — отличная точка входа.

Шаг 1: Настройка Notion API

Создание интеграции

Прежде чем писать код, нужно создать интеграцию в Notion:

  1. Перейдите на developers.notion.com
  2. Нажмите «New integration»
  3. Дайте имя (например, «Python Automation»)
  4. Выберите workspace, к которому будет доступ
  5. Настройте Capabilities — какие действия разрешены (Read content, Update content, Insert content)
  6. Скопируйте Internal Integration Token — это ваш API-ключ

Настройка доступа к базам данных

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

  1. Откройте нужную базу данных в Notion
  2. Нажмите «...» (меню) → «Add connections»
  3. Найдите вашу интеграцию и подключите её

Без этого шага API будет возвращать пустые результаты, и вы потратите часы на отладку несуществующей ошибки.

Получение ID базы данных

ID базы данных — это часть URL. Если URL выглядит так:

https://www.notion.so/workspace/abc123def456...?v=...

То ID — это abc123def456... (32 символа между последним / и ?).

Шаг 2: Настройка Python-окружения

Установка библиотек

Для работы с Notion API используем официальный SDK:

pip install notion-client python-dotenv

Базовая конфигурация

Создайте файл .env для безопасного хранения ключей:

NOTION_TOKEN=secret_abc123...
NOTION_DATABASE_ID=abc123def456...

И файл config.py:

import os
from dotenv import load_dotenv
from notion_client import Client

load_dotenv()

notion = Client(auth=os.environ["NOTION_TOKEN"])
DATABASE_ID = os.environ["NOTION_DATABASE_ID"]

Теперь у вас есть настроенный клиент, готовый к работе. Никогда не храните токены в коде — это базовое правило безопасности при Python-разработке.

Шаг 3: Чтение данных из базы

Получение всех записей

def get_all_records(database_id: str) -> list:
    """Получает все записи из базы данных Notion."""
    results = []
    has_more = True
    start_cursor = None

    while has_more:
        response = notion.databases.query(
            database_id=database_id,
            start_cursor=start_cursor
        )
        results.extend(response["results"])
        has_more = response["has_more"]
        start_cursor = response.get("next_cursor")

    return results

Обратите внимание на пагинацию — Notion API возвращает максимум 100 записей за запрос. Для больших баз данных (1000+ записей) обязательно нужно обрабатывать has_more и next_cursor.

Фильтрация и сортировка

Notion API поддерживает мощные фильтры прямо на уровне запроса:

def get_active_tasks(database_id: str) -> list:
    """Получает активные задачи со статусом 'В работе'."""
    response = notion.databases.query(
        database_id=database_id,
        filter={
            "and": [
                {
                    "property": "Статус",
                    "select": {"equals": "В работе"}
                },
                {
                    "property": "Приоритет",
                    "select": {"equals": "Высокий"}
                }
            ]
        },
        sorts=[
            {"property": "Дедлайн", "direction": "ascending"}
        ]
    )
    return response["results"]

Фильтрация на стороне API работает быстрее, чем загрузка всех данных и фильтрация в Python. Всегда используйте серверные фильтры, когда это возможно.

Извлечение значений свойств

Данные в Notion API имеют вложенную структуру. Вот утилита для извлечения значений:

def extract_property(page: dict, prop_name: str) -> str:
    """Извлекает значение свойства из страницы Notion."""
    prop = page["properties"].get(prop_name, {})
    prop_type = prop.get("type", "")

    if prop_type == "title":
        return prop["title"][0]["plain_text"] if prop["title"] else ""
    elif prop_type == "rich_text":
        return prop["rich_text"][0]["plain_text"] if prop["rich_text"] else ""
    elif prop_type == "select":
        return prop["select"]["name"] if prop["select"] else ""
    elif prop_type == "number":
        return prop["number"]
    elif prop_type == "date":
        return prop["date"]["start"] if prop["date"] else ""
    elif prop_type == "email":
        return prop["email"] or ""

    return ""

Шаг 4: Создание и обновление страниц

Создание новой записи

def create_task(title: str, status: str, priority: str, deadline: str):
    """Создаёт новую задачу в базе данных Notion."""
    notion.pages.create(
        parent={"database_id": DATABASE_ID},
        properties={
            "Название": {
                "title": [{"text": {"content": title}}]
            },
            "Статус": {
                "select": {"name": status}
            },
            "Приоритет": {
                "select": {"name": priority}
            },
            "Дедлайн": {
                "date": {"start": deadline}
            }
        }
    )

Обновление существующей записи

def update_task_status(page_id: str, new_status: str):
    """Обновляет статус задачи."""
    notion.pages.update(
        page_id=page_id,
        properties={
            "Статус": {
                "select": {"name": new_status}
            }
        }
    )

Добавление контента в страницу

Notion различает свойства страницы (properties) и содержимое (blocks). Чтобы добавить текст, списки, код — нужно работать с блоками:

def add_content_to_page(page_id: str, text: str):
    """Добавляет текстовый блок в страницу."""
    notion.blocks.children.append(
        block_id=page_id,
        children=[
            {
                "object": "block",
                "type": "heading_2",
                "heading_2": {
                    "rich_text": [{"text": {"content": "Автоматический отчёт"}}]
                }
            },
            {
                "object": "block",
                "type": "paragraph",
                "paragraph": {
                    "rich_text": [{"text": {"content": text}}]
                }
            }
        ]
    )

Хотите автоматизировать Notion?

Настроим интеграцию Notion с вашими системами

Заказать интеграцию

Шаг 5: Реальные сценарии автоматизации

Сценарий 1: Синхронизация CRM с Notion

Архитектура:

┌──────────┐     ┌──────────────┐     ┌──────────┐
│  amoCRM  │────▶│ Python-скрипт│────▶│  Notion  │
│          │◀────│  (sync.py)   │◀────│  DB      │
└──────────┘     └──────────────┘     └──────────┘
       │                │                    │
       └────────────────┼────────────────────┘
                        │
                   Cron (каждые 5 мин)

Скрипт каждые 5 минут проверяет новые сделки в CRM и создаёт/обновляет записи в Notion:

def sync_crm_to_notion():
    """Синхронизирует сделки из CRM в Notion."""
    # Получаем сделки из CRM
    deals = crm_client.get_deals(modified_since=last_sync_time)

    for deal in deals:
        # Проверяем, есть ли уже запись в Notion
        existing = find_notion_page_by_crm_id(deal["id"])

        if existing:
            update_notion_deal(existing["id"], deal)
        else:
            create_notion_deal(deal)

    save_last_sync_time()

Этот сценарий позволяет менеджерам видеть актуальную воронку продаж в Notion, а аналитикам — строить отчёты без доступа к CRM.

Сценарий 2: Автоматизация контент-плана

def create_content_plan(topics: list, start_date: str):
    """Создаёт контент-план в Notion на основе списка тем."""
    current_date = datetime.strptime(start_date, "%Y-%m-%d")

    for topic in topics:
        notion.pages.create(
            parent={"database_id": CONTENT_DB_ID},
            properties={
                "Тема": {"title": [{"text": {"content": topic["title"]}}]},
                "Статус": {"select": {"name": "Запланировано"}},
                "Автор": {"people": [{"id": topic["author_id"]}]},
                "Дата публикации": {"date": {"start": current_date.isoformat()}},
                "Канал": {"multi_select": [{"name": ch} for ch in topic["channels"]]},
                "SEO-ключи": {"rich_text": [{"text": {"content": ", ".join(topic["keywords"])}}]}
            }
        )
        current_date += timedelta(days=topic.get("interval", 3))

Сценарий 3: Автоматические отчёты

Скрипт, который каждую пятницу генерирует сводку по задачам:

def generate_weekly_report():
    """Генерирует еженедельный отчёт в Notion."""
    tasks = get_all_records(TASKS_DB_ID)

    completed = [t for t in tasks if extract_property(t, "Статус") == "Готово"]
    in_progress = [t for t in tasks if extract_property(t, "Статус") == "В работе"]
    overdue = [t for t in tasks if is_overdue(t)]

    report_text = f"""
    Завершено задач: {len(completed)}
    В работе: {len(in_progress)}
    Просрочено: {len(overdue)}
    """

    # Создаём страницу отчёта
    report_page = notion.pages.create(
        parent={"database_id": REPORTS_DB_ID},
        properties={
            "Название": {"title": [{"text": {"content": f"Отчёт за неделю {date.today().isocalendar()[1]}"}}]},
            "Дата": {"date": {"start": date.today().isoformat()}}
        }
    )

    add_content_to_page(report_page["id"], report_text)

Такие отчёты можно автоматически отправлять в Telegram-бот для руководителя, дублируя информацию из Notion.

Шаг 6: Вебхуки и триггеры

Проблема: Notion API не поддерживает вебхуки

На момент написания статьи Notion API не предоставляет нативные вебхуки. Это значит, что вы не можете получать уведомления при изменении данных в реальном времени. Есть несколько обходных решений:

Polling (опрос): запрашивайте данные по расписанию и сравнивайте с предыдущим состоянием.

def poll_for_changes(database_id: str, interval: int = 60):
    """Опрашивает базу данных на предмет изменений."""
    last_edit_time = load_last_check_time()

    response = notion.databases.query(
        database_id=database_id,
        filter={
            "timestamp": "last_edited_time",
            "last_edited_time": {"after": last_edit_time}
        }
    )

    if response["results"]:
        for page in response["results"]:
            handle_change(page)

    save_last_check_time(datetime.now().isoformat())

n8n или Make: используйте специализированные инструменты автоматизации с готовыми Notion-триггерами. Мы подробно сравниваем эти инструменты в статье n8n vs Make.

Notion + Zapier/Make: как промежуточное решение можно настроить триггер в Make, который будет вызывать ваш Python-скрипт через webhook.

Шаг 7: Обработка ошибок и лимиты

Rate limits Notion API

Notion API ограничивает количество запросов: максимум 3 запроса в секунду на одну интеграцию. При превышении лимита вы получите ошибку 429 (Too Many Requests).

Реализуйте retry с exponential backoff:

import time
from notion_client import APIResponseError

def safe_api_call(func, *args, max_retries=3, **kwargs):
    """Выполняет API-вызов с retry-логикой."""
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs)
        except APIResponseError as e:
            if e.status == 429:
                wait_time = 2 ** attempt
                print(f"Rate limit, ожидание {wait_time}с...")
                time.sleep(wait_time)
            elif e.status == 409:
                # Конфликт — данные изменились
                print("Конфликт данных, повторная попытка...")
                time.sleep(1)
            else:
                raise
    raise Exception(f"Не удалось выполнить запрос после {max_retries} попыток")

Лимиты на размер данных

  • Максимальный размер текстового блока: 2000 символов
  • Максимум 100 блоков за один запрос
  • Максимум 100 записей в ответе на query

Для больших объёмов данных всегда используйте пагинацию и разбивайте длинные тексты на блоки.

Логирование

Для production-сценариев обязательно ведите логи:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("notion_sync.log"),
        logging.StreamHandler()
    ]
)

logger = logging.getLogger(__name__)

Обсудим ваш проект?

Оставьте контакты — перезвоним и обсудим задачу

Шаг 8: Деплой и автоматизация запуска

Вариант 1: Cron на сервере

Самый простой способ — добавить скрипт в crontab:

# Синхронизация каждые 5 минут
*/5 * * * * cd /opt/notion-sync && /usr/bin/python3 sync.py >> /var/log/notion-sync.log 2>&1

Вариант 2: Cloud Functions

Для серверлесс-подхода используйте AWS Lambda, Google Cloud Functions или Yandex Cloud Functions:

# handler.py для Yandex Cloud Functions
import json

def handler(event, context):
    """Обработчик для Cloud Function."""
    sync_crm_to_notion()
    return {
        "statusCode": 200,
        "body": json.dumps({"status": "ok", "synced": True})
    }

Настройте триггер по расписанию (Cloud Scheduler / EventBridge).

Вариант 3: Docker + Docker Compose

Для более надёжного деплоя оберните скрипт в Docker:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "main.py"]
# docker-compose.yml
version: "3.8"
services:
  notion-sync:
    build: .
    env_file: .env
    restart: unless-stopped

Архитектура production-решения

┌─────────────┐    ┌──────────────┐    ┌──────────┐
│  Источники  │    │  Middleware   │    │  Notion  │
│             │    │              │    │          │
│ ● CRM      │───▶│ ● Queue      │───▶│ ● DB 1   │
│ ● Email    │    │ ● Workers    │    │ ● DB 2   │
│ ● Forms    │    │ ● Rate limiter│   │ ● Pages  │
│ ● Telegram │    │ ● Error handler│  │          │
└─────────────┘    └──────────────┘    └──────────┘
                          │
                   ┌──────┴──────┐
                   │  Мониторинг  │
                   │ ● Логи      │
                   │ ● Алерты    │
                   │ ● Метрики   │
                   └─────────────┘

Для серьёзного production-решения рекомендуем использовать очередь сообщений (Redis Queue или RabbitMQ) между источниками данных и Notion API. Это позволяет обрабатывать пиковые нагрузки, не превышая rate limits.

Типичные ошибки и как их избежать

  1. Забыть расшарить базу с интеграцией — самая частая ошибка новичков. API возвращает пустой результат без ошибки.

  2. Не обрабатывать пагинацию — если записей больше 100, вы получите только первую страницу. Всегда проверяйте has_more.

  3. Хардкод ID баз данных — используйте переменные окружения или конфиг-файл. ID может измениться при переносе базы.

  4. Игнорировать rate limits — без retry-логики скрипт упадёт при большом объёме данных.

  5. Не валидировать данные — перед отправкой в Notion проверяйте типы данных и длину строк.

Заключение

Notion API в связке с Python — мощный инструмент для автоматизации рабочих процессов. Вы можете синхронизировать данные между любыми системами, автоматизировать рутинные операции и строить отчёты без ручной работы.

Начните с простого сценария — например, автоматического создания задач из формы обратной связи. Когда убедитесь, что всё работает — масштабируйте решение, добавляя синхронизацию с CRM, контент-планы и дашборды.

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

Обсудим ваш проект?

Оставьте контакты — перезвоним и обсудим задачу

Содержание
  • Почему Notion нуждается в автоматизации
  • Шаг 1: Настройка Notion API
  • Шаг 2: Настройка Python-окружения
  • Шаг 3: Чтение данных из базы
  • Шаг 4: Создание и обновление страниц
  • Шаг 5: Реальные сценарии автоматизации
  • Шаг 6: Вебхуки и триггеры
  • Шаг 7: Обработка ошибок и лимиты
  • Шаг 8: Деплой и автоматизация запуска
  • Типичные ошибки и как их избежать
  • Заключение
Поделиться:

Похожие статьи

Make заблокирует ваш аккаунт без предупреждения. Мы потеряли 200 автоматизаций за одну ночь
Автоматизация

Make заблокирует ваш аккаунт без предупреждения. Мы потеряли 200 автоматизаций за одну ночь

11 мин
Я узнал о сгоревших остатках на WB через 3 часа. Теперь узнаю за 15 секунд — и вот как
Автоматизация

Я узнал о сгоревших остатках на WB через 3 часа. Теперь узнаю за 15 секунд — и вот как

11 мин
Автоматизация email-рассылок: best practices и инструменты 2026
Автоматизация

Автоматизация email-рассылок: best practices и инструменты 2026

12 мин
Feature IT

Feature IT — платформа по обучению программированию и разработке цифровых продуктов. Мы создаём современные веб-решения для бизнеса и обучаем этому других!

Политика конфиденциальностиПользовательское соглашение

О компании

  • Блог
  • Карьера

Услуги разработки

  • Разработка сайтов под ключ
  • Веб-приложения на React/Next.js
  • Telegram-боты для бизнеса
  • Mini Apps (Telegram, VK)
  • SEO-оптимизированные сайты
  • Автоматизация бизнес-процессов
  • Поддержка и развитие IT-продуктов

Обучение

  • Курс Python с нуля
  • Алгоритмы и структуры данных
  • Паттерны проектирования
  • Подготовка к собеседованиям в IT
  • Практика на реальных проектах

Инструменты

  • Генератор UTM-меток
  • Счётчик символов