> ## 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.

# API подтверждения владения кошельком получателя

> Подтвердите или отклоните владение кошельком получателя входящего перевода Travel Rule в статусе UNCONFIRMED_OWNERSHIP в Didit.



Подсказка для API подтверждения владения кошельком
        Скопировать промпт в буфер обмена



      
      

\<pre>

\`Confirm or deny wallet ownership on a Travel Rule transfer waiting on the beneficiary side - typically the beneficiary leg of an INTERNAL-rail transfer whose wallet address book entry has not been ownership-verified yet, a transfer whose counterparty wallet was declared self-hosted (counterparty.payment_method.method_type: "unhosted_wallet"), an inbound transfer in ON_HOLD, or an inbound TRP inquiry a compliance officer resolves by hand.

Endpoint:
POST https://verification.didit.me/v3/transactions/{transaction_id}/travel-rule/ownership/

Authentication:
Use the x-api-key header with my Didit API key. {transaction_id} is the Didit transaction uuid of the transfer your own application holds: on an INTERNAL-rail transfer that is your (beneficiary) side; on a declared self-hosted wallet it is the transaction you created, outbound or inbound.

Request body:
\{"confirmed": true}   or   {"confirmed": false}
Optionally {"confirmed": true, "wallet_address": "0x..."} - the payment address to return to the counterparty on an inbound TRP transfer.
On a declared self-hosted wallet transfer with no counterparty wallet on it, "wallet_address" supplies the wallet to verify; if neither the transfer nor the request names one, the request is rejected with 400.

Accepted states (anything else -> 409 "Transfer is not awaiting ownership confirmation."):
\- UNCONFIRMED_OWNERSHIP, in either direction.
\- ON_HOLD on an inbound transfer.
\- UNCONFIRMED_OWNERSHIP, ON_HOLD or COUNTERPARTY_MISMATCHED_DATA on an inbound TRP transfer.

Behavior on a transfer Didit created itself (INTERNAL rail, sunrise registration, declared self-hosted wallet):
\- confirmed: true - marks the matching wallet address book entry ownership-verified, then runs the beneficiary name match on both sides: COMPLETED on a pass, COUNTERPARTY_MISMATCHED_DATA on a fail.
An inbound transfer whose deposit already settled then moves on to FINISHED.
\- confirmed: true on a declared self-hosted wallet - records that the customer verified who controls the counterparty wallet and completes the transfer (COMPLETED), outbound or inbound; an inbound deposit whose on-chain hash is already known moves on to FINISHED. The wallet is the counterparty's: the destination of a withdrawal, the originator's source wallet of a deposit. If it is not in the wallet address book yet, it is added as ownership-verified under the counterparty's name; if the book already holds it under a different holder name, the transfer goes to COUNTERPARTY_MISMATCHED_DATA.
\- confirmed: false - moves both sides of the transfer to COUNTERPARTY_VASP_GENERAL_DECLINE.
\- Resolving an inbound ON_HOLD with no matching entry, or confirming a declared self-hosted wallet, creates the entry from the transfer's wallet address and marks it verified.

Behavior on an inbound TRP transfer (answering the counterparty's inquiry):
\- confirmed: true - needs a payment address, taken from the request's wallet_address, then the matched entry, then beneficiary_data.wallet_address.
Didit creates or verifies the entry, posts the inquiry-resolution callback to the counterparty, sets ownership_confirmed and moves the transfer to COMPLETED.
\- confirmed: false - posts a declined resolution and moves the transfer to COUNTERPARTY_VASP_GENERAL_DECLINE.

Transfers a network delivered (GTR or Sygna Bridge):
\- An inbound transfer that waits for your review (UNCONFIRMED_OWNERSHIP, ON_HOLD or COUNTERPARTY_MISMATCHED_DATA) is decided here: confirmed: true approves it (send wallet_address when the transfer names none), confirmed: false declines it. Didit answers the network after the response, with retries; the response's delivery field shows that answer.
\- VerifyVASP takes its answer when it asks, so a VerifyVASP transfer that would need your review is declined at once and cannot be decided here.
\- Receiving over a network is switched on by Didit per network, and none is switched on today.

What to read from the response:
\- The full transfer object. originator_data/beneficiary_data stay masked on inbound transfers (data_masked: true) until ownership is confirmed; data_unmasked then records when, why and by whom. data_match and mismatched_fields name the fields that differ after a mismatch.

Alternative: instead of this API call, send the end customer through the hosted wallet-ownership widget (POST /v3/travel-rule/widget-session/) and let them prove control cryptographically.

Failure modes:
\- 400 - on an inbound TRP approval with no payment address available: {"wallet_address": ["wallet_address is required to approve."]}.
\- 409 - the transfer is not in one of the accepted states, no entry in your wallet address book matches the transfer's wallet address (an inbound TRP approval, and an inbound ON_HOLD transfer that carries beneficiary_data.wallet_address, and a declared self-hosted wallet, create the missing entry instead), an INTERNAL transfer from another Didit customer needs a control proof (signed message or test deposit) first, or a network transfer was already answered over its network (a VerifyVASP transfer, or a GTR or Sygna Bridge transfer already decided).
\- 502 - the counterparty's TRP inquiry-resolution callback could not be delivered; the transfer keeps its current status.
\- 404 - unknown transaction or no Travel Rule transfer attached.

Full guide: /transaction-monitoring/travel-rule#confirming-wallet-ownership.`

\</pre>



      
      

Вставьте в

## Некастодиальные кошелькиКогда для кошелька контрагента указано, что он некастодиальный (`counterparty.payment_method.method_type: "unhosted_wallet"`), перевод ожидает в статусе `UNCONFIRMED_OWNERSHIP`.
Вызов этого endpoint с `confirmed: true` фиксирует, что ваш клиент подтвердил, кто контролирует этот кошелёк, и завершает перевод (`COMPLETED`) как для исходящих выводов, так и для входящих депозитов.
Входящий депозит, ончейн-хэш которого уже известен, переходит в статус `FINISHED`.Проверяется кошелёк контрагента: кошелёк назначения исходящего вывода или источник входящего депозита, то есть кошелёк отправителя.
Didit добавляет его в адресную книгу кошельков с отметкой о подтверждённом владении и привязывает к имени контрагента, поэтому сверка выполняется по имени контрагента (для депозита по имени отправителя).
Если в адресной книге этот кошелёк уже записан на другое имя владельца, перевод переходит в статус `COUNTERPARTY_MISMATCHED_DATA`.Если в переводе не указан кошелёк контрагента, передайте `wallet_address` в теле запроса.
Если ни перевод, ни запрос не содержат адрес кошелька, запрос отклоняется с ошибкой `400`.`confirmed: false` отклоняет перевод (`COUNTERPARTY_VASP_GENERAL_DECLINE`).


## OpenAPI

````yaml ru/openapi-25.json POST /v3/transactions/{transaction_id}/travel-rule/ownership/
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/transactions/{transaction_id}/travel-rule/ownership/:
    post:
      tags:
        - Travel Rule
      summary: Подтвердить или опровергнуть владение кошельком
      description: >-
        Разрешить перевод, ожидающий подтверждения владения кошельком: вызывайте
        этот метод со своей стороны перевода, когда он находится в статусе
        UNCONFIRMED_OWNERSHIP, или когда это входящий перевод в статусе ON_HOLD.
        Подтверждение помечает соответствующую запись в адресной книге кошельков
        как проверенную на владение (для входящего перевода в ON_HOLD без записи
        Didit создаёт её из beneficiary_data.wallet_address) и запускает
        сопоставление имени получателя на обеих сторонах перевода; отклонение
        отклоняет обе стороны. Входящий перевод, депозит по которому уже
        зачислен, переходит в FINISHED при успешном сопоставлении. Если кошелёк
        контрагента был заявлен как некастодиальный
        (counterparty.payment_method.method_type: unhosted_wallet),
        подтверждение фиксирует, что клиент проверил, кто контролирует этот
        кошелёк, и завершает перевод (COMPLETED) в обоих направлениях, либо
        переводит в FINISHED для входящего депозита, ончейн-хеш которого уже
        известен. Проверяемый кошелёк принадлежит контрагенту: это адрес
        назначения исходящего вывода или источник (кошелёк отправителя)
        входящего депозита. Если его ещё нет в вашей адресной книге кошельков,
        Didit добавляет его как проверенный на владение под именем контрагента;
        если в книге уже есть эта запись под другим именем владельца, перевод
        переходит в COUNTERPARTY_MISMATCHED_DATA. Для входящего перевода TRP в
        статусе UNCONFIRMED_OWNERSHIP, ON_HOLD или COUNTERPARTY_MISMATCHED_DATA
        Didit отправляет ваше решение инициирующему VASP: одобрение возвращает
        платёжный адрес (wallet_address или адрес совпавшей записи) и переводит
        перевод в COMPLETED, а отклонение отклоняет его. Этот же вызов выносит
        решение по входящему переводу, отправленному контрагентом GTR или Sygna
        Bridge, который ожидает вашей проверки (`UNCONFIRMED_OWNERSHIP`,
        `ON_HOLD` или `COUNTERPARTY_MISMATCHED_DATA`): `confirmed: true`
        одобряет его (передайте `wallet_address`, если в переводе он не указан),
        а `confirmed: false` отклоняет его, после чего сети отправляется ответ с
        повторными попытками. VerifyVASP получает ответ в момент запроса,
        поэтому перевод VerifyVASP, требующий вашей проверки, отклоняется сразу
        и не может быть разрешён позже.
      operationId: confirmTravelRuleOwnership
      parameters:
        - name: transaction_id
          in: path
          required: true
          description: >-
            Стабильный UUID транзакции Didit, которую ваше приложение хранит для
            этого перевода: транзакция на стороне получателя при переводе по
            каналу INTERNAL или транзакция, созданная вами (исходящая или
            входящая), если кошелёк контрагента был заявлен как некастодиальный.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TravelRuleOwnershipConfirmRequest'
            example:
              confirmed: true
      responses:
        '200':
          description: >-
            Обновлённый перевод. Для входящего перевода
            originator_data/beneficiary_data контрагента остаются маскированными
            (`data_masked: true`) до тех пор, пока не будет подтверждена
            структура владения, затем `data_unmasked` фиксирует, когда, почему и
            кем.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TravelRuleTransferDetail'
        '400':
          description: >-
            Ошибка валидации: отсутствует confirmed, входящее подтверждение TRP
            не содержит wallet_address и резервного адреса, либо передано
            `confirmed: true` для заявленного перевода на некастодиальный
            кошелёк, в котором не указан кошелёк контрагента и не был передан
            `wallet_address`.
          content:
            application/json:
              examples:
                No payment address:
                  value:
                    wallet_address:
                      - wallet_address is required to approve.
        '404':
          description: >-
            Неизвестная транзакция, либо у транзакции отсутствует перевод Travel
            Rule.
        '409':
          description: >-
            Перевод не ожидает подтверждения владения, ни одна запись в адресной
            книге кошельков не соответствует кошельку контрагента, внутренний
            (INTERNAL) перевод от другого клиента Didit требует подтверждения
            контроля (подписанного сообщения или тестового депозита) перед
            подтверждением либо по сетевому переводу уже был дан ответ через
            соответствующую сеть (перевод VerifyVASP или перевод GTR/Sygna
            Bridge, по которому вы или Didit уже приняли решение).
          content:
            application/json:
              examples:
                Not awaiting confirmation:
                  value:
                    detail: Transfer is not awaiting ownership confirmation.
                No matching address book entry:
                  value:
                    detail: wallet address entry no longer available
        '502':
          description: >-
            Только для входящих переводов TRP: Didit не удалось доставить ваше
            решение исходному VASP, поэтому статус перевода не меняется.
          content:
            application/json:
              examples:
                Callback not delivered:
                  value:
                    detail: >-
                      Counterparty inquiry-resolution callback could not be
                      delivered.
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: curl
          label: curl
          source: >-
            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}'
        - lang: python
          label: Python
          source: |-
            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)
        - 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.confirmOwnership("11111111-2222-3333-4444-555555555555",
            {
              confirmed: true,
            });

            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.ConfirmOwnership(ctx, \"11111111-2222-3333-4444-555555555555\", didit.TravelRuleOwnershipConfirmRequest{\n\tConfirmed: true,\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.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);
        - lang: php
          label: PHP
          source: >-
            <?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());
        - lang: ruby
          label: Ruby
          source: |-
            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_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.ConfirmOwnershipAsync("11111111-2222-3333-4444-555555555555",
            new TravelRuleOwnershipConfirmRequest

            {
                Confirmed = true,
            });

            Console.WriteLine(JsonSerializer.Serialize(result));
components:
  schemas:
    TravelRuleOwnershipConfirmRequest:
      type: object
      required:
        - confirmed
      properties:
        confirmed:
          type: boolean
          description: true для подтверждения владения, false для отклонения.
        wallet_address:
          type: string
          default: ''
          description: >-
            Входящие переводы TRP: адрес платежа, который Didit возвращает
            исходному VASP при одобрении. По умолчанию используется адрес из
            совпадающей записи адресной книги, затем
            beneficiary_data.wallet_address. Для заявленного перевода с
            некастодиального кошелька без указания кошелька контрагента:
            кошелёк, владение которым вы подтвердили; без него запрос
            отклоняется с кодом 400. Игнорируется для других переводов.
    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: >-
            Транспортная сеть (rail), через которую был направлен перевод, или
            null, если сеть не была выбрана (например, ниже порога,
            некастодиальный кошелёк контрагента, регистрация после депозита или
            отсутствие доступного контрагента). INTERNAL означает, что обе
            стороны являются приложениями Didit; EMAIL означает, что контрагент
            получил ссылку для получения по электронной почте. TEST_VASP
            означает, что Didit Test VASP ответил на перевод в песочнице. В
            сетях GTR, VERIFYVASP и SYGNA Didit считывает ответ контрагента из
            ответа сети или опрашивает её каждые 5 минут. TRUST работает только
            на отправку, поэтому перевод через TRUST остаётся в статусе
            AWAITING_COUNTERPARTY до истечения срока действия. Сетевой rail
            используется только тогда, когда вы подключили собственное участие
            (membership) для этой сети. Он выбирается после возврата ответа
            создания транзакции, поэтому в этом ответе он равен 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: >-
            Текущий статус последнего сообщения, которое этот перевод должен
            отправить другой стороне. Null, если перевод не требовал отправки
            сообщения (например, ниже `threshold_amount`, заявленный
            некастодиальный кошелёк или регистрация в рамках sunrise-периода).
        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 из каталога, у которого нет маршрута),
            `picked_member_without_proven_wallet` (конечный пользователь выбрал
            клиента Didit, который не подтвердил контроль над кошельком) или
            `no_directory_match`, если трассировка не возвращает иной причины.
            Повторная отправка продвигает перевод дальше, поэтому причина
            сбрасывается. См. [Почему перевод
            приостановлен](/ru/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`. Причина типа discovery предлагает
            `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`, где сравнивается каждое поле, поэтому перевод может
            иметь статус COUNTERPARTY_MISMATCHED_DATA, даже если здесь true.
        method:
          type: string
          enum:
            - none
            - exact_token
            - token_subset
            - token_containment
            - sequence_ratio
          description: >-
            Как определялось `matched`: none (`NONE`), exact_token (`STRICT`),
            token_subset (`DEFAULT`), token_containment (`CONTAINS`) или
            sequence_ratio (`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: Слова из `transfer_name`, найденные в `compared_name`.
        mismatched_names:
          type: array
          items:
            type: string
          description: >-
            Слова из `transfer_name`, отсутствующие в `compared_name`, затем
            слова из `compared_name`, отсутствующие в `transfer_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: >-
                  `not_compared`, если правило имеет значение `NONE` или на
                  одной из сторон отсутствует значение для поля.
              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: >-
            Кто подтвердил решение: email пользователя консоли или метка
            API-ключа. Пусто для автоматического решения.
    TravelRuleDelivery:
      type: object
      description: >-
        Текущий статус последнего сообщения, которое перевод должен отправить
        другой стороне. Didit связывается с контрагентом после возврата ответа
        на запрос, создавший или изменивший перевод, поэтому данный объект
        показывает, было ли доставлено это сообщение: в очереди, отправляется,
        ожидает повторной попытки после ошибки, доставлено или произошел сбой. В
        случае сбоя, после которого сеть еще может восстановиться (нет ответа
        вовремя, ошибка соединения, HTTP `408`, `429` или `5xx`), повторная
        попытка выполняется через 30 секунд, 2 минуты, 10 минут, 30 минут и 1
        час. Если первое сообщение (`kind: SEND`) окончательно завершается сбоем
        из-за отказа сети или неудачи шестой попытки, перевод переходит в статус
        `COUNTERPARTY_VASP_NOT_REACHABLE` с полем `last_error` в истории
        `timeline`; любое другое сообщение, окончательно завершившееся ошибкой,
        фиксируется в `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: >-
            Транспортная сеть (rail), передающая сообщение. Пусто до тех пор,
            пока 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`: имя VASP,
            LEI или юрисдикция, переданные вами в `beneficiary_data`.
            `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: >-
            Транспортная сеть (rail), через которую достигается этот контрагент,
            если шаг её обнаружил.
        at:
          type: string
          format: date-time
    TravelRuleNextAction:
      type: object
      description: >-
        Одно действие, которое позволяет продвинуть перевод со статусом
        `COUNTERPARTY_VASP_NOT_FOUND` или `COUNTERPARTY_VASP_NOT_REACHABLE`. См.
        раздел [Почему перевод
        завис](/ru/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`: укажите Didit, кто является контрагентом, с помощью
            названия VASP, LEI или Travel Address (например, `travel_address` в
            записи адресной книги кошелька назначения), затем повторите
            отправку. `update_compliance_email` и `resend` являются значениями
            `action` для `PATCH /v3/transactions/{transaction_id}/travel-rule/`:
            передайте адрес электронной почты комплаенс-службы контрагента
            повторно и перезапустите маршрутизацию.
        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` для
            перевода через 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, заслуживающие внимания: заявленный отправитель
            отсутствует во входах (inputs), заявленный получатель отсутствует в
            выходах (outputs), невозможно выделить единственный выход получателя
            или сумма в выходе получателя отличается от указанной в транзакции.
        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
            разделяется на классический адрес и тег); в Lightning это
            идентификатор узла получателя или Lightning Address.
        memo:
          type: string
          description: >-
            Destination tag или memo, являющиеся частью кошелька; `""`, если
            отсутствует.
        source:
          type: string
          enum:
            - declared
            - x_address
            - largest_input
            - only_non_change_output
            - amount_match
            - invoice_payee
            - updated
          description: >-
            Откуда получен кошелёк: `declared` (ваш запрос), `x_address`
            (выделен из X-адреса XRP), `largest_input` (входной адрес UTXO с
            наибольшим вкладом), `only_non_change_output` (единственный выход
            UTXO, не являющийся сдачей), `amount_match` (единственный выход
            UTXO, выплачивающий сумму перевода), `invoice_payee` (получатель,
            указанный в платежном запросе Lightning), `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: Необязательно. Транзакция, которую расходует вход (input).
        vout:
          type: integer
          nullable: true
          minimum: 0
          description: >-
            Необязательно. Индекс выхода (output index), который расходуется
            входом (input).
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API-ключ вашего приложения из раздела «Разработчикам» -> «API-ключи» в
        Business Console. Основной ключ имеет полный доступ. Именованный ключ
        может иметь ограниченную область действия: без доступа, чтение или
        запись для каждого ресурса, ограничение определенными сценариями или
        одобренными сессиями, списком IP-адресов и сроком действия. 401
        означает, что ключ неверен, отозван или его срок действия истек; 403
        означает, что ключ не был передан, у ключа нет доступа к этому ресурсу
        или действию, либо запрос поступил с адреса вне его списка IP-адресов;
        404 на маршруте сессии означает, что сессия не входит в сценарии или
        статусы ключа. Ключ без доступа к медиа получает URL изображений, видео
        и PDF как null, а ключ без прав на запись сессий получает ссылки на
        сессии и токены как null. См. https://docs.didit.me/console/api-keys.

````

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