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

Автоматизация 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: Деплой и автоматизация запуска
  • Типичные ошибки и как их избежать
  • Заключение
Поделиться:

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

Свои вебхуки: как отдавать события партнёрам и не потерять их
Автоматизация

Свои вебхуки: как отдавать события партнёрам и не потерять их

13 мин
OAuth 2.0 для интеграций: как подключить сайт к чужому сервису
Автоматизация

OAuth 2.0 для интеграций: как подключить сайт к чужому сервису

14 мин
Настройка API на сайте: 7 ошибок, которые вылезают только в проде
Автоматизация

Настройка API на сайте: 7 ошибок, которые вылезают только в проде

13 мин
Feature IT

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

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

О компании

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

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

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

Обучение

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

Инструменты

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