Docuseal 3.3.4 API 使用详解
Docuseal 3.3.4 REST API 实测使用详解:X-Auth-Token 认证与首次调用、模板/提交/签署人/事件/工具五大域端点逐一 curl 实测回显,分页与过滤约定、错误码排查、PDF 合并与验签实战。
Docuseal 3.3.4 API 使用详解
目标:把 Docuseal 3.3.4 自托管版对外提供的 REST API 完整过一遍——认证方式、五大端点域、分页与过滤约定、错误码行为,全部在真实实例上用 curl 逐条发起请求并记录原始回显,最终以 API 驱动完成「发起签署 → 回填字段 → 生成已签署 PDF → 数字验签」的端到端链路。已在 Ubuntu 22.04(实例部署方式见《Docuseal 3.3.4 Docker Compose 部署指南》)实测通过。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- Docuseal:3.3.4(自托管开源版,Ruby 4.0.9 + Puma 8.0.2)
- 实例入口:
http://127.0.0.1:8132(实例「设置 → App URL」配置为http://localhost:8132,回显中的文件链接域名以该设置为准) - 管理员账号:
admin@docuseal.local(密码q1w2e3r4,初始化过程见《Docuseal 3.3.4 Docker Compose 部署指南》) - 客户端工具:curl 8.18.0(
curl --version实查) - 数据库:PostgreSQL 16
- 实测日期:2026-10-30
- 路由证据:实例内
bin/rails routes输出(260 行,其中/api、/api/tools相关 27 条,完整清单见三、API 总览)
二、前置条件
2.1 获取 API Token
Docuseal 的 API 调用使用 API Token 鉴权,获取路径在 Web 界面内:
- 以
admin@docuseal.local/q1w2e3r4登录实例; - 进入右上角 Settings → API 页面;
- 点击 Create API Key,系统要求再次输入登录密码做二次确认(防止他人在已登录的浏览器上偷偷取走密钥);
- 确认后界面显示一串 40 位随机字符串,即 API Token,仅此一次完整展示,应立即复制保存。
按敏感信息占位约定,本文后续统一以环境变量注入 Token,不在正文落明文:
# 将界面上取到的 40 位 API Token 导出为环境变量,后续所有 curl 命令引用它
export DOCUSEAL_API_TOKEN='替换为你的40位API_Token'
2.2 客户端与连通性检查
# 确认实例可达:未带认证头访问列表接口应返回 401 JSON,而不是连接错误
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8132/api/templates
# 实测输出:401
返回 401 说明服务与 API 路由均正常,只差认证头,可以进入下一节。
三、API 总览
3.1 协议与版本约定
- 协议形态:HTTP + JSON 的 REST 风格接口,请求与响应主体均为 JSON(文件类参数用 base64 编码塞进 JSON);
- 路径前缀:自托管开源版所有 API 以
/api开头,没有/api/v1这样的版本子前缀(bin/rails routes实查:27 条 API 路由全部直接挂在/api下);DocuSeal 云端版(api.docuseal.com)的官方文档示例则使用独立 API 域名,两者端点集合并不相同; - 端点差异:开源版不提供「创建模板」「HTML 转签署表单」等云端专属端点——
POST /api/templates实测直接返回 404(见 5.2.6);模板只能走界面创建,或通过 clone 端点复制既有模板; - 鉴权方式:仅支持请求头
X-Auth-Token: <API Token>,不支持Authorization: Bearer(实测见 4.2); - 限流约定:应用依赖清单中未见任何限流组件(Gemfile 中无 rack-attack/throttle 相关条目,实查于 2026-10-30),自托管版未内置速率限制,公网暴露时需在反向代理层自行加防护;
- 幂等与软删除:
DELETE类端点默认是归档(写archived_at字段),提交类端点追加permanently=true参数才是永久删除。
3.2 端点域与路由总表
实测路由总表(按域归并,来自 bin/rails routes):
| 端点域 | 方法与路径 | 用途 |
|---|---|---|
| 账户 | GET /api/user | 查看当前 Token 对应的账号身份 |
| 模板 | GET /api/templates | 模板列表(分页+过滤) |
| 模板 | GET / PATCH / PUT / DELETE /api/templates/{id} | 模板详情 / 更新(含字段、角色、归档)/ 归档删除 |
| 模板 | POST /api/templates/{template_id}/clone | 克隆模板 |
| 模板 | GET / POST /api/templates/{template_id}/submissions | 某模板下的提交列表 / 发起签署 |
| 提交 | POST /api/submissions/init | 创建不发送邮件通知的提交(预创建) |
| 提交 | POST /api/submissions/emails | 创建提交并携带邮件正文发送 |
| 提交 | GET / POST /api/submissions | 提交列表(分页+过滤)/ 创建提交 |
| 提交 | GET / PATCH / PUT / DELETE /api/submissions/{id} | 提交详情 / 改名与过期时间 / 归档或永久删除 |
| 提交 | GET /api/submissions/{submission_id}/documents | 获取已签署文档与审计日志的下载地址 |
| 签署人 | GET /api/submitters | 签署人列表(分页+过滤) |
| 签署人 | GET / PATCH / PUT /api/submitters/{id} | 签署人详情 / 回填字段值并标记完成 |
| 表单视图 | POST /api/submitter_form_views | 上报「签署人已打开表单」(打点) |
| 事件 | GET /api/events/form/{type} | 按类型拉取表单侧事件(viewed/completed 等) |
| 事件 | GET /api/events/submission/{type} | 按类型拉取提交侧事件(created/completed 等) |
| 工具 | POST /api/tools/merge | 合并多个 PDF 为一个 |
| 工具 | POST /api/tools/verify | 校验 PDF 内数字签名的有效性 |
3.3 通用响应结构
- 单对象端点直接返回对象 JSON;列表端点固定返回
{"data": [...], "pagination": {...}}双键结构(见六、分页与过滤); - 资源对外同时有
id(整数)与slug(公开短串)两种标识:API 内部引用多用id,而面向被签署人的分享/嵌入链接全部用slug; - 时间字段一律 ISO 8601 UTC 格式(如
2026-10-30T12:03:09.843Z)。
四、认证与首次调用
4.1 首次调用:查看账号身份
# 用 API Token 调用最简单的账户端点,验证 Token 有效
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/user
实测回显:
{"id":1,"first_name":"Admin","last_name":"Docuseal","email":"admin@docuseal.local"}
4.2 认证失败的三种实测形态
认证相关的失败形态固定返回 HTTP 401 与 {"error":"Not authenticated"},以下三种情况实测回显完全一致:
# 情形一:不带认证头
curl -s -w '\nHTTP:%{http_code}\n' http://127.0.0.1:8132/api/templates
# 实测输出:{"error":"Not authenticated"} / HTTP:401
# 情形二:Token 值错误
curl -s -w '\nHTTP:%{http_code}\n' -H 'X-Auth-Token: WRONG_TOKEN_123' http://127.0.0.1:8132/api/templates
# 实测输出:{"error":"Not authenticated"} / HTTP:401
# 情形三:误用 Authorization: Bearer(不支持)
curl -s -w '\nHTTP:%{http_code}\n' -H "Authorization: Bearer $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/templates
# 实测输出:{"error":"Not authenticated"} / HTTP:401
排查口诀:先确认请求头名字是 X-Auth-Token 而不是 Authorization,再确认 Token 值是从「设置 → API」完整复制的 40 位字符串(界面只显示一次,丢了只能新建)。
五、各 API 域详解
5.1 模板域(/api/templates)
5.1.1 模板列表:GET /api/templates
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/templates
实测回显(节选,fields 中每个字段带 areas 坐标数组):
{"data":[{"id":2,"name":"Service Agreement Template","slug":"mgM7Xu5MVrjsEv",
"schema":[{"attachment_uuid":"81987210-eb82-412b-8b21-0c8da17ad07e","name":"test-contract"}],
"submitters":[{"name":"First Party","uuid":"26b45529-f40d-442a-9260-045181533520"}],
"fields":[
{"name":"Full Name","type":"text","required":true,
"areas":[{"x":72,"y":700,"w":200,"h":30,"attachment_uuid":"81987210-eb82-412b-8b21-0c8da17ad07e","page":1}]},
{"name":"Signature","type":"signature","required":true,
"areas":[{"x":72,"y":640,"w":200,"h":44,"attachment_uuid":"81987210-eb82-412b-8b21-0c8da17ad07e","page":1}]},
{"name":"Contract Date","type":"date",
"areas":[{"x":350,"y":700,"w":160,"h":30,"attachment_uuid":"81987210-eb82-412b-8b21-0c8da17ad07e","page":1}]}],
"variables_schema":{},"preferences":{},"source":"native",
"created_at":"2026-10-30T12:00:32.414Z","updated_at":"2026-10-30T12:02:31.257Z",
"archived_at":null,"author_id":1,"folder_name":"Default",
"author":{"id":1,"email":"admin@docuseal.local","first_name":"Admin","last_name":"Docuseal"},
"documents":[{"id":3,"uuid":"81987210-eb82-412b-8b21-0c8da17ad07e","url":"http://localhost:8132/file/…/test-contract.pdf","preview_image_url":"http://localhost:8132/file/…"}]},
…],
"pagination":{"count":1,"next":2,"prev":2}}
要点:fields[].areas[].x/y/w/h 是字段在文档页上的坐标(单位为 PDF 点),page 从 1 起;schema[].attachment_uuid 把字段坐标关联到具体文档附件;documents[].url 是带签名的临时下载地址。
5.1.2 模板详情:GET /api/templates/{id}
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/templates/2
实测回显结构与 5.1.1 的单元素一致(data 数组元素即模板详情对象),不再重复。
5.1.3 更新模板:PATCH /api/templates/{id}
支持整体替换 fields、调整角色 roles、移动目录 folder_name、归档 archived 等参数:
# 幂等改名:名称不变时仅返回 id 与原 updated_at
curl -s -X PATCH -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Service Agreement Template"}' \
http://127.0.0.1:8132/api/templates/2
实测回显:
{"id":2,"updated_at":"2026-10-30T12:02:31.257Z"}
模板字段(fields)与签署人角色(submitters/roles)在部署实例上的图形化编辑方式见《Docuseal 3.3.4 配置参数详解》中对实例设置体系的说明;本端点适合做字段的程序化批量调整。
5.1.4 克隆模板:POST /api/templates/{template_id}/clone
curl -s -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Cloned Service Agreement"}' \
http://127.0.0.1:8132/api/templates/2/clone
实测回显(节选,返回完整新模板对象,含与源模板相同坐标的 fields):
{"id":4,"name":"Cloned Service Agreement","slug":"QGJeVZGeEsTLnh",
"schema":[{"attachment_uuid":"99daa972-c8eb-4b03-ba64-b15a721b61b7","name":"test-contract"}],
"submitters":[{"name":"First Party","uuid":"2f6befc7-42dd-4a97-b0e3-eaea5f49df69"}],
"fields":[{"name":"Full Name","type":"text","required":true,
"areas":[{"x":72,"y":700,"w":200,"h":30,"attachment_uuid":"99daa972-c8eb-4b03-ba64-b15a721b61b7","page":1}],
"uuid":"08633619-edd7-482e-8a90-d60c8544cd85","submitter_uuid":null},
…]}
5.1.5 归档模板:DELETE /api/templates/{id}
# 清理克隆出的实验模板(id=4)
curl -s -X DELETE -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/templates/4
实测回显:
{"id":4,"archived_at":"2026-10-30T12:26:12.271Z"}
注意回显:DELETE 返回的是归档时间而非成功标记——模板删除是软删除,归档后从默认列表消失,可用 GET /api/templates?archived=true 找回。
5.1.6 开源版没有「创建模板」端点(实测)
curl -s -w '\nHTTP:%{http_code}\n' -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"x"}' http://127.0.0.1:8132/api/templates
实测回显:
{"status":404}
HTTP:404
路由表中 /api/templates/:id 只注册了 GET/PATCH/PUT/DELETE 四个动词,没有 POST。需要程序化建模板时,用 5.1.4 的 clone 端点复制一份再改字段。
5.2 提交域(/api/submissions)
「提交(Submission)」是模板的一次具体签署实例:模板是「空白合同」,提交是「发给张三的那份合同」。
5.2.1 发起签署:POST /api/templates/{template_id}/submissions
curl -s -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"submitters":[{"name":"Li Si","email":"lisi@example.com","role":"First Party","send_email":false}]}' \
http://127.0.0.1:8132/api/templates/2/submissions
实测回显(返回的是签署人数组,不是提交对象):
[{"id":4,"slug":"Jx8zrhpyr2rKf5","uuid":"26b45529-f40d-442a-9260-045181533520",
"name":"Li Si","email":"lisi@example.com","phone":null,
"completed_at":null,"declined_at":null,"external_id":null,"submission_id":4,
"metadata":{},"opened_at":null,"sent_at":null,
"created_at":"2026-10-30T12:26:10.738Z","updated_at":"2026-10-30T12:26:10.738Z",
"status":"awaiting","application_key":null,"values":[],
"preferences":{"send_email":false,"send_sms":false},"role":"First Party",
"embed_src":"http://localhost:8132/s/Jx8zrhpyr2rKf5"}]
参数要点:
| 参数 | 位置 | 说明 |
|---|---|---|
submitters | body 必填 | 签署人数组,缺省直接 422(见 5.2.6) |
submitters[].name/email/phone | body | 签署人身份信息,email 用于站内发送与通知 |
submitters[].role | body | 必须匹配模板中定义的角色名(本模板为 First Party) |
submitters[].send_email | body | 是否发邮件通知;省略时默认 true(源码 submissions_controller.rb:params[:send_email] = true unless params.key?(:send_email)),未配置 SMTP 的实例务必显式传 false |
submitters[].values | body | 可在发起时直接预填字段值 |
submitters[].completed | body | 传 true 可直接代替签署人完成(测试/批量场景) |
两个常用链接:embed_src(/s/{slug})是该签署人的填写表单地址,可直接嵌入业务系统的 iframe;提交本身还有 /e/{slug} 概览页地址(见 5.2.5 回显中的 submission_url)。
5.2.2 预创建提交:POST /api/submissions/init
与 5.2.1 的区别:不要求 email、不发送任何通知,适合「先建单、后补联系方式」的流程编排:
curl -s -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"template_id":2,"submitters":[{"name":"Wang Wu","role":"First Party","send_email":false}]}' \
http://127.0.0.1:8132/api/submissions/init
实测回显(节选):
{"id":3,"submitters":[{"id":3,"slug":"Px8Wat3SmQ54MA","uuid":"26b45529-f40d-442a-9260-045181533520",
"name":"Wang Wu","email":null,"phone":null,"completed_at":null,"submission_id":3,
"status":"awaiting","role":"First Party","embed_src":"http://localhost:8132/s/Px8Wat3SmQ54MA"}],
"expire_at":null,"created_at":"2026-10-30T12:24:58.333Z"}
5.2.3 提交列表与详情:GET /api/submissions、GET /api/submissions/{id}
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/submissions
实测回显(节选):
{"data":[{"id":1,"name":null,"slug":"H7JMvpqxhsZuGS","source":"api","submitters_order":"preserved",
"expire_at":null,"created_at":"2026-10-30T12:02:51.930Z","updated_at":"2026-10-30T12:03:11.033Z",
"archived_at":null,
"submitters":[{"id":1,"slug":"GjRRFCfzgaeuva","name":"Zhang San","email":"zhangsan@example.com",
"completed_at":"2026-10-30T12:03:09.843Z","status":"completed","role":"First Party"}],
"template":{"id":2,"name":"Service Agreement Template","folder_name":"Default"},
"created_by_user":{"id":1,"email":"admin@docuseal.local","first_name":"Admin","last_name":"Docuseal"},
…}],
"pagination":{"count":1,"next":1,"prev":1}}
单提交详情 GET /api/submissions/1 返回同一结构外加 submission_events 事件明细数组,此处不再重复。
5.2.4 更新与删除提交:PATCH / DELETE /api/submissions/{id}
# 重命名提交
curl -s -X PATCH -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Li Si Service Agreement"}' \
http://127.0.0.1:8132/api/submissions/4
实测回显(节选,name 已生效):
{"id":4,"name":"Li Si Service Agreement","slug":"1UfXHdM2q3UTJY","source":"api",
"updated_at":"2026-10-30T12:26:12.194Z",
"submitters":[{"id":4,"slug":"Jx8zrhpyr2rKf5","name":"Li Si","status":"completed",…}]}
# 永久删除(不带 permanently 则只是归档)
curl -s -X DELETE -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"permanently":true}' \
http://127.0.0.1:8132/api/submissions/4
实测回显:
{"id":4,"archived_at":null}
可更新字段白名单为 name、expire_at、archived、archived_at(源码 submissions_controller.rb 的 submission_params),其余字段改动会被静默忽略。
5.2.5 下载已签署文档:GET /api/submissions/{submission_id}/documents
签署完成后(完成动作见 5.3.2),通过该端点取回生成好的 PDF 与审计日志:
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/submissions/1/documents
实测回显:
{"id":1,"documents":[{"name":"test-contract","url":"http://localhost:8132/file/WyIyNzQ4ZWI5OS00MmM0LTQxNGItOTcwOC01ZWIzN2JlNTcxOTUiLCJibG9iIiwxNzkzMzY1MzkzXQ--bf2c7a1e6c77d8fc39c17b13385709247ad40067dd879516f862208e40119caa/test-contract.pdf"}]}
下载地址是带签名的临时 URL(含过期时间戳),直接 curl -o 即可取回文件;对提交 1 下载得到的已签署文档实测 9832 字节,含签署值与 DocuSeal 数字签名(验签见 5.4.2)。审计日志(Audit Log PDF,53533 字节)会随事件域回显中的 audit_log_url 一并给出。
5.2.6 参数缺失与资源不存在的错误形态(实测)
# 缺 submitters:HTTP 422 + 明确错误字段名
curl -s -w '\nHTTP:%{http_code}\n' -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" \
-H 'Content-Type: application/json' -d '{}' \
http://127.0.0.1:8132/api/templates/2/submissions
# 实测输出:{"error":"submitters is required"} / HTTP:422
# 资源不存在:HTTP 404
curl -s -w '\nHTTP:%{http_code}\n' -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" \
http://127.0.0.1:8132/api/templates/9999
# 实测输出:{"status":404} / HTTP:404
5.3 签署人域(/api/submitters)
5.3.1 列表与详情:GET /api/submitters、GET /api/submitters/{id}
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/submitters/1
实测回显:
{"id":1,"slug":"GjRRFCfzgaeuva","uuid":"26b45529-f40d-442a-9260-045181533520",
"name":"Zhang San","email":"zhangsan@example.com","phone":null,
"completed_at":"2026-10-30T12:03:09.843Z","declined_at":null,
"external_id":null,"submission_id":1,"metadata":{},"opened_at":null,"sent_at":null,
"created_at":"2026-10-30T12:02:51.955Z","updated_at":"2026-10-30T12:03:09.847Z",
"status":"completed","application_key":null,
"template":{"id":2,"name":"Service Agreement Template",
"created_at":"2026-10-30T12:00:32.414Z","updated_at":"2026-10-30T12:02:31.257Z"},
"values":[],
"documents":[{"name":"test-contract","url":"http://localhost:8132/file/…/test-contract.pdf"}],
"preferences":{"send_email":false,"send_sms":false},
"submission_events":[{"id":1,"submitter_id":1,"event_type":"api_complete_form",
"event_timestamp":"2026-10-30T12:03:09.908Z","data":{}}],
"role":"First Party"}
签署人列表 GET /api/submitters 返回 data + pagination 结构,元素与上述对象一致,并支持 submission_id、template_id、external_id、slug、完成时间区间等过滤(见六、表 6-2)。
5.3.2 代填字段并完成签署:PATCH /api/submitters/{id}
这是以 API 驱动整条签署链的核心端点:回填字段值后标记 completed,实例即生成已签署 PDF 与审计日志:
curl -s -X PATCH -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Li Si","values":{"Full Name":"Li Si","Contract Date":"2026-10-30"},"completed":true}' \
http://127.0.0.1:8132/api/submitters/4
实测回显(节选):
{"id":4,"slug":"Jx8zrhpyr2rKf5","name":"Li Si","email":"lisi@example.com",
"completed_at":"2026-10-30T12:26:10.975Z","status":"completed",
"opened_at":"2026-10-30T12:26:10.835Z",
"role":"First Party","embed_src":"http://localhost:8132/s/Jx8zrhpyr2rKf5",…}
参数要点:
values是「字段名 → 值」的字典,字段名必须与模板fields[].name完全一致(含大小写与空格),否则该值被静默丢弃;completed: true触发文档合成;完成后再次 PATCH 同一签署人会被拒绝(源码校验:已完成的签署人返回 422Submitter has already completed the submission.);- 其他可用参数:
declined(拒签)、metadata(自由 JSON,用于业务侧回传关联 ID)、fields数组(可细粒度指定每个字段)。
5.4 工具域(/api/tools)
5.4.1 合并 PDF:POST /api/tools/merge
请求体为 JSON:files 数组放多个 base64 编码的 PDF(本例为提交 1 生成的已签署合同 9832B 与其审计日志 53533B):
# 用 python 生成请求体并调用(base64 来自上一步下载的两份 PDF)
python3 - <<'EOF'
import base64, json
def b64(p):
return base64.b64encode(open(p,'rb').read()).decode()
body = {"files": [b64('signed-contract.pdf'), b64('audit-log.pdf')]}
open('merge_req.json','w').write(json.dumps(body))
EOF
curl -s -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
--data-binary @merge_req.json http://127.0.0.1:8132/api/tools/merge > merge_resp.json
# 从响应中解码出合并结果
python3 -c "import json,base64;d=json.load(open('merge_resp.json'));open('merged.pdf','wb').write(base64.b64decode(d['data']))"
ls -l merged.pdf
实测结果:响应为 {"data":"JVBERi0xLjcNCi…"}(base64,内含换行符,解码库会自动忽略),解码落盘得到 merged.pdf 共 54543 字节,可正常打开,页数为两份输入之和。
5.4.2 验证数字签名:POST /api/tools/verify
请求体为 JSON:file 放一个 base64 编码的 PDF(本例为已签署合同):
python3 -c "import base64,json;open('verify_req.json','w').write(json.dumps({'file':base64.b64encode(open('signed-contract.pdf','rb').read()).decode()}))"
curl -s -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
--data-binary @verify_req.json http://127.0.0.1:8132/api/tools/verify
实测回显(完整):
{"checksum_status":"verified",
"signatures":[{"verification_result":[
{"type":"success","content":"Signature valid"},
{"type":"success","content":"Signed with trusted certificate"},
{"type":"info","content":"Certificate chain: DocuSeal -> DocuSeal Sub-CA -> DocuSeal Root CA"}],
"signer_name":"DocuSeal","signing_reason":"Signed with DocuSeal.com",
"signing_time":"2026-10-30T12:03:10.000Z","signature_type":"adbe.pkcs7.detached"}]}
要点:checksum_status: verified 表示文档内容自签署后未被篡改;实例使用自建证书链(DocuSeal 根证书 → 子 CA → 文档签名),签名格式为 Adobe 通用 的 adbe.pkcs7.detached,Adobe Reader 等主流阅读器可显示签名面板。
5.5 表单视图与事件域
5.5.1 上报表单打开事件:POST /api/submitter_form_views
curl -s -X POST -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"submitter_slug":"Jx8zrhpyr2rKf5"}' \
http://127.0.0.1:8132/api/submitter_form_views
实测回显:
{}
响应体恒为空对象;副作用才是重点:源码(submitter_form_views_controller.rb)显示该调用会把签署人的 opened_at 置为当前时间、追加 form.viewed 跟踪事件——适合把自有系统的「用户已打开填写页」动作同步进 Docuseal 的审计事件流。
5.5.2 拉取事件:GET /api/events/submission/{type}、GET /api/events/form/{type}
curl -s -H "X-Auth-Token: $DOCUSEAL_API_TOKEN" http://127.0.0.1:8132/api/events/submission/completed
实测回显(节选,data 数组每项是一个事件快照):
{"data":[{"event_type":"submission.completed","timestamp":"2026-10-30T12:03:09.843Z",
"data":{"id":1,"slug":"H7JMvpqxhsZuGS","source":"api","submitters_order":"preserved",
"submitters":[{"id":1,"slug":"GjRRFCfzgaeuva","name":"Zhang San","status":"completed",
"documents":[{"name":"test-contract","url":"http://localhost:8132/file/…/test-contract.pdf"}],
"role":"First Party"}],
"template":{"id":2,"name":"Service Agreement Template","folder_name":"Default"},
"created_by_user":{"id":1,"email":"admin@docuseal.local",…},…}},…]}
表单侧事件 GET /api/events/form/completed 返回 event_type: form.completed,载荷额外带 audit_log_url、submission_url(/e/{slug} 概览页)与签署值明细。事件类型与 URL 中的 {type} 对应(completed、viewed、created 等),自托管版以拉取方式消费事件;云端版的 Webhook 推送在开源版中不存在。
六、分页、过滤与通用约定
6.1 分页结构(实测)
所有列表端点固定返回双键结构,pagination 采用游标式(以资源 id 为游标),而非页码式:
"pagination": {"count": 1, "next": 2, "prev": 2}
count:本页条数;next/prev:下一页/上一页的起始资源 id(本页只有一条时两者相同);- 翻页参数为
per_page与page(page语义配合next游标使用),如GET /api/submissions?per_page=1&page=1实测返回单条记录与对应pagination。
6.2 过滤参数(源码实查,2026-10-30)
| 端点 | 支持的查询参数 |
|---|---|
GET /api/templates | q(关键词)、archived、application_key、external_id、slug、shared |
GET /api/submissions | q、slug、template_folder(按模板目录全名)、archived,及通用过滤(模板 id、创建时间区间等) |
GET /api/submitters | application_key、external_id、slug、submission_id、template_id、完成时间区间 |
6.3 其他通用约定
- 链接域名:回显中的文件/表单链接域名取自实例「设置 → App URL」(本实例配置为
http://localhost:8132),与 curl 请求所用的127.0.0.1不同属正常现象;生产环境应把 App URL 设为对外域名,否则生成的签署链接不可访问; - 临时下载地址:
/file/{签名}/{文件名}形态的 URL 带过期时间戳,取到后应及时下载,不能长期外发; - 错误码速查:
401认证失败(见 4.2)、404资源不存在或动词未注册(见 5.1.6)、422参数校验失败(错误说明在error字段,如submitters is required)。
七、常见问题
Q1:请求一直返回 {"error":"Not authenticated"} 怎么排查?
按顺序核对三点:请求头名必须是 X-Auth-Token(Authorization: Bearer 不被识别,实测 401);Token 值是否完整复制(40 位,界面只展示一次);Token 是否与目标实例匹配(多套实例的 Token 不通用)。
Q2:明明资源存在,请求却 404?
优先检查 HTTP 动词。典型陷阱:curl 的 -d 参数默认发送 POST,若目标是 PATCH/DELETE 端点而不加 -X PATCH/-X DELETE,实际请求的是未注册的 POST /api/xxx/{id},返回 404。本文所有变更类示例均显式写了 -X 动词,即源于此实测教训。
Q3:POST /api/templates/2/submissions 返回 422 submitters is required?
请求体缺 submitters 数组。注意数组内每项的 role 必须与模板角色名逐字一致;未配置 SMTP 时务必传 send_email: false,否则省略时默认 true,提交会进入邮件发送队列并等待重试。
Q4:签署人完成后再调 PATCH 报 422?
签署完成后提交整体锁定,再次更新同一签署人返回 Submitter has already completed the submission.。需要修订时只能创建新提交;values 预填应在发起提交(submitters[].values)或首次完成前完成。
Q5:values 里填了字段但生成的 PDF 没有值?
字段名键必须与模板 fields[].name 完全一致(含大小写与空格),不匹配的键会被静默忽略而不报错。先 GET /api/templates/{id} 核对字段名再回填。
Q6:回显里的链接为什么是 localhost 而不是我访问用的地址?
生成链接的域名取自实例设置中的 App URL,与请求 Host 无关。部署后应在「设置 → App URL」中配置真实对外地址(含端口或反代域名),否则发给签署人的 embed_src、/e/{slug} 链接在对方环境不可达。
Q7:/api/tools/merge 返回的 data 直接 base64 解码失败?
响应中的 base64 按行折叠含有换行符,Python 的 base64.b64decode 会自动忽略,部分语言的严格解码器需要先去除 \n 再解码。
八、参考链接
- 《Docuseal 3.3.4 Docker Compose 部署指南》:https://www.quzuo.net/document/mWAuoENTrgGz (实例部署与管理员初始化)
- 《Docuseal 3.3.4 配置参数详解》:https://www.quzuo.net/document/EYTIRw2Tyued (环境变量与实例设置体系,含 App URL 说明)
- 《Docuseal 3.3.4 介绍与选型指南》:https://www.quzuo.net/document/IVumgpyNfzBb (定位、架构与同类选型对比)
- DocuSeal 官方 API 文档:https://www.docuseal.com/docs/api (云端版接口参考,2026-10-30 查询;开源版端点以本文
bin/rails routes实查为准) - DocuSeal Postman 合集:https://www.postman.com/docuseal/docuseal/collection/baauu23/docuseal-api (官方维护,2026-10-30 查询)
- DocuSeal 源码仓库:https://github.com/docusealco/docuseal (路由与参数白名单的最终依据)