Автоматизация Notion через API: сводки и теги для базы с помощью Claude
Скрипт на Python читает записи базы Notion, получает от Claude сводку и теги и записывает их в свойства страницы. С учётом data sources и лимитов Notion API.
5 мин · · автоматизация · разработка
Заметки, протоколы встреч и входящие заявки в Notion быстро копятся, и разбирать их вручную долго. Автоматизация Notion через API решает это: скрипт берёт новые записи базы, отправляет текст в Claude и записывает обратно короткую сводку и теги. Ниже — рабочий скрипт на Python с актуальной версией notion-client, которая работает с базами через data sources.
Что понадобится
- Python 3.10+ и пакеты:
pip install notion-client openai python-dotenv- Токен Notion. По документации Notion есть два варианта: внутреннее подключение (internal connection) — отдельный бот-пользователь, которому нужно дать доступ к базе, или персональный токен (personal access token), который действует с вашими правами. Оба создаются в Developer portal Notion. Для командной автоматизации документация советует внутреннее подключение.
- Ключ Zukko вида
fetch_...из кабинета.
Если используете внутреннее подключение, откройте базу в Notion и выдайте подключению доступ к ней: без этого API вернёт ошибку «not found», даже если ID верный. Доступ к родительской странице наследуется дочерними.
Подготовка базы
В примере база содержит свойства:
| Свойство | Тип | Зачем |
|---|---|---|
Name | Title | заголовок записи |
Status | Select | значения To process и Processed |
Summary | Text | сюда пишется сводка |
Tags | Multi-select | сюда пишутся теги |
Если у вас колонка статуса типа Status (а не Select), замените в коде ключ "select" на "status" — и в фильтре, и при обновлении.
ID базы берётся из её адреса: это 32 символа перед ?v=. Удобнее передать в скрипт адрес целиком — функция extract_database_id из notion_client.helpers сама вытащит ID.
Файл .env:
NOTION_TOKEN=ntn_...
NOTION_DATABASE=https://www.notion.so/workspace/Inbox-0123456789abcdef0123456789abcdef?v=...
ZUKKO_API_KEY=fetch_...
ZUKKO_MODEL=claude-sonnet-5
Автоматизация Notion через API: базы и data sources
С версии Notion API 2025-09-03 у базы может быть несколько источников данных (data sources), и запрос записей идёт к источнику, а не к базе: POST /v1/data_sources/{data_source_id}/query. Старый метод databases.query в свежем notion-client (ветка 3.x) отсутствует, поэтому код из старых примеров падает с AttributeError.
Порядок такой, как в руководстве по переходу:
notion.databases.retrieve(database_id=...)возвращает базу со спискомdata_sources.- Берём
idнужного источника (у обычной базы он один). notion.data_sources.query(data_source_id=..., filter=...)возвращает страницы.
Ответы Notion постраничные (has_more, next_cursor). Вспомогательная функция collect_paginated_api из notion_client.helpers сама проходит по всем страницам результата.
Текст страницы
Содержимое страницы — это блоки: notion.blocks.children.list(block_id=page_id). У текстовых блоков (абзацы, заголовки, пункты списков, цитаты) текст лежит в rich_text — массиве фрагментов. Склеиваем plain_text всех фрагментов, а не только первого: иначе обрежется всё после первой ссылки или выделения.
Вложенные блоки (содержимое toggle, вложенные списки) этот код не обходит. Если они важны, вызывайте blocks.children.list рекурсивно для блоков с has_children: true.
Полный скрипт
import json
import os
from dotenv import load_dotenv
from notion_client import Client
from notion_client.helpers import collect_paginated_api, extract_database_id
from openai import APIStatusError, OpenAI
load_dotenv()
notion = Client(auth=os.environ["NOTION_TOKEN"])
llm = OpenAI(base_url="https://api.zukko.pro/v1", api_key=os.environ["ZUKKO_API_KEY"])
DATABASE_ID = extract_database_id(os.environ["NOTION_DATABASE"])Несколько решений в коде:
- Один запрос вместо двух. Сводка и теги просим одним JSON-ответом — вдвое меньше запросов и повторной отправки одного и того же текста.
- Ограничение длины.
MAX_CHARSне даёт отправить в модель огромную страницу целиком. Точное число токенов показывает полеusageв ответе или эндпоинт подсчёта токенов. - Лимиты Notion. Notion ограничивает частоту запросов (по документации — в среднем 3 запроса в секунду на подключение для большинства тарифов) и длину текстового фрагмента в свойстве (2000 символов). Свежий
notion-clientсам повторяет запрос после ответа 429; сводку режем до 2000 символов. - Запятые в тегах. Notion не принимает запятые в названиях вариантов multi-select, поэтому заменяем их пробелами.
Запуск по расписанию
Скрипт обрабатывает только записи со статусом To process и после обработки меняет статус, поэтому его безопасно запускать повторно. Например, cron раз в час:
0 * * * * cd /opt/notion-bot && .venv/bin/python notion_summary.py >> run.log 2>&1Подойдёт и GitHub Actions по расписанию — тогда NOTION_TOKEN и ZUKKO_API_KEY храните в секретах репозитория.
Сколько стоит
Цены в Zukko за 1M токенов (вход/выход): claude-sonnet-5 — $0.30 / $0.30, gpt-5.6-luna — $0.10 / $0.10, glm-5.3-flash — $0.04 / $0.04. Актуальный список — GET https://api.zukko.pro/v1/models или страница «Модели» в кабинете.
Пример: 100 заметок, на каждую 3 000 входных токенов и 200 выходных.
claude-sonnet-5: 100 × (3 000 + 200) × $0.30 / 1 000 000 = $0.096.glm-5.3-flash: 100 × (3 000 + 200) × $0.04 / 1 000 000 = $0.0128.
Какая модель даёт подходящие сводки и теги для ваших заметок, проверьте на своих задачах: прогоните 20 записей через две модели и сравните результат. Задача несложная, и дешёвая модель может оказаться достаточной.
Частые вопросы
API Notion отвечает «Could not find database»
Чаще всего у подключения нет доступа к базе: выдайте его в меню страницы базы или во вкладке доступа подключения в Developer portal. Вторая причина — ID страницы вместо ID базы: для встроенной (inline) базы откройте её как отдельную страницу и возьмите адрес оттуда.
Почему notion.databases.query не работает?
В notion-client 3.x этого метода нет: начиная с версии API 2025-09-03 записи запрашиваются через источник данных — notion.data_sources.query. ID источника берётся из notion.databases.retrieve.
Модель иногда возвращает текст вместо JSON
Код такие записи пропускает и оставляет статус To process, так что при следующем запуске они обработаются снова. Чтобы ошибок было меньше, держите промпт коротким и явно пишите «только JSON».
Можно ли писать результат в тело страницы, а не в свойство?
Да, через notion.blocks.children.append(block_id=page_id, children=[...]) с блоком paragraph. Для сводки удобнее свойство: по нему можно фильтровать и сортировать базу. Подробнее о запросах к модели — в справочнике chat completions.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- Перевод субтитров нейросетью: SRT без сбитых таймкодовГлавный риск при переводе SRT нейросетью — сломанная структура файла. Показываем схему, где таймкоды не попадают к модели, и скрипт на Python с проверкой.
- Редактирование текстов нейросетью: корректура, стиль и сокращениеРазные виды редактуры требуют разных промптов. Показываем формулировки для корректуры, стиля и сокращения, как получать правки с объяснением и не терять авторский голос.
- Нейросеть для написания скриптов: Bash, PowerShell и PythonМодель быстро пишет скрипты для рутины, но запускать их вслепую нельзя. Показываем, как ставить задачу, требовать безопасный режим dry-run и проверять результат до запуска.
- Dify в Docker: установка, первичная настройка и подключение моделейСтавим Dify через Docker Compose, создаём администратора и подключаем модели Claude, GPT и DeepSeek по одному ключу. Отдельно — что делать, если контейнеры не стартуют.