发起一次签署
以“家长为孩子签署课程服务合同”为例:先确认人和家庭关系,再选文档、预览、发邮件,最后查询结果。所有请求都由你的后端发出,沿用快速开始中的 Base URL 和 Bearer API key。
下面是合成数据,不是真实客户记录,也不是生产响应截图。 ID 必须替换为目标组织查询得到的值;发送前确认收件邮箱是你控制的测试邮箱。示例模板文案仅说明接口结构,不能作为正式合同。
准备好哪些东西
| 准备项 | 怎么确认 |
|---|---|
| 组织 | GET /v1/me 返回预期的俱乐部 |
| 权限 | club.contacts.read、club.contacts.read_pii、club.compliance.read、club.compliance.write |
| 家长、孩子及关系 | 已在该俱乐部维护;孩子有准确生日,家长有可用邮箱 |
| 模板 | 商户已配置课程、排期、价格及附加文档规则,并发布可用版本 |
| 签后文件(可选) | 只有需要在第 5 步核对签后文件时才要 club.compliance.read_files |
本文不创建客户资料。如需补资料,使用商户后台,或新建一把带 club.contacts.write 的 key 并完成切换后调用人员接口——已有 key 的权限不可修改,见权限范围。字段分别由谁维护,见字段来源。
1. 找到家长和孩子
先调用 GET /v1/club/contacts?search=Demo&page=1&pageSize=20。列表采用家庭视图,孩子不一定单独占一行;名称和联系方式也可能脱敏。不要直接取第一条结果当签署人。
选定候选家长后,调用 GET /v1/club/contacts/{id} 核对完整资料,再调用 GET /v1/club/contacts/{id}/households 查看家庭成员。例如,家长 3101 的家庭返回:
{
"data": [
{
"id": "9900",
"name": "Demo household",
"members": [
{
"contactId": "3101",
"relation": "primary_guardian",
"firstName": "Alex",
"lastName": "Demo",
"birthday": "1985-05-06",
"roles": ["PARENT"]
},
{
"contactId": "3102",
"relation": "dependent",
"firstName": "Robin",
"lastName": "Demo",
"birthday": "2016-03-14",
"roles": ["PLAYER"]
}
]
}
]
}这里签字的人是家长 3101,合同涉及的参与者是孩子 3102。家庭记录用于核对,不是自动证明法律监护资格;有歧义时请商户确认,不要按同姓或邮箱推断关系。还应查询孩子详情,确认他属于当前俱乐部且资料完整。
如果搜索返回下面的结果,表示“本次查询未命中”,不是权限错误,也不能证明平台上不存在此人:
{
"data": [],
"meta": {
"page": 1,
"pageSize": 20,
"total": 0
}
}先调整查询或请商户核对已有资料,不要因为空结果就自动重复建人。
2. 选合同及附加文档
调用 GET /v1/club/compliance/document-templates?documentKind=service_contract&active=true。例如:
{
"data": [
{
"id": "810",
"templateKey": "demo-program-agreement",
"title": "Demo program agreement",
"documentKind": "service_contract",
"ownerScope": "tenant_group",
"groupId": "123",
"active": true,
"currentVersion": 3,
"currentVersionId": "8103",
"effectiveFrom": "2026-09-01T00:00:00.000Z",
"aiSummary": null
}
]
}再读取 GET /v1/club/compliance/document-templates/{id},核对标题、字段定义及课程配置。需要版本历史时调用 GET /v1/club/compliance/document-templates/{id}/versions。
注意三个不同的值:模板 ID 是 810,版本号是 3,版本 ID 是 8103。发送时需要版本 ID,不是前两个值。如果 currentVersionId 为 null,先请商户发布版本。
对孩子调用 POST /v1/club/compliance/signing-requests/resolve-waivers,请求体如下。这里的 contactId 指参与者,不是之后收邮件的家长:
{
"contactId": "3102",
"pdsaTemplateId": "810"
}成功时 HTTP 200,示例结果:
{
"data": {
"memberIsMinor": true,
"dobMissing": false,
"appendixMatch": "matched",
"items": [
{
"waiverTemplateKey": "demo-risk-acknowledgment",
"templateVersionId": "8201",
"documentKind": "waiver",
"title": "Demo risk acknowledgment",
"applicability": "minorOnly",
"reason": "Selected by the demo template rule",
"defaultChecked": true
}
]
}
}defaultChecked 是规则给出的默认选择,不是“法律义务已经满足”。由商户核对最终文档集合,并把确认后的版本放进下一步的 items。
如果返回 dobMissing: true、memberIsMinor: null,不能把孩子当成年人。先补生日再解析;年龄相关项未默认勾选,不等于不需要。appendixMatch: "ambiguous" 则需要人工确认运动项目对应的附加文档。
3. 预览,不发送
调用 POST /v1/club/compliance/signing-requests/preview,不需要 Idempotency-Key:
{
"contactId": "3101",
"dependentContactId": "3102",
"flowFlavor": "standard",
"items": [
{
"documentKind": "service_contract",
"templateVersionId": "8103",
"required": true,
"displayOrder": 0
},
{
"documentKind": "waiver",
"templateVersionId": "8201",
"required": true,
"displayOrder": 1
}
]
}contactId 现在指收邮件并签字的家长;dependentContactId 指孩子。普通代签合同也使用 flowFlavor: "standard",不要仅因为有孩子就切到 parental_consent,后者有独立的同意记录逻辑。
成功时 HTTP 200,返回每份文档一项:
{
"data": [
{
"documentKind": "service_contract",
"templateVersionId": "8103",
"title": "Demo program agreement",
"renderedMarkdown": "# Demo program agreement\n\nClub: Demo Club\nProgram: Demo program\nParticipant: [to be completed at signing]\nSigned at: [recorded at signing]\n"
},
{
"documentKind": "waiver",
"templateVersionId": "8201",
"title": "Demo risk acknowledgment",
"renderedMarkdown": "# Demo risk acknowledgment\n\n…\n"
}
]
}返回顺序对应请求里的 items,用 templateVersionId 对上是哪一份,不要按下标假定。
逐份检查 renderedMarkdown。检查俱乐部信息、课程、价格、顺序和必签项。预览不是最终签署文件:姓名等签署字段可能仍为 [to be completed at signing],时间及设备字段可能为 [recorded at signing]。创建时也可能补入电子签署同意项。
当前此预览接口走 Markdown 渲染;如果模板绑定的是 PDF/DOCX 等二进制母版,不要期待它在这里返回完整可视预览。请在商户签署流程核对文件,不要收到渲染错误后跳过核对继续发送。
4. 创建并发送邀请
确认无误后,调用 POST /v1/club/compliance/signing-requests。请求头使用 Content-Type: application/json,并为本次发送设置唯一的 Idempotency-Key,例如 demo-signing-20260912-001。
{
"contactId": "3101",
"dependentContactId": "3102",
"flowFlavor": "standard",
"items": [
{
"documentKind": "service_contract",
"templateVersionId": "8103",
"required": true,
"displayOrder": 0
},
{
"documentKind": "waiver",
"templateVersionId": "8201",
"required": true,
"displayOrder": 1
}
],
"ttlHours": 72
}HTTP 201 示例:
{
"data": {
"signingRequestId": "9200",
"status": "sent",
"expiresAt": "2026-09-15T09:00:00.000Z",
"consentBundled": false
}
}保存 signingRequestId,关联到你自己的业务记录。此例签署人已有有效电子签署同意,所以没有补项;若返回 consentBundled: true,表示本次补入或复用了当前同意项,最终项目列表以查询结果为准。
sent 表示请求已发起,不是邮箱送达回执。 SportsX 负责发送签署邮件;Partner API 不返回原始签署 token,不要用请求 ID 自行拼 deeplink。超时或 409 的处理见写请求与重试,不要换一个幂等键重复发信。
5. 查询签署结果
调用 GET /v1/club/compliance/signing-requests/{id} 查询刚创建的请求 9200。例如,家长打开链接后,文档仍未签完:
{
"data": {
"id": "9200",
"groupId": "123",
"contactId": "3101",
"status": "opened",
"expiresAt": "2026-09-15T09:00:00.000Z",
"sentAt": "2026-09-12T09:00:00.000Z",
"firstOpenedAt": "2026-09-12T09:10:00.000Z",
"completedAt": null,
"declinedAt": null,
"cancelledAt": null,
"flowFlavor": "standard",
"dependentContactId": "3102",
"signingTokenVersion": "1",
"createdByContactId": null,
"createdAt": "2026-09-12T09:00:00.000Z",
"updatedAt": "2026-09-12T09:10:00.000Z",
"items": [
{
"id": "9300",
"documentKind": "service_contract",
"templateVersionId": "8103",
"required": true,
"displayOrder": 0,
"itemStatus": "pending",
"confirmedAt": null,
"signedAt": null
},
{
"id": "9301",
"documentKind": "waiver",
"templateVersionId": "8201",
"required": true,
"displayOrder": 1,
"itemStatus": "pending",
"confirmedAt": null,
"signedAt": null
}
],
"signedDocuments": []
}
}opened 只表示打开过,不能向你的业务系统写“已签署”。此时 completedAt 为 null,文档项目尚未签署,signedDocuments 为空。
| 状态 | 接入方怎么处理 |
|---|---|
draft、sent、opened、in_progress | 尚未完成;低频、有次数上限地查询,遵守限流响应 |
partially_completed | 不要标记全部完成;检查逐项结果,交给商户核对 |
completed | 核对完成时间及逐项证据,再同步业务完成状态 |
declined、cancelled、expired | 保留当前结果,由商户决定后续动作,不自动重新发起 |
需要追踪查看、签署等过程时,调用 GET /v1/club/compliance/signing-requests/{id}/events。
取签后文件需要另外授予 club.compliance.read_files(已有 key 改不了权限,须新建并切换)。completed 后重新查询请求详情,signedDocuments 里每项的 finalFileAssetId 就是签署完成的文件;结业证明另有 completionCertificateFileAssetId,可能为 null。拿这个 ID 调:
{
"data": {
"url": "https://files.example.com/demo-signed.pdf?sig=…",
"expiresAt": "2026-09-12T10:00:00.000Z"
}
}url 是限时地址,过期就失效,不要存进你的业务库当永久链接,需要时重新换一次。每次换取都会计入审计。
验收时至少完成一次“受控邮箱收信 → 家长打开 → 逐项签署 → 查询完成状态 → 核对签后文件”。API 返回正确,不代表字段、邮件、文件及最终证据都已经验收通过。