跳转到内容

文档 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 查看。

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(文件名)说明了文件的类型和名称。

GET https://api.automadoc.cc/api/v1/templates
GET 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。

名称。 每个键转换为占位符名称的方式,与多维表格字段名完全相同:空格、点号和其他符号变为 _,任何语言的字母和数字都会保留,并区分大小写。

您发送的键 它填充的占位符
"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。

将 data 设为最多 50 个对象的列表,即可为每一项生成一份文档。响应会列出这些文档:

{ "documents": [ { "generationId": "…", "status": "processing", "statusUrl": "…" }, … ] }

只要有任何一项被拒绝,就不会生成任何文档。列表不能与 recordId 同时使用。

如果模板设置为由多条记录生成一份文档(列表、每条记录一页或标签),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 被拒绝,而不会返回与脚本预期数量不同的文件。

Terminal window
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 卡片可以复制一个类似的请求,它根据该模板自己的占位符生成。

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
}

添加 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)。

如果模板设置了 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 触发器合计)