TechPlex Blog 記事一覧
生産性

Notion API活用術 — 自動化で作業時間を半分にする実践ガイド

この記事でわかること

  • Notion APIの初期セットアップ手順(インテグレーション作成からトークン取得まで)
  • Pythonでデータベースの読み書きを自動化する具体的なコード
  • 日報・週報の自動生成やタスクのステータス一括更新の実装例
  • Zapier / Make との連携でノーコード自動化を実現する方法
  • 自動化テンプレートの設計パターンと運用のコツ

Notionをヘビーに使い始めて2年くらい経った頃、毎朝やっている作業がどうにも面倒になってきた。前日のタスクDBを開いて、完了していないものを今日の日付に移す。週の終わりには案件ごとの作業時間を集計して週報ページにまとめる。月末には収支DBからデータを拾って月次レポートを書く。どれも5分から15分の作業だけど、積み重なると週に2時間近く「Notionのお世話」をしている計算になる。

そんなとき知ったのがNotion APIだった。2021年に公開されて以来、アップデートを重ねて今ではかなり実用的になっている。僕はPythonスクリプトを書いて上の作業を全部自動化した結果、週2時間のNotion作業が実質ゼロになった。この記事では、その具体的なやり方を全部共有します。

1. 「手作業Notion」の限界を感じた日

Notionは最高のツールだけど、運用が定着するほど「定型作業」が増えるという矛盾がある。データベースのビューを切り替えてフィルターをかけて、結果を別のページにコピペして――この手の作業は人間がやる必要がない。機械に任せたほうが速いし、ミスもない。

自動化すべきかどうかの判断基準はシンプルで、「同じ操作を週3回以上繰り返しているなら自動化する価値がある」というルールで考えるとちょうどいい。具体的に自動化して効果が大きかったのはこの3つ。

日報・週報の自動生成

タスクDBの完了データを集計して、レポートページを毎日自動で作成。手書きゼロ。

タスク一括更新

期限切れタスクのステータス変更、優先度の再設定を一括で自動処理。

外部サービス連携

Slackの投稿からNotionタスク作成、Googleカレンダーとの双方向同期。

Notionの基本的なデータベース設計がまだ固まっていない方は、先にフリーランスのNotion活用完全ガイドを読んで土台を作ってから戻ってくると、自動化の効果を最大限に引き出せます。

2. Notion APIの初期セットアップ

Notion APIを使うには、まず「インテグレーション」を作成してAPIトークンを取得する必要がある。難しそうに聞こえるけど、実際は5分で終わる。

ステップ1:インテグレーションの作成

  1. 1

    notion.so/my-integrations にアクセスして「新しいインテグレーション」をクリック。

  2. 2

    名前を入力(例:「自動化Bot」)。関連ワークスペースを選択。タイプは「Internal」のまま。

  3. 3

    「送信」すると「内部インテグレーションシークレット」が表示される。ntn_ で始まる文字列がAPIトークン。これをコピーして安全な場所に保管。

ステップ2:データベースとの接続

インテグレーションを作っただけでは、まだどのページにもアクセスできない。Notion側で明示的に「このページにこのインテグレーションがアクセスしていいよ」と許可する必要がある。

  1. 1.自動化したいデータベースのページを開く
  2. 2.右上の「...」メニューから「接続」を選択
  3. 3.先ほど作ったインテグレーション名を検索して追加

注意:子ページは親ページの接続設定を自動的に継承する。つまり、ワークスペースのルートページにインテグレーションを接続すれば、配下の全ページにアクセス可能。ただしセキュリティ上、必要なページだけに絞るのがベター。

ステップ3:データベースIDの取得

APIでデータベースを操作するにはデータベースIDが必要。取得方法は簡単で、データベースページのURLに含まれている。https://notion.so/ワークスペース/ここがデータベースID?v=ビューID という構造になっている。32文字の英数字部分をコピーすればOK。

3. PythonでNotion APIを叩く — 基本操作

環境が整ったら、実際にコードを書いていく。Pythonの requests ライブラリだけで十分動くけど、notion-client という公式SDKを使うともっと楽。

インストール

pip install notion-client python-dotenv

データベースの中身を読み取る

まずは一番基本的な操作、データベースからデータを取得するコード。

query_database.py

import os
from notion_client import Client
from dotenv import load_dotenv

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

# データベースのページを取得
results = notion.databases.query(
    database_id=os.environ["TASK_DB_ID"],
    filter={
        "property": "ステータス",
        "select": {"equals": "進行中"}
    }
)

for page in results["results"]:
    title = page["properties"]["タスク名"]["title"][0]["plain_text"]
    print(f"進行中: {title}")

このコードでは、タスク管理DBから「ステータスが進行中」のタスクだけをフィルターして取得している。Notion APIのフィルター構文は最初ちょっと分かりにくいけど、パターンを覚えれば難しくない。プロパティのタイプ(select, date, number等)ごとにフィルター条件が決まっていて、公式ドキュメントに全パターンが載っている。

新しいページ(レコード)を追加する

create_task.py

from datetime import date

notion.pages.create(
    parent={"database_id": os.environ["TASK_DB_ID"]},
    properties={
        "タスク名": {
            "title": [{"text": {"content": "APIで作ったタスク"}}]
        },
        "ステータス": {
            "select": {"name": "未着手"}
        },
        "期限": {
            "date": {"start": str(date.today())}
        },
        "優先度": {
            "select": {"name": "中"}
        }
    }
)

APIから直接データベースにレコードを追加できる。Slackのメッセージからタスクを作ったり、メールの受信をトリガーにして案件を登録したり、応用範囲は広い。Python自動化入門を読んだ方なら、ここまでのコードは特に難しくないはず。

4. 実践:日報・週報を自動生成する

ここから実践編。僕が最初に自動化したのが日報の生成で、これが一番効果が大きかった。

やっていることはシンプル。タスクDBから「今日完了したタスク」をフィルターで引っ張ってきて、その情報を整形して日報ページとしてNotionに書き戻す。cronで毎日18時に回しておけば、退勤前には日報ができている。

daily_report.py(核心部分を抜粋)

from datetime import date, timedelta

today = str(date.today())

# 今日完了したタスクを取得
done_tasks = notion.databases.query(
    database_id=TASK_DB_ID,
    filter={
        "and": [
            {"property": "ステータス", "select": {"equals": "完了"}},
            {"property": "完了日", "date": {"equals": today}}
        ]
    }
)

# 日報ページを作成
task_lines = []
total_hours = 0
for page in done_tasks["results"]:
    name = page["properties"]["タスク名"]["title"][0]["plain_text"]
    hours = page["properties"]["実績時間"]["number"] or 0
    task_lines.append(f"- {name}({hours}h)")
    total_hours += hours

report_body = "\n".join(task_lines)

notion.pages.create(
    parent={"database_id": REPORT_DB_ID},
    properties={
        "タイトル": {"title": [{"text": {"content": f"日報 {today}"}}]},
        "日付": {"date": {"start": today}},
        "合計時間": {"number": total_hours}
    },
    children=[
        {
            "object": "block",
            "type": "heading_2",
            "heading_2": {"rich_text": [{"text": {"content": "完了タスク"}}]}
        },
        {
            "object": "block",
            "type": "paragraph",
            "paragraph": {"rich_text": [{"text": {"content": report_body}}]}
        }
    ]
)

週報も同じ要領で、フィルターの日付範囲を「今週」に変えるだけ。案件ごとにグルーピングして時間単価まで計算させれば、手で書くよりずっと正確なレポートが出来上がる。

実行環境のヒント:cronのためだけにサーバーを借りる必要はない。GitHub Actionsのスケジュール実行(無料枠で月2,000分)を使えば、毎日のスクリプト実行は余裕で賄える。schedule: cron: '0 9 * * *' をワークフローに追加するだけ。

5. 実践:タスクのステータス一括更新と通知

次に自動化したのが、期限切れタスクの処理。月曜の朝にNotionを開いて、先週の金曜が期限だったタスクが「進行中」のまま残っていると地味に萎える。これをスクリプトで自動処理する。

overdue_check.py

yesterday = str(date.today() - timedelta(days=1))

# 期限切れ&未完了のタスクを取得
overdue = notion.databases.query(
    database_id=TASK_DB_ID,
    filter={
        "and": [
            {"property": "期限", "date": {"before": yesterday}},
            {"property": "ステータス", "select": {"does_not_equal": "完了"}}
        ]
    }
)

overdue_names = []
for page in overdue["results"]:
    name = page["properties"]["タスク名"]["title"][0]["plain_text"]
    overdue_names.append(name)
    # ステータスを「要確認」に変更
    notion.pages.update(
        page_id=page["id"],
        properties={
            "ステータス": {"select": {"name": "要確認"}}
        }
    )

# Slack通知(webhook)
if overdue_names:
    import requests
    webhook_url = os.environ["SLACK_WEBHOOK"]
    msg = f"期限切れタスク {len(overdue_names)}件:\n" + "\n".join(f"- {n}" for n in overdue_names)
    requests.post(webhook_url, json={"text": msg})

ポイントは、期限切れタスクを単に放置するんじゃなく「要確認」というステータスに変えている点。ボードビューで「要確認」レーンが目に入れば、対応を忘れることがなくなる。さらにSlackに通知を飛ばしているので、Notionを開く前に状況が分かる。

こうしたデータの整形や確認作業には、ToolPlexのJSON整形ツールが地味に便利。APIのレスポンスを確認するとき、ブラウザでサッと整形できる。

6. ノーコード派向け:ZapierとMakeでNotion自動化

「Pythonは書けないけどNotion自動化はしたい」という方は、ZapierやMake(旧Integromat)を使えば同じことがノーコードでできる。正直、定型的な処理ならコードを書くよりこっちのほうが早い場面も多い。

すぐ使えるZap例

Googleフォーム → Notionデータベース

お問い合わせフォームの回答を自動でNotionの案件管理DBに登録。ステータスは「商談中」で初期化。手動転記がゼロになる。

Notionステータス変更 → Slack通知

案件のステータスが「納品済」に変わったらSlackの#completedチャンネルに自動通知。チームへの共有を自動化。

Googleカレンダー → Notionタスク

カレンダーに予定を入れると、Notionのタスク管理DBにも自動で反映。ダブル入力を排除。

Zapierの無料プランでは月100タスクまで使える。個人利用なら十分なケースが多い。Makeは無料枠が月1,000オペレーションとさらに太っ腹なので、複雑なフローを組むならMakeのほうがコスパがいい。

組み合わせの妙:Python + Zapier/Make の「ハイブリッド」もおすすめ。複雑なデータ加工はPythonで処理し、トリガーと通知はZapierに任せる。全部を一つの方法で賄う必要はない。

7. 自動化を前提としたNotionテンプレート設計

Notion APIで自動化していて痛感したのが、最初のデータベース設計が雑だと自動化で地獄を見るということ。たとえばステータスを「やることリスト」のタイトルに日本語で直書きしていたり、日付を「3/15」のようにテキストプロパティで入力していたりすると、APIでのフィルタリングが極めて面倒になる。

自動化を見据えたNotionテンプレート設計には、いくつかの鉄則がある。

鉄則 良い例 悪い例
ステータスはセレクト セレクトプロパティで「未着手/進行中/完了」 チェックボックスで完了/未完了だけ
日付は日付型で 日付プロパティを使う テキストに「3月15日」と書く
金額は数値型で 数値プロパティ(円表示設定) テキストに「¥10,000」と書く
プロパティ名は一貫性 全DBで「ステータス」に統一 DB Aは「状態」、DB Bは「ステータス」

Notionテンプレートの設計思想についてもっと詳しく知りたい方は、Notionテンプレートの作り方完全ガイドも参照してください。テンプレートの基本設計がしっかりしていれば、API連携は驚くほどスムーズに進む。

もう一つのコツは、自動化専用のプロパティを仕込んでおくこと。たとえば「最終更新スクリプト」というテキストプロパティを作っておいて、APIで更新するたびにスクリプト名とタイムスタンプを書き込む。こうしておくと、「このレコードはどのスクリプトがいつ更新したのか」が追跡できてデバッグが楽になる。

8. ハマりやすい落とし穴と対処法

Notion APIを使い込んでいく中で、何度かハマったポイントがある。同じ轍を踏まないようにまとめておく。

レート制限(Rate Limit)

Notion APIには1秒あたり3リクエストという制限がある。大量のページを一括処理するときに、何も考えずにforループを回すとすぐに429エラーが返ってくる。対策は単純で、リクエスト間に time.sleep(0.4) を挟むだけ。あるいは tenacity ライブラリでリトライを自動化するのが確実。

リトライ付きのリクエスト

from tenacity import retry, wait_exponential, stop_after_attempt

@retry(wait=wait_exponential(min=1, max=10), stop=stop_after_attempt(5))
def safe_query(db_id, **kwargs):
    return notion.databases.query(database_id=db_id, **kwargs)

ページネーション

データベースのクエリ結果は1回のリクエストで最大100件しか返ってこない。100件を超えるデータベースを扱う場合、レスポンスの has_more フラグと next_cursor を使って次のページを取得するループを書く必要がある。これを忘れると、101件目以降のデータが無視される。

リッチテキストの構造

Notion APIでテキストを扱うとき、文字列がそのまま返ってくると思ったら大間違い。全てのテキストは「リッチテキスト配列」という構造になっていて、太字や色がついた部分は別の要素として分離される。タイトルプロパティから単なる文字列を取り出すだけでも page["properties"]["タスク名"]["title"][0]["plain_text"] という長いアクセスパスが必要。最初は面食らうけど慣れの問題。

デバッグ時のコツ:APIレスポンスのJSON構造を確認するとき、ToolPlexのJSON整形ツールにレスポンスを貼り付けると、ネストされた構造が一発で見やすくなる。print文でターミナルに吐くより断然効率がいい。

9. まとめ

Notion APIを使った自動化の全体像を、セットアップから実践例、注意点まで一通り解説しました。

  • 1. Notion APIのセットアップはインテグレーション作成・接続許可・DB IDの取得の3ステップ。5分で完了する
  • 2. データの読み書きはPythonの公式SDKで簡潔に書ける。フィルター・ソート・ページネーションを押さえれば基本操作は網羅できる
  • 3. 日報・週報の自動生成タスク一括更新は効果が大きい。cronやGitHub Actionsで定期実行すれば完全自動化
  • 4. ノーコード派はZapierやMakeで同等の自動化が可能。PythonとのハイブリッドもOK
  • 5. テンプレート設計が自動化の成否を分ける。プロパティの型を正しく選び、命名を統一することが最重要

僕の場合、最初に日報自動生成を作るのに2時間かかった。でもそれ以降、毎日15分の日報作成がゼロになった。2週間で元が取れる計算。タスク一括更新やSlack通知も合わせると、Notionの「お世話時間」は週2時間から実質ゼロになった。自動化の投資対効果としてはかなり高い部類だと思う。

自動化の土台となるNotionのデータベース設計がまだの方は、テンプレートを使って一気に構築するのが現実的。案件管理・タスク管理・収支管理の3つが連携した状態で始められるので、API連携もすぐに着手できます。

フリーランスOS — API連携に最適化されたNotionテンプレート

この記事で紹介した自動化をすぐに始められるよう、プロパティの型・命名が統一されたNotionテンプレートを用意しました。案件管理・タスク管理・収支管理の3つのデータベースがリレーションで接続済み。インポートしたその日からAPI連携が可能です。

  • - 案件管理DB(API連携用プロパティ設計済み)
  • - タスク管理DB(ステータス・日付型を統一設計)
  • - 収支管理DB(数値型・セレクト型で集計最適化)
  • - セットアップガイド + APIサンプルコード付き(¥1,980)

まずは一番単純な自動化から始めてみてください。「データベースの中身をPythonで取得してprintする」だけでいい。APIが動く感動を一度味わえば、「次はあれも自動化しよう」と自然にアイデアが湧いてくるはずです。