LogoSignFastAi
  • 功能
  • 价格
  • 博客
  • API

API 参考文档

通过程序化方式从你的 SignFastAi 模板发送文档。

SignFastAi 对外 API 可以让你从已保存的模板(仪表盘中的"我的模板")创建并发送文档、查询文档的签署状态、下载最终签署完成的 PDF——全程无需打开浏览器。它是为自动化场景设计的(Zapier 之类的脚本、你自己的工具),用于从其他系统触发签署请求。

概览

可用范围

对外 API 是 Pro / Lifetime 专属功能。每个接口都需要来自这两种套餐账号的有效 API 密钥。

基础地址

所有接口都在以下地址下:

https://<your-domain>/api/v1

将 <your-domain> 替换为你访问 SignFastAi 时使用的域名。

快速示例

curl https://<your-domain>/api/v1/presets \
  -H "x-api-key: YOUR_API_KEY"

暂不支持的内容

这是一个刻意保持精简的接口集——创建/发送、查询状态、下载。目前还没有管理模板、客户或现场签署会话本身的接口;这些操作暂时只能在仪表盘中完成。

身份认证

创建密钥

  1. 登录后打开 设置 → API 密钥(/settings/apikeys)。此页面需要 Pro 或 Lifetime 套餐——免费套餐账号会看到升级提示。
  2. 点击创建 API 密钥并为其命名。
  3. 复制对话框中显示的密钥值。之后你也可以随时在 API 密钥列表里再次显示和复制它(密钥列里的眼睛和复制图标),不必先另外保存。如果密钥泄露,请删除它并重新创建一个。

使用密钥

在每个请求中通过 x-api-key 请求头携带密钥:

curl https://<your-domain>/api/v1/presets \
  -H "x-api-key: YOUR_API_KEY"

不支持 Authorization: Bearer 方式——请使用 x-api-key。

速率限制

每个密钥限制为每 24 小时滚动窗口内 1000 次请求。这只是一个防滥用的兜底限制,并不是你真正的发送额度——你每月实际能发送的文档数量由你的套餐决定(见发送额度),与此处的请求速率上限相互独立。超出限制会返回 429——见错误代码。

认证错误

状态码错误码含义
401MISSING_API_KEY未发送 x-api-key 请求头
401INVALID_API_KEY(或其他密钥相关错误码)密钥不存在、已被撤销或格式不正确
403UPGRADE_REQUIRED密钥有效,但所属账号的套餐不包含 API 权限
429RATE_LIMITED当前 24 小时窗口内请求次数过多

模板

列出你的模板

GET /api/v1/presets

返回你账号下保存的每一个模板(内部称为 "preset"),以及模板的签署角色。在调用 POST /api/v1/documents 之前你需要先查询这个接口——收件人是通过角色的 id 来匹配角色的,而不是通过角色的显示名称,所以你需要先在这里查到对应的 ID。

为什么用角色 ID 而不是角色名称来匹配? 同一个模板上的两个角色可能共用同一个显示名称(例如两个都叫"签署人"的角色)。ID 始终唯一,因此不会出现收件人被分配到哪个角色不明确的情况。

模板返回结果

{
  "success": true,
  "data": {
    "presets": [
      {
        "id": "b3f6b6b0-...",
        "title": "Freelance Agreement",
        "roles": [
          {
            "id": "0e2b0f2e-...",
            "role": "Client",
            "requireAccessCode": false
          },
          {
            "id": "9a1c9d3f-...",
            "role": "Witness",
            "requireAccessCode": true
          }
        ]
      }
    ]
  }
}
  • roles 的顺序与模板中签署人的签署顺序一致。
  • requireAccessCode: true 表示分配到该角色的收件人在发送文档时必须同时提供 accessCode——见访问码。

该接口不做分页——每个账号的模板数量都很少(免费套餐上限为 1 个;该接口本身也要求 Pro/Lifetime 套餐)。

文档

创建并发送

POST /api/v1/documents

从模板创建一份文档并立即发送——作为本次调用的一部分,每位收件人都会收到签署链接邮件(除非模板开启了顺序签署,此时只会通知第一位签署人;其余签署人会在前一位完成后自动收到通知,与在仪表盘中发送的行为一致)。

请求体

{
  "presetId": "b3f6b6b0-...",
  "title": "Freelance Agreement — Acme Corp",
  "recipients": [
    {
      "roleId": "0e2b0f2e-...",
      "name": "Jane Client",
      "email": "jane@acme.example"
    },
    {
      "roleId": "9a1c9d3f-...",
      "name": "Bob Witness",
      "email": "bob@acme.example",
      "accessCode": "4471"
    }
  ]
}
字段是否必填说明
presetId是来自 GET /api/v1/presets
title否覆盖该文档使用的模板标题
recipients是模板上每个角色对应一条记录——见下方说明
recipients[].roleId是必须是属于 presetId 的角色 ID
recipients[].name是
recipients[].email是
recipients[].accessCode视情况而定如果该角色 requireAccessCode: true 则必填

模板上的每个角色都必须、且只能对应一位收件人。API 会在创建任何内容之前完成以下校验:

  • roleId 不属于该 presetId → UNKNOWN_ROLE_ID
  • 同一个 roleId 被使用了两次 → DUPLICATE_ROLE_ID
  • 某个角色没有对应的收件人 → MISSING_ROLE_RECIPIENT
  • 需要访问码的角色未提供(或提供了空值)accessCode → ACCESS_CODE_REQUIRED

完整的错误返回格式见错误代码。

访问码

与仪表盘的批量发送功能不同(该功能只支持单角色模板,且会拒绝需要访问码的模板),API 支持多角色模板,并允许你直接提供每位收件人的访问码——由于没有 UI 环节来收集访问码,这部分信息必须由你自己提供。

发送额度

在创建文档之前,API 会检查你所在套餐的月度发送额度(与仪表盘发送时执行的检查相同)。如果发送这份文档会超出额度,会返回 409 SIGN_LIMIT_EXCEEDED,且不会创建任何内容。

创建返回结果

{
  "success": true,
  "data": {
    "documentId": "c1d2e3f4-...",
    "status": "sent",
    "signers": [
      {
        "id": "...",
        "name": "Jane Client",
        "email": "jane@acme.example",
        "role": "Client",
        "status": "sent",
        "signingUrl": "https://<your-domain>/sign/s/..."
      },
      {
        "id": "...",
        "name": "Bob Witness",
        "email": "bob@acme.example",
        "role": "Witness",
        "status": "pending",
        "signingUrl": null
      }
    ]
  }
}

signingUrl 只会在本次调用中被通知到的签署人身上有值——如果某位签署人还在顺序签署的队列中排队等待,则为 null(轮到他们时会拿到真实链接并收到通知)。

查询状态

GET /api/v1/documents/:id

返回文档当前的状态以及每位签署人的状态/时间戳。如果文档不存在或属于其他账号,都会返回 404(错误码 DOCUMENT_NOT_FOUND)——API 不会透露具体是哪种情况。

{
  "success": true,
  "data": {
    "id": "c1d2e3f4-...",
    "title": "Freelance Agreement — Acme Corp",
    "status": "sent",
    "sentAt": "2026-09-23T09:00:00.000Z",
    "completedAt": null,
    "signers": [
      {
        "id": "...",
        "name": "Jane Client",
        "email": "jane@acme.example",
        "role": "Client",
        "status": "viewed",
        "viewedAt": "2026-09-23T09:05:00.000Z",
        "signedAt": null,
        "declinedAt": null,
        "declineReason": null
      }
    ]
  }
}

下载已签署的 PDF

GET /api/v1/documents/:id/download

只有当 status 为 completed 时才可下载。直接返回最终的 PDF 文件(Content-Type: application/pdf),而不是 JSON 格式的返回体。在此之前调用会返回 409 DOCUMENT_NOT_COMPLETED。

签署后的 PDF 是在原文档基础上追加了一页签署证书。响应头说明:

  • Content-Disposition——原始文件名(文件名含非 ASCII 字符时,filename* 里带有 UTF-8 编码的文件名)。
  • X-Document-Sha256——文件的 SHA-256 值,可用来校验下载内容没有被篡改或截断。

从存储服务读取文件偶尔会临时失败(502 STORAGE_FETCH_FAILED,或 500)——直接重试即可,是安全的。

Webhook

无需再轮询 GET /documents/{id}:注册一个地址,你的任何文档(无论是通过 API、后台还是批量发送创建的)一有变化,我们就会向它 POST 一个事件。

在 设置 → API 密钥 → Webhook 中管理。最多可添加 5 个地址,每个地址可选择要接收的 事件,可以发送测试事件,并能查看 30 天内的每一次投递(包括对方返回的结果)。 Webhook 是 Pro / Lifetime 专属功能。

事件

事件触发时机
document.sent文档已发出待签署
signer.viewed签署人打开了文档
signer.signed某位签署人完成签署
document.completed所有签署人都已签署,最终 PDF 已可下载
document.declined某位签署人拒绝签署

document.completed 只会在最终 PDF 生成之后才发送,所以收到后就可以立刻调用 GET /documents/{id}/download。

请求内容

每个请求是带 JSON 正文的 POST:

{
  "id": "evt_2f6c1b0e-7a1d-4a55-9a52-2f7c0f8f1a11",
  "type": "document.signed",
  "createdAt": "2026-09-24T09:15:02.000Z",
  "data": {
    "document": {
      "id": "0b0c7a4e-...",
      "title": "服务协议 — Acme",
      "status": "sent",
      "createdVia": "api",
      "sentAt": "2026-09-24T09:10:00.000Z",
      "completedAt": null,
      "finalFileHash": null,
      "signers": [
        { "id": "…", "name": "Ada Lovelace", "email": "ada@example.com", "status": "signed" }
      ]
    },
    "signer": { "id": "…", "name": "Ada Lovelace", "email": "ada@example.com", "status": "signed" }
  }
}

signer.* 事件才会带 data.signer。同一个事件可能被多次投递(例如重试之后), 请把 id 当作幂等键。

校验签名

每个请求都带有以下请求头:

请求头值
X-SignFast-Signaturet=<Unix 秒>,v1=<十六进制 HMAC-SHA256>
X-SignFast-Event事件类型,如 document.completed
X-SignFast-Delivery本次投递的唯一 ID

签名是 HMAC-SHA256(secret, "<t>.<原始请求正文>"),其中 secret 是该地址的签名密钥 (创建时显示,之后随时可在地址列表中查看)。请对原始正文计算,用恒定时间比较, 并拒绝时间戳偏差超过几分钟的请求:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(secret, header, rawBody) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
  const expected = createHmac('sha256', secret)
    .update(`${parts.t}.${rawBody}`)
    .digest('hex');
  const a = Buffer.from(expected);
  const b = Buffer.from(parts.v1 ?? '');
  return a.length === b.length && timingSafeEqual(a, b);
}

投递与重试

请在 8 秒内返回任意 2xx 状态码表示已收到。其他状态码(或超时)都算失败:我们会在约 5 秒后和约 30 秒后各重试一次,之后将该次投递标记为失败。失败的投递可以在后台重新发送。 不会跟随重定向。

地址必须是 https:// 且公网可访问——内网地址、localhost 和云元数据网段会被拒绝。

调用记录

使用你的 API 密钥发出的每一次请求(方法、路径、状态码、错误码、耗时)都会被记录, 并显示在 设置 → API 密钥 → 调用记录 中,可按密钥和成功/出错筛选,保留 30 天。 API 密钥列表还会显示每个密钥的最近使用时间和近 30 天的调用次数;通过 API 创建的文档会在文档列表里带上 “API” 标记。

用量统计 标签会按小时(最近 24 小时)或按天(7 / 30 天)画出请求数图表,区分成功、客户端错误和服务端错误,并给出响应时间以及按接口、按密钥的分布。调用记录可以导出为 CSV;你还可以开启错误告警:最近一小时的失败率超过你设定的阈值时,我们会发邮件通知你(每 6 小时最多一封)。

错误代码

返回体格式

所有 JSON 返回(除了 PDF 下载接口)都使用相同的返回体格式:

{ "success": true, "data": { /* ... */ } }
{
  "success": false,
  "error": {
    "code": "MISSING_ROLE_RECIPIENT",
    "message": "Every template role needs a recipient",
    "details": { "missingRoleIds": ["9a1c9d3f-..."] }
  }
}

details 字段只会出现在那些有程序化可操作信息的错误里(比如具体是哪些角色 ID 出了问题、你的套餐额度是多少等)——建议先检查 details,再回退到解析 message。

错误码一览

状态码错误码出现位置含义
401MISSING_API_KEY所有接口未发送 x-api-key 请求头
401INVALID_API_KEY(或类似错误码)所有接口密钥不存在、已被撤销或格式不正确
403UPGRADE_REQUIRED所有接口密钥有效,但账号不是 Pro/Lifetime 套餐
429RATE_LIMITED所有接口该密钥在过去 24 小时内请求次数超过 1000 次
400INVALID_BODYPOST /documents请求体未通过校验
404PRESET_NOT_FOUNDPOST /documentspresetId 不存在或不属于你
400UNKNOWN_ROLE_IDPOST /documentsroleId 不属于该模板
400DUPLICATE_ROLE_IDPOST /documents同一个 roleId 被用于两位收件人
400MISSING_ROLE_RECIPIENTPOST /documents某个模板角色没有对应收件人
400ACCESS_CODE_REQUIREDPOST /documents需要访问码的角色缺少 accessCode
409SIGN_LIMIT_EXCEEDEDPOST /documents发送这份文档会超出套餐的月度发送额度
404DOCUMENT_NOT_FOUNDGET /documents/:id、.../download文档不存在或不属于你
409DOCUMENT_NOT_COMPLETEDGET /documents/:id/download尚未所有签署人都完成签署
502STORAGE_FETCH_FAILEDGET /documents/:id/download存储服务临时故障——请重试
500INTERNAL_ERROR所有接口服务器发生未预期的错误

目录

概览可用范围基础地址快速示例暂不支持的内容身份认证创建密钥使用密钥速率限制认证错误模板列出你的模板模板返回结果文档创建并发送请求体访问码发送额度创建返回结果查询状态下载已签署的 PDFWebhook事件请求内容校验签名投递与重试调用记录错误代码返回体格式错误码一览
LogoSignFastAi

上传、标记、发送——几分钟内完成文件签署。

X (Twitter)
产品
  • 功能
  • 价格
  • 常见问题
资源
  • 博客
  • API 文档
对比
  • vs DocuSign
  • vs Adobe Acrobat Sign
  • vs PandaDoc
  • vs Dropbox Sign
  • vs SignWell
  • vs DocuSeal
公司
  • 关于我们
  • 联系我们
法律
  • Cookie政策
  • 隐私政策
  • 服务条款
Listed on Turbo0Featured on Findly.toolsFeatured on Twelve ToolsFeatured on Saasgrave LaunchesFazier badgeFeatured on TheDevToolsList
© 2026 SignFastAi. All Rights Reserved.