文档 API
文档 API 用您以 JSON 发送的数据填充模板(数据可以来自 ERP、网页表单或脚本),背后不需要任何记录。您会取回成品文档的链接,格式为模板的输出格式,或您在请求中指定的格式。
所有类型的模板都可以使用。模板原有的数据源不会被使用:您发送的 JSON 就是记录。
在 X-Webhook-API-Key 请求头中发送 API 密钥。以下两种密钥均可使用:
- 模板自己的密钥:位于模板标签页的文档 API 下(与 HTTP 触发器使用同一个密钥)。它只能访问这一个模板。
- 公司 API 密钥:由管理员(飞书企业中为飞书应用管理员)在企业门户的公司 → API 密钥下创建。它可以访问贵公司的所有模板。密钥只在创建时显示一次,请像保管密码一样保管它。审批模板没有自己的密钥,请为其使用公司 API 密钥。
吊销公司 API 密钥或重置模板的密钥后,原密钥会立即失效。
POST https://api.automadoc.cc/api/v1/templates/{templateId}/documents模板 ID 包含在模板文档 API 卡片显示的接口地址中。
| 字段 | 必填 | 作用 |
|---|---|---|
data |
是 | 记录:其键即占位符。传入对象列表时,每一项生成一份文档;若模板设置为由多条记录生成一份文档,则所有项合成一份文档(参见一次生成多份文档)。 |
format |
否 | "pdf"、"png"(第一页的图片)或 "native"(模板自身的文件格式,例如 .docx)。默认使用模板的设置。 |
filename |
否 | 仅用于本次请求的文件名模式,可包含 {Field} 占位符,替代模板的文件名模式。 |
recordId |
否 | 单份文档时 {Record_ID} 输出的内容。默认为该文档的 ID。 |
mode |
否 | "separate"、"list"、"continuous" 或 "labels":模板生成的内容,作为核对发送。省略时由模板决定(参见一次生成多份文档)。 |
加上 ?wait=20(最长 25 秒)可让响应等到文档生成完成后再返回,这样一个请求就够了。不加时,响应会立即返回,您需要轮询状态地址。
遵循 202 + Location 轮询约定的工作流工具(Power Automate、Logic Apps 等)可以改为加上 ?async=true:文档生成期间,202 响应会带有可供轮询的 Location 标头和 Retry-After 标头(5 秒)。轮询该地址会一直返回 202,直到文档生成完成(200)或失败(422,附带 "code": "DOCUMENT_FAILED",原因在 error 中)。如果在响应请求时文档已经失败,会直接得到这个 422。状态接口同样接受 ?async=true。async 只跟踪一份文档,因此对于按每一项生成一份文档的模板,不能在 data 中发送列表时使用(INVALID_ASYNC)。Power Automate 连接器使用的就是这种方式。
响应:文档仍在生成时返回 202 Accepted;wait 期间文档已生成完成时返回 200 OK:
{ "generationId": "5d2f0c1e-6a1b-4c7e-9f0a-2b8c3d4e5f60", "templateId": "9b1c…", "status": "processing", "statusUrl": "https://api.automadoc.cc/api/v1/documents/5d2f0c1e-6a1b-4c7e-9f0a-2b8c3d4e5f60", "createdAt": 1791878400000}GET https://api.automadoc.cc/api/v1/documents/{generationId}使用与创建请求相同的密钥。status 为 processing、completed 或 failed:
{ "generationId": "5d2f0c1e-6a1b-4c7e-9f0a-2b8c3d4e5f60", "status": "completed", "filename": "Invoice-INV-2026-001.pdf", "downloadUrl": "https://api.automadoc.cc/api/generations/…/download?expires=…&signature=…", "downloadUrlExpiresAt": 1792137600000}downloadUrl 无需密钥即可访问。只要贵公司仍保留已生成的文档(保留期限由套餐决定),它就一直有效;如果文档设置为永久保留,则有效期为 30 天;文档被删除后即失效。每次查询状态都会返回一个新链接。状态为 failed 的文档会在 error 中说明原因。已完成的文档可能带有 warnings:说明有哪些内容未能放入文档,例如无法从 URL 获取的图片,以字段名和 URL 的主机名标明。数据中没有值的占位符会在其他警告之后合并为一行列出(“3 fields had no value in the data: …”)。
该接口同样可以查询由 HTTP 触发器启动的文档:HTTP 触发器的响应会列出它们的 generationIds。
密钥只能看到它可以访问的模板所生成的文档。在插件中手动生成的文档无法通过 API 查看。
用密钥下载文件
Section titled “用密钥下载文件”GET https://api.automadoc.cc/api/v1/documents/{generationId}/file使用同一个密钥直接获取生成好的文件本身,适用于接收文件而非链接的工具。文档生成期间返回 409 和 DOCUMENT_NOT_READY;文档失败时返回 422 和 DOCUMENT_FAILED,原因在 error 中;文件已被公司的保留期限删除后返回 404 和 DOCUMENT_FILE_MISSING。Content-Type 和 Content-Disposition(文件名)说明了文件的类型和名称。
列出模板及其数据
Section titled “列出模板及其数据”GET https://api.automadoc.cc/api/v1/templatesGET https://api.automadoc.cc/api/v1/templates/{templateId}第一个接口列出贵公司的所有模板,包括 id、name、source(base 或 approval)、templateFormat、mode(请求会生成什么,见一次生成多份文档)、outputFormat 和 ready(模板还没有文件或存在需要修复的错误时为 false)。它需要公司 API 密钥;使用模板自己的密钥会被拒绝,返回 COMPANY_KEY_REQUIRED。
第二个接口描述单个模板(两种密钥都可以使用),并额外返回 dataSchema(该模板接收的 data 的 JSON 架构:每个占位符一个属性,可以是文本、数字或图片地址,条件为是/否,循环为列表)、sampleData 和 documentsUrl。工作流工具据此为每个占位符显示一个输入项。
这些接口的完整说明是一份 OpenAPI 文档,地址为 https://api.automadoc.cc/api/v1/openapi.json。
数据如何填入模板
Section titled “数据如何填入模板”名称。 每个键转换为占位符名称的方式,与多维表格字段名完全相同:空格、点号和其他符号变为 _,任何语言的字母和数字都会保留,并区分大小写。
| 您发送的键 | 它填充的占位符 |
|---|---|
"Customer" |
{Customer} |
"Invoice No." |
{Invoice_No_} |
"Unit price" |
{Unit_price} |
"客户名称" |
{客户名称} |
同一对象中如果有两个键转换后得到相同的名称(例如 "Unit price" 和 "Unit-price"),请求会以 DATA_NAME_COLLISION 被拒绝,而不会悄悄地只保留其中一个。
值。
- 文本和数字按发送的内容输出。数字仍是数字,因此
number、currency和sum等过滤器可以直接用于它们。 true/false可用于条件:{#if Paid}…{/if}。null和空列表不输出任何内容,在{#if}中视为空。- 对象用于填充带点号的占位符:
{"Customer": {"Name": "Acme"}}填充{Customer.Name}。 - 对象列表即循环:
{"Items": [{"Product": "Pen", "Qty": 2}]}填充{#Items}{Product} × {Qty}{/Items}。 - 普通值列表以逗号连接输出:
["red", "blue"]输出red, blue。 - 图片:模板中有图片占位符的位置(替代文字为
{Logo}的图片,循环行内同样适用),请发送https://地址;对于{Photos[1]}、{Photos[2]},则发送地址列表。该地址必须能从互联网访问。在其他位置,地址只是普通文本。 - 附件:
{ATTACH:Field}只能添加多维表格附件字段或审批表单中的文件。文档 API 无法为它发送文件:不会添加任何内容,为它发送的地址会作为文本输出。 {QR:Field}和{BARCODE:Field}会把您发送的文本输出为二维码或条形码。
Record_ID、Template_Name 和 Print_Time 由 AutomaDoc 设置;同名的键会被替换(响应中会给出警告)。
对于审批模板,请发送其页面上变量中列出的名称。审批模板的默认文件名以审批申请命名,而 JSON 中没有申请,因此通过 API 生成的文档会命名为 {Template_Name}-{Record_ID},除非您发送了 filename。
一次生成多份文档
Section titled “一次生成多份文档”将 data 设为最多 50 个对象的列表,即可为每一项生成一份文档。响应会列出这些文档:
{ "documents": [ { "generationId": "…", "status": "processing", "statusUrl": "…" }, … ] }只要有任何一项被拒绝,就不会生成任何文档。列表不能与 recordId 同时使用。
所有项合成一份文档
Section titled “所有项合成一份文档”如果模板设置为由多条记录生成一份文档(列表、每条记录一页或标签),data 中的列表只生成一份文档:每一项按发送顺序成为 {#Records} 循环中的一条记录、一页或一张标签。最多 500 项;单个对象生成只含一项的文档。响应即该文档,并带有 recordCount:
{ "generationId": "…", "status": "processing", "statusUrl": "…", "recordCount": 120 }{Record_ID}输出每一项的位置,从1到项数。- 文件名规则读取第一项,以及
{RecordCount}和{Date}。未设置时,文档命名为{Template_Name}-{Date}。 "format": "png"会生成 PDF:图片只能容纳第一页。- 计为一份文档。在公司每分钟 600 份文档的限制中,每条记录一页时每项计为一份,列表或标签时每十项计为一份。
- 不能发送签署(
ESIGN_COMBINED)。
由模板的每份文档的记录设置决定。如果发送 mode(每项一份文档为 "separate",或 "list"、"continuous"(每条记录一页)、"labels"),而模板的设置不同,请求会以 MODE_MISMATCH 被拒绝,而不会返回与脚本预期数量不同的文件。
示例:curl
Section titled “示例:curl”curl -X POST 'https://api.automadoc.cc/api/v1/templates/TEMPLATE_ID/documents?wait=20' \ -H 'X-Webhook-API-Key: YOUR_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "data": { "Invoice No.": "INV-2026-001", "Customer": { "Name": "Acme Corp", "Address": "1 Main St" }, "Items": [ { "Product": "Consulting", "Qty": 10, "Price": 120 }, { "Product": "Travel", "Qty": 1, "Price": 340 } ], "Logo": "https://example.com/logo.png" }, "format": "pdf" }'模板的文档 API 卡片可以复制一个类似的请求,它根据该模板自己的占位符生成。
示例:Node.js
Section titled “示例:Node.js”const API = 'https://api.automadoc.cc'const headers = { 'X-Webhook-API-Key': process.env.AUTOMADOC_KEY, 'Content-Type': 'application/json' }
async function generate(templateId, data) { const res = await fetch(`${API}/api/v1/templates/${templateId}/documents?wait=20`, { method: 'POST', headers, body: JSON.stringify({ data, format: 'pdf' }), }) let doc = await res.json() if (!res.ok) throw new Error(`${doc.code}: ${doc.error}`)
// Still processing after the wait: poll the status URL. while (doc.status === 'processing') { await new Promise((r) => setTimeout(r, 2000)) doc = await (await fetch(doc.statusUrl, { headers })).json() } if (doc.status === 'failed') throw new Error(doc.error) return doc.downloadUrl}发送文档签署
Section titled “发送文档签署”添加 sign 块,即可在文档生成后立即发出签署。除生成文档本身外,不产生额外费用。
sign 适用于飞书多维表格模板:含签名字段的 Word 模板(参见电子签名),每条记录生成一份文档,且 data 以单个对象发送。其他模板都会以 SIGN_BASE_TEMPLATES_ONLY 拒绝它:Excel、SharePoint 列表、Dataverse、Google Sheets 和仅 API 的模板,以及飞书审批模板(这类模板在审批流程中签署)。只有飞书账户才有飞书多维表格模板,因此在 Microsoft、Google 或邮箱账户中,没有任何模板接受 sign。
{ "data": { "Customer": "Acme Corp" }, "sign": { "signers": { "Customer": { "name": "Budi Santoso", "contact": "budi@acme.example" }, "Supplier": { "larkUserId": "ou_1234…" } }, "order": "sequential" }}| 字段 | 作用 |
|---|---|
signers |
按角色名为模板的每个签署角色指定一位签署人。每个角色都必须指定:这里没有记录可供读取签署人。公司外部的人使用 { "name", "contact"? }:一个姓名,以及可选的联系方式备注(例如邮箱地址),随请求一起保存,不会向其发送任何内容。同事使用 { "larkUserId" }:其飞书 open_id,适用于贵公司飞书中使用 AutomaDoc 的成员。 |
order |
"parallel"(所有人同时签署)或 "sequential"(按模板中的顺序依次签署)。默认使用模板的设置。 |
generatePasswords |
为每位外部签署人生成一个密码。默认为 true。 |
locale |
机器人消息和审计页的语言,例如 "en"。 |
文档生成完成后,签署请求随即开始。同事会在飞书中收到 AutomaDoc 机器人的消息。外部签署人的链接(以及生成的密码)只返回一次:请求开始后,由第一次 GET /api/v1/documents/{generationId} 返回:
{ "status": "completed", "signing": { "status": "started", "requestId": "…", "links": [{ "role": "Customer", "displayName": "Budi Santoso", "url": "https://…/sign/…", "password": "K7mQ…" }] }}请自行把链接转发给签署人,如有可能,把密码分开发送。之后的查询仍会返回这些条目,但 url 和 password 为 null,并带有 "linksRedacted": true。如果链接遗失,请在电子签名页面生成新链接。文档完成前,signing.status 为 queued;请求开启时会短暂显示为 starting;之后为 started 或 failed(附带 error 代码)。
data 为列表时,sign 会被拒绝(SIGN_SINGLE_DOCUMENT);在由多条记录生成一份文档的模板上也会被拒绝(ESIGN_COMBINED)。
文档生成完成时
Section titled “文档生成完成时”如果模板设置了 Webhook 回调,通过 API 生成的文档同样会触发回调,并附带下载链接;与所有自动生成的文档一样,需要专业版(或试用期)或 Business 席位。
每个被拒绝的请求都会返回一个 code 和一条英文的 error:
| 状态码 | code |
原因 |
|---|---|---|
| 400 | INVALID_JSON、DATA_REQUIRED、DATA_NOT_OBJECT |
请求体不是 JSON、没有 data,或 data 既不是对象也不是对象列表 |
| 400 | DATA_NAME_COLLISION、DATA_INVALID_NAME |
两个键填充同一个占位符;某个键不含任何字母或数字 |
| 400 | DATA_MIXED_ARRAY |
列表中混有对象和普通值 |
| 400 | DATA_TOO_DEEP、DATA_ARRAY_TOO_LONG、DATA_TOO_MANY_KEYS、DATA_STRING_TOO_LONG |
超出限制 |
| 400 | IMAGE_URL_NOT_ALLOWED、TOO_MANY_IMAGES |
图片地址不是公开的 http(s) 地址;图片过多 |
| 400 | BATCH_EMPTY、BATCH_TOO_LARGE |
列表为空;超过 50 项(由多条记录生成一份文档的模板为 500 项) |
| 400 | INVALID_FORMAT、INVALID_FILENAME、INVALID_RECORD_ID、INVALID_WAIT、INVALID_MODE、INVALID_ASYNC |
某个选项无效 |
| 400 | TEMPLATE_VALIDATION_ERRORS |
模板文件存在需要先修正的错误(列在 validationErrors 中) |
| 400 | MODE_MISMATCH |
mode 与模板生成的内容不符 |
| 401 | API_KEY_MISSING |
缺少 X-Webhook-API-Key 请求头 |
| 403 | API_KEY_INVALID |
密钥错误、已被吊销,或无权访问此模板;模板 ID 不存在时也返回此错误 |
| 403 | QUOTA_EXCEEDED |
本月已无可用文档额度;请购买文档包或席位 |
| 403 | TEMPLATE_DISABLED |
该模板超出了套餐的模板上限 |
| 403 | COMPANY_KEY_REQUIRED |
列出模板需要公司 API 密钥,不能使用模板自己的密钥 |
| 404 | TEMPLATE_NOT_FOUND、DOCUMENT_NOT_FOUND |
此密钥下不存在该模板或文档 |
| 404 | DOCUMENT_FILE_MISSING |
文档的文件已被公司的保留期限删除 |
| 409 | TEMPLATE_FILE_MISSING、TEMPLATE_NO_OWNER |
模板还没有文件;模板没有所有者(打开并保存一次,或使用公司 API 密钥) |
| 409 | DOCUMENT_NOT_READY |
下载仍在生成中的文档的文件 |
| 413 | BODY_TOO_LARGE |
请求体超过 1 MB |
| 422 | DOCUMENT_FAILED |
下载失败文档的文件,或对失败的文档使用 async=true 发送请求或查询状态;原因见 error |
| 429 | RATE_LIMITED |
单个模板每分钟超过 60 次请求、单家公司每分钟超过 600 份文档、单份文档每分钟超过 60 次状态查询或 60 次下载,或单家公司每分钟超过 60 次模板列表查询。HTTP 触发器生成的文档计入公司的 600 份;其请求有独立的限制,每个模板每分钟 300 次 |
| 400 | SIGN_INVALID、SIGN_SINGLE_DOCUMENT、SIGN_BASE_TEMPLATES_ONLY |
sign 块无效、data 是列表,或模板不是飞书多维表格模板,因此其文档无法发送签署 |
| 400、409 | ESIGN_… |
被电子签名拒绝:ESIGN_ROLES_MISMATCH(某个角色没有签署人,或角色不存在)、ESIGN_SIGNER_FIELD(签署人从字段读取)、ESIGN_INVALID_SIGNER(某个 larkUserId 不是贵公司的用户)、ESIGN_NO_MASTER(模板没有签名字段)、ESIGN_COMBINED(模板由多条记录生成一份文档)、ESIGN_RECORD_UNREADABLE(模板没有可代为发起请求的所有者) |
| 502 | WORKER_UNAVAILABLE |
无法连接文档生成服务;请稍后重试 |
| 503 | TEMPLATE_FORMAT_UNAVAILABLE |
模板是文档服务暂时无法打开的 Excel 或 PowerPoint 文件,请稍后重试 |
| 503 | COMBINED_UNAVAILABLE |
暂时无法由多条记录生成一份文档,请稍后重试 |
| 503 | ATTACHMENTS_UNAVAILABLE |
模板由多条记录生成一份文档,并会把附件加入 PDF,暂时无法完成,请稍后重试 |
| 请求体 | 1 MB |
| 每个请求的文档数 | 50;由多条记录生成的一份文档为 500 项 |
| 对象和列表的嵌套层数 | 8 层 |
| 列表中的项数 | 1,000 |
| 对象中的键数 | 500 |
| 单个值的字符数 | 100,000 |
| 每份文档的图片数 | 50;由多条记录生成的一份文档,所有项合计 500 |
wait |
25 秒 |
| 每个模板的请求数 | 每分钟 60 次(HTTP 触发器另有独立限制:每分钟 300 次) |
| 每份文档的状态查询次数 | 每分钟 60 次(文件下载另有独立的 60 次) |
| 模板列表 | 每家公司每分钟 60 次(单个模板的说明每分钟 60 次) |
| 每家公司的文档数 | 每分钟 600 份(文档 API 与 HTTP 触发器合计) |