合同生成接口
版本 1 管理后台 下载接口定义
服务端调用

合同生成接口:四步接完

你只需要服务地址和授权码。先拉取可用名称,再提交生成,等待任务完成,最后领取合同成品。

授权码只能保存在你自己的后端。 不能写进网页、小程序、客户端安装包、前端代码或公开仓库。前端先请求你自己的后端,再由后端调用本接口。
  1. 1
    拉目录获取能用的模板、分组、企业和字段
  2. 2
    提交生成单个模板或整个分组二选一
  3. 3
    等结果用返回的任务编号轮询状态
  4. 4
    领成品每个文件只允许成功领取一次

全部接口

方法地址用途
GET/api/v1/catalog获取当前授权范围
POST/api/v1/generate生成单个模板或整个分组
GET/api/v1/generation-jobs/{jobId}查询一份合同的任务状态
GET/api/v1/generation-jobs查询当前授权码的历史任务
GET/api/v1/generation-files/{fileId}/download领取指定成品文件
GET/api/v1/generation-jobs/{jobId}/download领取任务的第一个成品文件

接入时必须遵守

  • 所有名称和字段都从最新目录获取,不自己猜。
  • 模板名称和分组名称只能提交一个。
  • 字段直接使用中文名称,例如“剧目名称”。
  • 同一笔业务始终使用同一个幂等键。
  • 整组生成要保存返回的全部任务编号。
  • 文件首次领取成功后立即保存,不能再次下载。

完整可运行代码

下面代码包含目录校验、单个或整组生成、状态轮询和成品保存。修改开头的模式、名称、企业和字段即可运行。

Node.js 20 及以上版本

运行方式

设置授权码并运行
# Windows PowerShell
$env:CONTRACT_API_KEY="管理员给你的完整授权码"
node contract-client.js

# Linux
CONTRACT_API_KEY="管理员给你的完整授权码" node contract-client.js

第一步:拉取目录

每次打开生成页面时调用一次。目录里有什么,你就只能展示和提交什么。

请求
响应重点
{
  "groups": [
    {
      "name": "腾讯",
      "contractCount": 2,
      "fields": [
        { "key": "{剧目名称}", "label": "剧目名称", "required": true },
        { "key": "{集数}", "label": "集数", "required": true }
      ],
      "formats": ["pdf", "image"]
    }
  ],
  "templates": [
    {
      "name": "腾讯-承诺函",
      "groupName": "腾讯",
      "fields": [
        { "key": "{剧目名称}", "label": "剧目名称", "required": true }
      ],
      "formats": ["pdf", "image"]
    }
  ],
  "companies": [
    { "name": "示例文化科技有限公司" }
  ],
  "catalogVersion": "e8a9e147f2e064c1"
}
要做什么使用哪个值
生成单个模板提交 templates[].nametemplateName
生成整个分组提交 groups[].namegroupName
选择企业提交 companies[].namecompanyName
显示输入框使用所选模板或分组的 fields
提交字段使用 fields[].label 作为字段名,最简单
公司名称、税号和签署日期不用提交。 这些资料由合同服务器根据所选企业自动填写。目录中没返回的字段不要提交。

第二步:提交生成

接口地址固定为 POST /api/v1/generate。单个模板和整个分组只能选择一种。

生成单个模板
生成整个分组

请求规则

参数规则
templateName单个生成时必填,必须和目录名称完全一致
groupName整组生成时必填,必须和目录名称完全一致
companyName必填,必须和目录中的企业名称完全一致
fields必填;没有需要填写的字段时传空对象 {}
outputFormatpdfimage,不传时默认 PDF
Idempotency-Key请求头;使用你自己的订单号,同一笔业务重试时不能更换
受理成功
{
  "mode": "group",
  "groupName": "腾讯",
  "companyName": "示例文化科技有限公司",
  "results": [
    { "jobId": "job_example_1", "status": "queued" },
    { "jobId": "job_example_2", "status": "queued" }
  ],
  "total": 2,
  "alreadyExists": false
}

202 表示新任务已受理;200alreadyExists=true 表示相同幂等键的任务已经存在。两种情况都继续使用响应中的任务编号。

第三步:等待结果

遍历生成响应中的全部 jobId。建议等待 1 秒、2 秒、4 秒,然后每 5 秒查询一次。

查询任务
queued:排队中running:生成中succeeded:成功failed:失败
状态处理方式
queued继续等待,不要重复提交生成
running继续等待,不要重复提交生成
succeeded遍历响应中的 files 并领取全部文件
failed停止轮询,记录并展示 errorMessage
成功任务响应
{
  "id": "job_example_1",
  "status": "succeeded",
  "outputFormat": "pdf",
  "errorMessage": null,
  "files": [
    {
      "id": "file_example_1",
      "fileName": "示例剧目-合同成品.pdf",
      "mimeType": "application/pdf",
      "fileSize": 245812
    }
  ]
}

第四步:领取成品

每个成品文件只能成功领取一次。 服务器完整发送响应后立即删除文件,不需要另行确认。传输中断时文件会保留,可重新请求。
按文件编号领取
  • PDF 通常只有一个文件,图片格式可能有多个 PNG 文件。
  • 必须遍历每个成功任务的 files,再逐个领取。
  • 不要先试下载再正式下载,试下载也会消耗唯一一次领取机会。
  • 不要只调用任务下载地址处理多页图片,否则可能只拿到第一页。
  • 同一文件正在发送时,重复请求返回 409;等待当前请求结束后再决定是否重试。
  • 未领取文件最长保留 30 天;领取后立即从服务器删除。

报错怎么处理

状态码常见原因直接处理
400缺字段、字段名错误、同时传模板和分组、企业资料缺税号error 修正;企业资料缺失时联系管理员补资料
401授权码错误、停用、过期或已重置停止请求,换管理员提供的新授权码
403名称不存在、已改名、未授权或格式不允许立即重新拉目录;目录中没有就不能使用
404任务不存在,或成品已被领取检查任务编号;已领取文件不能恢复下载
409名称重复、幂等任务不完整,或同一文件正在发送按错误信息处理;文件发送中应等待当前请求结束
429一分钟请求超过 10 次,或生成额度用完Retry-After 等待;额度用完联系管理员
500服务器临时错误使用原来的幂等键重试,不能换新键

需要反馈问题时一次性提供这些信息

问题信息模板
发生时间:
调用接口:
HTTP 状态码:
响应 error:
任务 jobId:
模板名或分组名:
企业名称:
授权码前 7 位:

不要发送完整授权码。

权限更新

管理员新增模板、改名、改字段、调整企业权限或停用内容后,目录接口会立即反映最新结果。

  • 打开生成页面时重新拉取目录。
  • 页面长时间打开时,每 60 秒刷新一次目录。
  • 生成返回 403 时,立即刷新目录,不要继续提交旧名称。
  • 可以保存响应头 ETag,下次携带 If-None-Match;返回 304 表示目录没变。
  • 授权码停用、到期或重置后,下一次请求直接返回 401。

安全边界

接口能看到

  • 当前授权的模板名称和分组名称。
  • 当前授权的企业名称和需要填写的字段。
  • 自己的任务状态、错误信息和合同成品。

接口看不到

  • 模板内容、模板源文件和内部模板编号。
  • 原始印章文件、印章路径和盖章坐标。
  • 企业税号、账号、印章配置和服务器路径。
  • 可编辑的 DOCX 成品。

成品合同中的印章本来就会显示,收件人可以截图或裁剪;系统只能保护原始印章文件不被接口下载。

旧版兼容

旧系统仍可使用 POST /api/v1/generation-jobs/batchcombinationIdcompanyId。新接入不要使用旧编号,统一调用 POST /api/v1/generate 并传名称。