关于 sumsub-create-transaction
此 Skill 根据精简规格生成并提交 Sumsub KYT 交易数据,校验必填字段,并报告响应标识与风险结果,面向处理沙盒交易监控的 Agent。
主要功能
- 01从精简规格构建 KytTxnData
- 02校验必填字段和枚举值
- 03适配现有或新申请人的请求路由
- 04向 Sumsub KYT 提交交易
- 05报告评分及仪表板链接
适用场景
- 01提交支付交易进行 KYT 监控
- 02记录旅行规则交易或平台事件
- 03查看风险评分和审核结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sumsub/ agent-skills --skill sumsub-create-transaction安装后在 Claude Code 中输入/sumsub-create-transaction确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/crypto-in.jsonfiat-out.jsonlogin-event.jsonnew-applicant.jsontravel-rule.jsonreferences/transaction-schema.mdscripts/build_transaction.pypost_transaction.sh详细介绍
Sumsub — 创建交易(KYT)
根据精简规格构建 KytTxnData JSON 负载,将其 POST 到 Sumsub KYT 端点,并报告返回的 txnId / score / reviewAnswer。
端点
有两个变体,由 post 脚本自动选择:
| 情况 | 方法 + 路径 |
|---|---|
| 申请人已存在 | POST https://api.sumsub.com/resources/applicants/{applicantId}/kyt/txns/-/data |
申请人不存在(Sumsub 根据 applicant.externalUserId 创建申请人) | POST https://api.sumsub.com/resources/applicants/-/kyt/txns/-/data?levelName=<levelName> |
请求正文:KytTxnData。返回附有监控评分的持久化 KytTxn。
这两个端点都已标记为弃用,但仍是官方文档中的规范“提交交易”入口。目前没有 v2/v3 替代方案。
身份验证 — App Token + 密钥(仅限沙盒)
此技能会调用 Sumsub 公共 API,并根据身份验证参考为每个请求签名。完整的工作原理说明见 sumsub-api-auth 技能——如果遇到 401 Invalid signature,请阅读该说明。
⚠️ 仅限沙盒令牌。 请勿在此接受或使用生产环境 App Token——交易监控会处理真实申请人数据,并可能触发真实的 KYT 警报。如果用户提供生产环境令牌,请拒绝并让其前往 https://cockpit.sumsub.com/checkus/home?sbx=true 生成一组沙盒凭据(Connect Sumsub to your AI agent -> Build & configure -> Generate token)。令牌和密钥只会显示一次——关闭对话框前请复制两者。辅助脚本会强制执行此要求——不接受未以
sbx:开头的令牌。
| 变量 | 示例 |
|---|---|
SUMSUB_APP_TOKEN | sbx:... — 控制面板中的沙盒 App Token。 |
SUMSUB_SECRET_KEY | 创建令牌时仅显示一次的配对密钥。 |
SUMSUB_BASE | 可选。默认为 https://api.sumsub.com。 |
为解析后的路径签名
这是唯一需要注意的路由细节——必须对包含查询字符串的路径签名。post 脚本会处理此事:它会读取构建器生成的旁路路由文件,选择 URI(/resources/applicants/{id}/… 或 /resources/applicants/-/…?levelName=…),对动态片段进行 URL 编码,并对发送的相同字节进行签名。如果绕过该脚本,请记住:
- 对实际发送的路径签名——使用编码后的形式,并包含查询字符串。
- 签名所用的请求正文字节必须与发送的字节一致(不得重新排布空白字符)。
如果用户已在对话中提供凭据,请重复使用;否则,请在运行前询问一次。绝不要回显密钥。
流程
-
将用户意图映射到以下精简规范。绝大多数交易都是
type: finance(付款)——对于这类交易,用户实际提供的是金额 + 币种 + 方向 + 申请人 + 交易对手方。 -
验证:
txnId非空,applicant.externalUserId非空,并按type验证:finance/travelRule→ 必须提供info.amount、info.currencyCode、info.direction(OpenAPI 将这三项标记为KytTxnInfo的必填字段)。userPlatformEvent→ 必须提供userPlatformEvent.type。- 枚举(
direction、currencyType、applicant.type、nameType等)需提前检查,验证失败时列出所有允许值。
-
使用
${CLAUDE_SKILL_DIR}/scripts/build_transaction.py生成完整载荷(通过标准输入传入精简规范 → 通过标准输出获取完整的KytTxnData载荷)。 -
通过
${CLAUDE_SKILL_DIR}/scripts/post_transaction.shPOST — 根据规范中是否设置了_applicantId,自动路由到现有申请人或非现有申请人的 URL(而不是根据载荷中的设置判断——见下文)。 -
构建仪表板链接。 从响应正文中读取
id(服务器分配的标识符,不是你提供的txnId)和clientId,并按以下格式生成:https://cockpit.sumsub.com/checkus/kyt/txns/<id>?clientId=<clientId>&sbx=true规范中用户提供的
txnId(例如finance-2026-05-21-0001)不会放入 URL — Sumsub 在持久化时会分配单独的标识符。sbx=true查询参数指向 Sandbox 工作区 — 这是所有技能共用的规范 Sandbox 链接参数。 -
报告:
txnId(你提供的)、服务器id、申请人的externalUserId、方向 + 金额 + 币种、交易对手方(如果有),响应中的score/reviewAnswer/riskLabels(如果存在),以及作为可点击 Markdown 链接的仪表板链接。
精简规范格式(通过标准输入传入 JSON 或 YAML)
# Top-level
txnId: "finance-2026-05-21-0001" # REQUIRED, unique alphanumeric in your system
txnDate: "2026-05-21 14:30:00+0000" # optional; format: yyyy-MM-dd HH:mm:ss+XXXX
zoneId: "UTC+01:00" # optional, time zone string
type: finance # finance | travelRule | kyc | userPlatformEvent | iGamingSession (default: finance)
# Routing — pick ONE
_applicantId: "67abc..." # post to existing applicant (path id, NOT a payload field)
# - OR -
_levelName: "Default" # post to non-existing-applicant URL with ?levelName=...
# (Sumsub creates the applicant from applicant.externalUserId)
# Finance / Travel Rule info (required for those types)
amount: 1500.50
currency: USD # ISO-4217 fiat or crypto ticker (BTC, ETH, …)
currencyType: fiat # fiat | crypto (default: fiat)
direction: out # in | out
amountInDefaultCurrency: 1500.50 # optional, converted to client default
defaultCurrencyCode: USD
paymentDetails: "Invoice #INV-2026-001"
mcc: 5411 # optional, 4-digit Merchant Category Code
# Crypto-only block (used when currencyType=crypto)
crypto:
chain: ETH # ETH | BTC | TRX | … (mandatory for tokens; empty for native)
contract: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
paymentTxnId: "0x1234abcd..." # on-chain hash
fingerprint: "0x1234abcd..." # alternative blockchain identifier
attemptId: "attempt-01" # optional, when retrying
outputIndex: 0 # for UTXO chains
# Applicant (REQUIRED) — the person/entity acting on your platform
applicant:
externalUserId: "user-001" # REQUIRED — your stable user id
type: individual # individual | company (default: individual)
fullName: "John Smith" # required for company; recommended for non-existing-applicant flow
dob: "1990-05-01"
email: "[email protected]"
phone: "+1234567890"
placeOfBirth: "London"
address:
country: USA
town: "New York"
street: "5th Avenue"
formatted: "5th Avenue, New York, USA"
paymentMethod:
type: bankCard # bankCard | bankAccount | crypto | cryptoWallet |
# eWallet | unhostedWallet | card | other
accountId: "4111********1111" # IBAN, last4-hash, wallet address, etc.
issuingCountry: USA
"3dsUsed": true
"2faUsed": false
memo: "optional memo"
idDoc:
number: "A12345678"
country: USA
idDocType: PASSPORT
device:
fingerprint: "abc123"
userAgent: "Mozilla/5.0 ..."
ipInfo: { ip: "1.2.3.4" }
# Counterparty (typical for finance + travelRule; same shape as applicant + a few extras)
counterparty:
externalUserId: "merchant-XYZ"
type: company
fullName: "Acme Inc."
registrationNumber: "12345678"
leiCode: "529900XXXX0000XXXX00"
residenceCountry: QAT
address: { country: QAT }
institution: # → institutionInfo
code: "ACME-CODE"
name: "Acme Bank"
internalId: "<VASP id from directory>"
ceo: # only for company counterparties (Travel Rule)
firstName: "Jane"
lastName: "Roe"
# user-platform-event only (when type=userPlatformEvent)
userPlatformEvent:
type: login # login | failedLogin | signup | passwordReset | twoFaReset | general
twoFaUsed: true
passwordHash: "..."
# Optional escape hatches
sourceKey: "<segregation key>"
props: # custom string-string map
customField: "value"
dailyOutLimit: "10000"
枚举(提前验证)
| 字段 | 允许值 |
|---|---|
type(顶层) | finance、travelRule、kyc、auditTrailEvent、userPlatformEvent、scheduledEvent、iGamingSession |
direction | in、out |
currencyType | crypto、fiat |
applicant.type / counterparty.type | individual、company |
applicant.nameType | aliasName、birthName、maidenName、legalName、shortName、tradingName、other |
userPlatformEvent.type | login、failedLogin、signup、passwordReset、twoFaReset、general |
有意不对 paymentMethod.type 执行枚举验证 — OpenAPI 列出了 KytTxnPaymentMethodType(仅含 smartContract、bankCard、bankAccount),但文档和实时数据接受更多类型(如 crypto、eWallet、unhostedWallet 等)。构建器会原样转发调用方提供的值。
输出
成功时,报告以下所有内容:
txnId(你提供的)以及id(服务器分配,用于仪表板链接)。- 申请人的
externalUserId。 direction amount currency、交易对手方(如果有)。- 响应返回的
score/reviewAnswer/riskLabels。 - 仪表板链接:
https://cockpit.sumsub.com/checkus/kyt/txns/<id>?clientId=<clientId>&sbx=true。将其呈现为可点击的 Markdown 链接。<id>是服务器分配的标识符(不是你发送的txnId);这两个值都在 POST 响应正文中;sbx=true指向 Sandbox 工作区。
失败时:报告 HTTP 状态码以及 Sumsub 的 description/errorName。最可能遇到的 4xx 情况:
409 Entity already exists—txnId冲突(请使用新的 id,或使用批量导入方法进行更新)。400— 缺少必填字段(常见字段:info.amount、info.currencyCode、info.direction或applicant.externalUserId)。400—levelName未知(使用非现有申请人流程时)。
示例
examples/fiat-out.json— 向境外交易对手支付欧元银行卡款项(文档中的标准示例)。examples/crypto-in.json— 接收 ETH 存款,包含cryptoParams.cryptoChain=ETH、合约地址和链上paymentTxnId。examples/travel-rule.json— 使用type: travelRule进行加密货币出账,交易对手的institution.internalId(VASP ID)。examples/login-event.json— 用户通过双重身份验证成功登录时的type: userPlatformEvent。examples/new-applicant.json— 新申请人流程:设置_levelName,使 POST 请求发送到/-/kyt/txns/-/data,并附带?levelName=...。
另请参阅
- references/transaction-schema.md — 完整的
KytTxnData架构、所有子对象和枚举、现有申请人与新申请人的路由方式、评分响应字段及常见注意事项。 - Sumsub 文档 — 提交交易
- Sumsub 文档 — 为非现有申请人提交交易
- Sumsub 文档 — 提交交易并审核结果