【実践】Notion API × Claude Code で自動テックブログを構築する
実装約10分で読めます

この記事でわかること
- Notion Integration を作って、対象ページに接続するまでの手順
- 技術記事を管理するデータベースのプロパティ設計
- Notion のページが properties(メタデータ)と children(ブロック)でできていること
- 見出し・コード・Callout の具体的な JSON の形
- 「Could not find database」など、最初に必ず踏むエラーの原因
Notion アカウント(無料プランで可)。curl などで HTTP リクエストを投げれば十分です。Claude Code は必須ではありません。
ポイント
Notion APIとClaude Codeを組み合わせて、開発セッションの内容を自動でNotionに保存するシステムを構築します。データベース設計からAPI連携まで、実践的な実装方法を解説します。
はじめに
開発中に得た知見やトラブルシューティングの内容を記録したいと思っても、手動でメモを取るのは面倒です。Claude Codeで開発しながら、その内容を自動でNotionに記事として保存できたら便利ですよね。
この記事では、Notion APIを使ってClaude Codeから直接Notionにコンテンツを作成するシステムの構築方法を解説します。
システム全体像
まず、構築するシステムの全体像をmermaidで確認しましょう。
flowchart LR
A[Claude Code] -->|API Call| B[Notion API]
B -->|Create| C[Database]
B -->|Create| D[Page]
D -->|Contains| E[Blocks]
subgraph Notion
C
D
E
end
subgraph Block_Types
E --> F[Heading]
E --> G[Paragraph]
E --> H[Code]
E --> I[Callout]
end
Step 1: Notion Integrationの作成
1-1. Integration作成ページにアクセス
Notion APIを使用するには、まずIntegration(統合)を作成する必要があります。
- My integrations にアクセス
- 「新しいインテグレーション」をクリック
- 名前を入力(例: claude_code_integration)
- 関連付けるワークスペースを選択
1-2. 権限設定
メモ
必要な権限:
• コンテンツを読み取る
• コンテンツを挿入
• コンテンツを更新
1-3. シークレットトークンの取得
Integrationを作成すると、シークレットトークン(ntn_xxx...)が発行されます。このトークンは一度しか表示されないので、安全な場所に保存してください。
# 環境変数として設定(推奨)
export NOTION_API_TOKEN="ntn_xxxxxxxxxxxxx"1-4. ページへの接続
注意
重要: Integrationを作成しただけでは、ページにアクセスできません!
Notionで対象ページを開き、右上の「...」→「接続」から作成したIntegrationを追加する必要があります。
Step 2: データベース設計
2-1. テックブログ用プロパティ
技術記事を管理するのに適したプロパティ構成を設計します。
erDiagram
TECH_ARTICLES {
title Title PK
multi_select Tags
select Category
select Status
date Created
}
2-2. カテゴリの選択肢
- トラブルシューティング - エラー解決、デバッグ記録
- 設定・環境構築 - 開発環境、ツール設定
- 実装 - 機能開発、コーディング
- 設計 - アーキテクチャ、設計パターン
- 学習メモ - 新しい技術、概念の学び
2-3. APIでデータベースを作成
curl -X POST "https://api.notion.com/v1/databases" \
-H "Authorization: Bearer $NOTION_API_TOKEN" \
-H "Notion-Version: 2022-06-28" \
-H "Content-Type: application/json" \
-d '{
"parent": {"page_id": "親ページのID"},
"title": [{"text": {"content": "Tech Articles"}}],
"properties": {
"Title": {"title": {}},
"Tags": {
"multi_select": {
"options": [
{"name": "React", "color": "blue"},
{"name": "TypeScript", "color": "blue"}
]
}
},
"Category": {
"select": {
"options": [
{"name": "実装", "color": "purple"},
{"name": "設計", "color": "orange"}
]
}
},
"Status": {
"select": {
"options": [
{"name": "Draft", "color": "gray"},
{"name": "Published", "color": "green"}
]
}
},
"Created": {"date": {}}
}
}'Step 3: ページ作成の実装
3-1. API呼び出しのシーケンス
Notion APIでページを作成する流れを図解します。
sequenceDiagram
participant C as Claude Code
participant A as Notion API
participant D as Database
participant P as Page
C->>A: POST /pages
A->>D: Validate parent
A->>P: Create page
A->>P: Add blocks
A-->>C: Return page object
3-2. プロパティとブロックの指定
const pageData = {
parent: { database_id: "データベースID" },
icon: { type: "emoji", emoji: "📝" },
cover: {
type: "external",
external: { url: "https://images.unsplash.com/..." }
},
properties: {
Title: { title: [{ text: { content: "記事タイトル" } }] },
Tags: { multi_select: [{ name: "React" }] },
Category: { select: { name: "実装" } },
Status: { select: { name: "Published" } },
Created: { date: { start: "2026-01-19" } }
},
children: [
// ブロックの配列(後述)
]
};3-3. 主要なブロックタイプ
Notionのコンテンツは「ブロック」の集まりです。主要なブロックタイプを紹介します。
ポイント
見出し(heading_2, heading_3)
{
"type": "heading_2",
"heading_2": {
"rich_text": [{ "text": { "content": "セクションタイトル" } }]
}
}メモ
コードブロック(code)- 言語指定が可能
{
"type": "code",
"code": {
"rich_text": [{ "text": { "content": "console.log('Hello');" } }],
"language": "typescript"
}
}ポイント
Callout(強調ボックス)- アイコンと背景色を指定
{
"type": "callout",
"callout": {
"rich_text": [{ "text": { "content": "重要なポイント" } }],
"icon": { "type": "emoji", "emoji": "💡" },
"color": "blue_background"
}
}Step 4: 実践的な記事作成
4-1. Zenn/Qiita品質のテンプレート
const articleBlocks = [
// 概要Callout
{
type: "callout",
callout: {
rich_text: [{ text: { content: "この記事の概要..." } }],
icon: { type: "emoji", emoji: "💡" },
color: "blue_background"
}
},
// 目次
{ type: "table_of_contents", table_of_contents: { color: "gray" } },
// はじめに
{ type: "heading_2", heading_2: { rich_text: [{ text: { content: "はじめに" } }] } },
{ type: "paragraph", paragraph: { rich_text: [{ text: { content: "背景説明..." } }] } },
// この記事でわかること
{ type: "heading_2", heading_2: { rich_text: [{ text: { content: "この記事でわかること" } }] } },
{ type: "bulleted_list_item", bulleted_list_item: { rich_text: [{ text: { content: "学べること1" } }] } },
// ... 続く
];Tips: よくあるエラーと対処法
重要
- 「Could not find database」エラー → Integrationがページに接続されていない。Notionで「接続」を追加する。
重要
- 「Invalid request」エラー → JSONの構造が間違っている。特にrich_textは配列である必要がある。
重要
- 「Unauthorized」エラー
→ トークンが違うか、
Authorization: Bearerの形式が崩れている。環境変数が展開されずに空文字列になっているケースも多いので、echo $NOTION_API_TOKENで確かめる。
ポイント
Notion-Version ヘッダーは日付で固定する仕様で、指定した日付の振る舞いが保たれます。この記事の 2022-06-28 は今も動きますが、新しい版ではデータベース周りのモデルが変わっています(データソースという層が入りました)。上げるときはレスポンスの形が変わるので、差分を確認してからにしてください。参考リンク
まとめ
- Notion Integrationを作成し、対象ページに接続する
- データベースは適切なプロパティ(Title, Tags, Category, Status, Created)で設計
- ページ作成はproperties(メタデータ)とchildren(ブロック)で構成
- ブロックタイプを理解すれば、リッチなコンテンツが作成可能
次のステップとして、Claude Code Skills と組み合わせることで、開発セッションの内容を自動で記事化するシステムを構築できます。具体的な設計は Claude Code × Notion で開発セッションを自動記事化する仕組み に書いています。
また、ここで作ったデータベースを Next.js から読んで実際のブログにする部分は Notion API でブログシステムを構築する で扱っています。
更新履歴
- 参考リンクと本文の裸 URL をタイトル付きリンクに変更。Unauthorized エラーの説明にあった「期限切れ」を修正(Integration トークンに有効期限はないため、実際に多い原因に差し替え)。Notion-Version ヘッダーの意味と、新しい版でデータベース周りのモデルが変わっていることを補足。内容が隣接する他記事へのリンクを末尾に追加。「この記事でわかること」「対象読者」「前提条件」を概要プロパティへ移動。OGP Description を内容に即したものに変更。

