> ## 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 للمستفيد

> أكّد عبر Didit أو ارفض أن عميلك يتحكم في محفظة المستفيد لتحويل Travel Rule الوارد المعلّق في حالة UNCONFIRMED_OWNERSHIP.



طلب واجهة 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 ar/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: >-
        كائن التحويل الكامل الذي يتم إرجاعه بواسطة endpoints الخاصة بتأكيد
        الملكية والإنهاء/الإلغاء. طالما أن ملكية المحفظة لتحويل وارد غير مؤكدة،
        يتم إرجاع `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 (الاختصاص القضائي، التحقق، البروتوكول، معرّف الكيان
                القانوني LEI، السجل، الأساسيات، الاستجابة)، كل منها يحتوي على
                {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: >-
            صحيح طالما أن البيانات الشخصية للطرف المقابل محجوبة في هذه
            الاستجابة.
        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` عندما لا يُقدم التتبع أي سبب آخر.
            تؤدي إعادة الإرسال إلى تحريك المعاملة، وبالتالي يتم مسح السبب. راجع
            [سبب تعثر
            المعاملة](/ar/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`، الذي يقارن كل حقل، لذلك يمكن أن يكون التحويل
            COUNTERPARTY_MISMATCHED_DATA بينما تكون هذه القيمة true.
        method:
          type: string
          enum:
            - none
            - exact_token
            - token_subset
            - token_containment
            - sequence_ratio
          description: >-
            كيفية تحديد `matched`: لا يوجد (`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: >-
            من أكده: البريد الإلكتروني لمستخدم لوحة التحكم أو تسمية مفتاح API.
            فارغ في حالة القرار التلقائي.
    TravelRuleDelivery:
      type: object
      description: >-
        حالة آخر رسالة يتعين على التحويل إرسالها إلى الطرف المقابل. تتواصل Didit
        مع الطرف المقابل بعد عودة استجابة الطلب الذي أنشأ التحويل أو عدّله، لذا
        يوضح هذا الكائن ما إذا كانت تلك الرسالة قد وصلت: في قائمة الانتظار
        (queued)، أو قيد الإرسال (being sent)، أو في انتظار إعادة المحاولة بعد
        حدوث خطأ (waiting to be retried after an error)، أو تم تسليمها
        (delivered)، أو فشلت (failed). عند حدوث فشل قد تتعافى منه الشبكة لاحقاً
        (عدم وجود رد في الوقت المحدد، أو فشل الاتصال، أو رموز HTTP `408` أو
        `429` أو `5xx`)، تتم إعادة المحاولة بعد 30 ثانية، ودقيقتين، و10 دقائق،
        و30 دقيقة، وساعة واحدة. عندما تفشل الرسالة الأولى (`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: >-
            المسار الذي ينقل الرسالة. يكون فارغاً حتى تختار 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: المسار الذي يصل إلى ذلك الطرف المقابل، عندما تعثر الخطوة على مسار.
        at:
          type: string
          format: date-time
    TravelRuleNextAction:
      type: object
      description: >-
        إجراء واحد ينقل تحويلاً بحالة `COUNTERPARTY_VASP_NOT_FOUND` أو
        `COUNTERPARTY_VASP_NOT_REACHABLE` إلى المرحلة التالية. راجع [أسباب تعثر
        التحويل](/ar/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 التي تستحق المراجعة: المُرسِل المُعلَن ليس مدخلاً، أو
            المستفيد المُعلَن ليس مخرجاً، أو لم يتم التمكن من تمييز مخرج مستفيد
            واحد، أو أن مخرج المستفيد يدفع مبلغاً مختلفاً عما تنص عليه المعاملة.
        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` (مفصولة من عنوان XRP
            X-address)، `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: اختياري. المعاملة التي ينفقها مدخل ما.
        vout:
          type: integer
          nullable: true
          minimum: 0
          description: اختياري. فهرس المخرج الذي ينفقه مدخل ما.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        مفتاح API الخاص بتطبيقك، من Developers -> API keys في Business Console.
        يمتلك المفتاح الأساسي وصولاً كاملاً. يمكن تحديد نطاق المفتاح المسمى: لا
        شيء، أو قراءة، أو كتابة لكل مورد، ومحدوداً ببعض مسارات العمل أو بالجلسات
        المقبولة، وبقائمة من عناوين IP، وبتاريخ انتهاء الصلاحية. يشير 401 إلى أن
        المفتاح غير صحيح أو ملغى أو منتهي الصلاحية؛ ويشير 403 إلى أنه لم يتم
        إرسال أي مفتاح، أو أن المفتاح ليس لديه حق الوصول إلى هذا المورد أو
        الإجراء، أو أن الطلب جاء من عنوان خارج قائمة عناوين IP الخاصة به؛ ويشير
        404 في مسار جلسة إلى أن الجلسة خارج مسارات العمل أو الحالات الخاصة
        بالمفتاح. يتلقى المفتاح الذي لا يمتلك حق الوصول إلى الوسائط عناوين URL
        للصور ومقاطع الفيديو وملفات PDF كـ 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.