您好!作为一名资深的 全栈集成解决方案架构师,我非常理解您对 Notion API 深度和细节的渴望。Notion API 是一个强大而灵活的工具,它能将您的 Notion 工作区提升到前所未有的自动化和集成水平。本指南将带您深入探讨 Notion API 的各个方面,从核心概念到高级用法。
Notion API 遵循 RESTful 架构,所有资源都通过唯一的 URL 标识。请求和响应都以 JSON 格式传输。理解其背后的模型是高效交互的基础。
理解 API 交互的生命周期是构建稳健应用的基础。
Notion API 提供两种主要的认证方式:
Notion API 提供了丰富的端点来操作不同类型的资源。理解其请求和响应的 JSON 结构至关重要。
所有 API 请求都必须包含以下 HTTP 头:
| Header 名称 | 说明 | 示例值 |
|---|---|---|
Authorization |
认证凭据,格式为 Bearer YOUR_TOKEN。 |
Bearer secret_YOUR_TOKEN |
Notion-Version |
指定您希望使用的 API 版本。Notion 会定期发布新版本,旧版本可能会废弃。 | 2022-06-28 (推荐使用最新稳定版) |
Content-Type |
请求体的数据类型。对于 POST/PATCH 请求通常是 JSON。 | application/json |
POST /v1/databases/{database_id}/query):
这是最常用的端点之一,用于检索数据库中的页面。可以包含 `filter` (过滤), `sorts` (排序), `start_cursor` (分页游标), `page_size` (每页大小) 等。
// 请求体示例:查询状态为 "Done" 的任务
{
"filter": {
"property": "Status",
"select": {
"equals": "Done"
}
},
"sorts": [
{
"property": "Last edited time",
"direction": "descending"
}
],
"page_size": 100
}
// 响应体结构片段:
{
"object": "list",
"results": [
{
"object": "page",
"id": "page_id_1",
"created_time": "...",
"last_edited_time": "...",
"properties": {
"Name": {
"id": "...",
"type": "title",
"title": [
{
"type": "text",
"text": { "content": "我的任务标题" },
"plain_text": "我的任务标题"
}
]
},
"Status": {
"id": "...",
"type": "select",
"select": { "id": "...", "name": "Done", "color": "green" }
},
// ... 其他属性
},
// ...
},
// ...更多页面
],
"next_cursor": "...", // 用于下一页请求
"has_more": true,
"type": "page_or_database",
"page_or_database": {}
}
GET /v1/databases/{database_id}):
获取数据库的元数据,包括其所有属性的定义。
// 响应体结构片段:
{
"object": "database",
"id": "database_id_1",
"cover": null,
"icon": { "type": "emoji", "emoji": "📋" },
"created_time": "...",
"last_edited_time": "...",
"title": [
{
"type": "text",
"text": { "content": "我的任务数据库" }
}
],
"properties": {
"Name": { "id": "...", "type": "title", "title": {} },
"Status": { "id": "...", "type": "select", "select": { "options": [...] } },
"Tags": { "id": "...", "type": "multi_select", "multi_select": { "options": [...] } },
// ... 其他属性定义
},
// ...
}
POST /v1/pages):
在数据库中创建新条目,或创建独立的顶级页面。
// 请求体示例:在数据库中创建新页面,并添加内容块
{
"parent": { "database_id": "YOUR_DATABASE_ID" },
"properties": {
"任务名称": { // 注意这里是数据库中实际的属性名称
"title": [
{ "text": { "content": "新的 API 任务条目" } }
]
},
"状态": {
"select": { "name": "待办" }
},
"负责人": {
"people": [
{ "id": "user_id_of_assigned_person" } // Notion 用户 ID 或集成 ID
]
}
},
"children": [ // 可以在创建时直接添加子块
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [
{ "text": { "content": "这是任务的详细描述。" } }
]
}
},
{
"object": "block",
"type": "to_do",
"to_do": {
"rich_text": [
{ "text": { "content": "完成子任务 1" } }
],
"checked": false
}
}
]
}
PATCH /v1/pages/{page_id}):
修改现有页面的属性值。
// 请求体示例:更新页面状态和添加标签
{
"properties": {
"Status": {
"select": { "name": "已完成" }
},
"Tags": {
"multi_select": [
{ "name": "API" },
{ "name": "自动化" }
]
}
}
}
Notion 的内容是基于块构建的。每个页面都是一系列块的集合。
GET /v1/blocks/{block_id}/children):
获取页面或任何容器块(如 Callout、Toggle list、Column)中的所有子块。这对于读取页面内容至关重要。
// 响应体结构片段:
{
"object": "list",
"results": [
{
"object": "block",
"id": "block_id_1",
"type": "paragraph",
"paragraph": {
"rich_text": [
{ "type": "text", "text": { "content": "这是一个段落。" } }
],
"color": "default"
}
},
{
"object": "block",
"id": "block_id_2",
"type": "heading_1",
"heading_1": {
"rich_text": [
{ "type": "text", "text": { "content": "主标题" } }
]
}
},
// ...更多块
],
"next_cursor": null,
"has_more": false
}
PATCH /v1/blocks/{block_id}/children):
在现有页面或块的末尾追加新的子块,或更新现有子块的顺序。
// 请求体示例:在页面末尾添加一个代码块和一个图片块
{
"children": [
{
"object": "block",
"type": "code",
"code": {
"rich_text": [
{ "text": { "content": "print('Hello Notion API!')" } }
],
"language": "python"
}
},
{
"object": "block",
"type": "image",
"image": {
"external": {
"url": "https://example.com/your-image.png"
}
}
}
]
}
PATCH /v1/blocks/{block_id}):
更新单个块的内容。例如,改变一个段落的文本,或更新一个 To-do 列表项的 `checked` 状态。
// 请求体示例:更新一个 To-do 块的完成状态
{
"to_do": {
"checked": true
}
}
DELETE /v1/blocks/{block_id}):
将块移动到垃圾桶。注意,删除块是不可逆的(无法通过 API 恢复)。
Notion 中几乎所有的文本内容(标题、段落、属性文本)都以富文本对象数组的形式表示。每个富文本对象可以包含不同的样式(粗体、斜体、下划线、颜色、链接)或提及(用户、页面、日期)。
[
{
"type": "text",
"text": {
"content": "这是一段",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "这是一段",
"href": null
},
{
"type": "text",
"text": {
"content": "加粗斜体",
"link": null
},
"annotations": {
"bold": true,
"italic": true,
"strikethrough": false,
"underline": false,
"code": false,
"color": "red"
},
"plain_text": "加粗斜体",
"href": null
},
{
"type": "mention",
"mention": {
"type": "page",
"page": {
"id": "another_page_id"
}
},
"annotations": { /* ... */ },
"plain_text": "@另一页",
"href": "https://www.notion.so/..."
}
]
Notion API 默认限制每页返回的条目数量 (通常是 100)。对于大型数据库,您需要使用 `next_cursor` 和 `has_more` 字段来迭代所有结果。
import requests
def query_database_all_pages(database_id, notion_token):
url = f"https://api.notion.com/v1/databases/{database_id}/query"
headers = {
"Authorization": f"Bearer {notion_token}",
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
all_results = []
has_more = True
next_cursor = None
while has_more:
payload = {
"page_size": 100
}
if next_cursor:
payload["start_cursor"] = next_cursor
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status() # 如果请求失败,抛出异常
data = response.json()
all_results.extend(data['results'])
has_more = data['has_more']
next_cursor = data['next_cursor']
return all_results
# 使用示例
# pages = query_database_all_pages("YOUR_DATABASE_ID", "secret_YOUR_TOKEN")
# print(f"检索到 {len(pages)} 个页面。")
Notion API 有严格的速率限制。当达到限制时,API 会返回 429 Too Many Requests 错误。您应该实现指数退避 (Exponential Backoff) 策略来处理这种情况。
常见的错误状态码:
400 Bad Request: 请求体格式错误或参数无效。401 Unauthorized: 认证令牌无效或缺失。403 Forbidden: 集成没有访问资源的权限。404 Not Found: 资源 ID 不存在。429 Too Many Requests: 速率限制。500 Internal Server Error: Notion 服务器端错误。Notion 官方提供了两种编程语言的 SDK,强烈推荐使用它们来简化开发:
这些 SDK 封装了 HTTP 请求细节、认证、版本管理以及复杂的 JSON 结构,提供了更友好的面向对象接口。
// 使用 Notion JavaScript SDK 查询数据库
const { Client } = require("@notionhq/client");
const notion = new Client({ auth: process.env.NOTION_TOKEN });
(async () => {
const databaseId = process.env.NOTION_DATABASE_ID;
const response = await notion.databases.query({
database_id: databaseId,
filter: {
property: "Status",
select: {
equals: "待办",
},
},
});
console.log(response.results);
})();
Notion API 提供了一个与您 Notion 工作区深度交互的强大接口。通过掌握其核心概念、API 端点和数据结构,您可以构建各种自动化工具和集成方案,极大地提升您的工作效率。
记住,实践是最好的学习方式。尝试从小功能开始,逐步扩展您的集成。Notion 官方文档和社区资源也将是您宝贵的伙伴。
祝您在 Notion API 的世界中探索愉快,并构建出令人惊叹的解决方案!如果您有任何更具体的集成场景或代码问题,请随时提出,我将继续为您提供专业支持。