关于 sumsub-manage-webhooks
用于通过 Sumsub 公共 API 列出、读取、创建和更新 ClientWebhook 订阅的技能。它使用沙盒 App Token,并检查目标地址可达性及事件等配置。
主要功能
- 01列出和读取 Webhook 订阅
- 02创建和更新 Webhook 配置
- 03从精简 JSON 或 YAML 规范生成载荷
- 04校验事件与签名设置
- 05拒绝仅本机可访问的目标地址
适用场景
- 01检查现有沙盒 Webhook
- 02试配 KYC 事件订阅
- 03更新 Webhook 目标地址或请求头
- 04整理供人工配置生产环境的设置
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sumsub/ agent-skills --skill sumsub-manage-webhooks安装后在 Claude Code 中输入/sumsub-manage-webhooks确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/basic-http.jsonlegacy-sha1.jsonupdate-existing.jsonwith-headers-and-restrictions.jsonreferences/webhook-schema.mdscripts/build_webhook_payload.pymanage_webhooks.sh详细介绍
Sumsub — 管理客户端 Webhook
列出、检索、创建和更新 ClientWebhook
事件订阅。读取操作使用 /resources/api/clientWebhooks;写入操作使用
/resources/api/agent/clientWebhooks。
端点
| 方法 | 路径 | 用途 |
|---|---|---|
GET | /resources/api/clientWebhooks | 列出租户中的 Webhook。返回 EntityResult<ClientWebhook>({list: {items: [...] }})。服务端最多返回最早的 50 个(getOldest50)。 |
GET | /resources/api/clientWebhooks/{id} | 按 ID 读取单个 Webhook。可用它根据已知 ID 查找 name,或验证写入后保存的内容。 |
POST | /resources/api/agent/clientWebhooks | 创建。请求正文不得包含 id——由服务器分配。(模型层仍会在内部执行 upsert,但请求 DTO 是不含 id 的 ClientWebhookCreateRequest。) |
PATCH | /resources/api/agent/clientWebhooks | 更新现有 Webhook(在请求正文中通过 id 指定)。DTO 为 ClientWebhookUpdateRequest。 |
所需权限:manageClientSettings。
公开 API 没有 DELETE 操作,也没有 /stats 端点——
如需删除 Webhook 或查看每个 Webhook 的投递统计信息,请使用 Sumsub 控制面板 UI。
身份验证 — App Token + 密钥(仅限沙盒)
此技能会调用 Sumsub 公开 API,并根据
身份验证参考为每个请求签名。
完整的工作原理说明见 sumsub-api-auth
技能——如果遇到 401 Invalid signature,请阅读该说明。
⚠️ 仅限沙盒 Token。 此处不得接受或使用生产环境 App Token。 如果用户提供了此类 Token,请拒绝,并要求他们前往 https://cockpit.sumsub.com/checkus/home?sbx=true 生成一组沙盒凭据 (Connect Sumsub to your AI agent -> Build & configure -> Generate token)。 Token 和密钥只会显示一次——关闭对话框前请复制两者。辅助脚本会强制执行此规则——除非设置了
SUMSUB_ALLOW_PROD=1,否则会拒绝不以sbx:开头的 Token。
| 变量 | 示例 |
|---|---|
SUMSUB_APP_TOKEN | sbx:... — 来自控制面板的沙盒 App Token。 |
SUMSUB_SECRET_KEY | 创建 Token 时显示一次的配对密钥。 |
SUMSUB_BASE | 可选。默认值为 https://api.sumsub.com。 |
如果用户已在对话中提供凭据,请重复使用;否则,请在运行前询问一次。切勿复述密钥。
仅限沙盒的范围 — 生产环境 Webhook 必须由人工创建
由于此技能只接受沙盒 App Token,因此它创建或更新的所有 Webhook 都位于沙盒工作区。Sumsub 将沙盒和生产环境视为独立租户——没有“升级到生产环境”的途径,而且 使用生产环境 Token 重新运行此技能并不是设置真实 Webhook 的正确方式。
当用户准备配置生产环境 Webhook 时:
- 不要提出通过此技能进行配置,即使用户提出请求也不行。
- 不要索取或接受生产环境 App Token(除非设置了
SUMSUB_ALLOW_PROD=1,否则脚本会拒绝;而且你不应建议用户使用此覆盖设置)。 - 告知用户,生产环境 Webhook——目标 URL、签名密钥、事件订阅、自定义标头——应由人工直接在 Sumsub 控制面板中配置(前往 Integrations → Webhooks,并将工作区切换为 Production)。设置生产环境 Webhook 属于安全敏感操作(签名密钥用于验证真实个人身份信息的投递),审计记录应归属到具体人员。
- 正确的工作流程是:使用此技能针对沙盒进行原型验证,记录用户需要的最终规格(事件列表、标头、签名算法),然后将该规格整理为纯文档,交由人工在生产环境中重新配置。
子命令
manage_webhooks.sh 是编排脚本:
manage_webhooks.sh list # GET all webhooks (table summary; capped at 50)
manage_webhooks.sh list --json # raw JSON of all webhooks
manage_webhooks.sh get <webhookId> # one webhook (filtered from the list)
manage_webhooks.sh create <spec.json> # POST without id (compact spec → ClientWebhook)
manage_webhooks.sh update <spec.json> # POST with id (spec MUST contain id)
create 和 update 都会调用 build_webhook_payload.py 来展开精简规格。
提交前:目标必须可从公网访问
Sumsub 从自己的基础设施发送 Webhook,因此 target URL 必须能够解析,并接受来自公网的连接。常见问题:用户在本地开发时填写了 http://localhost:3000/webhook(或 127.0.0.1、0.0.0.0、::1)。Sumsub 会在创建时接受该 URL,但每次投递都会失败;此类 target 也会被技能的负载构建器提前拒绝。
如果用户提供的 URL 类似 localhost,不要提交。相反,应在创建 Webhook 前引导他们通过公共隧道暴露本地服务:
- 推荐 ngrok(最常见的选择)。在 macOS 上:
brew install ngrok/ngrok/ngrok。其他平台:从链接下载。首次使用的用户需要注册免费的 ngrok 账户以获取身份验证令牌,然后执行一次ngrok config add-authtoken <TOKEN>。 - 询问他们的本地 Webhook 接收器监听哪个端口(通常是 3000 / 8080 / 4000)。
- 让他们在单独的终端中运行
ngrok http <port>,并保持终端打开。 - ngrok 会输出一行
Forwarding https://<random>.ngrok-free.app -> http://localhost:<port>。其中https://...ngrok-free.app部分就是公共 URL。 - 在该 URL 后附加接收器的 Webhook 路径(例如
/webhook、/sumsub),并将完整 URL 用作target。然后重新运行create子命令。
需要提醒:使用免费的 ngrok 方案时,每次重启 ngrok,公共 URL 都会变化——每次会话都需要通过 update(使用现有的 id 和新的 target 发起 POST 请求)更新 Webhook。保留域名(付费)或使用 --domain=<your-subdomain> 可以保持 URL 稳定。如果用户更愿意使用其他方案,还可以选择 Cloudflare Tunnel(cloudflared tunnel)、Tailscale Funnel、localtunnel——原理和步骤相同。
create / update 的精简规范
# Identity (omit on create; required on update)
id: 698bfc... # id from a previous list / create response
# Display + addressing
name: "Production webhook" # required (no min length but the dashboard expects something)
description: "Sends KYC events to our backend"
target: "https://example.com/sumsub/webhook" # required — destination URL (or slack / email / telegram address depending on targetType)
targetType: http # http | email | slack | telegram (default: http)
# Subscription
types: # required — event-type strings (see "Event types" below)
- applicantReviewed
- applicantPending
- applicantOnHold
- applicantCreated
applicantType: individual # individual | company (omit to subscribe to both)
sourceKeys: [] # optional — restrict to specific source keys
# Auth + delivery
secretKey: "..." # HMAC secret used to sign payloads
signatureAlgorithm: HMAC_SHA256_HEX # HMAC_SHA1_HEX | HMAC_SHA256_HEX | HMAC_SHA512_HEX (default: SHA256)
headers: # optional extra HTTP headers added to each delivery
- { key: "X-Source", value: "sumsub" }
- { key: "Authorization", value: "Bearer ${MY_TOKEN}" } # caller substitutes before sending
# Lifecycle flags
notResendFailedWebhooks: false # default false; true = no automatic retries on delivery failure
构建器会校验枚举值(targetType、signatureAlgorithm、applicantType),拒绝空的 types,并封装 headers,使其 key/value 结构符合 ClientWebhookHeader。未知键会原样传递(逃生口)。
事件类型(types[])
OpenAPI 将 types 保留为自由格式的 string[]。以下名称涵盖了
常见的 Sumsub 事件。服务器端会静默接受未知事件类型,而 webhook 则永远
不会触发——因此 API 不会捕获拼写错误。
| 分组 | 事件类型 | 触发时机 |
|---|---|---|
| 申请人生命周期 | applicantCreated | 创建新申请人 |
applicantPrechecked | 预筛查完成 | |
applicantPending | 已提交审核 | |
applicantReviewed | 得出最终审核结果(GREEN / RED) | |
applicantOnHold | 审核已挂起 / 暂停 | |
applicantActivated | 申请人已激活 | |
applicantDeactivated | 申请人已停用 | |
applicantReset | 验证已重置(重试) | |
applicantLevelChanged | 已重新分配等级 | |
applicantTagsChanged | 已添加 / 移除标签 | |
applicantPersonalInfoChanged | 个人信息已编辑 | |
applicantDeleted | 申请人已删除 | |
applicantPersonalDataDeleted | 已执行 GDPR 个人数据擦除 | |
| 操作工作流 | applicantActionPending / applicantActionReviewed / applicantActionOnHold | 操作流程事件 |
| 工作流 | applicantWorkflowCompleted | 工作流运行已完成(不是 applicantWorkflowRunCompleted) |
| 视频身份验证 | videoIdentStatusChanged | 实时状态更新 |
videoIdentCompositionCompleted | 录制内容合成完成 | |
| KYT(申请人范围) | applicantKytTxnApproved / applicantKytTxnRejected / applicantKytTxnReviewed / applicantKytTxnDeleted / applicantKytTxnDataChanged / applicantKytTxnAwaitingUser / applicantKytOnHold | 按申请人划分的交易监控事件 |
| KYT(案件范围) | kytCaseCreated / kytCaseStatusChanged / kytCaseReviewed | KYT 案件管理事件(注意:这是 kytCaseStatusChanged,不是 kytCaseUpdated) |
| AML 案件 | amlCaseApproved / amlCaseRejected / amlCaseOnHold | AML 案件处置事件 |
| Travel Rule | travelRuleAction | Travel Rule 生命周期事件 |
| KYB | kybCompanyActivity | KYB 持续监控事件 |
此技能会转发调用方填写的任何内容——不进行客户端验证,因为 Sumsub 添加事件的速度可能快于此列表的更新速度。
输出
list— 包含id、name、target、disabled、types[]、applicantType、signatureAlgorithm、createdAt的表格。get— 完整的单个 webhook JSON(出于防护考虑,输出中会隐藏secretKey)。create/update— 已持久化的ClientWebhook(创建时包含服务器分配的id)以及一行摘要。
示例
examples/basic-http.json— 最简 webhook:HTTPS 端点、四个申请人生命周期事件、SHA-256 签名。examples/with-headers-and-restrictions.json— 范围限定为特定sourceKey的广泛事件集,并包含自定义 HTTP 标头。examples/legacy-sha1.json— 使用 SHA1 签名的 webhook,适用于已验证 SHA1 的接收方。examples/update-existing.json— 与 basic 示例相同,但设置了id,用于演示更新流程。
另请参阅
references/webhook-schema.md— 完整的ClientWebhook架构、所有枚举以及注意事项(secret 并非只写入、签名语义)。- Sumsub 文档:Webhook system、Webhook event types、Verify webhook signatures。