2025.05.16

Difyの外部ナレッジAPIでNotion APIのデータを取得
- Dify
- AI
- Notion
- React
はじめに
Difyのナレッジは簡単にNotionと同期でき便利に使えます。前回の記事ではNotionから同期
でナレッジを作成しチャットbotを動かしましたが、この方法ではNotion側でデータの更新があった場合にDify側では手動でそれを更新しなければいけませんでした。
https://topaz-inc.dev/articles/dify-notion-knowledge-ai-chat-bot-react/
いずれはDifyがアップデートしてそれが自動でできるようになるかもしれませんが、現時点でそれを解決するためにNotion APIと外部アプリAPIを使い手動同期なしに最新のNotionにあるデータをナレッジとして使う方法を本記事を通して記録しました。
Notion APIの設定
まずはNotionのインテグレーションを新規作成します。


インテグレーションシークレットキーをコピーして、機能は今回はコンテンツを読み取る
だけにしました。

Notion APIとして使いたいページで先ほど作成したインテグレーションと接続します。

試しにページIDと先ほどのシークレットキーを含めて、Curlでリクエストしてみると正常に返ってきました。
curl -X GET \
'https://api.notion.com/v1/blocks/<page_id>/children' \
-H 'Notion-Version: 2022-06-28' \
-H 'Authorization: Bearer <integration_secret_key>'
外部アプリAPIの用意
外部APIに /api/notion_api/retrieval となるようなAPIエンドポイントを設置してDifyからのリクエストを受けて、Notion APIの値を取得し、それを返すような処理を実装します。
Dify が期待する形式は、records
配列を含む JSONなのでそれに合わせます。
今回は取り急ぎ、Gatsby(React, TypeScript)で用意しています。
import type { GatsbyFunctionRequest, GatsbyFunctionResponse } from "gatsby"
interface NotionRichText {
plain_text: string
}
interface NotionParagraph {
rich_text: NotionRichText[]
}
interface NotionBlock {
type: string
paragraph: NotionParagraph
}
interface NotionResponse {
results: NotionBlock[]
}
interface Record {
metadata: {
path: string
description: string
}
score: number
title: string
content: string
}
export default async function handler(
req: GatsbyFunctionRequest,
res: GatsbyFunctionResponse
) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" })
}
try {
const NOTION_INTEGRATION_SECRET_KEY = "xxx"
const NOTION_PAGE_ID = "xxx"
const NOTION_API_URL = `https://api.notion.com/v1/blocks/${NOTION_PAGE_ID}/children`
const response = await fetch(NOTION_API_URL, {
method: "GET",
headers: {
"Notion-Version": "2022-06-28",
Authorization: `Bearer ${NOTION_INTEGRATION_SECRET_KEY}`,
"Content-Type": "application/json",
},
})
if (!response.ok) {
throw new Error(`Notion API error: ${response.statusText}`)
}
const data = (await response.json()) as NotionResponse
const records = data.results
.map((block: NotionBlock): Record | null => {
if (
block.type === "paragraph" &&
block.paragraph.rich_text.length > 0
) {
const content = block.paragraph.rich_text
.map((textItem: NotionRichText) => textItem.plain_text)
.join("\n")
const title = "Notion Content"
const metadata = {
path: `notion://page/${NOTION_PAGE_ID}`,
description: "Notion ページの内容",
}
return { metadata, score: 1.0, title, content }
}
return null
})
.filter((record): record is Record => record !== null)
return res.status(200).json({ records })
} catch (error) {
console.error("Error:", error)
return res.status(500).json({ error: "Internal server error" })
}
}
Dify側の設定
上記で作成した外部APIのエンドポイントを、外部ナレッジベース連携APIに設定します。

ナレッジと外部ナレッジ連携APIを連携します。

そのナレッジをチャットボットアプリで使うよう選択します。

これでNotion側を更新した後に、外部アプリから動かしてみると、Notionにしかない内容を元にチャットボットが返信してくれました。

最後に
これでDify側のナレッジベースを更新することなく、書き慣れているNotion側の変更だけで済むので管理が楽になりました。
今回は簡単に再現してみましたが、実際の業務フローを想定するともっとやるべき点があると思いますので、セキュリティ面なども踏まえ、実用に向けてさらに構築していきたいと思います。