关于 didit-transaction-monitoring
用于在金融与加密交易工作流中集成 Didit 交易监控 API 的技能,涵盖同步规则判定、钱包与交易筛查,以及与对手方 VASP 进行 FATF/EU TFR Travel Rule 数据交换。
主要功能
- 01同步返回交易判定
- 02创建规则并进行回测
- 03筛查加密钱包和交易哈希
- 04处理 Travel Rule 转账
- 05查询交易记录和详情
适用场景
- 01筛查存款和提款
- 02按规则评估交易活动
- 03检查加密钱包或交易哈希
- 04与 VASP 交换 Travel Rule 数据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ didit-protocol/ skills --skill didit-transaction-monitoring安装后在 Claude Code 中输入/didit-transaction-monitoring确认已加载。
附带文件scripts/submit_transaction.py
详细介绍
Didit 交易监控与 Travel Rule API
概述
使用规则引擎(条件、频率窗口、阻止名单)实时评估每笔交易,通过区块链分析筛查加密货币钱包和交易哈希,并与交易对手 VASP 执行 FATF / EU TFR Travel Rule 信息交换。
关键信息:
POST /v3/transactions/为同步接口:筛查、Travel Rule 路由和规则均在调用过程中运行,因此201响应中已包含判定结果。交易创建时状态为APPROVED;规则可能会将其状态改为IN_REVIEW、DECLINED或AWAITING_USER。transaction_id在每个应用内必须唯一。重复使用会被拒绝(返回400和{"transaction_id": "A transaction with this transaction_id already exists."};若两个请求发生竞争,则返回409);系统绝不会返回已有交易。发生超时后,应将该400视为“已创建”,并通过GET /v3/transactions/查找记录,而不是重新提交。GET /v3/transactions/{uuid}/使用 Didit 在创建响应中返回的uuid,而非你的transaction_id。- 沙盒应用会存储交易,但跳过规则、加密货币筛查、Webhook 和计费(交易状态会保持为
APPROVED)。 - 非货币活动(登录、游戏过程、奖励、拒付)应发送到事件 API:参见 didit-event-monitoring 技能。
**定价:**每笔交易收费 $0.02(交易筛查);Travel Rule 转账单独按每笔出站转账收费 $0.02,而非交易筛查费用;钱包验证与筛查(与交易关联或按需进行)使用 Didit 管理的分析服务时起价为 $0.15,使用你自己的服务商密钥时为 $0.02;即使 Travel Rule 归因需要进行相同查询,也只收费一次。沙盒永不收费。以上为截至 2026 年 11 月 1 日的标价,届时 Didit 将调整定价,每月 500 次免费检查将改为每月 $10 免费额度。请访问 didit.me/pricing 查看当前价格。
API 参考: https://docs.didit.me/management-api/transactions/create 功能指南: https://docs.didit.me/transaction-monitoring/overview | https://docs.didit.me/transaction-monitoring/rules-api | https://docs.didit.me/transaction-monitoring/travel-rule | https://docs.didit.me/transaction-monitoring/wallet-screening
身份验证
每个请求都需要 x-api-key 标头。请使用 Didit Business Console 中 Developers > API keys 下的应用 API 密钥,或通过编程方式创建账户和密钥(参见入门指南)。具有自定义访问权限的命名密钥需要具备 Transactions 权限(GET 需要读取权限,POST、PUT、PATCH 和 DELETE 需要写入权限);仅限访问部分工作流或仅限已通过审核的会话的密钥,无法获得 Transactions 权限。
有两个例外:GET /v3/travel-rule/widget/{token}/ 无需密钥(令牌即为凭证);设备端点 /v1/transactions/ 使用 X-Transaction-Token 进行身份验证(参见 SDK 交易令牌)。
入门指南(还没有账户?)
如果你还没有 Didit API 密钥,只需调用 2 个 API 即可创建:
- **注册:**使用
{"email": "[email protected]", "password": "MyStr0ng!Pass"}调用POST https://apx.didit.me/auth/v2/programmatic/register/ - 查收邮件,获取 6 位验证码
- **验证:**使用
{"email": "[email protected]", "code": "A3K9F2"}调用POST https://apx.didit.me/auth/v2/programmatic/verify-email/。密钥位于响应的application.api_key中。
**添加额度:**调用 GET /v3/billing/balance/ 查询余额;调用 POST /v3/billing/top-up/ 并传入 {"amount_in_dollars": 50},获取 Stripe 结账链接。
如需完整的平台管理指南(工作流、会话、用户、计费),请参见 didit-verification-management 技能。
端点
基础 URL:https://verification.didit.me
| 方法 | 路径 | 用途 |
|---|---|---|
POST | /v3/transactions/ | 提交交易(同步判定) |
GET | /v3/transactions/ | 按时间倒序列出交易(limit,默认为 50,以及 offset) |
GET | /v3/transactions/{uuid}/ | 交易完整详情 |
POST | /v3/transactions/sdk-token/ | 为 /v1/transactions/ 生成设备令牌 |
GET, POST | /v3/transactions/rules/ | 列出 / 创建规则 |
GET, PATCH, DELETE | /v3/transactions/rules/{rule_uuid}/ | 读取 / 更新 / 删除规则 |
POST | /v3/transactions/rules/backtest/ | 根据历史记录评估假设规则 |
GET | /v3/transactions/rules/library/ | 预设库,包含 is_installed |
POST, DELETE | /v3/transactions/rules/install/ | 安装 / 卸载预设 |
POST | /v3/wallet-screening/ | 筛查单个钱包,不创建交易 |
POST | /v3/wallet-screening/pdf/ | 将筛查结果生成为 PDF |
GET, PUT | /v3/travel-rule/settings/ | Travel Rule 设置(PUT 为部分更新) |
PATCH | /v3/transactions/{uuid}/travel-rule/ | 完成、取消或重新发送转账 |
POST | /v3/transactions/{uuid}/travel-rule/ownership/ | 确认或否认钱包所有权 |
GET, POST | /v3/travel-rule/wallet-addresses/ | 钱包地址簿 |
PATCH, DELETE | /v3/travel-rule/wallet-addresses/{entry_uuid}/ | 更新 / 删除地址条目 |
GET | /v3/travel-rule/vasps/?search= | VASP 目录 |
POST | /v3/travel-rule/inbound/ | 登记已结算的入金(sunrise) |
POST | /v3/travel-rule/widget-session/ | 生成钱包所有权小组件链接 |
GET | /v3/travel-rule/widget/{token}/ | 小组件进度(无需 API 密钥) |
创建交易
POST https://verification.didit.me/v3/transactions/
请求正文(JSON)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
transaction_id | 字符串 | 是 | 你的 ID,最多 128 个字符,每个应用中必须唯一。别名 txnId。 |
transaction_category | 字符串 | 是 | finance、kyc、travel_rule、user_event、audit_trail_event、gambling_bet、gambling_limit_change、gambling_bonus_change。也接受 camelCase:travelRule、userPlatformEvent、auditTrailEvent、gamblingBet、gamblingLimitChange、gamblingBonusChange。别名键 type。多词值会以 camelCase 格式回显在 transaction_type 中。 |
transaction_details.direction | 字符串 | 是 | inbound / outbound(也接受 in / out,不区分大小写)。回显为 INBOUND / OUTBOUND。 |
transaction_details.amount | 数字或十进制字符串 | 是 | 最多 18 位小数;如需精确表示,请发送字符串。 |
transaction_details.currency | 字符串 | 是 | ISO 4217 代码或加密资产符号。 |
transaction_details.currency_kind | 字符串 | 否 | fiat 或 crypto。crypto 会启用加密货币筛查。 |
transaction_details.action_type | 字符串 | 否 | 例如 deposit、withdrawal、transfer。默认值为交易类别。 |
transaction_details.payment_reference_id | 字符串 | 否 | 外部参考编号;对于加密货币,为链上哈希(会切换为哈希筛查)。 |
transaction_details.crypto_params.crypto_chain | 字符串 | 否 | 筛查所用网络(BTC、ETH、LTC、XRP、BCH、DOGE、TRX、SOL、MATIC、BNB、BASE、OP、ARB;只有在已连接 Elliptic 或 Chainalysis 密钥时,才可使用 LIGHTNING)。 |
transaction_details.amount_in_default_currency、default_currency、payment_details | 否 | 预先换算的金额及其币种;自由文本备注。 | |
subject.vendor_data | 字符串 | 是 | 最多 255 个字符。你的用户 ID:将交易关联到 KYC 会话所用的同一用户资料(用于频率限制和升级验证时存储的人脸信息)。 |
subject.full_name | 字符串 | 是 | |
subject.entity_type | 字符串 | 否 | individual(默认值)或 company。 |
subject.* | 否 | first_name、last_name、date_of_birth(YYYY-MM-DD)、address(country 为 ISO alpha-3,含 town、state、street、post_code)、institution_details、device_context、payment_method。 | |
subject.payment_method / counterparty.payment_method | 对象 | 否 | method_type(bank_card、bank_account、crypto_wallet、ewallet、unhosted_wallet、other)、account_id(IBAN、钱包地址)、issuing_country。 |
counterparty | 对象 | 否 | 结构与 subject 相同;没有必填字段。 |
custom_properties | 对象 | 否 | 自定义键值,可在规则中通过 custom_values.<key> 读取。别名 props。 |
travel_rule_details | 对象 | 否 | 别名 travelRule。如果发送,则必须包含 status(缺失时返回 400)。请参阅 Travel Rule。 |
include_crypto_screening | 布尔值 | 否 | 按调用覆盖应用默认值(null/省略 = 默认值)。 |
transaction_at、time_zone | 字符串 | 否 | ISO 时间戳(默认当前时间)和 IANA 时区。别名 txnDate、zoneId。 |
如果用户/企业封锁名单中存在主体或交易对手的 vendor_data,则返回 400(不会创建任何内容)。如果钱包、银行账户、IP 或设备指纹在封锁名单中,则会创建交易,并在运行规则前立即将其标记为 DECLINED,且 decision_reason_code 为 "blocklisted"。
示例
curl -X POST https://verification.didit.me/v3/transactions/ \
-H "x-api-key: $DIDIT_API_KEY" -H "Content-Type: application/json" \
-d '{
"transaction_id": "tx-0001",
"transaction_category": "finance",
"transaction_details": {"direction": "outbound", "amount": "1500.50", "currency": "EUR", "action_type": "withdrawal"},
"subject": {"entity_type": "individual", "vendor_data": "user-42", "full_name": "John Doe"},
"counterparty": {"entity_type": "company", "full_name": "Acme Energy"},
"custom_properties": {"order_id": "ORD-7891"}
}'
import os, requests
r = requests.post(
"https://verification.didit.me/v3/transactions/",
headers={"x-api-key": os.environ["DIDIT_API_KEY"]},
json={
"transaction_id": "tx-0001",
"transaction_category": "finance",
"transaction_details": {"direction": "outbound", "amount": "1500.50", "currency": "EUR"},
"subject": {"vendor_data": "user-42", "full_name": "John Doe"},
},
timeout=60,
)
tx = r.json()
print(r.status_code, tx.get("uuid"), tx.get("status"), tx.get("score"))
响应(201)
完整的交易详情(结构与 GET /v3/transactions/{uuid}/ 相同):
| 字段 | 说明 |
|---|---|
uuid | Didit ID;在每个后续路径中使用此值 |
txn_id | 你的 transaction_id |
transaction_type、action_type、direction | 存储的值 |
status | APPROVED、IN_REVIEW、DECLINED、AWAITING_USER |
score、severity | 规则评分(通常为 0-100);严重级别为 UNKNOWN/LOW/MEDIUM/HIGH/CRITICAL 或 null |
decision_reason_code、decision_reason_label | 状态的原因 |
amount、currency、currency_type、preferred_currency_amount、preferred_currency_code、payment_txn_id | 金额以十进制字符串表示 |
rule_runs[]、alerts[]、provider_results[]、tags[]、parties[]、payment_methods[] | 评估详情;筛查结果在 provider_results 中 |
travel_rule | 简短的转账对象(uuid、status、protocol、required、obligations_count、originator_data、beneficiary_data、metadata)或 null |
action_required | 待处理的最终用户操作或 null(见下文) |
cost_breakdown | total_price 和 items[] |
environment | live 或 sandbox |
action_required
type | 适用情况 | 字段 | 操作 |
|---|---|---|---|
wallet_ownership | 只要交易的 Travel Rule 转账存在待处理(未完成、未过期)的钱包所有权组件会话,无论交易状态如何 | url、widget_session_id、expires_at | 在真实浏览器或自定义标签页中打开 url,切勿使用移动 WebView |
verification_session | 仅当交易处于 AWAITING_USER 状态且规则创建了补救会话时 | url、session_id、session_token、status | 将用户引导至 url,或在 Didit SDK 中使用 session_token 启动会话 |
两者同时适用时,优先返回 wallet_ownership。解决后,action_required 会变为 null。补救操作不会重新运行规则:会话的判定会直接设置交易状态(Approved -> APPROVED、Declined -> DECLINED、In Review -> IN_REVIEW,并将 decision_reason_code 设为 user_action_approved / user_action_declined / user_action_in_review),同时触发 transaction.status.updated。会话过期或被放弃时,交易仍处于 AWAITING_USER 状态。
加密货币筛查(与交易关联)
当 transaction_details.currency_kind 为 crypto 且应用已开启监控(或设置了 include_crypto_screening: true)时运行;false 会跳过筛查。筛查的钱包取决于交易方向,以及你是否在 payment_reference_id 中发送了链上哈希:
| 方向 | 转账前(无哈希) | 转账后(payment_reference_id 中包含哈希) |
|---|---|---|
| 入账 | counterparty.payment_method.account_id 中的发送方钱包 | 在 subject.payment_method.account_id 中限定到你的入金地址的哈希(缺失时返回 400) |
| 出账 | counterparty.payment_method.account_id 中的目标钱包 | 在 counterparty.payment_method.account_id 中限定的哈希(缺失时返回 400) |
网络:transaction_details.crypto_params.crypto_chain;未提供时,会将币种用作链;USDT/USDC 默认使用 Ethereum,除非哈希表明使用的是 Tron 或 Solana。对于代币,务必设置此项;如果使用的是其他 EVM 链,切勿发送 ETH。如果没有已连接的 Elliptic 或 Chainalysis 密钥,LIGHTNING 会在筛查或计费前返回 400。创建交易并不能证明已完成筛查:请检查 provider_results。
钱包筛查(按需)
POST https://verification.didit.me/v3/wallet-screening/:筛查单个地址,不创建交易。需要配置服务提供商(Transactions > Settings > Provider Preferences),否则返回 409。
| 字段 | 必填 | 说明 |
|---|---|---|
wallet_address | 是 | 必须与链匹配(例如,EVM 地址为 0x + 40 位十六进制字符)。别名:address。 |
blockchain | 是 | BTC、LIGHTNING、ETH、LTC、XRP、BCH、DOGE、TRX、SOL、MATIC、BNB、BASE、OP、ARB、USDT、USDC。USDT/USDC 是 Ethereum 的旧别名,不会搜索多条链。LIGHTNING 需要连接 Elliptic 或 Chainalysis 密钥(否则返回 400)。别名:currency。 |
direction | 否 | inbound、outbound、deposit、withdrawal。仅作上下文信息;不会影响评分。 |
响应 200:provider、screening_type(WALLET_SCREENING)、risk_score(0-100)、severity(0-9 为 UNKNOWN,10-39 为 LOW,40-69 为 MEDIUM,70-89 为 HIGH,90-100 为 CRITICAL;UNKNOWN 是一个等级,绝不代表通过)、status(SCREENED、PENDING、ERROR:只有 SCREENED 是已完成的判定,评分为 0 的 PENDING 结果并不表示安全)、summary、wallet_address、blockchain、sanctions_hit、pep_counterparty(null = 没有可用的 PEP 发现)、dominant_risk_category、risk_factors[](前 5 个风险驱动因素:source、category、label、entity_name、direction、exposure_type、amount_usd、percentage、is_high_risk、description)、source_of_funds[]、destination_of_funds[]、counterparty_connections[]、raw_response、report_signature。错误:400 校验错误,409 未配置服务提供商,502 服务提供商失败(稍后重试)。每次成功筛查计费一次。
PDF: 使用筛查返回的原样 JSON(包括 report_signature)调用 POST /v3/wallet-screening/pdf/,会返回 application/pdf 字节数据。不会调用服务提供商、不会计费,也不会存储任何内容。缺少签名或任何字段被修改都会返回 400。
RESULT=$(curl -s -X POST https://verification.didit.me/v3/wallet-screening/ \
-H "x-api-key: $DIDIT_API_KEY" -H "Content-Type: application/json" \
-d '{"wallet_address": "0x94f1b9b64e2932f6a2db338f616844400cd58e8a", "blockchain": "ETH"}')
curl -X POST https://verification.didit.me/v3/wallet-screening/pdf/ \
-H "x-api-key: $DIDIT_API_KEY" -H "Content-Type: application/json" \
-d "$RESULT" -o wallet_screening_report.pdf
Travel Rule(FATF / EU TFR)
设置
GET / PUT /v3/travel-rule/settings/(PUT 为部分更新)。启用 is_enabled 时,必须提供非空白的 legal_name(已存储或在同一请求中提供),否则返回 400。
| 字段 | 默认值 | 说明 |
|---|---|---|
is_enabled | false | 管理 travelRule 交易的交易所 |
legal_name、lei、compliance_email | "" | 您的 VASP 资料 |
jurisdiction | "EU" | 最多 8 个字符;设置 custom_values.travel_rule_regime |
threshold_amount | "0.00" | 低于该金额时,转账结果为 NOT_APPLICABLE(EU TFR 没有最低金额限制) |
name_matching_strictness | DEFAULT | NONE、STRICT、DEFAULT、FUZZY |
confirmation_timeout_hours | 48 | 最低为 1;超时后状态从 AWAITING_COUNTERPARTY 变为 EXPIRED |
timeout_outcome | HOLD | 超时后:HOLD(审核)、REJECT(拒绝)、PROCEED(不作处理) |
inbound_auto_accept | true | 自动接受转入已验证通讯录条目的转账,前提是名称匹配 |
auto_wallet_verification | true | 自动将所有权小组件注入 action_required |
allow_screenshot_proof、allow_self_declaration | true | 小组件提供的证明方式 |
vasp_attribution_enabled | true | 未通过任何通道解析时,使用区块链分析进行归属识别 |
disabled_networks | [] | 跳过 Didit 平台成员网络:GTR、TRUST、VERIFYVASP、SYGNA |
is_discoverable | true | 在 VASP 目录中列出,并可通过 INTERNAL 通道访问 |
networks、travel_address | 只读:每个网络的 {rail, mode, platform_available, connected}(mode 为 own/didit/off/unavailable),以及您自己的 Travel Address |
发送转账
使用 transaction_category: "travelRule"(或 travel_rule)和 travel_rule_details 创建交易:
- 每个请求都必须提供
status。启用 Travel Rule 时会忽略该值,由 Didit 处理交互;请发送"AWAITING_COUNTERPARTY"。禁用 Travel Rule 时,travel_rule_details会以你发送的status(当前值或旧版值)被动存储,不会运行任何轨道。 beneficiary_data:包含wallet_address、name,以及可选的路由字段travel_address、counterparty_vasp_lei、counterparty_vasp_name、counterparty_vasp_email、counterparty_gtr_vasp_code、counterparty_trust_membership_id、counterparty_verifyvasp_id、counterparty_sygna_vasp_code。originator_data为可选项(采用 IVMS 101 风格,拉丁字母)。- 对手方的
payment_method.method_type: "unhosted_wallet"表示这是一个可自托管钱包:不会运行任何轨道,转账从UNCONFIRMED_OWNERSHIP状态开始,并且在启用auto_wallet_verification时,组件链接会进入action_required状态。 - 否则,轨道会按优先级依次运行:
INTERNAL->TRP->GTR->TRUST->VERIFYVASP->SYGNA->EMAIL,然后区块链分析归因会再次运行这些轨道一次。
curl -X POST https://verification.didit.me/v3/transactions/ \
-H "x-api-key: $DIDIT_API_KEY" -H "Content-Type: application/json" \
-d '{
"transaction_id": "trv-0001",
"transaction_category": "travelRule",
"transaction_details": {"direction": "outbound", "amount": "0.25", "currency": "ETH", "currency_kind": "crypto"},
"subject": {"vendor_data": "user-42", "full_name": "Jane Doe"},
"counterparty": {"full_name": "Ana Diaz", "payment_method": {"method_type": "crypto_wallet", "account_id": "0xBeneficiaryWallet01"}},
"travel_rule_details": {
"status": "AWAITING_COUNTERPARTY",
"beneficiary_data": {"wallet_address": "0xBeneficiaryWallet01", "name": "Ana Diaz"}
}
}'
转账状态值(travel_rule.status)
| 状态 | 含义 / 操作 |
|---|---|
AWAITING_COUNTERPARTY | 已发送;等待对手方 VASP 响应。不要结算。 |
UNCONFIRMED_OWNERSHIP | 等待钱包控制权证明(通过组件或 .../ownership/)。不可重新发送。 |
ON_HOLD | 等待人工处理(例如,入账时没有匹配的地址簿条目);交易显示为 AWAITING_USER。 |
COMPLETED | 数据已匹配:现在可以安全地在链上广播。 |
FINISHED | 终态。你已报告链上哈希(出站),或已结算日出入金。 |
CANCELLED | 终态。已通过 action: "cancel" 取消。 |
EXPIRED | 终态。confirmation_timeout_hours 已过;已对交易应用 timeout_outcome。 |
COUNTERPARTY_MISMATCHED_DATA | 受益人姓名未通过 name_matching_strictness 检查。 |
COUNTERPARTY_VASP_GENERAL_DECLINE | 对手方已拒绝,或所有权验证未通过。 |
COUNTERPARTY_VASP_NOT_FOUND | 没有轨道或归因解析出 VASP。可重新发送。 |
COUNTERPARTY_VASP_NOT_REACHABLE | 已识别 VASP,但其 TRP 端点失败。可重新发送。 |
NOT_ENOUGH_COUNTERPARTY_DATA | 对手方已响应,但未提供足够的数据。可重新发送。 |
NOT_APPLICABLE | 金额低于 threshold_amount,或你在被动记录中发送的值。 |
在状态变为 COMPLETED 前,绝不要广播。 然后调用 PATCH /v3/transactions/{uuid}/travel-rule/:
{"payment_txn_id": "0xhash"}->FINISHED(仅适用于出站且状态为COMPLETED的转账,否则返回409){"action": "resend"}-> 重新运行路由(仅适用于处于三个可重新发送状态之一的出站转账,否则返回409);请先完善对手方数据{"action": "cancel"}-> 取消任何非终态转账(若为终态则返回409)
交易自身的 status 是独立的(允许 / 暂停 / 拒绝);travel_rule_eu_tfr 预设配置包会在数据不匹配、未验证的可自托管钱包(默认币种金额 >= 1000)以及超时的情况下,将交易转入审核状态。
接收与钱包所有权
- 地址簿: 使用
POST /v3/travel-rule/wallet-addresses/,并传入address、chain、holder_name、holder_vendor_data、entity_type、travel_address、self_declared(设为true可创建已验证条目)。重复的address+chain会返回400。PATCH .../{entry_uuid}/接受holder_name、holder_vendor_data、entity_type、travel_address。DELETE会删除条目(204)。匹配仅依据地址进行。 - 确认所有权: 在受益方一侧使用
POST /v3/transactions/{uuid}/travel-rule/ownership/,并传入{"confirmed": true|false}(仅适用于UNCONFIRMED_OWNERSHIP,否则返回409)。设为true会验证该条目并执行名称匹配;设为false会返回COUNTERPARTY_VASP_GENERAL_DECLINE。确认所有权前,入站的originator_data/beneficiary_data会保持隐藏。 - 小组件: 使用
POST /v3/travel-rule/widget-session/,并传入wallet_address、chain、可选的holder_name、vendor_data、transaction_id(用于推进的 Didit 交易 UUID)、satoshi_deposit_address(启用 Satoshi 测试)、callback_url、expires_in_minutes(默认值为 60,范围为 5-10080),可获得{widget_session_id, token, url, expires_at}。在浏览器中原样打开url。使用GET /v3/travel-rule/widget/{token}/进行轮询,不需要 API 密钥(验证完成后completed_at非 null;未知令牌返回404,已过期令牌返回410),或等待travel_rule.status.updated。 - Sunrise(已结算的入金): 使用
POST /v3/travel-rule/inbound/,并传入必填的chain、txid、wallet_address、amount(十进制字符串)、currency,以及可选的originator_data、beneficiary_data、originating_vasp({name, lei, travel_address})。按txid+wallet_address去重:新入站交易返回201和created: true,复用已有交易时返回200和created: false。结果可能为ON_HOLD(无条目)、UNCONFIRMED_OWNERSHIP、COUNTERPARTY_MISMATCHED_DATA,或COMPLETED,之后变为FINISHED。 - 目录:
GET /v3/travel-rule/vasps/?search=<name>(limit默认为 50,offset):返回name、lei、jurisdiction、dd_status、dd_score、dd_score_breakdown、reachable_rails、is_didit_customer。
SDK 交易令牌(客户端提交)
在后端签发:使用 POST /v3/transactions/sdk-token/,并传入 vendor_data(必填)、ttl_seconds(默认值为 900,范围为 60-86400)、max_uses(>= 1;省略或设为 null 表示在 TTL 内不限制使用次数),可获得 201 {"sdk_token", "expires_at"}。
设备通过 X-Transaction-Token 标头调用 POST https://verification.didit.me/v1/transactions/ 和 GET /v1/transactions/{uuid}/。主体会被强制设为令牌的 vendor_data,服务器会添加 IP 和 user agent,且读取操作只会返回该 vendor_data 的交易。令牌被拒绝(缺失、未知、过期或超过 max_uses)时返回 401。Didit Web、iOS、Android、React Native 和 Flutter SDK 会将其封装为 submitTransaction,并自动启动 wallet_ownership 操作(参见 didit-sdk-integration 技能)。切勿在应用中打包 API 密钥。
规则 API
与控制台中的 Transactions > Rules 规则相同。在 TEST 模式下创建并进行回测,然后切换到 ACTIVE。规则不会在沙盒应用上运行。
| 字段 | 说明 |
|---|---|
title | 必填,在每个应用内唯一(重复则返回 400) |
category | 必填,例如 finance、aml_ctf、crypto_monitoring、travel_rule |
mode | 必填:ACTIVE、TEST(记录运行结果,但不会更改评分或状态)、DISABLED |
evaluation_mode | 对 conditions 使用 ALL(默认值)或 ANY |
scope | transaction_types、directions(INBOUND/OUTBOUND)、action_types;事件规则使用 record_types(默认为 ["transaction"],也可以是 ["event"] 或两者)和 event_categories |
conditions[] | {field, operator, value};运算符包括 eq、ne、gt、gte、lt、lte、in、not_in、contains、not_contains、contains_any、regex、fuzzy_match(需要 score)、exists、not_exists 及其别名;可选 value_type(list、field、relative_date)和 group_index |
aggregation[] | {metric, field?, operator, value, window, filters};指标包括 count、sum、avg、min、max、distinct_count;时间窗口为 <N>m/<N>h/<N>d;筛选条件中的 "__current__" 表示“与当前交易的值相同” |
actions[] | add_score(value)、change_status(value 为 APPROVED/IN_REVIEW/DECLINED/AWAITING_USER;AWAITING_USER 需要 workflow_id)、add_tags、add_note、add_to_list(list_id)、open_case |
GET /v3/transactions/rules/筛选参数:source(PRESET/CUSTOM)、category、mode、bundle、search、ordering、limit、offset。PATCH .../rules/{rule_uuid}/:自定义规则接受所有字段;预设规则仅接受mode(其他字段会返回400)。DELETE .../rules/{rule_uuid}/:删除自定义规则(204);预设规则会返回400(应卸载,而非删除)。POST .../rules/backtest/,参数为conditions、aggregation、evaluation_mode(默认为ALL)、scope、period_days(默认为 90),返回{evaluated, matched, affected_entities, period_days}。请对准备启用的确切配置进行回测。GET .../rules/library/(bundle、category、search)列出 150 多个预设规则及其is_installed状态。使用{"library_keys": [...]}或{"bundle": "travel_rule_eu_tfr"}调用POST .../rules/install/,返回{installed_library_keys, installed_count};使用相同请求体调用DELETE,返回{uninstalled_count}。两者都未提供则返回400。
curl -X POST https://verification.didit.me/v3/transactions/rules/ \
-H "x-api-key: $DIDIT_API_KEY" -H "Content-Type: application/json" \
-d '{
"title": "High-value withdrawal step-up",
"category": "finance",
"mode": "TEST",
"scope": {"directions": ["OUTBOUND"]},
"conditions": [{"field": "preferred_currency_amount", "operator": "gte", "value": 5000}],
"actions": [{"type": "change_status", "value": "AWAITING_USER", "workflow_id": "YOUR_BIOMETRIC_WORKFLOW_ID"}]
}'
由 open_case 打开的案件由 didit-case-management 技能处理。
Webhook
使用 POST /v3/webhook/destinations/(subscribed_events)订阅:
transaction.created和transaction.status.updated:transaction_id(Didit uuid)、txn_id、status、score、severity、amount、currency、direction、action_required。如需了解原因,请获取完整记录。travel_rule.status.updated:transaction_id、txn_id、travel_rule_status、rail、direction。
扁平信封包含 webhook_type、event_id(去重键,重试时会重复使用)、timestamp、created_at、application_id、environment;使用 X-Timestamp 验证 X-Signature-V2。沙盒应用不会发送交易 webhook。事件不会发送 webhook。
错误响应
| 状态 | 含义 | 操作 |
|---|---|---|
400 | 请求无效:缺少字段、重复使用 transaction_id({"transaction_id": "A transaction with this transaction_id already exists."})、缺少 travel_rule_details.status、哈希筛查缺少钱包、vendor_data 被列入黑名单、不支持的链、PDF 载荷已被编辑 | 查看响应正文中的字段错误 |
401 | API 密钥已过期;或在 /v1/transactions/ 上,X-Transaction-Token 缺失、无效、过期或已用尽 | 轮换密钥,或签发新的 SDK 令牌 |
403 | API 密钥缺失、错误或已撤销;受限密钥无权访问此端点;请求来自密钥 IP 允许列表以外;或额度不足(交易和钱包筛查会返回 "code": "insufficient_credits") | 查看 detail 或 error 中的消息:修正 x-api-key 标头或密钥权限,或充值 |
404 | 未知交易、规则、地址条目或 widget 令牌(或不是 uuid) | 使用 Didit uuid |
409 | 两个使用相同 transaction_id 的创建请求发生竞争;当前状态不允许执行 Travel Rule 操作;未配置提供商的情况下进行钱包筛查 | 重读记录后再重试 |
410 | Widget 会话已过期 | 签发新的 widget 会话 |
429 | 速率限制:每个密钥每分钟可发送 300 个 POST/PATCH/DELETE 请求和 600 个 GET 请求 | 等待 Retry-After 指定的秒数,然后重试 |
502 | 钱包筛查提供商失败 | 稍后重试 |
常见工作流
使用 Travel Rule 进行加密货币提现(端到端)
- 调用一次
PUT /v3/travel-rule/settings/,设置is_enabled: true和legal_name。 - 使用
transaction_category: "travelRule"调用POST /v3/transactions/,提供加密货币transaction_details(含crypto_params.crypto_chain)、作为subject的用户、作为对手方payment_method的目的地(如果是用户自己的钱包,则使用unhosted_wallet),以及包含status和beneficiary_data的travel_rule_details。 - 如果
action_required.type == "wallet_ownership",则在浏览器中将用户引导至其url。 - 等待
travel_rule.status == "COMPLETED"(通过travel_rule.status.updatedwebhook 或GET /v3/transactions/{uuid}/获取),并等待交易status不为拒绝状态。 - 在链上广播,然后使用
payment_txn_id调用PATCH .../travel-rule/,将状态更新为FINISHED。
对高价值交易进行阶梯式生物识别验证
- 创建一条规则(通过 Rules API 或控制台),其
change_status操作将目标状态设为AWAITING_USER,并指定生物识别验证workflow_id;先进行回测,然后执行PATCH {"mode": "ACTIVE"}。 - 按常规提交交易,并使用与用户 KYC 相同的
vendor_data;规则触发时,action_required.type == "verification_session"。 - 将用户引导至
url:系统会将一张实时自拍与用户注册时验证过的人脸进行匹配。 - 会话决策会将交易状态设为
APPROVED、DECLINED或IN_REVIEW,并触发transaction.status.updated。
结算后进行存款筛查
发送 direction: "inbound"、currency_kind: "crypto",在 payment_reference_id 中提供哈希,在 subject.payment_method.account_id 中提供你的存款地址,并在 crypto_params.crypto_chain 中提供网络;读取 provider_results 和交易 status。
实用脚本
scripts/submit_transaction.py 会提交一笔交易,并打印 JSON 和摘要(uuid、status、score、travel_rule.status、action_required.type)。
export DIDIT_API_KEY="your_api_key"
python scripts/submit_transaction.py --txn-id tx-0001 --amount 1500.50 --currency EUR \
--vendor-data user-42 --subject-name "John Doe" --counterparty-name "Acme Energy" \
--counterparty-entity-type company
# Outbound crypto withdrawal with wallet screening
python scripts/submit_transaction.py --txn-id wd-0001 --amount 0.25 --currency ETH --chain ETH \
--vendor-data user-42 --subject-name "Jane Doe" --counterparty-name "Ana Diaz" \
--wallet 0xBeneficiaryWallet01 --crypto
# Travel Rule transfer to the user's own self-hosted wallet
python scripts/submit_transaction.py --txn-id trv-0001 --amount 0.25 --currency ETH --chain ETH \
--vendor-data user-42 --subject-name "Jane Doe" --counterparty-name "Jane Doe" \
--wallet 0xJanesColdWallet01 --crypto --category travel_rule --unhosted