# ? OpenClaw ???????
export NOTION_API_KEY="secret_xxxxxxxxxxxxxxxxxxxxxx"
export NOTION_DATABASE_ID="your_database_id_here"
1.3 ????????
Integration ???????????????????????:
- ??????? Notion ??
- ?????
... ? Connections ? ???? Integration
- ?????,???? Integration ??Can edit???
??OpenClaw ??? Notion ??
? OpenClaw ???????? Notion ????:
{
"skills": {
"notion": {
"enabled": true,
"config": {
"apiKey": "${NOTION_API_KEY}",
"databases": {
"blogIdeas": "database_id_for_blog_ideas",
"meetingNotes": "database_id_for_meeting_notes",
"knowledgeBase": "database_id_for_knowledge_base"
},
"syncDirection": "bidirectional",
"pollInterval": 300
}
}
}
}
????????
3.1 ?? Notion ?????
// skills/notion/skill.js
const fetch = require('node-fetch');
module.exports = {
name: 'notion',
description: 'Sync with Notion databases and pages',
async queryDatabase(databaseId, filter = {}) {
const response = await fetch(`https://api.notion.com/v1/databases/${databaseId}/query`, {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.NOTION_API_KEY,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
},
body: JSON.stringify(filter)
});
return response.json();
},
async getPage(pageId) {
const response = await fetch(`https://api.notion.com/v1/pages/${pageId}`, {
headers: {
'Authorization': 'Bearer ' + process.env.NOTION_API_KEY,
'Notion-Version': '2022-06-28'
}
});
return response.json();
}
};
3.2 ?? Notion ???
// ?????????
async function createDatabaseItem(databaseId, properties) {
const response = await fetch('https://api.notion.com/v1/pages', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + process.env.NOTION_API_KEY,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
},
body: JSON.stringify({
parent: { database_id: databaseId },
properties: properties
})
});
return response.json();
}
// ??:??????? Notion
await createDatabaseItem(process.env.NOTION_DATABASE_ID, {
'Title': { title: [{ text: { content: 'OpenClaw ????' } }] },
'Status': { select: { name: 'Idea' } },
'Tags': { multi_select: [{ name: 'Tutorial' }, { name: 'OpenClaw' }] },
'Created': { date: { start: new Date().toISOString() } }
});
3.3 ??????
async function updatePage(pageId, properties) {
const response = await fetch(`https://api.notion.com/v1/pages/${pageId}`, {
method: 'PATCH',
headers: {
'Authorization': 'Bearer ' + process.env.NOTION_API_KEY,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
},
body: JSON.stringify({ properties })
});
return response.json();
}
// ??:??????????
await updatePage('page_id_here', {
'Status': { select: { name: 'Published' } },
'PublishedDate': { date: { start: new Date().toISOString() } }
});
????????
????????? OpenClaw ?????????,???? Notion ????:
// skills/notion/sync.js
const fs = require('fs').promises;
const path = require('path');
module.exports = {
async bidirectionalSync(databaseId) {
const localCache = await this.loadLocalCache(databaseId);
const remoteData = await this.queryDatabase(databaseId);
const updates = [];
for (const page of remoteData.results) {
const localVersion = localCache[page.id];
const remoteUpdated = page.last_edited_time;
if (!localVersion || new Date(remoteUpdated) > new Date(localVersion.cachedAt)) {
// ?????,?????
await this.syncToLocal(page);
updates.push({ direction: 'remote?local', pageId: page.id });
}
}
// ?????????????
const localUpdates = await this.getLocalUpdates(databaseId);
for (const localItem of localUpdates) {
await this.syncToRemote(localItem);
updates.push({ direction: 'local?remote', pageId: localItem.pageId });
}
return { synced: updates.length, details: updates };
},
async loadLocalCache(databaseId) {
const cachePath = path.join('.openclaw', 'cache', 'notion', databaseId + '.json');
try {
const data = await fs.readFile(cachePath, 'utf8');
return JSON.parse(data);
} catch (e) {
return {};
}
}
};
????????
5.1 ????????
??:??????????? Notion
??:??????????...
? ??? Notion ??:2026-05-16 ????
? ??? 12 ???
? ?????:OpenClaw?????
????:https://notion.Notion ????
5.2 ??????
? topics.json ? Notion ?????,?????????:
// ? Notion ????
const blogIdeas = await queryDatabase(notionDbId, {
filter: {
property: 'Status',
select: { equals: 'Idea' }
}
});
// ??? topics.json
const topics = blogIdeas.results.map(page => ({
id: page.properties.Slug.rich_text[0].plain_text,
title: page.properties.Title.title[0].plain_text,
status: page.properties.Status.select.name.toLowerCase()
}));
await fs.writeFile('blog/topics.json', JSON.stringify({ topics }, null, 2));
5.3 ???????
?? OpenClaw ?????,???? Notion ????????:
??:????????Docker ????????
??:? Notion ??????? 3 ?????:
1. ?? Docker ??????
????:2026-05-10
??:???????? Docker ?? OpenClaw...
??:https://notion.
2. ?? Docker Compose ????
????:2026-04-28
...
??????????????
???????????
// ???? Notion API ??
async function notionApiCall(url, options = {}, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, {
...options,
headers: {
...options.headers,
'Authorization': 'Bearer ' + process.env.NOTION_API_KEY,
'Notion-Version': '2022-06-28'
}
});
if (response.status === 429) {
// ????,?????
const retryAfter = response.headers.get('Retry-After') || 1;
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response.json();
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, i)));
}
}
}
?????????
- API Key ??:Notion API Key ?????????,?????Read all pages???
- ????:????? Notion ???????
- ????:?????????? Notion ??????
- ????:???? Notion API ??,??????
??
?? OpenClaw ? Notion ?????,???????????????????????????????,?????????,?????????????????? AI ??,??? Notion ????????