Bỏ qua để đến nội dung

API tài liệu

API tài liệu điền vào mẫu bằng dữ liệu bạn gửi dưới dạng JSON (từ ERP, biểu mẫu web hay một đoạn script) mà không cần bản ghi nào phía sau. Bạn nhận lại liên kết tới tài liệu hoàn chỉnh, theo định dạng đầu ra của mẫu hoặc định dạng bạn yêu cầu.

API dùng được cho mọi loại mẫu. Nguồn dữ liệu riêng của mẫu đơn giản là không được dùng: JSON bạn gửi chính là bản ghi.

Gửi khóa API trong header X-Webhook-API-Key. Có hai loại khóa dùng được:

  • Khóa riêng của mẫu: ở tab Mẫu, trong mục API tài liệu (cùng khóa với HTTP Trigger). Khóa này mở đúng một mẫu đó.
  • Khóa API của công ty: do quản trị viên tạo trong Cổng thông tin công ty (với công ty dùng Lark là quản trị viên ứng dụng Lark), tại Công ty → Khóa API. Khóa này mở mọi mẫu của công ty bạn. Khóa chỉ hiển thị một lần khi được tạo; hãy cất giữ như mật khẩu. Mẫu phê duyệt không có khóa riêng, vì vậy hãy dùng khóa của công ty cho chúng.

Thu hồi khóa của công ty, hoặc đặt lại khóa của mẫu, sẽ khiến khóa đó ngừng hoạt động ngay lập tức.

POST https://api.automadoc.cc/api/v1/templates/{templateId}/documents

Id của mẫu nằm trong endpoint hiển thị trên thẻ API tài liệu của mẫu.

Trường Bắt buộc Tác dụng
data có Bản ghi: các khóa của nó là các biến giữ chỗ. Một danh sách đối tượng sẽ tạo một tài liệu cho mỗi phần tử, hoặc, với mẫu tạo một tài liệu từ nhiều bản ghi, một tài liệu từ tất cả phần tử (xem Nhiều tài liệu cùng lúc).
format không "pdf", "png" (trang đầu tiên dưới dạng ảnh) hoặc "native" (tệp gốc của mẫu, ví dụ .docx). Mặc định theo cài đặt của mẫu.
filename không Mẫu tên tệp cho yêu cầu này, với các biến giữ chỗ {Field}, thay cho mẫu tên tệp của mẫu.
recordId không Giá trị mà {Record_ID} in ra, cho một tài liệu đơn lẻ. Mặc định là id của tài liệu.
mode không "separate", "list", "continuous" hoặc "labels": những gì mẫu tạo ra, gửi kèm để kiểm tra. Nếu bỏ qua, mẫu sẽ quyết định (xem Nhiều tài liệu cùng lúc).

Thêm ?wait=20 (tối đa 25 giây) để giữ phản hồi cho đến khi tài liệu sẵn sàng, nhờ đó chỉ cần một yêu cầu. Nếu không có tham số này, phản hồi được trả về ngay và bạn kiểm tra trạng thái qua URL trạng thái.

Các công cụ quy trình làm việc tuân theo quy ước thăm dò 202 + Location (Power Automate, Logic Apps và tương tự) có thể thêm ?async=true thay thế: trong khi tài liệu đang được tạo, phản hồi 202 có tiêu đề Location để thăm dò và tiêu đề Retry-After (5 giây). Địa chỉ đó trả về 202 cho đến khi tài liệu hoàn tất (200) hoặc thất bại (422, kèm "code": "DOCUMENT_FAILED" và lý do trong error). Tài liệu đã thất bại ngay khi yêu cầu được trả lời sẽ nhận 422 đó ngay lập tức. Endpoint trạng thái cũng nhận ?async=true. async theo dõi một tài liệu, nên không dùng được với một danh sách trong data cho mẫu tạo một tài liệu cho mỗi phần tử (INVALID_ASYNC). Trình kết nối Power Automate dùng cách này.

Phản hồi: 202 Accepted khi tài liệu đang được tạo, 200 OK khi wait thấy tài liệu đã xong:

{
"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}

Dùng cùng khóa như khi gửi yêu cầu. status là processing, completed hoặc 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 không cần khóa. Liên kết còn hiệu lực chừng nào công ty bạn còn lưu giữ tài liệu đã tạo (tùy theo gói của bạn), hoặc 30 ngày nếu tài liệu được lưu vô thời hạn, và ngừng hoạt động khi tài liệu bị xóa. Mỗi lần đọc trạng thái sẽ cho một liên kết mới. Tài liệu failed có trường error nêu lý do. Tài liệu đã hoàn tất có thể có warnings: những gì bị bỏ ra khỏi tài liệu, ví dụ một hình ảnh không tải được từ URL, ghi theo tên trường và máy chủ (host) của URL. Các trình giữ chỗ mà dữ liệu của bạn không có giá trị được liệt kê chung trên một dòng (“3 fields had no value in the data: …”), sau các cảnh báo khác.

Endpoint này cũng báo cáo các tài liệu do HTTP Trigger khởi tạo: phản hồi của trigger liệt kê generationIds của chúng.

Mỗi khóa chỉ thấy tài liệu của những mẫu mà nó mở được. Tài liệu được tạo thủ công trong tiện ích không hiển thị qua API.

GET https://api.automadoc.cc/api/v1/documents/{generationId}/file

Chính tệp đã hoàn tất, với cùng khóa, dành cho công cụ nhận tệp thay vì liên kết. Endpoint trả về 409 với DOCUMENT_NOT_READY khi tài liệu đang được tạo, 422 với DOCUMENT_FAILED và lý do trong error nếu tài liệu thất bại, và 404 với DOCUMENT_FILE_MISSING khi chính sách lưu giữ của công ty bạn đã xóa tệp. Content-Type và Content-Disposition (tên tệp) mô tả tệp.

Liệt kê các mẫu và dữ liệu của chúng

Phần tiêu đề “Liệt kê các mẫu và dữ liệu của chúng”
GET https://api.automadoc.cc/api/v1/templates
GET https://api.automadoc.cc/api/v1/templates/{templateId}

Đường dẫn đầu tiên liệt kê mọi mẫu của công ty bạn: id, name, source (base hoặc approval), templateFormat, mode (yêu cầu tạo ra gì, như trong Nhiều tài liệu cùng lúc), outputFormat và ready (false khi mẫu chưa có tệp, hoặc có lỗi cần sửa). Đường dẫn này cần khóa API của công ty; khóa riêng của một mẫu bị từ chối với COMPANY_KEY_REQUIRED.

Đường dẫn thứ hai mô tả một mẫu (dùng khóa nào cũng được) và thêm dataSchema, một lược đồ JSON của data mà mẫu nhận (mỗi biến giữ chỗ một thuộc tính: văn bản, số hoặc URL hình ảnh, có/không cho một điều kiện, danh sách cho một vòng lặp), sampleData và documentsUrl. Các công cụ quy trình làm việc dùng nó để hiển thị một ô nhập cho mỗi biến giữ chỗ.

Mô tả đầy đủ của các đường dẫn này là một tài liệu OpenAPI tại https://api.automadoc.cc/api/v1/openapi.json.

Dữ liệu của bạn điền vào mẫu như thế nào

Phần tiêu đề “Dữ liệu của bạn điền vào mẫu như thế nào”

Tên. Mỗi khóa được chuyển thành tên biến giữ chỗ giống hệt cách tên trường trong Base được chuyển: dấu cách, dấu chấm và các ký hiệu khác trở thành _, chữ cái và chữ số của mọi ngôn ngữ được giữ nguyên, và có phân biệt chữ hoa chữ thường.

Khóa bạn gửi Biến giữ chỗ được điền
"Customer" {Customer}
"Invoice No." {Invoice_No_}
"Unit price" {Unit_price}
"客户名称" {客户名称}

Hai khóa trong cùng một đối tượng mà chuyển thành cùng một tên, như "Unit price" và "Unit-price", sẽ bị từ chối với mã DATA_NAME_COLLISION, thay vì để một khóa âm thầm thắng.

Giá trị.

  • Văn bản và số được in đúng như khi gửi. Số vẫn là số, nên các bộ lọc như number, currency và sum dùng được với chúng.
  • true / false dùng được với điều kiện: {#if Paid}…{/if}.
  • null và danh sách rỗng không in ra gì, và được coi là rỗng trong {#if}.
  • Một đối tượng điền vào các biến giữ chỗ có dấu chấm: {"Customer": {"Name": "Acme"}} điền {Customer.Name}.
  • Một danh sách đối tượng là một vòng lặp: {"Items": [{"Product": "Pen", "Qty": 2}]} điền {#Items}{Product} × {Qty}{/Items}.
  • Một danh sách giá trị đơn được in nối với nhau bằng dấu phẩy: ["red", "blue"] in ra red, blue.
  • Hình ảnh: ở chỗ mẫu có biến giữ chỗ hình ảnh (một ảnh có Alt Text là {Logo}, kể cả bên trong một hàng lặp), hãy gửi một URL https://, hoặc một danh sách URL cho {Photos[1]}, {Photos[2]}. URL phải truy cập được từ internet. Ở mọi chỗ khác, URL chỉ là văn bản.
  • Tệp đính kèm: {ATTACH:Field} chỉ thêm các tệp của một trường tệp đính kèm trong Base hoặc của một biểu mẫu phê duyệt. API tài liệu không thể gửi tệp cho nó: không có gì được thêm, và các URL gửi cho nó được in ra dưới dạng văn bản.
  • {QR:Field} và {BARCODE:Field} in mã của đoạn văn bản bạn gửi.

Record_ID, Template_Name và Print_Time do AutomaDoc đặt; khóa có tên trùng sẽ bị thay thế (phản hồi sẽ cảnh báo bạn).

Với mẫu phê duyệt, các biến được liệt kê trên trang của mẫu chính là các tên cần gửi. Tên tệp mặc định của mẫu phê duyệt dựa theo yêu cầu phê duyệt, mà JSON thì không có, nên tài liệu tạo qua API được đặt tên {Template_Name}-{Record_ID} trừ khi bạn gửi filename.

Gửi data dưới dạng danh sách tối đa 50 đối tượng để tạo một tài liệu cho mỗi phần tử. Phản hồi liệt kê các tài liệu đó:

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

Nếu bất kỳ phần tử nào bị từ chối, sẽ không có tài liệu nào được tạo. Không dùng được recordId với một danh sách.

Nếu mẫu được đặt để tạo một tài liệu từ nhiều bản ghi (danh sách, mỗi bản ghi một trang, hoặc nhãn) thì danh sách trong data sẽ tạo một tài liệu: mỗi phần tử là một bản ghi trong vòng lặp {#Records}, một trang hoặc một nhãn, theo thứ tự đã gửi. Tối đa 500 phần tử; một đối tượng đơn lẻ tạo tài liệu có một phần tử. Phản hồi là tài liệu đó, kèm recordCount:

{ "generationId": "…", "status": "processing", "statusUrl": "…", "recordCount": 120 }
  • {Record_ID} in vị trí của từng phần tử, từ 1 đến số phần tử.
  • Mẫu tên tệp đọc phần tử đầu tiên, cùng {RecordCount} và {Date}. Nếu không có, tài liệu được đặt tên {Template_Name}-{Date}.
  • "format": "png" sẽ tạo PDF: một hình ảnh chỉ chứa được trang đầu tiên.
  • Được tính là một tài liệu. Với giới hạn 600 tài liệu mỗi phút của công ty, mỗi phần tử được tính là một nếu là mỗi bản ghi một trang, và cứ mười phần tử được tính là một nếu là danh sách hoặc nhãn.
  • Không thể gửi để ký (ESIGN_COMBINED).

Cài đặt Bản ghi trên mỗi tài liệu của mẫu sẽ quyết định. Nếu bạn gửi mode ("separate" cho mỗi phần tử một tài liệu, hoặc "list", "continuous" cho mỗi bản ghi một trang, hay "labels") mà mẫu được đặt khác đi, yêu cầu sẽ bị từ chối với MODE_MISMATCH, thay vì trả về số tệp khác với số mà script của bạn chờ đợi.

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"
}'

Thẻ API tài liệu của mẫu cho phép sao chép một yêu cầu giống như trên, được dựng từ chính các biến giữ chỗ của mẫu.

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
}

Thêm khối sign để gửi tài liệu đi ký ngay khi tài liệu được tạo xong. Ngoài lượt tạo tài liệu, bạn không tốn thêm gì.

sign dùng được với mẫu Lark Base: một mẫu Word có trường chữ ký (xem Chữ ký điện tử), tạo mỗi bản ghi một tài liệu, với data gửi dưới dạng một đối tượng. Mọi mẫu khác đều từ chối nó với SIGN_BASE_TEMPLATES_ONLY: mẫu Excel, danh sách SharePoint, Dataverse, Google Sheets và mẫu chỉ dùng API, cùng mẫu Lark Approval, vốn được ký ngay trong phê duyệt. Chỉ tài khoản Lark mới có mẫu Lark Base, nên trong tài khoản Microsoft, Google hoặc email, không mẫu nào nhận sign.

{
"data": { "Customer": "Acme Corp" },
"sign": {
"signers": {
"Customer": { "name": "Budi Santoso", "contact": "budi@acme.example" },
"Supplier": { "larkUserId": "ou_1234…" }
},
"order": "sequential"
}
}
Trường Tác dụng
signers Một người ký cho mỗi vai trò ký của mẫu, theo tên vai trò. Vai trò nào cũng phải có người ký: không có bản ghi nào để lấy người ký. Người bên ngoài công ty bạn là { "name", "contact"? }: một cái tên, và tùy chọn một ghi chú liên hệ được lưu cùng yêu cầu, chẳng hạn địa chỉ email (không có gì được gửi tới đó). Đồng nghiệp là { "larkUserId" }: open_id Lark của họ, dành cho một người trong công ty Lark của bạn có dùng AutomaDoc.
order "parallel" (tất cả cùng lúc) hoặc "sequential" (lần lượt theo thứ tự của mẫu). Mặc định theo cài đặt của mẫu.
generatePasswords Tạo một mật khẩu cho mỗi người ký bên ngoài. Mặc định true.
locale Ngôn ngữ của tin nhắn bot và trang nhật ký kiểm tra, ví dụ "en".

Yêu cầu ký bắt đầu khi tài liệu đã sẵn sàng. Đồng nghiệp nhận tin nhắn từ bot AutomaDoc trong Lark. Liên kết của người ký bên ngoài, kèm mật khẩu tự tạo, chỉ được trả về một lần, trong lần gọi GET /api/v1/documents/{generationId} đầu tiên sau khi yêu cầu bắt đầu:

{
"status": "completed",
"signing": {
"status": "started",
"requestId": "…",
"links": [{ "role": "Customer", "displayName": "Budi Santoso", "url": "https://…/sign/…", "password": "K7mQ…" }]
}
}

Bạn tự chuyển các liên kết này cho người ký, và gửi mật khẩu riêng nếu có thể. Những lần đọc sau vẫn hiển thị các mục đó, nhưng url và password là null, kèm "linksRedacted": true. Nếu mất liên kết, hãy tạo liên kết mới từ trang Chữ ký. signing.status là queued cho đến khi tài liệu xong, starting trong chốc lát khi yêu cầu đang được mở, sau đó là started hoặc failed (kèm mã error).

sign bị từ chối khi data là danh sách (SIGN_SINGLE_DOCUMENT) và với mẫu tạo một tài liệu từ nhiều bản ghi (ESIGN_COMBINED).

Nếu mẫu có Callback Webhook, callback này cũng được gọi cho tài liệu tạo qua API, kèm liên kết tải xuống, khi có Pro (hoặc bản dùng thử) hoặc suất Business, như với mọi tài liệu tự động.

Mọi lần từ chối đều có code và thông báo error bằng tiếng Anh:

Trạng thái code Lý do
400 INVALID_JSON, DATA_REQUIRED, DATA_NOT_OBJECT Nội dung không phải JSON, không có data, hoặc data không phải một đối tượng hay danh sách đối tượng
400 DATA_NAME_COLLISION, DATA_INVALID_NAME Hai khóa điền cùng một biến giữ chỗ; một khóa không có chữ cái hay chữ số nào
400 DATA_MIXED_ARRAY Một danh sách trộn lẫn đối tượng và giá trị đơn
400 DATA_TOO_DEEP, DATA_ARRAY_TOO_LONG, DATA_TOO_MANY_KEYS, DATA_STRING_TOO_LONG Vượt quá một giới hạn
400 IMAGE_URL_NOT_ALLOWED, TOO_MANY_IMAGES URL hình ảnh không phải địa chỉ http(s) công khai; quá nhiều hình ảnh
400 BATCH_EMPTY, BATCH_TOO_LARGE Danh sách rỗng; nhiều hơn 50 phần tử (500 với mẫu tạo một tài liệu từ nhiều bản ghi)
400 INVALID_FORMAT, INVALID_FILENAME, INVALID_RECORD_ID, INVALID_WAIT, INVALID_MODE, INVALID_ASYNC Một tùy chọn không hợp lệ
400 TEMPLATE_VALIDATION_ERRORS Tệp mẫu có lỗi cần sửa trước (liệt kê trong validationErrors)
400 MODE_MISMATCH mode không phải là những gì mẫu tạo ra
401 API_KEY_MISSING Không có header X-Webhook-API-Key
403 API_KEY_INVALID Khóa sai, đã bị thu hồi, hoặc không mở được mẫu này; một mã mẫu không tồn tại cũng nhận phản hồi này
403 QUOTA_EXCEEDED Đã hết tài liệu trong tháng này; hãy mua một gói tài liệu hoặc một suất
403 TEMPLATE_DISABLED Mẫu vượt quá giới hạn mẫu của gói
403 COMPANY_KEY_REQUIRED Liệt kê mẫu cần khóa API của công ty, không phải khóa riêng của một mẫu
404 TEMPLATE_NOT_FOUND, DOCUMENT_NOT_FOUND Không có mẫu hoặc tài liệu như vậy cho khóa này
404 DOCUMENT_FILE_MISSING Tệp của tài liệu đã bị xóa theo chính sách lưu giữ của công ty bạn
409 TEMPLATE_FILE_MISSING, TEMPLATE_NO_OWNER Mẫu chưa có tệp; mẫu không có chủ sở hữu (hãy mở và lưu mẫu một lần, hoặc dùng khóa của công ty)
409 DOCUMENT_NOT_READY Tải xuống tệp của một tài liệu vẫn đang được tạo
413 BODY_TOO_LARGE Nội dung vượt quá 1 MB
422 DOCUMENT_FAILED Tải xuống tệp của một tài liệu đã thất bại, hoặc gửi yêu cầu hay đọc trạng thái với async=true cho tài liệu đó; error cho biết lý do
429 RATE_LIMITED Hơn 60 yêu cầu mỗi phút cho một mẫu, 600 tài liệu mỗi phút cho một công ty, 60 lần đọc trạng thái hoặc 60 lần tải xuống mỗi phút cho một tài liệu, hoặc 60 lần liệt kê mẫu mỗi phút cho một công ty. Tài liệu từ HTTP Trigger được tính vào mức 600 của công ty; yêu cầu của nó có giới hạn riêng 300 mỗi phút cho mỗi mẫu
400 SIGN_INVALID, SIGN_SINGLE_DOCUMENT, SIGN_BASE_TEMPLATES_ONLY Khối sign không hợp lệ, data là một danh sách, hoặc mẫu không phải mẫu Lark Base, nên tài liệu của nó không thể gửi đi ký
400, 409 ESIGN_… Bị tính năng chữ ký điện tử từ chối: ESIGN_ROLES_MISMATCH (một vai trò chưa có người ký, hoặc một vai trò không tồn tại), ESIGN_SIGNER_FIELD (người ký được đọc từ một trường), ESIGN_INVALID_SIGNER (một larkUserId không phải người dùng của công ty bạn), ESIGN_NO_MASTER (mẫu không có trường chữ ký), ESIGN_COMBINED (mẫu tạo một tài liệu từ nhiều bản ghi), ESIGN_RECORD_UNREADABLE (mẫu không có chủ sở hữu để đứng tên gửi yêu cầu)
502 WORKER_UNAVAILABLE Không kết nối được dịch vụ tạo tài liệu; hãy thử lại sau ít phút
503 TEMPLATE_FORMAT_UNAVAILABLE Mẫu là tệp Excel hoặc PowerPoint mà dịch vụ tài liệu chưa mở được; hãy thử lại sau
503 COMBINED_UNAVAILABLE Hiện chưa thể tạo một tài liệu từ nhiều bản ghi; hãy thử lại sau
503 ATTACHMENTS_UNAVAILABLE Mẫu tạo một tài liệu từ nhiều bản ghi và thêm tệp đính kèm vào PDF, việc này hiện chưa thực hiện được; hãy thử lại sau
Nội dung yêu cầu 1 MB
Số tài liệu mỗi yêu cầu 50, hoặc 500 phần tử trong một tài liệu từ nhiều bản ghi
Độ sâu lồng nhau của đối tượng và danh sách 8 cấp
Số phần tử trong một danh sách 1.000
Số khóa trong một đối tượng 500
Số ký tự trong một giá trị 100.000
Số hình ảnh mỗi tài liệu 50; tổng cộng 500 trên mọi phần tử của một tài liệu từ nhiều bản ghi
wait 25 giây
Số yêu cầu cho mỗi mẫu 60 mỗi phút; HTTP Trigger có giới hạn riêng 300 mỗi phút
Số lần đọc trạng thái mỗi tài liệu 60 mỗi phút; tải tệp xuống có giới hạn riêng 60
Danh sách mẫu 60 mỗi phút cho mỗi công ty; mô tả của một mẫu 60 mỗi phút
Tài liệu mỗi công ty 600 mỗi phút, tính chung API tài liệu và HTTP Trigger