curl -X POST https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/ownership/ \
-H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \
-d '{"confirmed": true}'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.transactions.travel_rule.confirm_ownership(
"11111111-2222-3333-4444-555555555555",
confirmed=True,
)
print(result)import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.transactions.travelRule.confirmOwnership("11111111-2222-3333-4444-555555555555", {
confirmed: true,
});
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.Transactions.TravelRule.ConfirmOwnership(ctx, "11111111-2222-3333-4444-555555555555", didit.TravelRuleOwnershipConfirmRequest{
Confirmed: true,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import me.didit.Didit;
import me.didit.types.TravelRuleOwnershipConfirmRequest;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.transactions().travelRule().confirmOwnership("11111111-2222-3333-4444-555555555555", TravelRuleOwnershipConfirmRequest.builder()
.confirmed(true)
.build());
System.out.println(result);<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->transactions->travelRule->confirmOwnership('11111111-2222-3333-4444-555555555555', [
'confirmed' => true,
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.transactions.travel_rule.confirm_ownership(
"11111111-2222-3333-4444-555555555555",
confirmed: true
)
puts result.to_husing System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.Transactions.TravelRule.ConfirmOwnershipAsync("11111111-2222-3333-4444-555555555555", new TravelRuleOwnershipConfirmRequest
{
Confirmed = true,
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "AWAITING_COUNTERPARTY",
"direction": "INBOUND",
"rail": "INTERNAL",
"protocol": "<string>",
"ivms_version": "ivms101.2023",
"required": true,
"ownership_confirmed": true,
"deadline_at": "2023-11-07T05:31:56Z",
"timeline": [
{
"status": "<string>",
"at": "2023-11-07T05:31:56Z",
"detail": "<string>",
"name_match": {
"score": 50,
"matched": true,
"method": "none",
"strictness": "NONE",
"compared_with": "wallet_holder",
"transfer_name": "<string>",
"compared_name": "<string>",
"matched_names": [
"<string>"
],
"mismatched_names": [
"<string>"
]
},
"reason": "<string>"
}
],
"counterparty_vasp": {
"name": "<string>",
"lei": "<string>",
"dd_score": 123,
"dd_score_breakdown": {},
"dd_assessed_at": "2023-11-07T05:31:56Z"
},
"originator_data": {},
"beneficiary_data": {},
"name_match": {
"score": 50,
"matched": true,
"method": "none",
"strictness": "NONE",
"compared_with": "wallet_holder",
"transfer_name": "<string>",
"compared_name": "<string>",
"matched_names": [
"<string>"
],
"mismatched_names": [
"<string>"
]
},
"data_match": {
"matched": true,
"mismatched_fields": [
"name"
],
"fields": {}
},
"mismatched_fields": [
"<string>"
],
"data_unmasked": {
"at": "2023-11-07T05:31:56Z",
"reason": "ownership_confirmed",
"actor": "<string>"
},
"data_masked": true,
"created_at": "2023-11-07T05:31:56Z",
"delivery": {
"kind": "SEND",
"status": "QUEUED",
"rail": "INTERNAL",
"attempts": 1,
"last_error": "email undeliverable",
"next_attempt_at": "2023-11-07T05:31:56Z",
"delivered_at": "2023-11-07T05:31:56Z"
},
"discovery": [
{
"step": "internal_address_book",
"outcome": "match",
"reason": "<string>",
"vasp": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"rail": "<string>",
"at": "2023-11-07T05:31:56Z"
}
],
"reason": "<string>",
"next_actions": [
{
"action": "select_counterparty_vasp",
"url": "<string>"
}
],
"chain_details": {
"chain": "<string>",
"shape": "utxo",
"originator": {
"address": "<string>",
"memo": "<string>",
"source": "declared"
},
"beneficiary": {
"address": "<string>",
"memo": "<string>",
"source": "declared"
},
"utxo": {
"inputs": [
{
"address": "<string>",
"amount": "0.0125",
"txid": "<string>",
"vout": 1
}
],
"outputs": [
{
"address": "<string>",
"amount": "0.0125",
"txid": "<string>",
"vout": 1
}
],
"change_output_indexes": [
123
],
"beneficiary_output_index": 123
},
"lightning": {},
"warnings": [
"declared_originator_not_an_input"
],
"not_applicable_reason": "LIGHTNING_NO_PAYEE_IDENTIFIER"
}
}确认钱包所有权 API:Travel Rule 收款人
通过 Didit 确认或拒绝客户对处于 UNCONFIRMED_OWNERSHIP 状态的入站 Travel Rule 转账所使用的收款钱包拥有控制权。
curl -X POST https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/ownership/ \
-H 'x-api-key: YOUR_API_KEY' -H 'Content-Type: application/json' \
-d '{"confirmed": true}'from didit import Didit
# Reads DIDIT_API_KEY.
client = Didit()
result = client.transactions.travel_rule.confirm_ownership(
"11111111-2222-3333-4444-555555555555",
confirmed=True,
)
print(result)import Didit from "@didit-protocol/sdk-node";
// Reads DIDIT_API_KEY.
const didit = new Didit();
const result = await didit.transactions.travelRule.confirmOwnership("11111111-2222-3333-4444-555555555555", {
confirmed: true,
});
console.log(result);ctx := context.Background()
// Reads DIDIT_API_KEY.
client := didit.NewClient()
result, err := client.Transactions.TravelRule.ConfirmOwnership(ctx, "11111111-2222-3333-4444-555555555555", didit.TravelRuleOwnershipConfirmRequest{
Confirmed: true,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", result)import me.didit.Didit;
import me.didit.types.TravelRuleOwnershipConfirmRequest;
// Reads DIDIT_API_KEY.
Didit client = new Didit();
var result = client.transactions().travelRule().confirmOwnership("11111111-2222-3333-4444-555555555555", TravelRuleOwnershipConfirmRequest.builder()
.confirmed(true)
.build());
System.out.println(result);<?php
require 'vendor/autoload.php';
use Didit\DiditClient;
// Reads DIDIT_API_KEY.
$didit = new DiditClient();
$result = $didit->transactions->travelRule->confirmOwnership('11111111-2222-3333-4444-555555555555', [
'confirmed' => true,
]);
print_r($result->toArray());require "didit"
# Reads DIDIT_API_KEY.
didit = Didit::Client.new
result = didit.transactions.travel_rule.confirm_ownership(
"11111111-2222-3333-4444-555555555555",
confirmed: true
)
puts result.to_husing System;
using System.Text.Json;
using Didit;
// Reads DIDIT_API_KEY.
using var client = new DiditClient();
var result = await client.Transactions.TravelRule.ConfirmOwnershipAsync("11111111-2222-3333-4444-555555555555", new TravelRuleOwnershipConfirmRequest
{
Confirmed = true,
});
Console.WriteLine(JsonSerializer.Serialize(result));{
"uuid": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "AWAITING_COUNTERPARTY",
"direction": "INBOUND",
"rail": "INTERNAL",
"protocol": "<string>",
"ivms_version": "ivms101.2023",
"required": true,
"ownership_confirmed": true,
"deadline_at": "2023-11-07T05:31:56Z",
"timeline": [
{
"status": "<string>",
"at": "2023-11-07T05:31:56Z",
"detail": "<string>",
"name_match": {
"score": 50,
"matched": true,
"method": "none",
"strictness": "NONE",
"compared_with": "wallet_holder",
"transfer_name": "<string>",
"compared_name": "<string>",
"matched_names": [
"<string>"
],
"mismatched_names": [
"<string>"
]
},
"reason": "<string>"
}
],
"counterparty_vasp": {
"name": "<string>",
"lei": "<string>",
"dd_score": 123,
"dd_score_breakdown": {},
"dd_assessed_at": "2023-11-07T05:31:56Z"
},
"originator_data": {},
"beneficiary_data": {},
"name_match": {
"score": 50,
"matched": true,
"method": "none",
"strictness": "NONE",
"compared_with": "wallet_holder",
"transfer_name": "<string>",
"compared_name": "<string>",
"matched_names": [
"<string>"
],
"mismatched_names": [
"<string>"
]
},
"data_match": {
"matched": true,
"mismatched_fields": [
"name"
],
"fields": {}
},
"mismatched_fields": [
"<string>"
],
"data_unmasked": {
"at": "2023-11-07T05:31:56Z",
"reason": "ownership_confirmed",
"actor": "<string>"
},
"data_masked": true,
"created_at": "2023-11-07T05:31:56Z",
"delivery": {
"kind": "SEND",
"status": "QUEUED",
"rail": "INTERNAL",
"attempts": 1,
"last_error": "email undeliverable",
"next_attempt_at": "2023-11-07T05:31:56Z",
"delivered_at": "2023-11-07T05:31:56Z"
},
"discovery": [
{
"step": "internal_address_book",
"outcome": "match",
"reason": "<string>",
"vasp": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"rail": "<string>",
"at": "2023-11-07T05:31:56Z"
}
],
"reason": "<string>",
"next_actions": [
{
"action": "select_counterparty_vasp",
"url": "<string>"
}
],
"chain_details": {
"chain": "<string>",
"shape": "utxo",
"originator": {
"address": "<string>",
"memo": "<string>",
"source": "declared"
},
"beneficiary": {
"address": "<string>",
"memo": "<string>",
"source": "declared"
},
"utxo": {
"inputs": [
{
"address": "<string>",
"amount": "0.0125",
"txid": "<string>",
"vout": 1
}
],
"outputs": [
{
"address": "<string>",
"amount": "0.0125",
"txid": "<string>",
"vout": 1
}
],
"change_output_indexes": [
123
],
"beneficiary_output_index": 123
},
"lightning": {},
"warnings": [
"declared_originator_not_an_input"
],
"not_applicable_reason": "LIGHTNING_NO_PAYEE_IDENTIFIER"
}
}自托管钱包
当交易对手钱包被声明为自托管(counterparty.payment_method.method_type: "unhosted_wallet")时,转账会停留在 UNCONFIRMED_OWNERSHIP 状态。
使用 confirmed: true 调用此端点,表示您的客户已验证该钱包由谁控制,转账随即完成(COMPLETED),适用于出站提现和入站存款。
如果入站存款的链上哈希已知,则转账会进入 FINISHED 状态。
被验证的钱包属于交易对手:对于出站提现,是提现的目标地址;对于入站存款,是来源地址(即汇款人的钱包)。
Didit 会将该钱包以交易对手的名称添加到钱包地址簿中,并标记为所有权已验证,因此它会与交易对手的名称进行匹配(对于存款,则与汇款人的名称匹配)。
如果地址簿中该钱包已登记在其他持有人名下,转账将改为进入 COUNTERPARTY_MISMATCHED_DATA 状态。
如果转账完全没有指定交易对手钱包,请在请求体中传入 wallet_address。
若转账和请求中都没有提供钱包地址,请求将被拒绝,并返回 400。
confirmed: false 会拒绝该转账(COUNTERPARTY_VASP_GENERAL_DECLINE)。授权
您的应用 API 密钥,可在 Business Console 的“开发者 -> API 密钥”中获取。主密钥拥有完整访问权限。指定名称的密钥可设置作用域:针对每个资源设为无权限、只读或读写,限定于特定工作流或已通过的会话、限定于 IP 地址列表,以及设置到期日期。401 表示密钥错误、已撤销或已过期;403 表示未发送密钥、密钥无权访问该资源或操作,或请求来自其 IP 列表之外的地址;在会话路由上返回 404 表示该会话不在该密钥允许的工作流或状态范围内。没有媒体访问权限的密钥获取到的图片、视频和 PDF URL 将为 null;没有会话写入权限的密钥获取到的会话链接和 token 将为 null。请参阅 https://docs.didit.me/console/api-keys。
路径参数
您的应用针对此转账所持有的 Didit 稳定交易 UUID:在 INTERNAL 通道转账中为收款人侧交易,或在交易对手钱包被声明为自托管钱包时您创建的交易(出账或入账)。
请求体
响应
已更新的转账。对于入向转账,交易对手的 originator_data/beneficiary_data 会保持脱敏状态(data_masked: true),直到所有权得到确认,然后由 data_unmasked 记录数据解除屏蔽的时间、原因和操作人员。
所有权确认以及完成/取消 endpoint 返回的完整转账对象。当入站转账的钱包所有权未确认时,交易对手的 originator_data 和 beneficiary_data 会被掩码返回(保留每个单词的首字母;钱包、链以及 VASP 路由保持可读),且 data_masked 为 true。
AWAITING_COUNTERPARTY, ON_HOLD, COMPLETED, FINISHED, CANCELLED, EXPIRED, COUNTERPARTY_MISMATCHED_DATA, COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_VASP_GENERAL_DECLINE, NOT_ENOUGH_COUNTERPARTY_DATA, NOT_APPLICABLE INBOUND, OUTBOUND 转账路由所使用的通道,如果未选择通道(例如低于阈值、交易对手为自托管钱包、充值后登记或无触达的交易对手),则为 null。INTERNAL 表示双方均为 Didit 应用;EMAIL 表示通过电子邮件发送的提取链接触达交易对手。TEST_VASP 表示由 Didit Test VASP 响应沙盒转账。在 GTR、VERIFYVASP 和 SYGNA 上,Didit 会从网络响应中读取交易对手的回答,或每 5 分钟轮询一次。TRUST 仅支持发送,因此 TRUST 转账将一直保持 AWAITING_COUNTERPARTY 状态直至过期。网络通道仅在您已关联该网络自身会员资格时使用。它在交易创建返回后选定,因此在该响应中为 null。
INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA, EMAIL, TEST_VASP, null "ivms101.2023"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
汇款人方。对于入账转账,在所有权确认之前,交易对手的值将被掩码遮盖。
收款人方。对于入账转账,在确认所有权之前,交易对手的值将被遮蔽。
决定转账的姓名比对结果,在运行比对前为 null。在当事方被脱敏期间,以及在 INTERNAL 交易另一方客户的副本上,transfer_name、compared_name、matched_names 和 mismatched_names 将被隐藏。score 和 matched 可能会不一致:matched 遵循严格程度规则,score 则是两个全名之间的相似度。
Show child attributes
Show child attributes
转账当事方数据与对方已知的钱包持有人信息之间的逐字段比对。该项仅指明字段和结果,绝不包含具体值,因此在交易对手数据被脱敏的同时仍保持可读性。在执行比对前为 null。
Show child attributes
Show child attributes
data_match.mismatched_fields 的快捷方式。无差异时为空。
交易对手数据解除掩码时刻的审计记录。当数据仍处于掩码状态时以及出站转账时为 null。
Show child attributes
Show child attributes
在此响应中交易对手的个人数据被遮蔽时为 True。
此转账应发送给对方的最新消息所处的状态。当转账从未需要发送消息时(例如低于 threshold_amount、声明的自托管钱包或 sunrise 注册)为 null。
Show child attributes
Show child attributes
Didit 查找交易对手的方式,每个运行的步骤对应一个条目。未运行发现流程时为空,例如对于入站转账。
Show child attributes
Show child attributes
COUNTERPARTY_VASP_NOT_FOUND 或 COUNTERPARTY_VASP_NOT_REACHABLE 转账受阻的原因;任何其他状态下为 ""。首先由失败的投递决定(仅适用于 COUNTERPARTY_VASP_NOT_REACHABLE):email_undeliverable(邮件服务商拒绝了合规邮件,且没有可尝试的地址:发送时、发送提醒时或后续报告为永久退信)或 delivery_failed(负责投递的通道彻底失败:网络通道拒绝了消息或重试次数耗尽、TRP 身份主机未应答,或交易对手的 TRP 主机不接受查询)。否则由 discovery 追踪记录决定:awaiting_end_user(没有任何步骤指定 Didit 可触达的交易对手)、directory_match_no_route(某步骤指定了名录中的 VASP,但该 VASP 没有可用路由)、picked_member_without_proven_wallet(终端用户选择的 Didit 客户尚未证明对该钱包的控制权),或者在追踪记录未提供其他原因时的 no_directory_match。重新发送后转账会继续推进,因此该原因将被清除。参见转账受阻的原因。
推进转账的操作;除 COUNTERPARTY_VASP_NOT_FOUND 或 COUNTERPARTY_VASP_NOT_REACHABLE 之外的任何状态均返回 []。email_undeliverable 提供 update_compliance_email,然后提供 resend。delivery_failed 提供 resend。发现原因提供 select_counterparty_vasp、declare_self_hosted、add_vasp_hint 和 resend。
Show child attributes
Show child attributes
当转账涉及的不止是一个地址向另一个地址付款时,该交易所在区块链对其两个钱包的命名方式。对于账户模型区块链上的转账(EVM、Solana、Tron),由于两个地址本身就是钱包,因此该字段为空({})。匹配、路由和地址簿会优先从此字段读取钱包信息。
Show child attributes
Show child attributes