Outline API开发指南:构建协作式知识管理系统
核心能力解析
基础交互层
文档生命周期管理
文档是Outline系统的核心实体,所有知识管理操作都围绕文档展开。以下是文档从创建到删除的完整生命周期管理接口。
创建文档
创建新文档是使用Outline API的第一步。这个接口允许你定义文档的基本属性,包括标题、内容、所属集合等。
import requests
import json
def create_document(token, title, text, collection_id):
url = "/api/documents.create"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {
"title": title,
"text": text,
"collectionId": collection_id,
"publish": True
}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
# 使用示例
token = "your_jwt_token_here"
new_doc = create_document(token, "API使用指南", "这是一篇关于Outline API的使用指南...", "collection_uuid")
print(f"创建的文档ID: {new_doc['data']['id']}")
⚠️ 注意:文档内容text字段需要使用ProseMirror JSON格式,这是一种结构化的文档表示方式,支持富文本格式。
获取文档详情
获取文档详情接口用于检索单个文档的完整信息,包括内容、元数据、修订历史和评论等。
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type DocumentInfoRequest struct {
Id string `json:"id"`
}
type DocumentInfoResponse struct {
Data struct {
Document struct {
Id string `json:"id"`
Title string `json:"title"`
Text string `json:"text"`
CreatedAt string `json:"createdAt"`
} `json:"document"`
} `json:"data"`
}
func getDocumentInfo(token, docId string) (*DocumentInfoResponse, error) {
url := "/api/documents.info"
client := &http.Client{}
requestBody := DocumentInfoRequest{Id: docId}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var response DocumentInfoResponse
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
return &response, nil
}
更新文档
更新文档接口允许你修改现有文档的内容和属性。支持全量更新或部分更新。
def update_document(token, doc_id, title=None, text=None):
url = "/api/documents.update"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {"id": doc_id}
if title:
data["title"] = title
if text:
data["text"] = text
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
删除文档
删除文档接口提供了两种删除模式:普通删除(放入回收站)和永久删除。
func deleteDocument(token, docId string, permanent bool) error {
url := "/api/documents.delete"
client := &http.Client{}
requestBody := struct {
Id string `json:"id"`
Permanent bool `json:"permanent"`
}{docId, permanent}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("删除文档失败: %s", resp.Status)
}
return nil
}
适用场景:基础文档管理操作适用于任何需要创建、查看、更新或删除文档的场景,如内容管理系统集成、自动化文档生成工具等。
文档状态控制
Outline提供了灵活的文档状态管理机制,包括发布、取消发布、归档和恢复等操作。
发布文档
发布文档会将文档状态设置为"已发布",使其对有权限的用户可见。
def publish_document(token, doc_id):
url = "/api/documents.update"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {
"id": doc_id,
"publish": True
}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
取消发布
取消发布操作会将文档状态从"已发布"改为"草稿",限制其可见范围。
def unpublish_document(token, doc_id):
url = "/api/documents.unpublish"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {"id": doc_id}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
归档文档
归档功能允许你将不常用但需要保留的文档移至归档状态,减少主视图中的干扰。
func archiveDocument(token, docId string) error {
url := "/api/documents.archive"
client := &http.Client{}
requestBody := struct {
Id string `json:"id"`
}{docId}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
恢复文档
从归档或删除状态恢复文档,使其重新可用。
func restoreDocument(token, docId, collectionId string) error {
url := "/api/documents.restore"
client := &http.Client{}
requestBody := struct {
Id string `json:"id"`
CollectionId string `json:"collectionId"`
}{docId, collectionId}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
高级操作层
文档批量操作
当需要处理多个文档时,批量操作可以显著提高效率。
批量获取文档列表
def list_documents(token, collection_id=None, sort="updatedAt", direction="DESC", limit=20):
url = "/api/documents.list"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {
"sort": sort,
"direction": direction,
"limit": limit
}
if collection_id:
data["collectionId"] = collection_id
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
复制文档
复制文档功能允许你创建现有文档的副本,可选择是否递归复制子文档。
func duplicateDocument(token, docId, newTitle, collectionId string) (*DocumentInfoResponse, error) {
url := "/api/documents.duplicate"
client := &http.Client{}
requestBody := struct {
Id string `json:"id"`
Title string `json:"title"`
CollectionId string `json:"collectionId"`
Recursive bool `json:"recursive"`
}{docId, newTitle, collectionId, false}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var response struct {
Data struct {
Id string `json:"id"`
Title string `json:"title"`
} `json:"data"`
}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
// 获取新文档的详细信息
return getDocumentInfo(token, response.Data.Id)
}
移动文档
将文档从一个集合移动到另一个集合,或调整其在集合中的位置。
def move_document(token, doc_id, collection_id, parent_document_id=None, index=0):
url = "/api/documents.move"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {
"id": doc_id,
"collectionId": collection_id,
"index": index
}
if parent_document_id:
data["parentDocumentId"] = parent_document_id
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
⚠️ 注意:批量操作建议使用异步处理方式,避免长时间阻塞主线程。对于超过100个文档的批量操作,考虑分批次处理。
文档内容搜索
Outline提供了强大的文档搜索功能,支持标题搜索和内容搜索两种模式。
搜索文档标题
def search_document_titles(token, query, collection_id=None):
url = "/api/documents.search_titles"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {"query": query}
if collection_id:
data["collectionId"] = collection_id
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
搜索文档内容
func searchDocumentContent(token, query string) ([]DocumentInfo, error) {
url := "/api/documents.search"
client := &http.Client{}
requestBody := struct {
Query string `json:"query"`
}{query}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var response struct {
Pagination struct {
Offset int `json:"offset"`
Limit int `json:"limit"`
Total int `json:"total"`
} `json:"pagination"`
Data []DocumentInfo `json:"data"`
}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return nil, err
}
return response.Data, nil
}
适用场景:高级操作适用于文档管理系统、知识检索工具、批量内容迁移等需要处理多个文档或进行复杂操作的场景。
安全控制层
权限管理
Outline提供了细粒度的权限控制机制,支持针对用户和组设置不同级别的访问权限。
添加用户权限
def add_document_permission(token, doc_id, user_id, permission):
"""
为用户添加文档权限
permission参数可选值:
- "read": 只读权限
- "read_write": 读写权限
- "admin": 管理员权限
"""
url = "/api/documents.add_user"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {
"id": doc_id,
"userId": user_id,
"permission": permission
}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
添加组权限
func addGroupPermission(token, docId, groupId, permission string) error {
url := "/api/documents.add_group"
client := &http.Client{}
requestBody := struct {
Id string `json:"id"`
GroupId string `json:"groupId"`
Permission string `json:"permission"`
}{docId, groupId, permission}
jsonBody, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
移除权限
def remove_user_permission(token, doc_id, user_id):
url = "/api/documents.remove_user"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {token}"
}
data = {
"id": doc_id,
"userId": user_id
}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json()
适用场景:权限管理适用于需要控制文档访问范围的场景,如团队协作环境、客户文档共享、内部知识库等。
操作指南
API基础交互
认证机制
Outline API使用JWT(JSON Web Token) 进行认证。JWT是一种紧凑的、URL安全的方式,用于表示在双方之间传递的声明。
获取JWT令牌
def get_auth_token(email, password):
url = "/api/auth.login"
headers = {"Content-Type": "application/json"}
data = {
"email": email,
"password": password
}
response = requests.post(url, headers=headers, data=json.dumps(data))
return response.json().get("data", {}).get("token")
⚠️ 注意:JWT令牌有过期时间,通常为24小时。生产环境中应实现令牌自动刷新机制。
通用响应结构
所有Outline API接口返回的响应都遵循统一的结构:
{
"pagination": {
"offset": 0,
"limit": 20,
"total": 100
},
"data": [],
"policies": {}
}
pagination:分页信息,仅在返回列表数据时包含data:接口返回的具体数据policies:权限信息,描述当前用户对返回资源的操作权限
错误处理
API错误响应格式统一为:
{
"error": {
"name": "ValidationError",
"message": "Invalid input provided",
"status": 422,
"details": [
{
"path": ["title"],
"message": "Title is required"
}
]
}
}
常见错误状态码:
| 状态码 | 描述 |
|---|---|
| 400 | 请求参数错误 |
| 401 | 未授权,需要认证 |
| 403 | 权限不足 |
| 404 | 资源不存在 |
| 422 | 验证错误 |
| 429 | 请求频率超限 |
| 500 | 服务器内部错误 |
文档管理工作流
以下是一个完整的文档管理工作流示例,展示了如何使用多个API接口协同完成任务。
graph TD
A[创建文档] --> B[更新文档内容]
B --> C[设置文档权限]
C --> D[发布文档]
D --> E[获取文档列表]
E --> F[搜索文档]
F --> G[移动文档]
G --> H[归档文档]
完整工作流代码示例
# 1. 获取认证令牌
token = get_auth_token("user@example.com", "password")
# 2. 创建新文档
new_doc = create_document(token, "API使用指南", "这是一篇关于Outline API的使用指南...", "collection_uuid")
doc_id = new_doc["data"]["id"]
# 3. 更新文档内容
update_document(token, doc_id, text="更新后的文档内容,包含更多详细信息...")
# 4. 设置文档权限
add_document_permission(token, doc_id, "user_uuid", "read_write")
add_group_permission(token, doc_id, "group_uuid", "read")
# 5. 发布文档
publish_document(token, doc_id)
# 6. 搜索文档
search_results = search_document_content(token, "API指南")
# 7. 移动文档到新集合
move_document(token, doc_id, "new_collection_uuid")
# 8. 归档文档(当不再需要但需保留时)
archive_document(token, doc_id)
最佳实践
接口设计理念
Outline API采用RESTful设计风格,同时结合了GraphQL的灵活性。主要设计理念包括:
- 资源导向:所有操作围绕资源(主要是文档)展开
- 统一接口:使用一致的请求和响应格式
- 无状态:每个请求包含所有必要信息,服务器不存储客户端状态
- 操作明确:API端点名称清晰反映其功能,如
documents.create、documents.update
不同于传统REST使用HTTP方法(GET、POST、PUT、DELETE)来表示操作类型,Outline API统一使用POST方法,通过端点名称区分操作类型。这种设计简化了API使用,特别适合复杂操作场景。
接口版本演进
Outline API经历了多个版本的演进,主要变化如下:
| 版本 | 主要变化 | 兼容性 |
|---|---|---|
| v1 | 初始版本,基础文档操作 | 已过时,不推荐使用 |
| v2 | 增加权限管理、高级搜索功能 | 完全兼容v1,推荐使用 |
| v3 | 引入异步操作支持、批量处理优化 | 部分兼容v2,新增功能需显式指定版本 |
要使用特定版本的API,可以在请求中指定apiVersion参数:
{
"id": "uuid",
"apiVersion": 2
}
性能优化建议
-
批量操作代替循环单个操作
对于需要处理多个文档的场景,使用批量接口代替循环调用单个接口:
# 不推荐 for doc_id in doc_ids: delete_document(token, doc_id) # 推荐(如果有批量删除接口) batch_delete_documents(token, doc_ids) -
分页获取大量数据
当获取大量文档时,使用分页参数控制返回数据量:
def get_all_documents(token, collection_id): all_docs = [] offset = 0 limit = 50 while True: response = list_documents(token, collection_id, limit=limit, offset=offset) docs = response.get("data", []) if not docs: break all_docs.extend(docs) offset += limit # 检查是否还有更多数据 pagination = response.get("pagination", {}) if offset >= pagination.get("total", 0): break return all_docs -
合理设置缓存策略
对于不常变化的数据(如文档列表、用户信息),实施缓存策略减少API调用:
from functools import lru_cache @lru_cache(maxsize=128) def get_collection_docs(token, collection_id): return list_documents(token, collection_id) -
异步处理长时间运行的操作
对于导入、导出等耗时操作,使用异步处理模式:
def export_document_async(token, doc_id): url = "/api/documents.export" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {token}" } data = {"id": doc_id} response = requests.post(url, headers=headers, data=json.dumps(data)) task_id = response.json().get("data", {}).get("taskId") return task_id def check_export_status(token, task_id): url = "/api/tasks.info" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {token}" } data = {"id": task_id} response = requests.post(url, headers=headers, data=json.dumps(data)) return response.json().get("data", {})
常见场景解决方案
场景一:构建自定义文档管理界面
解决方案:使用文档CRUD接口+权限管理接口
# 核心功能实现
class CustomDocumentManager:
def __init__(self, token):
self.token = token
def list_documents(self, collection_id):
"""列出集合中的所有文档"""
return list_documents(self.token, collection_id)
def create_document(self, title, content, collection_id):
"""创建新文档"""
return create_document(self.token, title, content, collection_id)
def get_document_details(self, doc_id):
"""获取文档详细信息"""
return get_document_info(self.token, doc_id)
def update_document_content(self, doc_id, content):
"""更新文档内容"""
return update_document(self.token, doc_id, text=content)
def set_document_permissions(self, doc_id, user_permissions):
"""设置文档权限"""
results = []
for user_id, permission in user_permissions.items():
result = add_document_permission(self.token, doc_id, user_id, permission)
results.append(result)
return results
场景二:实现文档自动同步
解决方案:使用文档列表、创建和更新接口,结合定时任务
import time
from datetime import datetime
def sync_documents(source_system, token, collection_id):
"""从外部系统同步文档到Outline"""
last_sync_time = datetime.now().isoformat()
while True:
# 从源系统获取更新的文档
updated_docs = source_system.get_updated_documents(since=last_sync_time)
for doc in updated_docs:
# 检查文档是否已存在
search_results = search_document_titles(token, doc["title"], collection_id)
if search_results["pagination"]["total"] > 0:
# 更新现有文档
existing_doc_id = search_results["data"][0]["id"]
update_document(token, existing_doc_id, title=doc["title"], text=doc["content"])
else:
# 创建新文档
create_document(token, doc["title"], doc["content"], collection_id)
# 更新最后同步时间
last_sync_time = datetime.now().isoformat()
# 等待一段时间后再次同步
time.sleep(3600) # 每小时同步一次
场景三:实现基于知识库的智能问答系统
解决方案:使用文档搜索接口+自然语言处理
import nltk
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
# 下载必要的NLTK资源
nltk.download('punkt')
nltk.download('stopwords')
def answer_question(token, question):
"""基于知识库回答问题"""
# 处理问题,提取关键词
tokens = word_tokenize(question.lower())
stop_words = set(stopwords.words('english'))
keywords = [word for word in tokens if word.isalpha() and word not in stop_words]
if not keywords:
return "无法提取关键词,请重新表述问题"
# 搜索相关文档
search_query = " ".join(keywords)
results = search_document_content(token, search_query)
if not results:
return "未找到相关文档"
# 简单的答案提取(实际应用中可使用更复杂的NLP技术)
best_match = results[0]
return f"根据文档 '{best_match['title']}': {best_match['text'][:200]}..."
通过以上API和最佳实践,你可以构建功能丰富的知识管理应用,充分利用Outline的协作能力和灵活的文档管理功能。无论是构建自定义界面、实现自动化工作流,还是集成到现有系统中,Outline API都提供了坚实的基础。
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
jiuwenclawJiuwenClaw 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。Python0208- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
AtomGit城市坐标计划AtomGit 城市坐标计划开启!让开源有坐标,让城市有星火。致力于与城市合伙人共同构建并长期运营一个健康、活跃的本地开发者生态。01
MarkFlowy一款 AI Markdown 编辑器TSX01