Paperless-ngx REST API 实战指南:认证、搜索、文档上传、批量编辑与版本化
Paperless-ngx 提供一套完整的 REST API 和可在 /api/schema/view/ 中浏览的交互式接口文档。本文基于仓库文档 docs/api.md 展开,覆盖五种认证方式、Tantivy 全文搜索、自定义字段过滤、文件上传消费流程、文档版本、对象级权限、批量编辑操作以及 API 版本协商机制,并结合 src/paperless/settings/init.py、src/paperless/middleware.py 与 src/documents/views.py 等源码,帮助你在集成自动化系统、二次开发客户端时准确掌握每个端点的行为与边界。
一、API 浏览入口与认证体系
API 的可浏览文档界面位于 /api/schema/view/,适合人工探索端点结构。程序化集成前,首先要解决认证问题——Paperless-ngx 提供五种认证形式:
1. Basic 认证
通过 HTTP 头提供 Base64 编码的 <username>:<password>:
Authorization: Basic <credentials>
2. Session 认证
在浏览器中登录 Paperless 后,会话 Cookie 自动适用于 API 请求,无需额外请求头。
3. Token 认证
在 Web UI 的用户下拉菜单中打开 "My Profile",点击环形箭头按钮即可生成(或重置)API Token。Token 也可通过端点程序化获取:向 /api/token/ POST 表单或 JSON 格式的 username 和 password,登录正确时服务器返回 Token,之后用如下请求头认证:
Authorization: Token <token>
Token 还可以在 Django admin 中管理。从源码看,认证类在 src/paperless/settings/init.py 中集中配置:PaperlessBasicAuthentication、TokenAuthentication 和 SessionAuthentication 依次生效;此外,登录 Token 端点默认受 DEFAULT_THROTTLE_RATES 中 login: 5/min(可用环境变量 PAPERLESS_TOKEN_THROTTLE_RATE 覆盖)的限流保护。
4. Remote User 认证
若已启用(对应配置项 PAPERLESS_ENABLE_HTTP_REMOTE_USER_API,见 docs/configuration.md),可通过 Reverse Proxy 提供的 Remote User 认证访问 API,适合反向代理后面接企业 SSO 的部署。
5. 无头 OIDC(Headless OIDC)
通过 django-allauth 在 api/auth/ 下暴露的 API 端点,允许第三方应用使用已配置的社会账号(如 OpenID Connect)完成无头认证。社交账号配置细节见 docs/advanced_usage.md。
二、文档搜索:全文检索与 __search_hit__
/api/documents/ 端点支持全文搜索,以下查询参数会触发 Tantivy 后端的搜索结果:
| 查询参数 | 行为 |
|---|---|
?text=your%20search%20query |
对标题和内容做简单子串式搜索 |
?title_search=your%20search%20query |
仅对标题做子串式搜索 |
?query=your%20search%20query |
使用完整全文查询语法,语法细节见 docs/usage.md |
?more_like_id=1234 |
搜索与 ID 为 1234 的文档相似的其他文档 |
分页行为与该端点普通请求完全一致。搜索命中时,每条返回文档会附带一个 __search_hit__ 属性:
{
"count": 31,
"next": "http://localhost:8000/api/documents/?page=2&query=test",
"previous": null,
"results": [
{
"id": 123,
"title": "title",
"content": "content",
"__search_hit__": {
"score": 0.343,
"highlights": "text <span class=\"match\">Test</span> text",
"rank": 23
}
}
]
}
三个关键字段的含义:
score:该文档与查询的相对匹配程度(相对于其他结果);highlights:文档内容节选,命中词以<span>标签高亮;rank:结果索引,从 0 开始。
按自定义字段过滤:custom_field_query
通过 custom_field_query 查询参数可以按自定义字段值过滤文档。文档给出的常见用法配方:
-
"due"(日期)字段在 2024-08-01 至 2024-09-01 之间(含端点):
?custom_field_query=["due", "range", ["2024-08-01", "2024-09-01"]] -
"customer"(文本)字段等于 "bob"(区分大小写):
?custom_field_query=["customer", "exact", "bob"] -
"answered"(布尔)字段为
true:?custom_field_query=["answered", "exact", true] -
"favorite animal"(select)字段为 "cat" 或 "dog":
?custom_field_query=["favorite animal", "in", ["cat", "dog"]] -
"address"(文本)字段为空:
?custom_field_query=["OR", [["address", "isnull", true], ["address", "exact", ""]]] -
没有名为 "foo" 的字段:
?custom_field_query=["foo", "exists", false] -
"references"(文档链接)字段同时指向文档 3 和 7:
?custom_field_query=["references", "contains", [3, 7]]
各字段类型支持的操作符范围:
- 所有字段类型:
exact、in、isnull、exists; - 字符串 / URL / 货币字段:额外支持
icontains、istartswith、iendswith等不区分子串匹配; - 整数 / 浮点 / 日期字段:支持
gt(>)、gte(>=)、lt(<)、lte(<=) 与range; - 文档链接字段:支持
contains,语义为"超集检查"。
自动补全端点
GET /api/search/autocomplete/ 返回搜索词的前缀补全:
term:未输入完整的词;limit:结果数量,默认 10。
结果按"每个候选词出现在多少个当前用户可见文档中"降序排列,返回一个纯字符串数组:
["term1", "term3", "term6", "term4"]
三、上传文档:POST /api/documents/post_document/
API 提供专门的文件上传端点 /api/documents/post_document/。向该端点 POST 一个 multipart 表单,表单字段 document 承载要上传的文件。文件名会被 sanitize 后用于存入临时目录,然后消费流程(consumer)从该目录拉取文档。
支持以下可选表单字段:
| 字段 | 说明 |
|---|---|
title |
指定消费者应使用的文档标题 |
created |
文档创建时间(如 "2016-04-19" 或 "2016-04-19 06:15:00+02:00") |
correspondent |
指定收件人(correspondent)ID |
document_type |
文档类型 ID,用法同上 |
storage_path |
存储路径 ID,用法同上 |
tags |
标签 ID,可多次指定以添加多个标签 |
archive_serial_number |
可选的归档序列号 |
custom_fields |
自定义字段 ID 数组(赋空值),或 {字段ID: 值} 的映射对象 |
异步消费与结果查询:端点在消费流程成功启动后立即返回 HTTP 200,响应体是消费任务的 UUID。由于实际消费发生在独立进程中,上传请求本身拿不到任何消费状态信息;需要用返回的 UUID 查询任务端点,例如 /api/tasks/?task_id={uuid},即可获取消费状态,消费成功时还会给出新建文档的 ID。
源码层面的印证在 src/documents/views.py 的 PostDocumentView:请求先校验 documents.add_document 权限(否则返回 403),随后将文件以 NFC 归一化后的文件名经 pathvalidate.sanitize_filename 清洗后写入 SCRATCH_DIR 下的临时目录,构造 ConsumableDocument(来源标记为 DocumentSource.ApiUpload)与 DocumentMetadataOverrides(其中 owner_id 自动设为当前请求用户),最后通过 consume_file.apply_async 以异步任务方式派发,并打上 trigger_source: API_UPLOAD 头,返回 async_task.id。上传路径的文件名 NFC 归一化行为另有专项测试 src/documents/tests/test_api_post_document_nfc.py 覆盖。
四、文档版本(Document Versions)
文档版本是链接到同一个根文档(root document)的文件级版本,文档中给出了清晰的职责划分:
- 根文档共享元数据:标题、标签、correspondent、文档类型、存储路径、自定义字段、权限;
- 版本特有的文件数据:文件本身、MIME 类型、校验和、归档信息、提取的文本内容。
版本感知端点一览:
| 端点 | 行为 |
|---|---|
GET /api/documents/{id}/ |
返回根文档数据;content 默认解析为最新版本内容,可用 ?version={version_id} 指定版本 |
PATCH /api/documents/{id}/ |
内容更新作用于所选版本(?version={version_id},默认最新);非内容元数据更新作用于根文档 |
GET .../download/、/preview/、/thumb/、/metadata/ |
均接受 ?version={version_id} |
POST /api/documents/{id}/update_version/ |
通过 multipart 字段 document 上传新版本,可选 version_label |
POST /api/documents/merge_as_versions/ |
将已有顶层文档合并为选定根文档的版本。JSON 体必须包含 documents(至少两个文档 ID)和 root_document_id(其中之一);合并单个源文档时可选提供 version_label |
PATCH /api/documents/{id}/versions/{version_id}/ |
更新指定版本的 version_label |
DELETE /api/documents/{root_id}/versions/{version_id}/ |
删除非根版本 |
五、对象级权限
所有对象(文档、标签等)都支持设置对象级权限,参数为可选的 owner 和 / 或 set_permissions:
{
"owner": 3,
"set_permissions": {
"view": {
"users": [1, 2],
"groups": [5]
},
"change": {
"users": [],
"groups": []
}
}
}
注意:数组中应填写用户或组的 ID 数字。提供这些参数会覆盖对象现有权限,前提是认证用户有权限这么做(必须是对象 owner 或超级用户)。
获取完整权限信息
默认情况下 API 返回对象级权限的截断形式——一个 user_can_change 布尔值,表示当前用户能否编辑该对象(因其是 owner 或被授予权限)。传入 full_perms=true 参数即可查看与上述 set_permissions 结构一致的完整权限数据。
六、批量编辑(异步执行)
API 支持多种异步执行的批量编辑操作。
文档批量编辑:/api/documents/bulk_edit/
接受如下 JSON 载荷:
{
"documents": [1, 2, 3],
"method": "set_correspondent",
"parameters": { "correspondent": 7 }
}
支持的方法及参数要求:
set_correspondent—parameters:{ "correspondent": CORRESPONDENT_ID }set_document_type—parameters:{ "document_type": DOCUMENT_TYPE_ID }set_storage_path—parameters:{ "storage_path": STORAGE_PATH_ID }add_tag—parameters:{ "tag": TAG_ID }remove_tag—parameters:{ "tag": TAG_ID }modify_tags—parameters:{ "add_tags": [...] }和 / 或{ "remove_tags": [...] }delete— 无需parametersreprocess— 可选parameters:{ "remote_ocr": true }可将文档发送到远程 OCR 引擎(见 docs/usage.md),默认 falseset_permissions—parameters可含:"set_permissions": PERMISSIONS_OBJ(格式见上文权限一节)和 / 或"owner": OWNER_ID or null"merge": true / false(默认 false);merge决定传入权限是整体覆盖(含删除)还是与现有权限合并
modify_custom_fields—parameters可含:"add_custom_fields": { CUSTOM_FIELD_ID: VALUE }:字段 ID:值 的 JSON 对象,也可为仅含字段 ID 的列表(赋空值)"remove_custom_fields": [CUSTOM_FIELD_ID]:要移除的字段 ID
文档编辑操作的端点迁移(v10+)
自 API v10 起,merge、rotate、edit_pdf 等文档编辑操作拥有各自独立的端点,其文档见 API spec / viewer。经 /api/documents/bulk_edit/ 调用这些旧方法仍受支持但已弃用,客户端应在其被移除前迁移到独立端点。
对象批量编辑:/api/bulk_edit_objects/
对 tags、文档类型等对象的支持操作为 set_permissions 和 delete,JSON 载荷格式:
{
"objects": [1, 2, 3],
"object_type": "tags",
"operation": "set_permissions",
"owner": 3,
"permissions": { "view": { "users": [] }, "change": { "users": [] } },
"merge": false
}
其中 object_type 取值为 tags、correspondents、document_types 或 storage_paths;owner 与 merge 为可选,merge 默认 false。v10 起该端点还支持 all 与 filters 参数,用于影响大量对象时避免发送冗长的 ID 列表。
七、API 版本协商
REST API 是版本化的,设计目标包括:
- 版本化保证 API 变更不破坏旧客户端;
- 客户端在每个请求中声明所用 API 版本,Paperless 按指定版本处理请求;
- 即使底层数据模型变化,受支持的旧版本 API 仍提供兼容数据;
- 未指定版本时,Paperless 使用配置的默认版本(当前为
10); - 当前受支持的版本为
9和10。
版本通过额外的 HTTP Accept 头声明:
Accept: application/json; version=10
指定非法版本时,Paperless 返回 406 Not Acceptable 并在响应体中给出错误信息。
源码中这与配置直接对应:src/paperless/settings/init.py 中 DEFAULT_VERSIONING_CLASS 为 rest_framework.versioning.AcceptHeaderVersioning,DEFAULT_VERSION 为 "10"(注释明确要求与前端 src-ui/src/environments/environment.prod.ts 保持一致),ALLOWED_VERSIONS 为 ["9", "10"] 并附有"版本必须有序、最新版在最后"的维护注释。
客户端兼容性探测流程
客户端要验证自己与某个服务器是否兼容,文档建议如下步骤:
-
对任意 API 端点发起一次已认证请求,服务器会在响应中加入两个自定义头:
X-Api-Version: 10 X-Version: <server-version> -
根据这两个头的存在与否及其值判断客户端兼容性。
从源码结构看,这一行为由 src/paperless/middleware.py 中的 ApiVersionMiddleware 实现:仅当 request.user.is_authenticated 时,X-Api-Version 取 ALLOWED_VERSIONS 的最后一项(即最新版本),X-Version 为服务器完整版本号字符串;未认证请求不会携带这两个头——因此"必须认证请求"这一要求并非多余。测试用例 src/documents/tests/test_api_permissions.py 分别断言了未认证响应不含、认证响应包含 X-Api-Version。
弃用政策
旧 API 版本至少在新版本发布后一年保证受支持;此后可能(但不保证)移除。
API 变更日志摘要
- v1:初始版本。
- v2:新增
Tag.color(十六进制颜色,如#a6cee3)与只读Tag.text_color(按Tag.color亮度取黑或白);移除Tag.colour。 - v3:新增权限端点;
/api/ui_settings/格式变化。 - v4:Consumption templates 重构为 workflows,相关端点随之调整。
- v5:新增文档与对象的批量删除方法。
- v6:任务确认端点迁移至
/api/tasks/acknowledge/。 - v7:select 型自定义字段格式变化——选项返回为带
id与label的对象数组而非纯字符串列表;创建/更新文档的 select 值时须用选项的id而非此前的索引。 - v8:文档笔记(notes)的 user 字段返回简化用户对象而非仅用户 ID。
- v9:文档
created字段变为日期(date)而非 datetime;created_date被弃用,将在未来移除。 - v10:
- Saved view 的
show_on_dashboard、show_in_sidebar字段移除,相关设置迁入 UISettings 模型(v10 之前版本保持兼容直到 v9 支持结束); merge、rotate、edit_pdf等文档编辑操作从 bulk edit 迁至独立端点(bulk edit 方式继续兼容);- 列表端点的
all参数弃用,将在未来移除; bulk_edit_objects支持all与filters参数;- 旧搜索参数
title_content弃用,应改用text(标题+内容)或title_search(仅标题); - 任务跟踪系统重设计:
/api/tasks/列表改为分页,任务对象改用task_type(原task_name)与trigger_source(原type);新增只读端点/api/tasks/summary/、/api/tasks/status_counts/、/api/tasks/active/提供聚合视图,POST /api/tasks/run/允许特权用户派发受支持的任务。API v9 继续以旧字段名提供不分页列表,直到 v9 支持结束。
- Saved view 的
八、集成建议与适用前提
- 本文所有行为均以当前仓库(默认 API 版本 10,受支持版本 9/10)为准;若你的客户端针对旧版本开发,请对照上文变更日志逐项核对字段与端点差异;
- 程序化集成首选 Token 认证(可经
/api/token/获取),并注意该端点的默认限流5/min,批量脚本应在调用前缓存 Token 而非反复登录; - 上传类操作(
post_document、bulk_edit等)均为异步语义:HTTP 200 只代表任务已派发,终态须通过/api/tasks/轮询确认,不要把 200 响应当作消费成功的信号; - 需要完整端点列表、请求/响应结构时,直接使用
/api/schema/view/交互式文档(由 drf-spectacular 生成,见 src/paperless/settings/init.py 中的DEFAULT_SCHEMA_CLASS配置),本文只覆盖文档重点介绍的端点。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00