首页
/ Paperless-ngx REST API 实战指南:认证、搜索、文档上传、批量编辑与版本化

Paperless-ngx REST API 实战指南:认证、搜索、文档上传、批量编辑与版本化

2026-09-05 16:44:41作者:裘旻烁

Paperless-ngx 提供一套完整的 REST API 和可在 /api/schema/view/ 中浏览的交互式接口文档。本文基于仓库文档 docs/api.md 展开,覆盖五种认证方式、Tantivy 全文搜索、自定义字段过滤、文件上传消费流程、文档版本、对象级权限、批量编辑操作以及 API 版本协商机制,并结合 src/paperless/settings/init.pysrc/paperless/middleware.pysrc/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 中集中配置:PaperlessBasicAuthenticationTokenAuthenticationSessionAuthentication 依次生效;此外,登录 Token 端点默认受 DEFAULT_THROTTLE_RATESlogin: 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-allauthapi/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 查询参数可以按自定义字段值过滤文档。文档给出的常见用法配方:

  1. "due"(日期)字段在 2024-08-01 至 2024-09-01 之间(含端点):

    ?custom_field_query=["due", "range", ["2024-08-01", "2024-09-01"]]

  2. "customer"(文本)字段等于 "bob"(区分大小写):

    ?custom_field_query=["customer", "exact", "bob"]

  3. "answered"(布尔)字段为 true

    ?custom_field_query=["answered", "exact", true]

  4. "favorite animal"(select)字段为 "cat" 或 "dog":

    ?custom_field_query=["favorite animal", "in", ["cat", "dog"]]

  5. "address"(文本)字段为空:

    ?custom_field_query=["OR", [["address", "isnull", true], ["address", "exact", ""]]]

  6. 没有名为 "foo" 的字段:

    ?custom_field_query=["foo", "exists", false]

  7. "references"(文档链接)字段同时指向文档 3 和 7:

    ?custom_field_query=["references", "contains", [3, 7]]

各字段类型支持的操作符范围:

  • 所有字段类型:exactinisnullexists
  • 字符串 / URL / 货币字段:额外支持 icontainsistartswithiendswith 等不区分子串匹配;
  • 整数 / 浮点 / 日期字段:支持 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.pyPostDocumentView:请求先校验 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_correspondentparameters: { "correspondent": CORRESPONDENT_ID }
  • set_document_typeparameters: { "document_type": DOCUMENT_TYPE_ID }
  • set_storage_pathparameters: { "storage_path": STORAGE_PATH_ID }
  • add_tagparameters: { "tag": TAG_ID }
  • remove_tagparameters: { "tag": TAG_ID }
  • modify_tagsparameters: { "add_tags": [...] } 和 / 或 { "remove_tags": [...] }
  • delete — 无需 parameters
  • reprocess — 可选 parameters: { "remote_ocr": true } 可将文档发送到远程 OCR 引擎(见 docs/usage.md),默认 false
  • set_permissionsparameters 可含:
    • "set_permissions": PERMISSIONS_OBJ(格式见上文权限一节)和 / 或
    • "owner": OWNER_ID or null
    • "merge": true / false(默认 false);merge 决定传入权限是整体覆盖(含删除)还是与现有权限合并
  • modify_custom_fieldsparameters 可含:
    • "add_custom_fields": { CUSTOM_FIELD_ID: VALUE }:字段 ID:值 的 JSON 对象,也可为仅含字段 ID 的列表(赋空值)
    • "remove_custom_fields": [CUSTOM_FIELD_ID]:要移除的字段 ID

文档编辑操作的端点迁移(v10+)

自 API v10 起,mergerotateedit_pdf 等文档编辑操作拥有各自独立的端点,其文档见 API spec / viewer。经 /api/documents/bulk_edit/ 调用这些旧方法仍受支持但已弃用,客户端应在其被移除前迁移到独立端点。

对象批量编辑:/api/bulk_edit_objects/

对 tags、文档类型等对象的支持操作为 set_permissionsdelete,JSON 载荷格式:

{
  "objects": [1, 2, 3],
  "object_type": "tags",
  "operation": "set_permissions",
  "owner": 3,
  "permissions": { "view": { "users": [] }, "change": { "users": [] } },
  "merge": false
}

其中 object_type 取值为 tagscorrespondentsdocument_typesstorage_pathsownermerge 为可选,merge 默认 false。v10 起该端点还支持 allfilters 参数,用于影响大量对象时避免发送冗长的 ID 列表。

七、API 版本协商

REST API 是版本化的,设计目标包括:

  • 版本化保证 API 变更不破坏旧客户端;
  • 客户端在每个请求中声明所用 API 版本,Paperless 按指定版本处理请求;
  • 即使底层数据模型变化,受支持的旧版本 API 仍提供兼容数据;
  • 未指定版本时,Paperless 使用配置的默认版本(当前为 10);
  • 当前受支持的版本为 910

版本通过额外的 HTTP Accept 头声明:

Accept: application/json; version=10

指定非法版本时,Paperless 返回 406 Not Acceptable 并在响应体中给出错误信息。

源码中这与配置直接对应:src/paperless/settings/init.pyDEFAULT_VERSIONING_CLASSrest_framework.versioning.AcceptHeaderVersioningDEFAULT_VERSION"10"(注释明确要求与前端 src-ui/src/environments/environment.prod.ts 保持一致),ALLOWED_VERSIONS["9", "10"] 并附有"版本必须有序、最新版在最后"的维护注释。

客户端兼容性探测流程

客户端要验证自己与某个服务器是否兼容,文档建议如下步骤:

  1. 对任意 API 端点发起一次已认证请求,服务器会在响应中加入两个自定义头:

    X-Api-Version: 10
    X-Version: <server-version>
    
  2. 根据这两个头的存在与否及其值判断客户端兼容性。

从源码结构看,这一行为由 src/paperless/middleware.py 中的 ApiVersionMiddleware 实现:仅当 request.user.is_authenticated 时,X-Api-VersionALLOWED_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 型自定义字段格式变化——选项返回为带 idlabel 的对象数组而非纯字符串列表;创建/更新文档的 select 值时须用选项的 id 而非此前的索引。
  • v8:文档笔记(notes)的 user 字段返回简化用户对象而非仅用户 ID。
  • v9:文档 created 字段变为日期(date)而非 datetime;created_date 被弃用,将在未来移除。
  • v10
    • Saved view 的 show_on_dashboardshow_in_sidebar 字段移除,相关设置迁入 UISettings 模型(v10 之前版本保持兼容直到 v9 支持结束);
    • mergerotateedit_pdf 等文档编辑操作从 bulk edit 迁至独立端点(bulk edit 方式继续兼容);
    • 列表端点的 all 参数弃用,将在未来移除;
    • bulk_edit_objects 支持 allfilters 参数;
    • 旧搜索参数 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 支持结束。

八、集成建议与适用前提

  • 本文所有行为均以当前仓库(默认 API 版本 10,受支持版本 9/10)为准;若你的客户端针对旧版本开发,请对照上文变更日志逐项核对字段与端点差异;
  • 程序化集成首选 Token 认证(可经 /api/token/ 获取),并注意该端点的默认限流 5/min,批量脚本应在调用前缓存 Token 而非反复登录;
  • 上传类操作(post_documentbulk_edit 等)均为异步语义:HTTP 200 只代表任务已派发,终态须通过 /api/tasks/ 轮询确认,不要把 200 响应当作消费成功的信号;
  • 需要完整端点列表、请求/响应结构时,直接使用 /api/schema/view/ 交互式文档(由 drf-spectacular 生成,见 src/paperless/settings/init.py 中的 DEFAULT_SCHEMA_CLASS 配置),本文只覆盖文档重点介绍的端点。
登录后查看全文
热门项目推荐
相关项目推荐