跳转至主要内容
Certyneo
公开 API v1

将电子签名集成到您的技术栈

发送信封、跟踪签名、接收 webhooks。简单的 REST API、OpenAPI 3.0、curl/Node/Python 示例 — 所有内容都可在数小时内将 Certyneo 连接到您的 HRIS、CRM 或业务软件。

快速开始

三个步骤:从参数设置中创建 API 密钥,将您的 PDF 编码为 base64,然后发送。响应包含 `signUrl`,您可以直接与收件人分享。

cURLbash
# 1. Upload the PDF (multipart) and capture the returned document id.
DOC_ID=$(curl -s -X POST https://certyneo.com/api/v1/documents \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -F "file=@contrat.pdf" | jq -r .id)

# 2. Create a DRAFT envelope referencing the uploaded document.
ENV_ID=$(curl -s -X POST https://certyneo.com/api/v1/envelopes \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d "{
    \"subject\": \"Contrat de prestation\",
    \"documentIds\": [\"$DOC_ID\"],
    \"recipients\": [
      { \"email\": \"client@example.com\", \"name\": \"Marie Dubois\", \"role\": \"SIGNER\" }
    ]
  }" | jq -r .id)

# 3. Dispatch the envelope — this sends the invitation email/SMS.
curl -X POST https://certyneo.com/api/v1/envelopes/$ENV_ID/send \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"
JavaScript / Nodets
// Plain fetch, no SDK to install.
const auth = { Authorization: `Bearer ${process.env.CERTYNEO_API_KEY}` };

// 1. Upload the PDF (multipart).
const fd = new FormData();
fd.append("file", new Blob([pdfBuffer], { type: "application/pdf" }), "contrat.pdf");
const doc = await fetch("https://certyneo.com/api/v1/documents", {
  method: "POST", headers: auth, body: fd,
}).then((r) => r.json());

// 2. Create the DRAFT envelope.
const envelope = await fetch("https://certyneo.com/api/v1/envelopes", {
  method: "POST",
  headers: { ...auth, "Content-Type": "application/json" },
  body: JSON.stringify({
    subject: "Contrat de prestation",
    documentIds: [doc.id],
    recipients: [
      { email: "client@example.com", name: "Marie Dubois", role: "SIGNER" },
    ],
  }),
}).then((r) => r.json());

// 3. Dispatch — this triggers the invitation channel for every recipient.
await fetch(`https://certyneo.com/api/v1/envelopes/${envelope.id}/send`, {
  method: "POST", headers: auth,
});
console.log(envelope.id);
Pythonpython
import os, requests

auth = {"Authorization": f"Bearer {os.environ['CERTYNEO_API_KEY']}"}

# 1. Upload the PDF (multipart).
with open("contrat.pdf", "rb") as f:
    doc = requests.post(
        "https://certyneo.com/api/v1/documents",
        headers=auth,
        files={"file": ("contrat.pdf", f, "application/pdf")},
    ).json()

# 2. Create the DRAFT envelope.
envelope = requests.post(
    "https://certyneo.com/api/v1/envelopes",
    headers={**auth, "Content-Type": "application/json"},
    json={
        "subject": "Contrat de prestation",
        "documentIds": [doc["id"]],
        "recipients": [
            {"email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER"},
        ],
    },
).json()

# 3. Dispatch — this triggers the invitation channel for every recipient.
requests.post(
    f"https://certyneo.com/api/v1/envelopes/{envelope['id']}/send",
    headers=auth,
)
print(envelope["id"])

从您的工具尝试 API

Postman 集合和 RapidAPI 卡片从记录此页面的 OpenAPI 规范生成。这三者保持与真实 API 对齐,逐端点对齐,而不是在第一次添加时分散。

Postman集合

25个请求按域名整理——信封、文档、模板、印章、webhooks——每个都包含请求体和响应示例。将您的密钥粘贴到集合中的apiKey变量,然后运行GET /health:它不需要认证,可确认您的配置在第一次认证调用前是否正确。

RapidAPI信息页

相同的端点目录,可直接从浏览器测试。测试工具需要两个不同的请求头:RapidAPI平台分配给您的密钥,以及您的Certyneo密钥(在Authorization中)——第二个才是真正授权调用的。

信封

创建、发送、状态跟踪、取消。一个信封可以包含多个文档和多个签署人(并行或顺序)。

网络钩子

所有信封和收件人事件(`envelope.sent`、`recipient.signed`、`envelope.completed` 等)都交付到您选择的 URL——完整列表见 /developers/webhooks。每个 payload 上使用 HMAC SHA-256 验证来源。

简单身份验证

Bearer 令牌。每个环境一个密钥(测试/生产)。可以立即撤销。限制为每个密钥每分钟 100 个请求,突发 200 个,干净的 429 响应带有 Retry-After 标头。

可用端点

53 条公开路由:账户、文档、信封、模板、webhooks、电子印章、API 密钥和计费。所有这些都接受 Bearer token 并返回 JSON。

方法路径描述
GET/api/v1/account/me已认证的调用者身份(id、电子邮件、套餐):不需要作用域的身份标识符测试
GET/api/v1/sandbox统计使用测试密钥创建的数据(30 天后自动删除)
DELETE/api/v1/sandbox删除使用测试密钥创建的所有数据,不影响真实数据
POST/api/v1/documents上传 PDF(multipart):返回文档 id
GET/api/v1/documents列出文档
GET/api/v1/documents/{id}读取文档元数据
DELETE/api/v1/documents/{id}删除文档
GET/api/v1/envelopes列出信封(使用 ?status= 和 ?limit= 过滤)
POST/api/v1/envelopes创建信封(状态为 DRAFT):从 templateId 或 documentIds 加上可选的 fields 数组创建
GET/api/v1/envelopes/{id}读取信封状态
PATCH/api/v1/envelopes/{id}修改 DRAFT 信封
DELETE/api/v1/envelopes/{id}删除 DRAFT 信封(发送后返回 409:改为取消)
POST/api/v1/envelopes/{id}/send发送 DRAFT 信封:发送邀请
POST/api/v1/envelopes/{id}/void取消已发送但尚未完全签署的信封:待处理的签署人将收到通知
POST/api/v1/envelopes/{id}/remind根据请求重新提醒等待已发送信封的签署人(可选指定一个收件人)
GET/api/v1/envelopes/{id}/audit-trail下载 eIDAS 审计日志 PDF
POST/api/v1/envelopes/{id}/embed-url返回收件人的签署URL,并为所请求的来源提供框架授权。应在点击时调用:授权有效期为两小时。
GET/api/v1/audit-anchors/{root}公开:已锚定的审计批次元数据,或使用 ?format=ots 的证明文件 .ots(无需认证)
POST/api/v1/audit-anchors/verify公开:验证审计条目及其证明与已锚定的 Merkle 根(无需认证,不透露任何信息)
GET/api/v1/envelopes/{id}/signed-document下载已签署的 PDF(COMPLETED 后)
GET/api/v1/envelopes/bulk列出您的批量发送
POST/api/v1/envelopes/bulk批量发送:从模板和 CSV 创建 N 个信封(仅限标准/商业版)
GET/api/v1/envelopes/bulk/{id}批量发送进度:计数器、每行失败、已创建的信封
GET/api/v1/templates列出可重复使用的信封模板
POST/api/v1/templates创建模板(文件、角色、定位字段)
GET/api/v1/workspaces列出您可以在其中创建信封的工作空间
POST/api/v1/sepa-mandates生成 SEPA 授权书的 PDF 及其 DRAFT 信封、字段已放置
POST/api/v1/payroll-adapters/normalize将工资单 CSV(Silae、Sage Paie、PayFit、Lucca)标准化为批量发送格式
POST/api/v1/ag-copropriete创建共有产权业主大会信封(决议和产权份额)
POST/api/v1/ag-copropriete/{envelopeId}/votes记录共有产权人在大会决议上的投票
POST/api/v1/ag-copropriete/{envelopeId}/tally开票大会:按决议的结果、按产权份额加权
GET/api/v1/videos/{videoId}下载保留的身份验证视频:RGPD 访问权(第 15 条)
GET/api/v1/webhooks列出 webhook
POST/api/v1/webhooks注册 webhook:仅返回一次签名密钥
GET/api/v1/webhooks/{id}读取 webhook 订阅
PATCH/api/v1/webhooks/{id}修改 URL、事件或活跃状态
DELETE/api/v1/webhooks/{id}取消注册 webhook
POST/api/v1/seals在文件上应用合格电子印章
GET/api/v1/seals/{id}读取印章状态
GET/api/v1/seals/{id}/certificate下载印章证书
GET/api/v1/payslips/workspaces工资单:此密钥分配、由客户持有或委托的空间(会计事务所、工资管理公司)
GET/api/v1/payslips/employees工资单:员工登记册,包括那些拒绝电子交付的员工(应交付纸质工资单)
PUT/api/v1/payslips/employees工资单:添加或更新员工登记簿中的员工(从不删除)
POST/api/v1/payslips将工资单(PDF)提交到员工的保险箱中:密封、保存50年、重试无重复
GET/api/v1/payslips列出已提交的工资单及其查阅证明
GET/api/v1/keys列出API密钥
POST/api/v1/keys创建API密钥:密钥仅显示一次
PATCH/api/v1/keys/{id}重命名或撤销密钥
DELETE/api/v1/keys/{id}删除密钥
GET/api/v1/billing/usage当前期间的消耗量和预计成本
GET/api/v1/status服务状态
GET/api/v1/health健康检查:数据库、队列和对象存储
GET/api/v1/openapi机器可读的OpenAPI规范

信封模板

模板一次性记录 PDF、角色和签名字段的位置,然后在每次发送时重用:在 templateId 中传递其标识符而不是 documentIds,已定位的字段会被复制到创建的信封上。

  • • 模板从仪表板创建(模板 → 新建模板),您可以在其中上传文档然后用鼠标定位字段——这是最简单的方法。API 也允许通过 POST /api/v1/templates 创建模板,提供文档、角色和字段;注意,字段在其中用绝对坐标定位(页、x、y、宽、高),因此您需要了解 PDF 的页面布局。
  • • 在尚未记录任何模板的账户上,GET /api/v1/templates 返回空列表。这是正常行为,不是身份验证缺陷。
  • • 列表仅包含属于 API 密钥所有者的模板。由同事创建的模板不会出现在其中,即使在共享工作区内:请从拥有该模板的账户生成密钥。
  • • templateId 和 documentIds 互相排斥:发送其中之一,永远不要同时发送两者或都不发送。
  • • 至少提供与模板签署人角色数量相等的 SIGNER 收件人,否则创建会被拒绝并返回 400。列表返回的 signerCount 字段指示预期数量。
  • • 模板的签名级别被信封继承,除非请求明确传递 signatureLevel。
cURLbash
# 1. Discover the templates saved on this account.
curl -s https://certyneo.com/api/v1/templates \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

# {
#   "data": [
#     { "id": "cmdq7f4k80001s6y2h1xa9pl3", "name": "Contrat de prestation",
#       "signerCount": 2, "documentCount": 1, "signatureLevel": "SIMPLE" }
#   ],
#   "pagination": { "page": 1, "pageSize": 20, "total": 1, "pages": 1 }
# }
#
# An empty "data" array means no template exists on this account yet —
# create one from the dashboard, it is not an authentication problem.

# 2. Create the envelope FROM the template: no documentIds and no field
#    coordinates, both are carried by the template. Pass one SIGNER
#    recipient per signer role, in the template's role order.
curl -X POST https://certyneo.com/api/v1/envelopes \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Contrat de prestation",
    "templateId": "cmdq7f4k80001s6y2h1xa9pl3",
    "recipients": [
      { "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" },
      { "email": "legal@example.com", "name": "Paul Martin", "role": "SIGNER" }
    ]
  }'

# 3. The envelope is DRAFT at this point — POST /envelopes/{id}/send
#    dispatches it, exactly as in the quick-start above.

从 Power Automate 或 Zapier

我们无代码连接器中的"创建信封"操作仅涵盖模板路径:"模板"字段为必填项。对于每次执行都变化的临时文档,请使用"上传文档"操作,然后使用原始 HTTP 操作调用 POST /api/v1/envelopes,传递返回的 documentIds。

文档发送:接受两种形式

POST /api/v1/documents 接受文件的两种方式(可任选)。两种情况下适用相同的控制:允许的类型、50 MB 上限、二进制签名验证和防病毒分析。

  • • 以 multipart/form-data 形式,使用名为 file 的部分。这是经典形式,也是 curl -F 和大多数库的形式。
  • • 原始正文:文件的字节构成请求正文,Content-Type 标头给出其类型(例如 application/pdf)。从传递内容原样而不包装请求的工具中很有用——这就是 Power Automate 连接器所做的。
  • • 在原始正文中,文件名在正文中没有位置:通过 X-File-Name 标头或 ?fileName= 参数指定它。没有它,文档按其类型命名。
  • • 不支持的类型以 415 响应,并命名两种接受的形式;声称为 multipart 但无法读取的正文以 400 响应。两者都不是服务器错误。
cURLbash
# a. multipart/form-data — the classic shape.
curl -X POST https://certyneo.com/api/v1/documents \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -F "file=@contrat.pdf;type=application/pdf"

# b. raw body — the file bytes ARE the body, typed by Content-Type.
#    The filename has nowhere to live in the body, so pass it as a header
#    (or ?fileName=). Without it the document is named after its type.
curl -X POST https://certyneo.com/api/v1/documents \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/pdf" \
  -H "X-File-Name: contrat.pdf" \
  --data-binary "@contrat.pdf"

# Both return the same 201 with the document id to pass as documentIds.

签名字段的放置

在没有模板的情况下,从 documentIds 创建的信封没有预先定位的字段:签署人收到的文档中没有签名位置。fields 数组在同一创建调用中传递,精确放置每个字段——这是 API 端的等效操作,相当于模板一次性记录的内容。

  • • 坐标以 PDF 点为单位,原点在页面左上角,Y 轴向下(A4 页面尺寸为 595 × 842 点)。x 和 y 指定字段的左上角,width 和 height 指定其大小。
  • • pageNumber 从 1 开始,documentIndex 从 0 开始。超出文档范围的页码在创建时不会被拒绝:该字段在签署时被忽略,不会出现在任何地方——当字段缺失时,这是首先要检查的地方。
  • • recipientEmail 必须与同一调用中的一个收件人匹配,不区分大小写。否则创建会失败,并列出所有有问题的行,这样可以避免逐个更正。
  • • fields 和 templateId 相互排斥:模板已经具有自己的布局。因此 fields 数组仅与 documentIds 一起使用。
  • • 接受的类型:SIGNATURE、INITIALS、DATE_SIGNED、TEXT、CHECKBOX 和 RADIO_GROUP。required 默认为 true;placeholder 和 dateFormat 是可选的,options 仅对 RADIO_GROUP 进行处理。
  • • 一个信封最多接受 100 个字段、20 个文档和 50 个收件人——您的计划限制可能更低。
cURLbash
# Ad-hoc envelope WITH pre-placed fields — no template involved.
# Coordinates are PDF points, origin TOP-LEFT of the page, +Y downwards
# (A4 = 595 x 842 pt). x / y are the field box's top-left corner.
#
# The last field is positioned by ANCHOR instead of by eye: the server
# locates "Signature du client" in the PDF and computes the spot. x / y
# stay required there — they are the fallback if the text is not found.
curl -X POST https://certyneo.com/api/v1/envelopes \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Contrat de prestation",
    "documentIds": ["cmdq7f4k80001s6y2h1xa9pl3"],
    "recipients": [
      { "email": "client@example.com", "name": "Marie Dubois", "role": "SIGNER" }
    ],
    "fields": [
      { "recipientEmail": "client@example.com", "documentIndex": 0,
        "pageNumber": 2, "fieldType": "SIGNATURE",
        "x": 90, "y": 640, "width": 180, "height": 44 },
      { "recipientEmail": "client@example.com", "documentIndex": 0,
        "pageNumber": 2, "fieldType": "DATE_SIGNED",
        "x": 320, "y": 640, "width": 140, "height": 30,
        "dateFormat": "DD/MM/YYYY" },
      { "recipientEmail": "client@example.com", "documentIndex": 0,
        "pageNumber": 2, "fieldType": "TEXT",
        "x": 90, "y": 700, "width": 200, "height": 30,
        "placeholder": "Fonction", "required": false },
      { "recipientEmail": "client@example.com", "documentIndex": 0,
        "pageNumber": 2, "fieldType": "SIGNATURE",
        "anchorText": "Signature du client", "anchorPlacement": "below",
        "anchorIndex": 0,
        "x": 90, "y": 640, "width": 180, "height": 44 }
    ]
  }'

# The envelope is DRAFT at this point — POST /envelopes/{id}/send
# dispatches it, exactly as in the quick-start above.

文本锚点:在不知道坐标的情况下放置字段

字段可以引用打印在文档中的文本,而不是坐标:anchorText 在 PDF 中查找它,服务器在创建时计算位置。当文档在每次发送时重新生成时,这是首选方法——邮件合并、合同生成器——因为布局会变化,但"客户签名"的措辞仍然保留。anchorPlacement 表示字段相对于文本的哪一侧放置(默认为 right,也可以是 below、above 或 left),anchorIndex 在文本出现多次时选择出现次数。

即使使用锚点,x 和 y 仍然是必需的:它们充当备用值。找不到锚点不会导致创建失败——该字段保留您提供的字面位置,响应中没有错误或警告。因此请提供可能的备用值而不是 0,0,并在首次发送时验证呈现。

集成签名:无需离开应用程序即可签署

您的客户从您自己的界面查看和签署文件。签署流程在您页面上方的窗口中打开,完成后自动返回到您的页面。在服务器端,没有什么新的:您像往常一样通过填写redirectUrl来创建信封,然后将签署URL交给SDK进行处理。

  • • 直接在您的点击处理程序中调用Certyneo.sign(),并通过getUrl传递您的服务器调用。在sign()前使用await会退出用户操作:Safari和Firefox随后会阻止该窗口。SDK会立即打开它,并在您的承诺解决时加载它。
  • • redirectUrl 是返回通道。我们通过添加 certyneo_status(completed 或 declined)和 certyneo_envelope 将签署人重定向到该地址。在此返回页面上加载相同的脚本:正是这个脚本会通知在后台保持打开的门户窗口。
  • • 在嵌入式模式下,我们自己的操作号召会被禁用。您的客户永远不会看到创建 Certyneo 账户的邀请。
  • • 如果浏览器拒绝打开窗口,SDK 会自动切换到全页重定向。签署人的流程保持相同,您的返回页面接收的参数完全相同。
  • • 按设计,不存在"用户已放弃"的回调:从您的页面无法读取窗口的状态,这样的回调会被错误地触发。未完成的签名会保持待处理状态,直到 webhook 到达。
JavaScriptjavascript
// 1. Your server creates and sends the envelope, then hands the browser the
//    recipient's signing URL. Nothing new on the API side:
//      POST /api/v1/envelopes        { …, "redirectUrl": "https://your-app.com/quote/42/signed" }
//      POST /api/v1/envelopes/{id}/send   → recipients[].accessToken
//      signingUrl = "https://certyneo.com/sign/" + accessToken

// 2. On your quote page — load the SDK once:
//      <script src="https://certyneo.com/embed.js"></script>

document.querySelector("#sign").addEventListener("click", () => {
  Certyneo.sign({
    // Called AFTER the window is already open, so no popup blocker ever
    // sees a delay between the click and window.open.
    getUrl: () =>
      fetch("/api/quote/42/signature", { method: "POST" })
        .then((r) => r.json())
        .then((d) => d.signingUrl),

    onCompleted: (e) => showConfirmation(e.envelopeId),
    onDeclined: () => showDeclined(),
    onError: (e) => showError(e),
  });
});

// 3. On https://your-app.com/quote/42/signed — your return page — load the
//    same script and render a short confirmation. It relays the outcome to
//    the portal window behind it, then closes itself.

浏览器事件不是签名证明

onCompleted 是一个显示信号,由浏览器发出,因此任何人都可以从其控制台伪造。永远不要基于此将文件切换为"已签署":使用它来刷新屏幕,并依靠您的服务器接收的已签署 envelope.completed webhook 来获取实际状态。这是支付集成的经典陷阱,在这里也完全相同。

在您的工作站上开发

使用测试密钥,redirectUrl 接受 http://localhost(和 127.0.0.1):您可以在部署前在您的机器上完成整个流程。实际密钥会拒绝它,以确保没有生产信封将真实签署人重定向到不属于他们的机器。

在您的页面中显示签署仪式

框架模式在您的界面内显示签署,无需弹窗。它比窗口模式多需一个步骤:证明将显示它的网站属于您。这可以防止第三方为了欺骗您的客户而嵌入我们的签署仪式。

  • • 在"设置"→"集成签署"中声明您的网站,然后发布指定的DNS记录。需要精确匹配地址:不同的子域或端口将被视为另一个网站。
  • • 每次签署时,向POST /api/v1/envelopes/{id}/embed-url请求一个新的URL。它携带显示授权,有效期为两小时,对应于点击时刻,而非信封创建时刻。
  • • 两种流程无法在框架内进行:合格签署(其身份验证拒绝被框架化)和签署时付款。在这两种情况下,签署人都会被引导至完整窗口。
  • • "由Certyneo提供支持"标签从商业计划及以上版本时从框架中消失。框架模式本身从标准计划开始就已包含。
JavaScriptjavascript
// Mode cadre : la cérémonie s'affiche DANS votre page.
//
// 1. Déclarez votre site une fois pour toutes dans Réglages → Signature
//    intégrée, et publiez l'enregistrement DNS qu'on vous y donne.
//
// 2. À chaque signature, votre serveur demande une URL fraîche. Elle porte
//    l'autorisation qui permet au navigateur d'afficher la cérémonie chez
//    vous, et vaut deux heures :
//
//      POST /api/v1/envelopes/{id}/embed-url
//      { "origin": "https://portail.exemple.fr" }
//      -> { "signingUrl": "…", "expiresAt": "…" }

Certyneo.sign({
  mode: "iframe",
  el: "#zone-signature",        // sélecteur ou nœud de votre page

  getUrl: () =>
    fetch("/api/devis/42/signature", { method: "POST" })
      .then((r) => r.json())
      .then((d) => d.signingUrl),

  onCompleted: (e) => afficherConfirmation(e.envelopeId),
  onDeclined: () => afficherRefus(),
});

// Le cadre parle à votre page par postMessage — pas besoin de page de retour,
// contrairement au mode fenêtre.

让某人签署而不发送任何电子邮件

在自己的门户网站上显示签署仪式的门户通常不需要我们的邀请:它出现在他自己的用户旅程旁边,并向不需要它的客户推荐一个账户。为收件人的通知渠道设置 NONE 值,这样就不会向他发送任何内容——您来负责引导他进行签署。

  • • 此设置按收件人设置,而不是按信封设置:您可以使您托管的客户保持静默,并为外部共同签署人保留电子邮件,他没有门户网站。
  • • 它仅限于签署人和批准人,这些是您唯一需要交付链接的角色。您可以在创建和发送的响应中读取它,或在点击时从 POST /api/v1/envelopes/{id}/embed-url 请求新的 URL。
  • • 自动催促会自行停止,对此收件人而言:我们从未写过信给他,我们不会以催促开始。其他收件人继续正常地接收催促。
  • • 签署证书会提及它,逐个收件人。如果证明文件在这一点上保持沉默,就会让人相信这个签署人收到了来自我们的邀请,而该邀请从未存在过。
JSONjson
POST /api/v1/envelopes

{
  "subject": "Mandat de gestion",
  "documentIds": ["doc_8f2c1a4b9e7d"],
  "recipients": [
    {
      "email": "client@exemple.fr",
      "name": "Camille Client",
      "role": "SIGNER",
      "notificationChannel": "NONE"
    },
    {
      "email": "notaire@exemple.fr",
      "name": "Maître Notaire",
      "role": "SIGNER"
    }
  ]
}

// La réponse rend le lien de chaque signataire :
//
//   "recipients": [
//     { "email": "client@exemple.fr",  "accessToken": "…",
//       "notificationChannel": "NONE"  },
//     { "email": "notaire@exemple.fr", "accessToken": "…",
//       "notificationChannel": "EMAIL" }
//   ]
//
// Le client ne reçoit rien : vous l'emmenez sur sa signature depuis votre
// portail. Le notaire, lui, reçoit son invitation comme d'habitude.

将您的客户名称显示为发件人

默认情况下,签署人会看到 API 密钥持有人的名称。如果您使用单个密钥为多个企业签署文件,请在创建信封时传递 sender 字段:签署页面和邀请及提醒电子邮件将显示相关企业的名称。

  • • 仅限商业计划及以上版本。对于较低的计划,创建将被拒绝,而不是让签署人看到与预期不同的名称。
  • • 名称是一个显示:证书和审计跟踪保留实际发件人,电子邮件始终来自 Certyneo。
  • • 地址是可选的。没有地址,签署人只会看到名称,永远看不到 API 密钥持有人的地址。
JSONjson
POST /api/v1/envelopes

{
  "subject": "Devis 2026-118",
  "documentIds": ["doc_8f2c1a4b9e7d"],
  "recipients": [
    { "email": "client@exemple.fr", "name": "Camille Client", "role": "SIGNER" }
  ],
  "sender": {
    "name": "1.2.3. Panneaux Solaires",
    "email": "devis@123-panneaux-solaires.fr"
  }
}

身份验证

每个调用在 Authorization 请求头中携带 API 密钥。密钥从设置 → API 密钥生成,仅显示一次。

HTTPhttp
GET /api/v1/account/me HTTP/1.1Host: certyneo.com
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxx

# 200 OK
{ "data": { "id": "usr_…", "email": "you@example.com", "plan": "BUSINESS", "environment": "live" } }
  • • 格式:生产环境为 sk_live_…,沙箱环境为 sk_test_…。请求头:Authorization: Bearer <密钥>。
  • • 作用域:envelopes、documents、webhooks、seals——以读取 (:read) 或写入 (:write) 模式。写入包含读取;作用域 * 授予所有权限。
  • • sk_test_ 密钥创建的沙盒资源不计入配额和账单。除非收件人地址与发送账户自己的邮箱一致,否则不会发送真实邮件——这有助于在自己身上测试完整流程。
  • • 错误:401 密钥无效,403 权限不足,429 速率限制超出,402 月度配额已达。

响应格式

编写客户端前需要了解的一点:集合被封装在data对象中,而单个资源以平面形式返回。因此在单个资源上读取 response.data.data 会返回undefined。

集合——已封装json
// GET /api/v1/envelopes
// Collections are WRAPPED in a "data" array.
{
  "data": [
    { "id": "env_abc123", "subject": "Contrat", "status": "SENT" }
  ]
}
单项资源 — 平面json
// GET /api/v1/envelopes/{id}
// Single resources are returned FLAT — no "data" envelope.
{
  "id": "env_abc123",
  "subject": "Contrat",
  "status": "COMPLETED",
  "recipients": [ /* … */ ]
}

速率限制

速率限制保证所有客户的服务质量稳定。如果您需要更多,请联系我们。

  • • 每个 API 密钥每分钟 100 个请求
  • • 允许突发到 10 秒内的 200 个请求
  • • 429 响应,带有指示延迟秒数的 Retry-After 标头

了解更多