> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# 触发测试 VASP 入站转账 API

> 仅限沙盒：让 Didit 测试 VASP 向您的应用发起一笔入站 Travel Rule 转账，验证您自己的决策、收件箱和股权结构流程。



触发测试 VASP 入站转账 API 提示词
        将提示词复制到剪贴板



      
      

\<pre>

\`Make the Didit Test VASP send my sandbox application an inbound Travel Rule transfer, to exercise the receiving side of an exchange before going live.

Endpoint:
POST https://verification.didit.me/v3/travel-rule/test-vasp/inbound/

Authentication:
Use the x-api-key header with my SANDBOX application's API key. A live application receives 400.

Request body (application/json):
\{
"beneficiary_wallet_address": "0xYourSandboxWallet",  // required: the destination wallet address
"scenario": "accept",                                // optional: accept (default) or name_mismatch
"chain": "ETH",                                      // optional
"amount": "1",                                       // optional, decimal string
"currency": "ETH",                                   // optional
"reference": "demo-001"                              // optional: repeat calls with it return the first transfer
}

Behavior:
\- The transfer is decided by the same logic a real inbound transfer runs, against my wallet address book: a verified wallet with the holder's name completes, an unverified wallet waits for ownership, a wallet with no matching address book entry is booked ON_HOLD, and name_mismatch ends as COUNTERPARTY_MISMATCHED_DATA.
\- Nothing leaves Didit. travel_rule.status.updated webhooks fire with environment "sandbox", test_vasp true and the scenario name.

What to read from the response:
\- transaction_id, txn_id - the booked inbound transaction.
\- travel_rule_status and detail - how my application decided it.
\- travel_rule - the full transfer.

Full guide: /transaction-monitoring/travel-rule#testing-without-network-credentials.`

\</pre>



      
      

粘贴到



## OpenAPI

````yaml zh/openapi-25.json POST /v3/travel-rule/test-vasp/inbound/
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification API
  description: 身份证件验证 API。使用 x-api-key 请求头进行身份验证。
servers:
  - url: https://verification.didit.me
security: []
tags: []
paths:
  /v3/travel-rule/test-vasp/inbound/:
    post:
      tags:
        - Travel Rule
      summary: 从 Didit 测试 VASP 触发入账转账（沙盒）
      description: >-
        仅限沙盒应用。Didit Test VASP 会向您的应用发送一笔入站 Travel Rule
        转账，以便您在上线生产环境之前端到端演练交易所的接收端。该转账由网络实际入站转账针对您的钱包地址簿运行的相同逻辑进行入账和决策，因此收件箱、决策和钱包所有权流程的表现与生产环境中一致。任何数据都不会离开
        Didit。生产环境应用将收到 400。再次发送相同的 `reference` 可获取首次调用入账的转账，而不是创建第二笔转账。
      operationId: triggerTravelRuleTestVaspInbound
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TravelRuleTestVaspInboundRequest'
            example:
              beneficiary_wallet_address: 0xYourSandboxWallet
              scenario: accept
              amount: '1'
              reference: demo-001
      responses:
        '201':
          description: 入账转账已记录并作出决策。使用相同的 `reference` 重复请求将返回相同的响应体。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TravelRuleTestVaspInboundResponse'
        '400':
          description: 无效的请求体、未知或不受支持的 `scenario`，或者该应用为生产环境应用。
          content:
            application/json:
              schema:
                type: object
        '409':
          description: 无法登记该转账，例如因为该应用未启用 Travel Rule。
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: >-
            curl -X POST
            https://verification.didit.me/v3/travel-rule/test-vasp/inbound/ \
              -H 'x-api-key: YOUR_SANDBOX_API_KEY' -H 'Content-Type: application/json' \
              -d '{"beneficiary_wallet_address":"0xYourSandboxWallet","scenario":"accept","reference":"demo-001"}'
        - lang: python
          label: Python
          source: |-
            from didit import Didit

            # Reads DIDIT_API_KEY.
            client = Didit()

            result = client.transactions.travel_rule.trigger_test_vasp_inbound(
                beneficiary_wallet_address="0xYourSandboxWallet",
                scenario="accept",
                amount="1",
                reference="demo-001",
            )
            print(result)
        - lang: javascript
          label: Node.js
          source: >-
            import Didit from "@didit-protocol/sdk-node";


            // Reads DIDIT_API_KEY.

            const didit = new Didit();


            const result = await
            didit.transactions.travelRule.triggerTestVaspInbound({
              beneficiary_wallet_address: "0xYourSandboxWallet",
              scenario: "accept",
              amount: "1",
              reference: "demo-001",
            });

            console.log(result);
        - lang: go
          label: Go
          source: "ctx := context.Background()\n// Reads DIDIT_API_KEY.\nclient := didit.NewClient()\n\nresult, err := client.Transactions.TravelRule.TriggerTestVASPInbound(ctx, didit.TravelRuleTestVASPInboundRequest{\n\tBeneficiaryWalletAddress: \"0xYourSandboxWallet\",\n\tScenario:                 didit.Some(didit.TravelRuleTestVASPInboundRequestScenario(\"accept\")),\n\tAmount:                   didit.String(\"1\"),\n\tReference:                didit.String(\"demo-001\"),\n})\nif err != nil {\n\tlog.Fatal(err)\n}\nfmt.Printf(\"%+v\\n\", result)"
        - lang: java
          label: Java
          source: >-
            import me.didit.Didit;

            import me.didit.types.TravelRuleTestVaspInboundRequest;


            // Reads DIDIT_API_KEY.

            Didit client = new Didit();


            var result =
            client.transactions().travelRule().triggerTestVaspInbound(TravelRuleTestVaspInboundRequest.builder()
                    .beneficiaryWalletAddress("0xYourSandboxWallet")
                    .scenario(TravelRuleTestVaspInboundRequest.Scenario.of("accept"))
                    .amount("1")
                    .reference("demo-001")
                    .build());
            System.out.println(result);
        - lang: php
          label: PHP
          source: |-
            <?php

            require 'vendor/autoload.php';

            use Didit\DiditClient;

            // Reads DIDIT_API_KEY.
            $didit = new DiditClient();

            $result = $didit->transactions->travelRule->triggerTestVaspInbound([
                'beneficiary_wallet_address' => '0xYourSandboxWallet',
                'scenario' => 'accept',
                'amount' => '1',
                'reference' => 'demo-001',
            ]);
            print_r($result->toArray());
        - lang: ruby
          label: Ruby
          source: |-
            require "didit"

            # Reads DIDIT_API_KEY.
            didit = Didit::Client.new

            result = didit.transactions.travel_rule.trigger_test_vasp_inbound(
              beneficiary_wallet_address: "0xYourSandboxWallet",
              scenario: "accept",
              amount: "1",
              reference: "demo-001"
            )
            puts result.to_h
        - lang: csharp
          label: .NET
          source: >-
            using System;

            using System.Text.Json;

            using Didit;


            // Reads DIDIT_API_KEY.

            using var client = new DiditClient();


            var result = await
            client.Transactions.TravelRule.TriggerTestVaspInboundAsync(new
            TravelRuleTestVaspInboundRequest

            {
                BeneficiaryWalletAddress = "0xYourSandboxWallet",
                Scenario = new TravelRuleTestVaspInboundRequestScenario("accept"),
                Amount = "1",
                Reference = "demo-001",
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    TravelRuleTestVaspInboundRequest:
      type: object
      required:
        - beneficiary_wallet_address
      properties:
        beneficiary_wallet_address:
          type: string
          description: >-
            目标钱包地址。Didit Test VASP
            会向其发送资金，并根据资产所在链与您的钱包地址簿进行匹配。没有匹配条目的钱包也会被接受，入向交易将记为 ON_HOLD。
        scenario:
          type: string
          enum:
            - accept
            - name_mismatch
          default: accept
          description: >-
            Didit Test VASP 声明的收款人身份。`accept` 声明持有人本人的姓名；`name_mismatch`
            声明任何持有人均不认可的姓名。决策本身始终由您做出。
        chain:
          type: string
          default: ETH
          description: 资产所在的区块链网络。
        amount:
          type: string
          default: '1'
          description: 以十进制字符串表示的金额。
        currency:
          type: string
          default: ETH
          description: 资产代码。
        reference:
          type: string
          description: 可选的幂等性密钥。使用相同值重试将返回首次调用所创建的转账。
    TravelRuleTestVaspInboundResponse:
      type: object
      properties:
        transaction_id:
          type: string
          format: uuid
          description: 入账转账的 Didit 交易 UUID。
        txn_id:
          type: string
          description: Didit 生成的 txn_id。
        scenario:
          type: string
          description: 运行的场景。
        travel_rule_status:
          type: string
          description: 您的应用自身决策解析出的状态。
        detail:
          type: string
          description: 转账最终判定为该状态的原因。
        test_vasp:
          type: boolean
          description: 始终为 true：发送方为 Didit Test VASP。
        travel_rule:
          $ref: '#/components/schemas/TravelRuleTransferDetail'
    TravelRuleTransferDetail:
      type: object
      description: >-
        所有权确认以及完成/取消 endpoint 返回的完整转账对象。当入站转账的钱包所有权未确认时，交易对手的 `originator_data`
        和 `beneficiary_data` 会被掩码返回（保留每个单词的首字母；钱包、链以及 VASP 路由保持可读），且
        `data_masked` 为 true。
      properties:
        uuid:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - 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
        direction:
          type: string
          enum:
            - INBOUND
            - OUTBOUND
        rail:
          type: string
          nullable: true
          enum:
            - INTERNAL
            - TRP
            - GTR
            - TRUST
            - VERIFYVASP
            - SYGNA
            - EMAIL
            - TEST_VASP
            - null
          description: >-
            转账路由所使用的通道，如果未选择通道（例如低于阈值、交易对手为自托管钱包、充值后登记或无触达的交易对手），则为
            null。INTERNAL 表示双方均为 Didit 应用；EMAIL 表示通过电子邮件发送的提取链接触达交易对手。TEST_VASP
            表示由 Didit Test VASP 响应沙盒转账。在 GTR、VERIFYVASP 和 SYGNA 上，Didit
            会从网络响应中读取交易对手的回答，或每 5 分钟轮询一次。TRUST 仅支持发送，因此 TRUST 转账将一直保持
            AWAITING_COUNTERPARTY
            状态直至过期。网络通道仅在您已关联该网络自身会员资格时使用。它在交易创建返回后选定，因此在该响应中为 null。
        protocol:
          type: string
          nullable: true
        ivms_version:
          type: string
          example: ivms101.2023
        required:
          type: boolean
        ownership_confirmed:
          type: boolean
          nullable: true
        deadline_at:
          type: string
          format: date-time
          nullable: true
        timeline:
          type: array
          items:
            type: object
            properties:
              status:
                type: string
              at:
                type: string
                format: date-time
              detail:
                type: string
              name_match:
                allOf:
                  - $ref: '#/components/schemas/TravelRuleNameMatch'
                nullable: true
                description: 该条目决定的姓名比对结果，位于 `detail` 旁边。未比对姓名的条目中不存在该字段。
              reason:
                type: string
                description: >-
                  仅在投递失败导致的状态流转条目中存在：`email_undeliverable` 或
                  `delivery_failed`，即转账的 `reason` 所报告的值。
        counterparty_vasp:
          type: object
          nullable: true
          properties:
            name:
              type: string
            lei:
              type: string
            dd_score:
              type: integer
              description: 尽职调查评分，范围为 0 到 100，分数越高越好。分值范围与 VASP 名录相同。
            dd_score_breakdown:
              type: object
              description: >-
                对 dd_score 的各组件贡献度，每个组件一个对象（对应 VASP 目录中的
                jurisdiction、verification、protocol、lei、history、essentials、responsiveness），每个组件均包含
                {points, max, reason, detail}。在交易对手完成评估前为 {}。
              additionalProperties:
                type: object
                properties:
                  points:
                    type: number
                    description: 为该组件分配的点数。
                  max:
                    type: integer
                    description: 该组件可赋予的最大分值。
                  reason:
                    type: string
                    description: 组件判定结果的机器可读代码。
                  detail:
                    type: string
                    description: 易于阅读的积分授予原因。
            dd_assessed_at:
              type: string
              format: date-time
              nullable: true
              description: 尽职调查评估上次运行的时间。在对交易对手进行评估之前为 Null。
        originator_data:
          type: object
          description: 汇款人方。对于入账转账，在所有权确认之前，交易对手的值将被掩码遮盖。
        beneficiary_data:
          type: object
          description: 收款人方。对于入账转账，在确认所有权之前，交易对手的值将被遮蔽。
        name_match:
          allOf:
            - $ref: '#/components/schemas/TravelRuleNameMatch'
          nullable: true
          description: >-
            决定转账的姓名比对结果，在运行比对前为 null。在当事方被脱敏期间，以及在 INTERNAL
            交易另一方客户的副本上，`transfer_name`、`compared_name`、`matched_names` 和
            `mismatched_names` 将被隐藏。`score` 和 `matched` 可能会不一致：`matched`
            遵循严格程度规则，`score` 则是两个全名之间的相似度。
        data_match:
          $ref: '#/components/schemas/TravelRuleDataMatch'
        mismatched_fields:
          type: array
          items:
            type: string
          description: '`data_match.mismatched_fields` 的快捷方式。无差异时为空。'
        data_unmasked:
          $ref: '#/components/schemas/TravelRuleDataUnmasked'
        data_masked:
          type: boolean
          description: 在此响应中交易对手的个人数据被遮蔽时为 True。
        created_at:
          type: string
          format: date-time
        delivery:
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TravelRuleDelivery'
          description: >-
            此转账应发送给对方的最新消息所处的状态。当转账从未需要发送消息时（例如低于 `threshold_amount`、声明的自托管钱包或
            sunrise 注册）为 null。
        discovery:
          type: array
          description: Didit 查找交易对手的方式，每个运行的步骤对应一个条目。未运行发现流程时为空，例如对于入站转账。
          items:
            $ref: '#/components/schemas/TravelRuleDiscoveryStep'
        reason:
          type: string
          description: >-
            `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`。重新发送后转账会继续推进，因此该原因将被清除。参见[转账受阻的原因](/zh/transaction-monitoring/travel-rule#为什么转账会卡住)。
        next_actions:
          type: array
          description: >-
            推进转账的操作；除 `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`。
          items:
            $ref: '#/components/schemas/TravelRuleNextAction'
        chain_details:
          $ref: '#/components/schemas/TravelRuleChainDetails'
    TravelRuleNameMatch:
      type: object
      nullable: true
      description: >-
        决定转账的姓名比对结果，在运行比对前为 null。在当事方被脱敏期间，以及在 INTERNAL
        交易另一方客户的副本上，`transfer_name`、`compared_name`、`matched_names` 和
        `mismatched_names` 将被隐藏。`score` 和 `matched` 可能会不一致：`matched`
        遵循严格程度规则，`score` 则是两个全名之间的相似度。
      properties:
        score:
          type: integer
          minimum: 0
          maximum: 100
          description: 两个姓名的相似度，0 到 100。当任一姓名为空时为 0。
        matched:
          type: boolean
          description: >-
            姓名是否满足 `strictness`。转账的结果取决于比对每个字段的 `data_match`，因此即使此处为
            true，转账状态仍可能为 COUNTERPARTY_MISMATCHED_DATA。
        method:
          type: string
          enum:
            - none
            - exact_token
            - token_subset
            - token_containment
            - sequence_ratio
          description: >-
            `matched` 的判定方式：无匹配（`NONE`）、精确 token（`STRICT`）、token
            子集（`DEFAULT`）、token 包含（`CONTAINS`）或序列比率（`FUZZY`）。
        strictness:
          type: string
          enum:
            - NONE
            - STRICT
            - CONTAINS
            - DEFAULT
            - FUZZY
        compared_with:
          type: string
          enum:
            - wallet_holder
            - counterparty_vasp
          description: >-
            wallet_holder：为钱包记录的持有者。counterparty_vasp：交易对手在邮件响应页面上回复的名称，或在沙盒中
            Didit Test VASP 回复的名称。
        transfer_name:
          type: string
          description: 转账上的姓名。
        compared_name:
          type: string
          description: 用于比对的姓名。
        matched_names:
          type: array
          items:
            type: string
          description: 在 `compared_name` 中找到的 `transfer_name` 词语。
        mismatched_names:
          type: array
          items:
            type: string
          description: >-
            `compared_name` 中缺失的 `transfer_name` 词语，紧接着是 `transfer_name` 中缺失的
            `compared_name` 词语。
    TravelRuleDataMatch:
      type: object
      nullable: true
      description: >-
        转账当事方数据与对方已知的钱包持有人信息之间的逐字段比对。该项仅指明字段和结果，绝不包含具体值，因此在交易对手数据被脱敏的同时仍保持可读性。在执行比对前为
        null。
      properties:
        matched:
          type: boolean
          description: 当比对的字段均无差异时为 true。
        mismatched_fields:
          type: array
          items:
            type: string
            enum:
              - name
              - date_of_birth
              - address
              - account
          description: 存在差异的字段。
        fields:
          type: object
          description: >-
            针对该参与方实体类型所比对的每个字段对应一个条目（`name`、`date_of_birth`、`address`、`account`；企业没有
            `date_of_birth`）。
          additionalProperties:
            type: object
            properties:
              result:
                type: string
                enum:
                  - matched
                  - mismatched
                  - not_compared
                description: 当规则为 `NONE` 或任一方该字段均无值时为 `not_compared`。
              strictness:
                type: string
                enum:
                  - NONE
                  - STRICT
                  - CONTAINS
                  - DEFAULT
                  - FUZZY
    TravelRuleDataUnmasked:
      type: object
      nullable: true
      description: 交易对手数据解除掩码时刻的审计记录。当数据仍处于掩码状态时以及出站转账时为 null。
      properties:
        at:
          type: string
          format: date-time
        reason:
          type: string
          enum:
            - ownership_confirmed
            - wallet_proof
            - address_book_match
            - own_verified_wallet
            - inquiry_approved
            - known_payment_method
            - travel_address
          description: >-
            确认股权结构的依据：ownership_confirmed（您通过控制台或 API
            进行的确认）、wallet_proof（小组件中的钱包证明，或在创建时设置的 INTERNAL
            入站转账）、address_book_match（已验证的地址簿钱包）、own_verified_wallet（您的用户本人的已验证钱包）、inquiry_approved（您对入站
            TRP 问讯或 GTR 或 Sygna 消息的批准）、known_payment_method（您的用户已用于付款的钱包）或
            travel_address（按钱包分配的 Travel Address 指定了该钱包）。
        actor:
          type: string
          description: 确认此项的主体：控制台用户的邮箱或 API 密钥的标签。自动决策时为空白。
    TravelRuleDelivery:
      type: object
      description: >-
        该转账应发送给对方的最新消息所处的状态。Didit
        会在创建或修改转账的请求返回后联系交易对手，因此该对象显示该消息是否成功送达：已排队（queued）、正在发送（being
        sent）、出错后等待重试（waiting to be retried after an
        error）、已投递（delivered）或已失败（failed）。网络仍可能恢复的故障（超时未响应、连接失败、HTTP `408`、`429`
        或 `5xx`）会在 30 秒、2 分钟、10 分钟、30 分钟和 1 小时后再次重试。当首条消息（`kind:
        SEND`）彻底失败（因为网络拒绝或第 6 次尝试也失败）时，转账状态将变为
        `COUNTERPARTY_VASP_NOT_REACHABLE`，并在其 `timeline` 中记录
        `last_error`；任何其他彻底失败的消息也会在 `timeline` 中标明。转账的 `status` 始终是交易本身的真实事实来源。
      required:
        - kind
        - status
        - rail
        - attempts
        - last_error
        - next_attempt_at
        - delivered_at
      properties:
        kind:
          type: string
          enum:
            - SEND
            - ANSWER
            - TXID
            - CANCEL
            - POLL
          description: >-
            该消息携带的内容。`SEND`：发送给交易对手的首条转账消息（出站；在发送时选择通道）。`ANSWER`：您对发起请求的网络做出的接受或拒绝（入站）。`TXID`：完成转账后的链上交易哈希。`CANCEL`：取消操作（在您取消转账之后）。`POLL`：向支持状态查询的网络发起的查询请求，在转账等待交易对手期间每
            5 分钟重复一次。
        status:
          type: string
          enum:
            - QUEUED
            - SENDING
            - RETRYING
            - DELIVERED
            - FAILED
          description: >-
            `QUEUED`：等待发送。`SENDING`：正在尝试发送。`RETRYING`：尝试失败，下一次尝试将在
            `next_attempt_at` 运行。`DELIVERED`：对方已接收消息。`FAILED`：对方拒绝接收，或最后一次尝试失败。
        rail:
          type: string
          enum:
            - INTERNAL
            - TRP
            - GTR
            - TRUST
            - VERIFYVASP
            - SYGNA
            - EMAIL
            - ''
          description: 承载该消息的通道。在 Didit 为第一条消息选定通道之前为空。
        attempts:
          type: integer
          minimum: 0
          description: 截至目前针对该消息进行的尝试次数。非状态轮询的消息最多尝试 6 次。
        last_error:
          type: string
          description: >-
            上次尝试遇到的失败类型，无失败时为 `""`：例如 `email undeliverable`、`trp identity
            endpoint unreachable` 或 `trp transfer inquiry delivery
            failed`。它从不包含交易对手自身的回复，后者保留在转账的 `timeline` 中。

            当 GTR 回复错误时，会包含其自身的状态码和消息。绝不包含响应体。
          example: email undeliverable
        next_attempt_at:
          type: string
          format: date-time
          nullable: true
          description: 当消息处于 `QUEUED` 或 `RETRYING` 状态时，下一次尝试运行的时间。
        delivered_at:
          type: string
          format: date-time
          nullable: true
          description: 对方接收消息的时间。
    TravelRuleDiscoveryStep:
      type: object
      description: Didit 为出站转账执行的交易对手发现中的一个步骤，按执行顺序排列。第一个指定了具有可用路由的 VASP 的步骤将终止链条。
      properties:
        step:
          type: string
          enum:
            - internal_address_book
            - wallet_attribution
            - network_lookup
            - customer_hint
            - end_user
          description: >-
            `internal_address_book`：已证明拥有目标钱包控制权的另一位 Didit
            客户。`wallet_attribution`：钱包的区块链分析归属。`network_lookup`：能够辨明持有该地址之 VASP
            的网络。`customer_hint`：您在 `beneficiary_data` 中发送的 VASP 名称、LEI
            或司法管辖区。`end_user`：终端用户（或您）选择的交易对手，或选择交易对手的请求。
        outcome:
          type: string
          enum:
            - match
            - miss
            - skipped
          description: '`match`：该步骤指明了交易对手。`miss`：已运行但未找到。`skipped`：无法运行，`reason` 说明了原因。'
        reason:
          type: string
          description: >-
            机器可读的原因，匹配时为
            `""`：`no_proven_internal_wallet`、`attribution_disabled`、`already_attributed`、`no_attributed_entity`、`directory_match_no_route`、`gtr_address_lookup_runs_on_dispatch`、`no_membership`、`network_switched_off`、`no_network_address_lookup`、`no_directory_match`、`awaiting_end_user`
            或 `picked_member_without_proven_wallet`。
        vasp:
          type: string
          format: uuid
          nullable: true
          description: 步骤中指定的目录 VASP（若有指定）。
        rail:
          type: string
          nullable: true
          description: 该步骤找到的、可触达该交易对手的通道。
        at:
          type: string
          format: date-time
    TravelRuleNextAction:
      type: object
      description: >-
        推动处于 `COUNTERPARTY_VASP_NOT_FOUND` 或 `COUNTERPARTY_VASP_NOT_REACHABLE`
        状态的转账继续进行的一项操作。请参阅[转账卡住的原因](/zh/transaction-monitoring/travel-rule#为什么转账会卡住)。
      properties:
        action:
          type: string
          enum:
            - select_counterparty_vasp
            - declare_self_hosted
            - add_vasp_hint
            - update_compliance_email
            - resend
          description: >-
            `select_counterparty_vasp`：终端用户在钱包所有权组件中选择目标 VASP，或者您通过 PATCH 传入
            `action=beneficiary_vasp`。`declare_self_hosted`：终端用户在组件中声明该钱包为自托管钱包。`add_vasp_hint`：通过
            VASP 名称、LEI 或 Travel Address（例如目标钱包地址簿条目上的 `travel_address`）告知 Didit
            交易对手是谁，然后重新发送。`update_compliance_email` 和 `resend` 是 `PATCH
            /v3/transactions/{transaction_id}/travel-rule/` 的 `action`
            取值：再次提供交易对手的合规邮箱，并重新运行路由。
        url:
          type: string
          format: uri
          description: >-
            钱包所有权小组件链接，当转账拥有开启的小组件会话时，出现在 `select_counterparty_vasp` 和
            `declare_self_hosted` 状态下。
      required:
        - action
    TravelRuleChainDetails:
      type: object
      description: >-
        当转账涉及的不止是一个地址向另一个地址付款时，该交易所在区块链对其两个钱包的命名方式。对于账户模型区块链上的转账（EVM、Solana、Tron），由于两个地址本身就是钱包，因此该字段为空（`{}`）。匹配、路由和地址簿会优先从此字段读取钱包信息。
      properties:
        chain:
          type: string
          description: 规范链，例如 `BTC`、`XRP`，或用于闪电网络转账的 `LIGHTNING`。
        shape:
          type: string
          enum:
            - utxo
            - memo
            - lightning
        originator:
          $ref: '#/components/schemas/TravelRuleChainSide'
        beneficiary:
          $ref: '#/components/schemas/TravelRuleChainSide'
        utxo:
          type: object
          description: 在 UTXO 转账中：存储的输入和输出（金额为十进制字符串）以及 Didit 将哪些输出读取为何种内容。
          properties:
            inputs:
              type: array
              items:
                $ref: '#/components/schemas/TravelRuleUtxoEntry'
            outputs:
              type: array
              items:
                $ref: '#/components/schemas/TravelRuleUtxoEntry'
            change_output_indexes:
              type: array
              items:
                type: integer
              description: 向输入地址回款的输出。
            beneficiary_output_index:
              type: integer
              nullable: true
              description: 向收款人付款的输出；若无法明确区分则为 null。
        lightning:
          type: object
          description: >-
            在 Lightning 转账中：付款请求的内容。始终包含
            `kind`（`bolt11`、`bolt12_offer`、`bolt12_invoice`、`bolt12_invoice_request`、`lnurl`、`lightning_address`、`node_id`
            或 `unknown`）；BOLT11 发票会附加
            `network`、`payee_node_id`、`payment_hash`、`amount_msat`、`created_at`
            和 `expires_at`；BOLT12 字符串附加 `blinded_paths` 和 `payee_node_id`；LNURL
            或 Lightning Address 附加其 `domain`。不会通过网络解析任何内容：仅对请求进行解码。
          additionalProperties: true
        warnings:
          type: array
          items:
            type: string
            enum:
              - declared_originator_not_an_input
              - declared_beneficiary_not_an_output
              - beneficiary_output_ambiguous
              - beneficiary_output_amount_differs
          description: >-
            值得关注的 UTXO
            不一致性：声明的汇款人不是输入、声明的收款人不是输出、无法区分出单一的收款人输出，或收款人输出支付的金额与交易声明的不一致。
        not_applicable_reason:
          type: string
          enum:
            - LIGHTNING_NO_PAYEE_IDENTIFIER
            - LIGHTNING_BOLT12_BLINDED_PAYEE
            - LIGHTNING_LNURL_NAMES_NO_PAYEE
          description: >-
            在未指明收款人的出站 Lightning 转账中：转账为何为
            `NOT_APPLICABLE`。`LIGHTNING_NO_PAYEE_IDENTIFIER`（请求未指明收款人节点，或无法解码）、`LIGHTNING_BOLT12_BLINDED_PAYEE`（报价通过盲化路径隐藏了收款人）、`LIGHTNING_LNURL_NAMES_NO_PAYEE`（LNURL
            指明的是服务而非收款人）。相同的代码会打开转账的最后一条 `timeline` 条目。
    TravelRuleChainSide:
      type: object
      description: Didit 根据链上数据解析出的其中一方钱包。
      properties:
        address:
          type: string
          description: >-
            钱包。在 memo 网络上为经典地址（XRP X-address 会被拆分为其经典地址和标签）；在闪电网络上为收款人节点 ID
            或闪电网络地址。
        memo:
          type: string
          description: 作为钱包一部分的目标标签或 memo；无则为 `""`。
        source:
          type: string
          enum:
            - declared
            - x_address
            - largest_input
            - only_non_change_output
            - amount_match
            - invoice_payee
            - updated
          description: >-
            钱包来源：`declared`（您的请求）、`x_address`（从 XRP X-address
            拆分）、`largest_input`（贡献最大的 UTXO 输入地址）、`only_non_change_output`（唯一的非找零
            UTXO 输出）、`amount_match`（支付转账金额的那个 UTXO
            输出）、`invoice_payee`（闪电网络付款请求中指定的收款人）、`updated`（稍后通过 `action:
            update_originator_wallet` 设置）。
    TravelRuleUtxoEntry:
      type: object
      description: UTXO 交易的一个输入或输出，与区块链上记录的一致。
      required:
        - address
      properties:
        address:
          type: string
          maxLength: 128
        amount:
          type: string
          nullable: true
          description: 以代币自身为单位的十进制字符串（BTC，而非聪）。可选。
          example: '0.0125'
        txid:
          type: string
          maxLength: 128
          description: 可选。输入所花费的交易。
        vout:
          type: integer
          nullable: true
          minimum: 0
          description: 可选。输入所花费的输出索引。
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        您的应用 API 密钥，可在 Business Console 的“开发者 -> API
        密钥”中获取。主密钥拥有完整访问权限。指定名称的密钥可设置作用域：针对每个资源设为无权限、只读或读写，限定于特定工作流或已通过的会话、限定于
        IP 地址列表，以及设置到期日期。401 表示密钥错误、已撤销或已过期；403 表示未发送密钥、密钥无权访问该资源或操作，或请求来自其 IP
        列表之外的地址；在会话路由上返回 404 表示该会话不在该密钥允许的工作流或状态范围内。没有媒体访问权限的密钥获取到的图片、视频和 PDF
        URL 将为 null；没有会话写入权限的密钥获取到的会话链接和 token 将为 null。请参阅
        https://docs.didit.me/console/api-keys。

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.