首页
/ Outline API开发指南:构建协作式知识管理系统

Outline API开发指南:构建协作式知识管理系统

2026-03-12 04:44:09作者:伍霜盼Ellen

核心能力解析

基础交互层

文档生命周期管理

文档是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的灵活性。主要设计理念包括:

  1. 资源导向:所有操作围绕资源(主要是文档)展开
  2. 统一接口:使用一致的请求和响应格式
  3. 无状态:每个请求包含所有必要信息,服务器不存储客户端状态
  4. 操作明确:API端点名称清晰反映其功能,如documents.createdocuments.update

不同于传统REST使用HTTP方法(GET、POST、PUT、DELETE)来表示操作类型,Outline API统一使用POST方法,通过端点名称区分操作类型。这种设计简化了API使用,特别适合复杂操作场景。

接口版本演进

Outline API经历了多个版本的演进,主要变化如下:

版本 主要变化 兼容性
v1 初始版本,基础文档操作 已过时,不推荐使用
v2 增加权限管理、高级搜索功能 完全兼容v1,推荐使用
v3 引入异步操作支持、批量处理优化 部分兼容v2,新增功能需显式指定版本

要使用特定版本的API,可以在请求中指定apiVersion参数:

{
  "id": "uuid",
  "apiVersion": 2
}

性能优化建议

  1. 批量操作代替循环单个操作

    对于需要处理多个文档的场景,使用批量接口代替循环调用单个接口:

    # 不推荐
    for doc_id in doc_ids:
        delete_document(token, doc_id)
    
    # 推荐(如果有批量删除接口)
    batch_delete_documents(token, doc_ids)
    
  2. 分页获取大量数据

    当获取大量文档时,使用分页参数控制返回数据量:

    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
    
  3. 合理设置缓存策略

    对于不常变化的数据(如文档列表、用户信息),实施缓存策略减少API调用:

    from functools import lru_cache
    
    @lru_cache(maxsize=128)
    def get_collection_docs(token, collection_id):
        return list_documents(token, collection_id)
    
  4. 异步处理长时间运行的操作

    对于导入、导出等耗时操作,使用异步处理模式:

    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]}..."

Outline项目Logo

通过以上API和最佳实践,你可以构建功能丰富的知识管理应用,充分利用Outline的协作能力和灵活的文档管理功能。无论是构建自定义界面、实现自动化工作流,还是集成到现有系统中,Outline API都提供了坚实的基础。

登录后查看全文
热门项目推荐
相关项目推荐