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

# Travel Rule API من FATF: امتثال VASP

> يوفر Didit رسائل Travel Rule لمنصات VASP وPSP: تبادل بيانات المُرسِل والمستفيد وتتبع البروتوكول والإصلاح التلقائي. $0.02 لكل تبادل.

تُجري Didit تبادل بيانات المُرسِل والمستفيد وفق لائحة FATF/الاتحاد الأوروبي بشأن تحويل الأموال (TFR) لتحويلات الأصول الافتراضية. فهي تبحث عن مسار يصل إلى الـ VASP المقابل، وتتفاوض على البيانات المطلوبة عبره، وتتابع التبادل عبر دورة حياة من 13 حالة، وتُخطرك عند اكتمال التبادل حتى تتمكن من تحرير الأموال على السلسلة.

## نظرة عامة

تُلزم توصية FATF رقم 16 (Travel Rule)، التي تُطبَّق في الاتحاد الأوروبي عبر لائحة تحويل الأموال (Transfer of Funds Regulation)، مزودَ خدمات الأصول الافتراضية المُرسِل (**originator VASP**) بجمع معلومات المُرسِل والمستفيد وإرسالها إلى مزود خدمات الأصول الافتراضية المستقبِل (**beneficiary VASP**) قبل تسوية تحويل الأصل الافتراضي.

على خلاف معظم الولايات القضائية، تُطبَّق لائحة TFR الأوروبية **دون حد أدنى للمبلغ**، أي أن كل تحويل للعملات المشفّرة يدخل في نطاقها، وليس فقط التحويلات التي تتجاوز عتبة الإبلاغ.

منتج Travel Rule من Didit تبادلٌ مُدار، وليس مجرد حقل بيانات:

* تُرسِل التحويل باستخدام `transaction_category: "travelRule"`.
* تجرّب Didit المسارات بحسب ترتيب الأولوية للوصول إلى مزود الخدمات المقابل، وتُنفّذ التبادل عبر أول مسار يصل إليه، وإذا أعاد الطرف الآخر اسم المستفيد، تُطابقه مع الاسم الذي أرسلته.
* لا تبثّ التحويل على السلسلة إلا بعد أن يصل التبادل إلى `COMPLETED`.
* ثم ترفع تجزئة معاملة على السلسلة إلى Didit لإغلاق التبادل بحالة `FINISHED`.

يتضمن هذا الإصدار سبعة مسارات تُجرَّب بترتيب أولوية صارم، والمسار الأول القادر على الوصول إلى الطرف المقابل يفوز:

| الأولوية | المسار | طريقة العمل |
| - | - | - |
| 1 | `INTERNAL` | يُستخدم عندما أثبت عميل آخر في Didit سيطرته على محفظة المستفيد بتوقيع رسالة أو بإيداع تجريبي. تُنشئ Didit تحويلًا واردًا مطابقًا في تطبيق ذلك العميل، وتتفاوض على التبادل داخل المنصة بالكامل دون أي استدعاء لشبكة خارجية. فوري. |
| 2 | `TRP` | تكامل أصلي مع بروتوكول Travel Rule المفتوح (TRP / OpenVASP). يُستخدم عندما يحمل التحويل [Travel Address](#عناوين-travel-address)، أو عندما يحتوي إدخال المحفظة المقصودة في دفتر العناوين على واحد، أو عندما يُحَلّ مزود الخدمات المقابل في [الدليل](#الدليل) مع نقطة نهاية TRP. يحمل الأصول المدرجة ضمن [معرّفات أصول TRP](#معرّفات-أصول-trp). تتبادل Didit بيانات المُرسِل والمستفيد آليًا بين الأنظمة، دون أي جولة عبر البريد الإلكتروني. |
| 3 | `GTR` | شبكة Global Travel Rule (GTR). يُحدَّد الطرف المقابل بواسطة `counterparty_gtr_vasp_code` صريح أو بإدخال في الدليل يحمله. تقرأ Didit رد الطرف المقابل من استجابة GTR، أو عبر الاستعلام عن حالة الطلب كل 5 دقائق أثناء انتظار التحويل. |
| 4 | `TRUST` | شبكة TRUST. يُحدَّد الطرف المقابل بواسطة `counterparty_trust_membership_id` أو بإدخال في الدليل يحمله. للإرسال فقط: لا يعيد TRUST أي شيء تستطيع Didit قراءته، لذلك يبقى التحويل في `AWAITING_COUNTERPARTY` حتى تنتهي صلاحيته. |
| 5 | `VERIFYVASP` | شبكة VerifyVASP. يُحدَّد الطرف المقابل بواسطة `counterparty_verifyvasp_id` أو بإدخال في الدليل يحمله. تقرأ Didit رد الطرف المقابل بالاستعلام عن حالة التحقق كل 5 دقائق. |
| 6 | `SYGNA` | شبكة Sygna Bridge (استحوذت عليها VerifyVASP في 2026، وما زالت تعمل للأعضاء الحاليين). تنفيذ أصلي لبروتوكول Sygna، يشمل IVMS101 مشفّرة بـ ECIES مع طلبات إذن موقّعة. يُحدَّد الطرف المقابل بواسطة `counterparty_sygna_vasp_code` أو بإدخال في الدليل يحمله. يُكمل رد الطرف المقابل بالقبول التحويل أو يرفضه: تستعلم Didit عن حالة التحويل كل 5 دقائق، وتتلقى الرد أيضًا عبر رد الاستدعاء الخاص بـ Sygna بمجرد تشغيل مضيف TRP العام الخاص بـ Didit. |
| 7 | `EMAIL` | مسار احتياطي يُستخدم عندما لا يصل أي بروتوكول أو مسار شبكة إلى الطرف المقابل، وتسمّي جهة اتصال الامتثال الخاصة به في `counterparty_vasp_email`، أو عندما يحمل إدخاله في الدليل [جهة اتصال للامتثال](#جهات-الاتصال). ترسل Didit إلى جهة الاتصال رابط استلام لمرة واحدة، فيمكنها تأكيد التبادل أو رفضه دون حساب في Didit. وهذا هو المسار الأساسي لمشكلة بدء التشغيل، أي الجهات التي لا يمكن الوصول إليها بعد عبر أي شبكة. |

تحتاج مسارات الشبكات (`GTR` و`TRUST` و`VERIFYVASP` و`SYGNA`) إلى عضوية شبكة لدى الجهة المُرسِلة، وحاليًا يجب أن تكون هذه العضوية **خاصة بك**.
اربط بيانات اعتماد عضويتك في وحدة التحكم ضمن **Marketplace** (فئة شبكات Travel Rule)، وستنتقل تحويلاتك بهوية الشبكة الخاصة بك.

**لا تملك Didit حاليًا أي عضوية منصّة في أي من الشبكات الأربع، وهي قيد التسجيل كمزوّد فيها.**
حتى يكتمل هذا الانضمام، تكون قيمة `platform_available` هي `false` للشبكات الأربع، ولا يكون وضع `didit` في الإعدادات (التوجيه عبر عضوية Didit في المنصة) متاحًا لأي شبكة، ولا تحتوي `disabled_networks` على شيء لإيقافه.
للعضوية التي تربطها بنفسك الأولوية دائمًا على عضوية المنصة.
لا تُضمَّن أي عضوية شبكة افتراضيًا، بما في ذلك GTR.
لا يؤدي تفعيل Travel Rule إلى تفعيل GTR أو TRUST أو VerifyVASP أو Sygna.
راجع [Get Travel Rule Settings](https://docs.didit.me/ar/management-api/travel-rule/get-settings.md) للاطلاع على أوضاع `networks` الفعّالة لتطبيقك، و[Travel Rule networks](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md) لمعرفة ما تصل إليه كل شبكة اليوم.
إذا أبلغت الشبكات الأربع جميعها عن `unavailable`، فلا تستطيع أي منها توجيه تبادل: اربط عضويتك الخاصة في **Marketplace**، أو استخدم طرفًا مقابلًا يمكن الوصول إليه عبر `INTERNAL` أو `TRP` أو `EMAIL`.

عند حفظ عضوية، يجب أن يكون رمز المشارك خاصًا بك: يُرفض الحفظ بالرد `400` إذا كان الرمز هو رمز Didit الخاص على تلك الشبكة، أو رمزًا تحمله بالفعل عضوية تطبيق آخر.
تحتاج عضوية GTR إلى مفتاحها الخاص ed25519 (بترميز base64)، وهو المفتاح الذي يُسجَّل مفتاحه العام في بوابة GTR: يُشفّر البيانات الشخصية التي ترسلها، ويفكّ تشفير البيانات التي تستقبلها.
تشير عضوية VerifyVASP إلى Enclave الخاص بك: عنوان URL الخاص بها هو عنوان Enclave الخاص بك، وtoken الخاص بها هو الذي يقدّمه Enclave إلى Didit.

حتى مع عضويتك الخاصة، لا يوجّه مسار الشبكة تحويلًا إلا إذا كان `beneficiary_data` يحمل معرّف الطرف المقابل على تلك الشبكة (`counterparty_gtr_vasp_code` أو `counterparty_trust_membership_id` أو `counterparty_verifyvasp_id` أو `counterparty_sygna_vasp_code`)، أو إذا كان إدخال الطرف المقابل في الدليل يدرجه على تلك الشبكة (انظر [Routes](#المسارات)).

يُبلغ `platform_available` عمّا إذا كانت عضوية المنصة مُعدّة، وليس فحصًا حيًا لصحة الشبكة. وبالمثل، تعني `connected` أن بيانات اعتماد عضويتك محفوظة وقد اجتازت التحقق المحلي، أما التحقق الفعلي منها لدى الشبكة فيحدث مع أول تبادل حي. ووضع `didit` أو `own` لا يضمن إمكانية وصول الطرف المقابل ولا نجاح التسليم.

بفضل عضويتك الخاصة، يقرأ Didit ردّ الطرف المقابل عبر `GTR` و`VERIFYVASP` و`SYGNA` من استجابة الشبكة، أو عبر الاستعلام عن الشبكة كل 5 دقائق، وهو ما يُكمل التحويل أو يرفضه.
`TRUST` يقتصر على الإرسال: يبقى التحويل المُرسل عبره في حالة `AWAITING_COUNTERPARTY` حتى تنقضي مدة `confirmation_timeout_hours`، ثم ينتقل إلى حالة `EXPIRED`، ويُطبَّق عندها `timeout_outcome` الخاص بك.
استقبال تحويل يرسله إليك VASP آخر عبر شبكة غير مفعّل بعد، ولم يُستكمل أي تبادل عبر شبكة مع شبكة فعلية حتى الآن: راجع [شبكات Travel Rule](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md).

الشبكات الأخرى، وهي CODE (التحالف الكوري)، وTRISA، وNotabene، وVeriscope، مدرجة في **Marketplace** في وحدة التحكم كبطاقات لطلب الوصول.
Didit لا يملك تكاملاً معها بعد، لذلك لا يمكن توجيه أي تحويل عبرها اليوم.

عندما تعجز المسارات السبعة كلها عن تحديد الطرف المقابل، ينفّذ Didit خطوة تحديد إضافية واحدة قبل أن يستسلم: إسناد تحليلات البلوكتشين.
يُبحث عن محفظة الوجهة في بيانات تحليلات البلوكتشين؛ فإذا كانت المحفظة تابعة لبورصة أو حافظ أمانة معروف، يسجّل Didit VASP المُسنَد على التحويل، ويضيفه إلى [الدليل](#الدليل)، ويعيد تشغيل المسارات مرة واحدة بالاسم الجديد.
راجع [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) للاطلاع على السلوك الكامل والأسعار.

التحويل الذي تكون وجهته [معلنةً كمحفظة ذاتية الاستضافة](#المحافظ-ذاتية-الاستضافة-المُصرَّح-بها) يتجاوز المسارات السبعة كلها، إذ لا يوجد VASP مقابل للتبادل معه، وينتقل مباشرةً إلى إثبات ملكية المستخدم النهائي للمحفظة.

> [!NOTE]
>
> يدير Didit أيضاً الجانب الموجَّه للطرف المقابل من التبادل: نقاط نهاية TRP العامة للهوية والاستعلام التي تستدعيها VASPs الأطراف المقابلة للوصول إليك، ونقاط نهاية الاستدعاء، وتدفق استلام البريد الإلكتروني.
> أنت لا تستدعي تلك النقاط بنفسك، فهي بنية تحتية مُدارة، لكن صفحة [التوافق البيني لـ Travel Rule](https://docs.didit.me/ar/transaction-monitoring/travel-rule-interoperability.md) توثّق كل واحدة منها حتى تتمكن VASPs الأطراف المقابلة من الاتصال بك.
> لا تتعامل مع Travel Rule إلا عبر نقاط النهاية `/v3/` الموضحة في هذه الصفحة.

## ما الذي ينفَّذ عند إرسال التحويل

تنفَّذ الفحوصات داخل استدعاء واحد هو `POST /v3/transactions/`. عند استلام الاستجابة يكون الفحص قد اكتمل، وتكون بيانات التحويل مخزَّنة، وتكون القواعد قد قُيّمت.
يبدأ التبادل نفسه بعد الاستجابة: تختار Didit المسار وتتواصل مع الطرف المقابل خارج طلبك، لذلك لا يمكن لأي شبكة أو طرف مقابل أن يبطئ إنشاء التحويل أو يُفشله.
يصل كل تغيير في الحالة بعد ذلك في صورة حدث [`travel_rule.status.updated`](#webhooks) يذكر المسار، ويحمل كائن التحويل الذي تعيده نقاط نهاية تحويلات Travel Rule حقلَ [`delivery`](#التسليم-وإعادة-المحاولة) الذي يبيّن ما إذا وصلت الرسالة.
لا يوجد خط معالجة يجب الاستعلام عنه بشكل دوري؛ الأجزاء غير المتزامنة هي التبادل، وردّ الطرف المقابل، وأي إجراء يقوم به المستخدم النهائي.

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant You as Your platform
    participant Didit as Didit API
    participant CP as Counterparty VASP
    participant User as Your customer

    You->>Didit: POST /v3/transactions/ (travelRule)
    Note over Didit: Validate + bind subject + blocklist check
    Note over Didit: Device & IP enrichment
    Note over Didit: Crypto screening (when crypto + monitoring on)
    Note over Didit: Threshold check -> transfer stored (AWAITING_COUNTERPARTY)
    Note over Didit: Rules engine (EU TFR bundle + your rules)
    Didit--)You: transaction.created webhook
    Didit-->>You: Transaction + travel_rule.status + action_required
    Note over Didit: After the response: rails in priority order -> analytics attribution
    Didit->>CP: Exchange over the first reachable rail
    Didit--)You: travel_rule.status.updated (each status change)
    User->>Didit: Proves wallet control (when action_required)
    CP-->>Didit: Confirms beneficiary data
    Didit--)You: travel_rule.status.updated (COMPLETED)
    You->>You: Broadcast on-chain
    You->>Didit: PATCH .../travel-rule/ { payment_txn_id }
    Didit--)You: travel_rule.status.updated (FINISHED)
```

خطوة بخطوة:

1. **التحقق وربط الجهة المعنية.** يُتحقق من صحة الحمولة.
   يُرفض `transaction_id` سبق استخدامه في تطبيقك بالرمز `400`، وإذا تزامن طلبان بالمعرّف نفسه، يتلقى أحدهما الرمز `409`.
   تُربط `subject` بملفك الشخصي للمستخدم أو للشركة عبر `vendor_data`، فيظهر التحويل على ذلك الملف لأغراض المراقبة.
   تُرفض الجهة المعنية أو قيمة `vendor_data` للطرف المقابل إذا كانت مدرجة في قائمة الحظر بالرمز `400`، ولا يُنشأ أي معاملة.
   تُفحص المحافظ وحسابات البنوك وعناوين IP والأجهزة المدرجة في قائمة الحظر في الخطوة 6، وترفض المعاملة هناك بعد تشغيل التوجيه.
2. **إثراء الجهاز والشبكة.** تُضاف بيانات الموقع الجغرافي إلى عناوين IP للأطراف، ويُوحَّد أي سياق للجهاز (يُجمع تلقائياً عند [إرسال SDK](https://docs.didit.me/ar/transaction-monitoring/sdk-transaction-submission.md)) داخل مخطط الأجهزة نفسه الذي تغذّيه جلسات KYC، فتعمل خاصية "مرتبطة بالجهاز" عبر التسجيل والمعاملات معاً.
3. **فحص العملات الرقمية.** بالنسبة إلى تحويلات العملات الرقمية مع تفعيل المراقبة، تُفحص المحفظة المعنية (أو التجزئة على السلسلة) أمام تحليلات البلوكتشين قبل تبادل أي شيء، لكشف التعرض للعقوبات، والقرب من خدمات الخلط، والأموال المسروقة. راجع [فحص العملات الرقمية والمحافظ](https://docs.didit.me/ar/transaction-monitoring/aml-screening.md).
4. **تحويل Travel Rule.** يتحقق محرك التبادل من الحد، ويعتمد [إقرار المحفظة ذاتية الاستضافة](#المحافظ-ذاتية-الاستضافة-المُصرَّح-بها)، ثم يخزّن التحويل: الحالة `NOT_APPLICABLE` إذا كان دون حدك، و`UNCONFIRMED_OWNERSHIP` لمحفظة ذاتية الاستضافة مُقرّ بها، و`COMPLETED` عندما تكون المحفظة الأخرى محفظتك الموثّقة، و`AWAITING_COUNTERPARTY` في غير ذلك، مع بقاء مساره فارغاً.
   يضع كل تغيير في الحالة حدث `travel_rule.status.updated` في الطابور، ويرسله Didit بعد `transaction.created` (الخطوة 7).
5. **إصدار جلسة ملكية المحفظة.** إذا كان التحويل يتطلب إثبات سيطرة من المستخدم النهائي، وكان `auto_wallet_verification` مفعلاً، تُنشأ جلسة [أداة ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) وتُعاد ضمن `action_required`.
6. **تقييم القواعد.** تعمل كل قاعدة نشطة. تتفاعل [حزمة EU TFR](#حزمة-قواعد-eu-tfr) مع حالة التحويل المحددة في الخطوة 4، وترى قواعدك المخصصة نتائج الفحص في الخطوة 3، ويمكن لقاعدة أن تحتجز المعاملة (`IN_REVIEW`)، أو ترفضها، أو تطلب [تحققاً إضافياً](https://docs.didit.me/ar/transaction-monitoring/sdk-transaction-submission.md#الإجراءات-المطلوبة-من-المستخدم) (`AWAITING_USER`).
7. **الفوترة والإشعار.** تُحتسب المعاملة الصادرة في بند واحد: [بند Travel Rule](#الأسعار) عندما تبدأ تبادلاً، وفحص المعاملات في غير ذلك. لا يُحتسب على التحويل الوارد أي رسم، ولا يُحاسَب تطبيق البيئة التجريبية أبداً.
   تُعاد الاستجابة، ويُطلق `transaction.created` إلى وجهات webhook الخاصة بك، تليه أحداث `travel_rule.status.updated` من الخطوة 4.
8. **التوجيه، بعد الاستجابة.** يمرّ Didit على [المسارات السبعة](#نظرة-عامة) بحسب الأولوية؛ فإذا لم يُحلّ أيٌّ منها، يحدّد [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) الطرف المقابل، وتُعاد تشغيل المسارات مرة واحدة. يتولى أول مسار متاح التبادل: يبقى التحويل `AWAITING_COUNTERPARTY` على ذلك المسار بينما يردّ الطرف المقابل، أو يُسوّى فوراً عندما يُطابَق طرف مقابل من نوع `INTERNAL` (`COMPLETED` أو `COUNTERPARTY_MISMATCHED_DATA`)، أو تصبح حالته `COUNTERPARTY_VASP_NOT_FOUND` عندما لا يصل أي مسار إلى الطرف المقابل. يُطلق كل تغيير الحدث `travel_rule.status.updated`، وتعمل قواعدك من جديد كلما تغيّرت الحالة أو المسار. أما التحويل الذي يتركه التوجيه في الحالة `COUNTERPARTY_VASP_NOT_FOUND`، فتُنشأ له جلسة أداة ملكية المحفظة في تلك اللحظة (عندما يكون `auto_wallet_verification` مفعلاً)، وتقرؤها من `action_required` الخاص بالمعاملة باستخدام [الحصول على معاملة](https://docs.didit.me/ar/management-api/transactions/get.md).

### كيف تُقابل كل خطوة التزاماتك

| خطوة المعالجة | الالتزام الذي تفي به |
| - | - |
| بيانات المُرسِل التي تزوّد بها في `originator_data` | دقة معلومات المُرسِل (توصية FATF رقم 16؛ المادة 14 من EU TFR). في المسارات التي تحمل بيانات الأشخاص (`INTERNAL` و`TRP` وشبكات المسارات)، ينقل Didit الهوية الموثّقة عندما تكون الجهة المعنية مستخدماً لديه عملية تحقق KYC معتمدة من Didit (راجع [البيانات الموثّقة ومصدرها](#البيانات-الموثّقة-ومصدرها))، وفي غير ذلك ينقل ما ترسله في `originator_data` تماماً. |
| التبادل عبر المسارات قبل التسوية | نقل معلومات المُرسِل والمستفيد إلى مزوّد خدمات الأصول الافتراضية المقابل **قبل** تسوية التحويل (توصية FATF رقم 16؛ المواد 14-16 من EU TFR) |
| مطابقة اسم المستفيد | التحقق من أن بيانات المستفيد تطابق الوجهة (التزامات المادة 16 على مزوّد خدمات الأصول المشفرة للمستفيد) |
| إثبات ملكية المحفظة ذاتية الاستضافة | التزام EU TFR بالمحفظة ذاتية الاستضافة: التحقق من ملكية عنوان غير مستضاف بدلاً من التبادل مع مزوّد خدمات أصول افتراضية |
| فحص العملات الرقمية وحزمة قواعد EU TFR | إجراءات قائمة على المخاطر للتحويلات التي تفتقر إلى معلومات كاملة أو تحتوي معلومات ناقصة، وضوابط التعرض للعقوبات |
| بوابة `COMPLETED` قبل البث | لا تُفرج الأموال قبل اكتمال التبادل، وهذا جوهر القاعدة |
| الإغلاق `FINISHED` مع التجزئة على السلسلة والجدول الزمني | حفظ السجلات: يحمل كل تحويل جدوله الزمني الكامل للتفاوض لأغراض التدقيق |

> [!NOTE]
>
> **ملاحظة الاختبار.** تتخطى تطبيقات البيئة التجريبية تقييم القواعد والفوترة، ولا ترسل أحداث `transaction.created` أو `transaction.status.updated` عبر webhook. تبقى معاملات البيئة التجريبية في الحالة `APPROVED` ما لم يطبّق تحويل Travel Rule منتهي الصلاحية قيمة `timeout_outcome` الخاصة بك، ولا يُحتسب أي رسم.
> يعمل محرك تبادل Travel Rule نفسه على تطبيقات البيئة التجريبية عند تفعيل Travel Rule، مع طرف مقابل واحد فقط: تذهب كل عملية تبادل **صادرة** إلى [Didit Test VASP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) على المسار `TEST_VASP`، الذي يجيب داخل Didit بالسيناريو الذي تختاره، فيكتمل التحويل أو يُرفض أو يحدث عدم تطابق فيه أو يصبح غير قابل للوصول أو تنتهي صلاحيته أو ينتظر ملكية المحفظة.
> لا تصل أي رسالة امتثال إلى مزوّد خدمات أصول افتراضية حقيقي، وتُسلَّم أحداث `travel_rule.status.updated` مع `environment: sandbox`.
> أما **الوارد**، فيمكن لمزوّد الاختبار أن يرسل إليك تحويلاً ([تشغيل تحويل وارد من VASP الاختباري](https://docs.didit.me/ar/management-api/travel-rule/trigger-test-vasp-inbound.md))، ويُسوّى التسجيل (`POST /v3/travel-rule/inbound/`) مقابل دفتر عناوين محافظك كما في التطبيق الحي: `ON_HOLD` أو `UNCONFIRMED_OWNERSHIP` أو `COUNTERPARTY_MISMATCHED_DATA` أو `COMPLETED` ثم `FINISHED`.
> راجع [اختبار Travel Rule في البيئة التجريبية](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md).

## دورة الحياة

لكل تحويل حالة `status` تُختار من 13 قيمة.
يبدأ التبادل بالحالة `AWAITING_COUNTERPARTY` في الحالة المعتادة، أو بالحالة `NOT_APPLICABLE` عندما يكون المبلغ أقل من `threshold_amount` الخاص بك، أو عندما يخلو طلب دفع Lightning من اسم المستلم (راجع [Lightning](#lightning))، أو بالحالة `UNCONFIRMED_OWNERSHIP` عندما تكون المحفظة المستلِمة قد [أُعلن عنها كمحفظة ذاتية الاستضافة](#المحافظ-ذاتية-الاستضافة-المُصرَّح-بها). وينتهي التبادل بإحدى الحالات النهائية: `FINISHED` أو `CANCELLED` أو `EXPIRED`.

يعمل التحويل بآلة حالات خاصة به، **منفصلة عن** حالة مراجعة المعاملة الأساسية.
لا تغيّر حالة التبادل حالة المعاملة وحدها أبداً، باستثناء حالة واحدة: عند انتهاء الصلاحية يُطبَّق `timeout_outcome` المُعدّ لديك (أو [سياسة sunrise أو سياسة عدم الاستجابة](#سياسات-sunrise-وعدم-الاستجابة) عند انطباقها).
في المقابل، تُعاد تشغيل قواعدك عند كل انتقال، فيمكن لـ[قواعد EU TFR](#حزمة-قواعد-eu-tfr) أو لأي قاعدة تعتمد على `travel_rule_status` أن تنقل المعاملة، مثلاً إلى `IN_REVIEW`.
يُضيف التحويل الذي يحتاج إلى إثبات من المستخدم النهائي على سيطرته على المحفظة كتلة `action_required` إلى المعاملة، لكن حالته `status` تبقى كما تركتها قواعدك.
اقرأ حالة التبادل من `travel_rule.status`، واقرأ قرار السماح / التعليق / الرفض من `status` الخاصة بالمعاملة نفسها.

يُنسخ كل انتقال (وكل حالة تُبلَّغ دون طلب مباشر) أيضاً إلى القيم المخصصة للمعاملة، حتى تتمكن [القواعد](https://docs.didit.me/ar/transaction-monitoring/rules.md) من الاعتماد عليها: `custom_values.travel_rule_status` (الحالة المعيارية)، و`custom_values.travel_rule_rail` (القناة التي حملت التبادل، وتكون فارغة إلى أن تُختار قناة)، و`custom_values.travel_rule_regime` (المشتق من `jurisdiction` في [الإعدادات](#الإعداد) لديك: `SG` → `singapore`، و`GB` → `uk`، وأي رمز لعضو في الاتحاد الأوروبي أو المنطقة الاقتصادية الأوروبية مثل `DE` أو `FR` → `eu`؛ والرموز غير المُدرجة تُكتب بأحرف صغيرة، مثلاً `US` → `us`. وقيمة `props.travel_rule_regime` التي ترسلها بنفسك تتقدم دائماً على القيمة المشتقة).

| الحالة | المعنى |
| - | - |
| `AWAITING_COUNTERPARTY` | ينتظر التحويلُ الطرفَ المقابلَ: أولاً بينما يختار Didit القناة ويرسل التبادل، مباشرة بعد الإنشاء، ثم بينما يردّ الطرف المقابل. يوضح الحقل [`delivery`](#التسليم-وإعادة-المحاولة) في التحويل ما إذا وصلت الرسالة. لا يقوم `TRUST` إلا بالإرسال، لذلك يبقى التحويل الذي يُرسل عبره في هذه الحالة إلى أن تنتهي صلاحيته. |
| `UNCONFIRMED_OWNERSHIP` | التحويل بانتظار إثبات سيطرة المحفظة. تُسجَّل هذه الحالة عندما تكون محفظة الطرف المقابل قد [أُعلن أنها ذاتية الاستضافة](#المحافظ-ذاتية-الاستضافة-المُصرَّح-بها) عند الإرسال (صادرة أو واردة)، أو عندما يُحلّ تحويل وارد إلى [إدخال في دفتر العناوين](#دفتر-عناوين-المحافظ) لم يُتحقق من ملكيته بعد. يتقدّم التحويل عبر [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) أو عبر [`POST .../travel-rule/ownership/`](#تأكيد-ملكية-المحفظة). |
| `ON_HOLD` | لا يضبط Didit هذه الحالة إلا على التحويلات الواردة: عندما لا تكون محفظة الوجهة في [تسجيل بعد الإيداع](#التسجيل-اللاحق-للإيداع) أو في استفسار `TRP` وارد موجودةً في [دفتر العناوين](#دفتر-عناوين-المحافظ) لديك، أو عندما ينتظر استفسار `TRP` وارد قرارك (القبول التلقائي متوقف، أو تعذّر تسليم الرد الآلي). تُعالج الحالة عبر [`POST .../travel-rule/ownership/`](#تأكيد-ملكية-المحفظة). ولا تغيّر حالة المعاملة وحدها؛ فالقاعدة `travel-rule-pending-action` التي يجب تفعيلها اختياريًا من [مكتبة القواعد](https://docs.didit.me/ar/transaction-monitoring/rules-library.md) هي التي تنقل هذه المعاملات إلى `AWAITING_USER`. |
| `COMPLETED` | اكتمل التبادل بنجاح: وافق الطرف المقابل (أو أنت، في التحويل الوارد) على التبادل، أو نجحت الفحوصات التي يُجريها Didit في ذلك المسار (مطابقة اسم المستفيد، وإثبات ملكية المحفظة). يمكن بثّ التحويل على السلسلة بأمان. |
| `FINISHED` | يُغلق التبادل بتجزئة معاملته على السلسلة. في التحويل الصادر تُبلَّغ التجزئة عبر [`PATCH .../travel-rule/`](#إرسال-تحويل). وفي التحويل الوارد يضبطها Didit عندما يكون الإيداع قد تمت تسويته بالفعل ([تسجيل بعد الإيداع](#التسجيل-اللاحق-للإيداع))، أو عندما يؤكد المُرسِل تحويل `TRP`، أو عندما ينتهي الجانب الصادر من `INTERNAL`. |
| `CANCELLED` | أُلغي يدوياً باستخدام `action: "cancel"` من أي حالة غير نهائية، أو ألغاه المُرسِل في تحويل `TRP` وارد. |
| `EXPIRED` | تنقضي مدة `confirmation_timeout_hours` والتحويل ما زال في `AWAITING_COUNTERPARTY`. تقوم مهمة مجدولة (كل 15 دقيقة) بإنهاء صلاحية التحويل وتطبيق `timeout_outcome` المُعدّ لديك على المعاملة الأساسية: يرفضها `REJECT`، ويحوّلها `HOLD` إلى المراجعة، ويتركها `PROCEED` كما هي. وتحل [سياسة sunrise أو سياسة عدم الاستجابة](#سياسات-sunrise-وعدم-الاستجابة) لديك محل `timeout_outcome` عند انطباقها. |
| `COUNTERPARTY_MISMATCHED_DATA` | لم يستوفِ اسم المستفيد `name_matching_strictness` المُعدّ لديك عند المقارنة مع الطرف الآخر: الاسم الذي أعاده الطرف المقابل، أو `holder_name` الخاص بإدخال دفتر العناوين المطابق. |
| `COUNTERPARTY_VASP_NOT_FOUND` | لم تتمكن أيٌّ من المسارات السبعة، ولا احتياطي [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين)، من تحديد VASP طرف مقابل يمكن الوصول إليه لهذا التحويل. تبقى أي جهة مُسندة مسجّلة على التحويل وفي الدليل. في التحويلات الصادرة يُنشئ Didit تلقائياً جلسة [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) (عند تفعيل `auto_wallet_verification`) حتى يتمكن التحويل من الاكتمال كتحويل إلى محفظة ذاتية الاستضافة. يوضح `reason` و`next_actions` السبب وما الذي يحرّك التحويل: راجع [لماذا يتوقف التحويل](#لماذا-يتوقف-التحويل). |
| `COUNTERPARTY_VASP_NOT_REACHABLE` | تم تحديد VASP طرف مقابل، لكن القناة المختارة لم تستطع التسليم: تعذّر الوصول إلى نقطة نهاية هوية `TRP` أو نقطة نهاية الاستفسار، أو لم تطابق الهوية التي أبلغ عنها الطرف المقابل `counterparty_vasp_lei` أو `counterparty_vasp_name`، أو رفضت الشبكة الرسالة أو لم تقبلها بعد ست محاولات (راجع [التسليم وإعادة المحاولة](#التسليم-وإعادة-المحاولة))، أو رفض مزوّد البريد بريد الامتثال. يميّز `reason` بين هذه الحالات، ويوضح `next_actions` ما الذي يحرّك التحويل: راجع [لماذا يتوقف التحويل](#لماذا-يتوقف-التحويل). أعد المحاولة باستخدام `action: "resend"` بعد أن يصبح الوصول إليه ممكناً من جديد. |
| `COUNTERPARTY_VASP_GENERAL_DECLINE` | رفض الطرف المقابل التبادل: إما بنفي الملكية، أو برفض استلام البريد الإلكتروني، أو برفض عبر `TRP` أو Sygna. |
| `NOT_ENOUGH_COUNTERPARTY_DATA` | حدّد استفسار `TRP` وارد المستفيد بلا اسم ولا عنوان محفظة، فلم يتمكن Didit من مطابقته مع دفتر العناوين لديك. لا تقبل نقطة نهاية الملكية ولا `resend` مثل هذا التحويل الوارد: لا يمكنك إلا إلغاؤه، والإلغاء لا يردّ على استفسار الطرف المقابل. لا يضبط Didit هذه الحالة أبداً على تحويل صادر؛ فإن سجّلتها بنفسك على تحويل صادر، فإن `action: "resend"` يعيد تشغيل التوجيه. |
| `NOT_APPLICABLE` | كان مبلغ التحويل أقل من `threshold_amount` المضبوط، أو لم يحدد طلب الدفع عبر [Lightning](#lightning) الصادر منك أي مستلم (يوضح `chain_details.not_applicable_reason` السبب)، أو سجّلت هذه الحالة بنفسك مع تعطيل Travel Rule (بما في ذلك القيمتان القديمتان `UNKNOWN` و`EXEMPT`، انظر أدناه). |

> [!WARNING]
>
> **لا تبثّ أبداً على السلسلة قبل الوصول إلى `COMPLETED`.**
> إطلاق الأموال على السلسلة أثناء وجود التحويل في حالة `AWAITING_COUNTERPARTY` أو `UNCONFIRMED_OWNERSHIP`، أو في أي حالة عدم تطابق أو رفض، يُفرغ عملية التبادل من غايتها.
> اجعل خطوة البث مشروطة بـ `status == "COMPLETED"`، ثم استدعِ `PATCH .../travel-rule/` مع `payment_txn_id` الناتج للانتقال إلى `FINISHED`.

الانتقالات بنظرة سريعة (يمكن الوصول إلى `CANCELLED` إضافةً من كل حالة غير نهائية باستخدام `action: "cancel"`):

```mermaid theme={null}
stateDiagram-v2
    [*] --> NOT_APPLICABLE: below threshold
    [*] --> UNCONFIRMED_OWNERSHIP: self-hosted wallet declared
    [*] --> AWAITING_COUNTERPARTY: transfer stored, routing queued
    [*] --> COMPLETED: your own verified wallet
    [*] --> ON_HOLD: inbound with no matching wallet entry
    [*] --> NOT_ENOUGH_COUNTERPARTY_DATA: inbound TRP inquiry names no beneficiary
    AWAITING_COUNTERPARTY --> COUNTERPARTY_MISMATCHED_DATA: INTERNAL rail, verified entry, name mismatch
    AWAITING_COUNTERPARTY --> COUNTERPARTY_VASP_NOT_FOUND: no rail resolved
    AWAITING_COUNTERPARTY --> COUNTERPARTY_VASP_NOT_REACHABLE: delivery failed
    AWAITING_COUNTERPARTY --> COMPLETED: counterparty confirmed, names match where checked
    AWAITING_COUNTERPARTY --> COUNTERPARTY_MISMATCHED_DATA: name match failed
    AWAITING_COUNTERPARTY --> COUNTERPARTY_VASP_GENERAL_DECLINE: counterparty declined
    AWAITING_COUNTERPARTY --> EXPIRED: confirmation timeout
    AWAITING_COUNTERPARTY --> COUNTERPARTY_VASP_NOT_REACHABLE: TRP inquiry not delivered
    UNCONFIRMED_OWNERSHIP --> COMPLETED: ownership proven, names match
    UNCONFIRMED_OWNERSHIP --> COUNTERPARTY_MISMATCHED_DATA: name match failed
    UNCONFIRMED_OWNERSHIP --> COUNTERPARTY_VASP_GENERAL_DECLINE: ownership denied
    ON_HOLD --> COMPLETED: you confirm the wallet, names match
    ON_HOLD --> COUNTERPARTY_MISMATCHED_DATA: you confirm the wallet, name mismatch
    ON_HOLD --> COUNTERPARTY_VASP_GENERAL_DECLINE: you deny the wallet
    COUNTERPARTY_MISMATCHED_DATA --> COMPLETED: you approve an inbound TRP inquiry
    COUNTERPARTY_MISMATCHED_DATA --> COUNTERPARTY_VASP_GENERAL_DECLINE: you decline an inbound TRP inquiry
    COUNTERPARTY_VASP_NOT_FOUND --> COMPLETED: wallet ownership proven in the widget
    COUNTERPARTY_VASP_NOT_FOUND --> AWAITING_COUNTERPARTY: action resend
    COUNTERPARTY_VASP_NOT_REACHABLE --> AWAITING_COUNTERPARTY: action resend
    COMPLETED --> FINISHED: payment_txn_id reported or deposit already settled
    FINISHED --> [*]
    EXPIRED --> [*]
```

### التسليم وإعادة المحاولة

يرسل Didit كل رسالة يتعيّن على التحويل إرسالها بصورة منفصلة عن الطلب الذي تسبّب فيها، ويعيد محاولة إرسالها حتى يستلمها الطرف الآخر.
يعيد الكائن الذي تُرجعه [إنهاء التحويل أو إلغاؤه أو إعادة إرساله](https://docs.didit.me/ar/management-api/travel-rule/update-transfer.md)، و[تأكيد الملكية](https://docs.didit.me/ar/management-api/travel-rule/confirm-ownership.md)، و[تسجيل sunrise](#التسجيل-اللاحق-للإيداع) آخرَ رسالة في `delivery`، ويحملها أيضاً كائن `travel_rule` المضمّن في المعاملة. وتكون قيمته `null` إذا لم يكن يتعيّن على التحويل إرسال أي رسالة قط.

| الحقل | المعنى |
| - | - |
| `kind` | `SEND` (الرسالة الأولى إلى الطرف المقابل)، أو `ANSWER` (قبولك أو رفضك، المستحق للشبكة التي طلبته)، أو `TXID` (تجزئة المعاملة على السلسلة، بعد إنهاء التحويل)، أو `CANCEL` (بعد إلغائه)، أو `POLL` (استعلام عن الحالة إلى شبكة توفره، كل 5 دقائق طالما ينتظر التحويل الطرف المقابل). |
| `status` | `QUEUED` أو `SENDING` أو `RETRYING` أو `DELIVERED` أو `FAILED`. |
| `rail` | القناة التي تحمل الرسالة؛ تبقى فارغة حتى يختار Didit قناة لأول رسالة. |
| `attempts` | عدد المحاولات المنفذة حتى الآن. |
| `last_error` | سبب فشل المحاولة الأخيرة، وتكون فارغة إذا لم تفشل أي محاولة. سبب قصير يحدد الخطوة ونوع الفشل، مثل `sygna permission request failed: HTTP 503` أو `sygna status query failed: no answer in time`. وعندما ترد GTR بخطأ، يُضمَّن رمز حالتها ورسالتها. لا تُضمَّن أبداً نصوص الاستجابات. |
| `next_attempt_at` | موعد المحاولة التالية، طالما كانت الرسالة `QUEUED` أو `RETRYING`. |
| `delivered_at` | موعد استلام الطرف الآخر للرسالة. |

تُعاد محاولة الفشل الذي قد تتعافى منه الشبكة (عدم الرد في الوقت المحدد، أو فشل الاتصال، أو رمز HTTP `408` أو `429` أو `5xx`) بعد 30 ثانية، ثم دقيقتين، ثم 10 دقائق، ثم 30 دقيقة، ثم ساعة واحدة.
عندما تفشل أول رسالة نهائياً، أي ترفضها الشبكة أو تفشل المحاولة السادسة أيضاً، ينتقل التحويل إلى `COUNTERPARTY_VASP_NOT_REACHABLE` مع `last_error` في `timeline`، ويمكنك إعادة المحاولة باستخدام `action: "resend"`.
وتُدوَّن في `timeline` أي رسالة أخرى تفشل نهائياً.
لا يحل `delivery` محل `status` الخاص بالتحويل أبداً: اقرأ حالة التبادل من `status`، واستخدم `delivery` لمعرفة سبب بقاء التحويل في حالة انتظار.

### قيم الحالة القديمة

إذا كنت ترسل `travel_rule_details.status` قبل هذا الإصدار، فلا تزال تلك القيم تعمل وتُحوَّل تلقائياً. كما تُقبل صيغ camelCase لأي حالة (مثل `counterpartyVaspNotFound`)، سواء عند الإرسال أو في قيم شروط [القاعدة](https://docs.didit.me/ar/transaction-monitoring/rules.md)، وتُطبَّع إلى الصيغة المعتمدة:

| القيمة القديمة | تُحوَّل إلى |
| - | - |
| `UNKNOWN` | `NOT_APPLICABLE` |
| `COMPLIANT` | `COMPLETED` |
| `PENDING_ACTION` | `ON_HOLD` |
| `PENDING_COUNTERPARTY` | `AWAITING_COUNTERPARTY` |
| `FAILED` | `CANCELLED` |
| `EXEMPT` | `NOT_APPLICABLE` |

## الإعداد

اضبط ملف VASP الخاص بك وسياسة التفاوض مرة واحدة لكل تطبيق باستخدام `GET`/`PUT /v3/travel-rule/settings/`.

```bash theme={null}
curl -X GET https://verification.didit.me/v3/travel-rule/settings/ \
  -H "x-api-key: YOUR_API_KEY"
```

```json theme={null}
{
  "is_enabled": false,
  "jurisdiction": "EU",
  "name_matching_strictness": "DEFAULT",
  "confirmation_timeout_hours": 48,
  "timeout_outcome": "HOLD",
  "threshold_amount": "0.00",
  "inbound_auto_accept": true,
  "allow_self_declaration": true,
  "allow_screenshot_proof": true,
  "auto_wallet_verification": true,
  "vasp_attribution_enabled": true,
  "counterparty_screening_enabled": false,
  "sunrise_policy": "",
  "sunrise_jurisdictions": ["CO", "KH", "VN"],
  "non_responsive_policy": "",
  "legal_name": "",
  "lei": "",
  "compliance_email": "",
  "is_discoverable": true,
  "travel_address": "",
  "disabled_networks": [],
  "networks": {
    "gtr": { "rail": "GTR", "mode": "unavailable", "platform_available": false, "connected": false },
    "trust": { "rail": "TRUST", "mode": "unavailable", "platform_available": false, "connected": false },
    "verifyvasp": { "rail": "VERIFYVASP", "mode": "unavailable", "platform_available": false, "connected": false },
    "sygna": { "rail": "SYGNA", "mode": "unavailable", "platform_available": false, "connected": false }
  }
}
```

```bash theme={null}
curl -X PUT https://verification.didit.me/v3/travel-rule/settings/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "is_enabled": true,
    "legal_name": "Origin CASP SL",
    "jurisdiction": "EU",
    "name_matching_strictness": "DEFAULT",
    "confirmation_timeout_hours": 48,
    "timeout_outcome": "HOLD",
    "is_discoverable": true
  }'
```

`PUT` هو تحديث جزئي، لذا أرسل الحقول التي تريد تغييرها فقط.

| الحقل | النوع | الوصف |
| - | - | - |
| `is_enabled` | boolean | يفعّل مسار التفاوض المُدار للمعاملات الصادرة من نوع `travelRule` في هذا التطبيق. يتطلب `legal_name` غير فارغ (محفوظاً مسبقاً أو مُرسلاً في الطلب نفسه)، وإلا يعيد الطلب `400`. |
| `legal_name` | string | الاسم القانوني لـ VASP الخاص بك. يُعرض على الطرف المقابل في صفحة استلام البريد الإلكتروني، ويُعاد في [دليل VASP](#الدليل). |
| `lei` | string | معرّف الكيان القانوني (Legal Entity Identifier) الخاص بك، ويُعاد في دليل VASP. |
| `jurisdiction` | string | رمز الولاية القضائية التي يعمل فيها VASP الخاص بك، حتى 8 أحرف (الافتراضي `"EU"`). |
| `name_matching_strictness` | string | `NONE` أو `STRICT` أو `CONTAINS` أو `DEFAULT` أو `FUZZY`، انظر أدناه. |
| `confirmation_timeout_hours` | integer | عدد الساعات التي يُسمح فيها لتحويل بحالة `AWAITING_COUNTERPARTY` بالبقاء قبل أن تنتهي صلاحيته تلقائياً. الحد الأدنى `1`، والافتراضي `48`. |
| `timeout_outcome` | string | ما يحدث للمعاملة الأساسية عند انتهاء صلاحية التحويل: `HOLD` تنقلها إلى المراجعة، و`REJECT` ترفضها، و`PROCEED` تترك حالتها دون تغيير. الافتراضي `HOLD`. تكون لـ `sunrise_policy` و`non_responsive_policy` الأولوية عندما تنطبق إحداهما. |
| `sunrise_policy` | string | `HOLD` أو `REJECT` أو `PROCEED`، أو `""` (الافتراضي) لاتباع `timeout_outcome`: ما يفعله التحويل المنتهي عندما يكون طرفه المقابل إدخالاً في الدليل من ولاية قضائية مدرجة في `sunrise_jurisdictions`. انظر [سياسات الشروق وعدم الاستجابة](#سياسات-sunrise-وعدم-الاستجابة). |
| `non_responsive_policy` | string | `HOLD` أو `REJECT` أو `PROCEED`، أو `""` (الافتراضي) لاتباع `timeout_outcome`: ما يفعله التحويل المنتهي عندما يكون طرفه المقابل إدخالاً في الدليل وتكون [حالة استجابته](#مدى-الاستجابة) `UNRESPONSIVE`. تُطبَّق `sunrise_policy` أولاً عندما تنطبق الاثنتان. |
| `sunrise_jurisdictions` | string\[] | للقراءة فقط. الدول التي تعدّها Didit في فترة بدء تطبيق Travel Rule، وهي حالياً `["CO", "KH", "VN"]`. تتبع أي ولاية قضائية أخرى `timeout_outcome`. |
| `compliance_email` | string | بريد إلكتروني لجهة الاتصال بالامتثال في ملف VASP الخاص بك. لا تُدرج [شبكة Didit](#شبكة-didit) ملفك إلا بعد تأكيد هذا العنوان عبر رابط يُرسل بالبريد الإلكتروني، وتغييره يتطلب تأكيداً جديداً. |
| `is_discoverable` | boolean | يحدد ما إذا كان ملف VASP الخاص بك يمكن إدراجه في [شبكة Didit](#شبكة-didit)، أي أن يعثر عليه عملاء Didit الآخرون في `GET /v3/travel-rule/vasps/` ويتواصلون معه عبر مسار INTERNAL. للإدراج شروط إضافية، ويوضح `didit_network` في الإعدادات الشروط الناقصة. الافتراضي `true`. |
| `inbound_auto_accept` | boolean | عندما تكون `true`، يُقبل تلقائياً أي استفسار `TRP` وارد تكون فيه المحفظة المستفيدة إدخالاً موثقاً في دفتر عناوينك ويتطابق اسمها. وعندما تكون `false`، ينتظر في `ON_HOLD` قرارك. لا تقرأ المسارات الواردة الأخرى هذا الإعداد. الافتراضي `true`. |
| `allow_self_declaration` | boolean | عندما تكون `true`، تعرض [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) التصريح الذاتي كوسيلة إثبات، ويمكنك إنشاء إدخالات في [دفتر عناوين المحافظ](#دفتر-عناوين-المحافظ) مع `self_declared: true`. الافتراضي `true`. |
| `allow_screenshot_proof` | boolean | عندما تكون `true`، تعرض [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) رفع لقطة شاشة كوسيلة لإثبات الملكية. لقطة الشاشة لا تتحقق من المحفظة وحدها، إذ يراجعها فريق الامتثال لديك ويؤكد التحويل. وهي أضعف من التوقيع التشفيري، فعطّلها حيث تتطلب سياستك إثباتاً بمستوى التوقيع. الافتراضي `true`. |
| `auto_wallet_verification` | boolean | عندما تكون `true`، فإن أي تحويل صادر يحتاج إلى إثبات سيطرة المستخدم النهائي على المحفظة ينشئ تلقائياً جلسة [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) مرتبطة بالمعاملة، ويعرضها في كتلة `action_required` الخاصة بالمعاملة، وتشغّلها حزم Didit SDK تلقائياً عند [الإرسال من جهة العميل](https://docs.didit.me/ar/transaction-monitoring/sdk-transaction-submission.md). الافتراضي `true`. |
| `counterparty_screening_enabled` | boolean | فحص اختياري للعقوبات والأخبار السلبية [لـ VASP الطرف المقابل](#فحص-الطرف-المقابل)، ويُحتسب عن كل فحص بسعر فحص AML للشركات. عندما تكون `true`، تفحص Didit الطرف المقابل الذي يصل إليه التبادل الصادر عند بدئه، وتعيد استخدام الفحص الذي يقل عمره عن 30 يوماً. الافتراضي `false`: لا يُفحص شيء ولا يُحتسب أي مبلغ. |
| `vasp_attribution_enabled` | boolean | عندما تكون `true`، فإن أي تحويل صادر لا يستطيع أي مسار توجيهه يُنسَب عبر [تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) إلى VASP مالك المحفظة المستقبِلة، فتُحدَّد هوية ذلك الـVASP، ويُضاف الكيان إلى الدليل، وتُعاد تشغيل المسارات مرة واحدة باسم الكيان المنسوب. الافتراضي `true`. |
| `threshold_amount` | string (decimal) | الحد الأدنى لمبلغ التحويل الذي يُفعّل تبادلاً مُداراً، بالعملة الافتراضية لتطبيقك. تقارن Didit المبلغ بمبلغ التحويل محولاً إلى تلك العملة (أو بالقيمة `amount_in_default_currency` التي ترسلها)، لا بالمبلغ بعملة التحويل نفسها. التحويلات الأقل منه تنتهي مباشرةً بالحالة `NOT_APPLICABLE` ولا تُفاوَض أبداً. إذا تعذّر على Didit تحويل المبلغ فلا يُطبَّق الحد ويُبادَل التحويل. لا تحوّل التطبيقات في البيئة التجريبية المبالغ، لذا يُطبَّق الحد هناك فقط عندما ترسل `amount_in_default_currency`. القيمة الافتراضية `0.00`، توافقاً مع إطار EU TFR الذي لا يضع حداً أدنى للمبلغ، فيُفحص كل تحويل مهما كان حجمه. |
| `ownership_validation_mode` | string | `FULL` أو `SIMPLIFIED` أو `AUTOMATED`، مقدار الإثبات المطلوب لإثبات ملكية المحفظة. انظر [أوضاع التحقق من الملكية](#أوضاع-التحقق-من-الملكية). الافتراضي `AUTOMATED`. |
| `simplified_validation_threshold` | string (decimal) | في وضع `SIMPLIFIED`، يُقبل التصريح الذاتي للتحويل الذي يقل عن هذا المبلغ. الافتراضي `0.00`. |
| `data_sharing_fields` | object | الحقول التي ترسلها عن مستخدميك، لكل نوع كيان. انظر [مشاركة البيانات](#مشاركة-البيانات). |
| `matching_rules` | object | مدى دقة مقارنة كل حقل من بيانات الطرف المقابل، لكل نوع كيان. انظر [المطابقة حسب الحقل](#مطابقة-الحقول). |
| `disabled_networks` | string\[] | مسارات الشبكات (`GTR` و`TRUST` و`VERIFYVASP` و`SYGNA`) التي يجب ألا تُوجَّه عبرها معاملاتك من خلال عضوية Didit في المنصة. لا يؤثر هذا الحقل أبداً في الشبكة التي ربطت لها عضويتك الخاصة (من Marketplace في الكونسول). لا تملك Didit عضوية منصة بعد، لذا لا أثر توجيهي لهذه القائمة اليوم (تُبلغ الشبكة المدرجة بـ `mode: off`). الافتراضي `[]`. |
| `networks` | object | للقراءة فقط. حالة كل شبكة مفهرسة بالمفاتيح `gtr` / `trust` / `verifyvasp` / `sygna`: `{rail, mode, platform_available, connected}`، حيث يكون `mode` إما `own` (عضويتك المربوطة)، أو `didit` (عضوية Didit في المنصة، وغير متاحة على أي شبكة بعد)، أو `off` (معطّلة من قِبلك)، أو `unavailable`. |
| `travel_address` | string | للقراءة فقط. Travel Address الخاص بـ VASP لديك، وهو نقطة نهاية استفسار `TRP` الوارد المشفّرة التي تستخدمها VASPs الأخرى للوصول إليك. تُملأ بعد تفعيل Travel Rule، على سبيل المثال: `ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeS5uNDp3dGW3bweBWLKws442chRsyNxmmJnyWc7frxjjSeABVsYR11UuBePkw6E`. |

### صرامة مطابقة الأسماء

| القيمة | السلوك |
| - | - |
| `NONE` | تُقبل أي قيمة لاسم المستفيد، ولا تُجرى أي مقارنة. |
| `STRICT` | يجب أن تتطابق مجموعتا token المطبّعتان للاسمين تماماً. |
| `CONTAINS` | تظهر كل كلمات اسم في الاسم الآخر، مهما كان عددها قليلاً. |
| `DEFAULT` | يجب أن تظهر كل token من الاسم الأقصر في الاسم الأطول (مطابقة مجموعة جزئية)، ويحتاج الاسم الأقصر إلى اثنين من token على الأقل ما لم يكن الاسمان متطابقين. |
| `FUZZY` | يجب أن تبلغ نسبة التشابه بين السلسلتين الكاملتين المطبّعتين `0.85` على الأقل. |

### أوضاع التحقق من الملكية

يحدد `ownership_validation_mode` مقدار الإثبات الذي تتطلبه ملكية المحفظة قبل أن تعتمد عليها المعاملة.

| الوضع | السلوك |
| - | - |
| `FULL` | يُشترط دائماً دليل: رسالة موقّعة، أو إيداع تجريبي، أو لقطة شاشة مُراجَعة. لا يُعتد أبداً بكلمة المستخدم النهائي. لا تعرض الأداة المضمّنة `SELF_DECLARATION`، ويؤدي بدء التصريح الذاتي إلى استجابة `403`، وإدخال في دفتر العناوين أُنشئ بـ `self_declared: true` يعيد `400`. |
| `SIMPLIFIED` | يُقبل التصريح الذاتي ما دامت المعاملة أقل من `simplified_validation_threshold`؛ وفوق هذا الحد يُشترط دليل. تُقاس المعاملة الواردة (طلب TRP، أو رسالة شبكة، أو إيداع تبلغ عنه) بمبلغها محوّلاً إلى العملة الافتراضية لتطبيقك بالسعر الحالي. يُعامَل الأصل الذي لا سعر له، وكل معاملة في تطبيق بيئة الاختبار، على أنه فوق الحد. |
| `AUTOMATED` | يحدّد دفتر العناوين وأدلة المستخدم النهائي السابقة ذلك تلقائياً، بما في ذلك التصريحات الذاتية ما دام `allow_self_declaration` يساوي `true`. هذا هو الوضع الافتراضي، وهو ما كانت تفعله كل التطبيقات قبل وجود الأوضاع. |

تُحفظ المحفظة لكل مستخدم نهائي بمجرد التحقق منها. في `FULL` و`SIMPLIFIED`، لا تعيد المعاملة اللاحقة استخدامها إلا إذا دعمها دليل يقبله الوضع لتلك المعاملة.
عندما لا يوجد في دفتر العناوين محفظة تطابق `inbound_auto_accept`، تحدد المحفظة الرقمية التي سجّلتها في معاملات مستخدم نهائي واحد فقط صاحبَها.
تضيف Didit هذه المحفظة إلى دفتر عناوين المستخدم النهائي بوصفها تصريحاً ذاتياً منك، ومُتحقَّقاً منها ما لم يكن الوضع `FULL`. ولا تضيف أبداً محفظة يسردها دفتر العناوين بالفعل تحت اسم آخر على السلسلة نفسها (`eth` و`ethereum`)، بما في ذلك المحفظة المسجّلة باسم VASP آخر.
تتبع أيضاً فحوصات العناوين التي تجريها VASPs الأخرى قبل الإرسال (عبر `GTR` و`Sygna` و`VerifyVASP`) الوضع نفسه: في `FULL`، لا تُبلَّغ المحفظة التي صرّح بها المستخدم النهائي وحده على أنها محفظتك.

### مشاركة البيانات

يحدد `data_sharing_fields` الحقول التي ترسلها Didit إلى الطرف المقابل عن مستخدميك، بشكل منفصل للأفراد والشركات:

```json theme={null}
{
  "data_sharing_fields": {
    "individual": ["name", "wallet_address", "address", "date_of_birth"],
    "company": ["name", "wallet_address", "address"]
  }
}
```

* يمكن للأفراد مشاركة `name` و`wallet_address` و`address` و`national_id` و`customer_identification` و`date_of_birth` و`place_of_birth`. وتشارك الشركات الحقول الخمسة الأولى فقط.
* يُرسل `name` و`wallet_address` دائماً.
* نوع الكيان الذي لم تختره أبداً يشارك كل الحقول. والقائمة الفارغة اختيار أيضاً: فهي تشارك الاسم والمحفظة فقط.
* يدمج `PUT` الإعدادات لكل نوع كيان، فإرسال `individual` لا يغيّر اختيار `company` المخزَّن.
* يُرفض الاختيار الذي لا يستوفي التزامات المُرسِل في نظام `jurisdiction` لديك (EU TFR أو توصية FATF 16)، بما في ذلك القائمة الفارغة، بخطأ `400`. تظهر الأخطاء تحت `data_sharing_fields`، مفهرسة حسب نوع الكيان.

### مطابقة الحقول

يحدد `matching_rules` مدى صرامة مقارنة كل حقل من بيانات الطرف المقابل بما لديك:

```json theme={null}
{
  "matching_rules": {
    "individual": { "name": "DEFAULT", "date_of_birth": "STRICT", "address": "NONE", "account": "STRICT" },
    "company": { "name": "FUZZY", "address": "NONE", "account": "STRICT" }
  }
}
```

تكون كل قيمة واحدة من: `NONE` أو `STRICT` أو `CONTAINS` أو `DEFAULT` أو `FUZZY`.
القيم الافتراضية: يتبع `name` القيمة `name_matching_strictness`، و`date_of_birth` و`address` قيمتهما `NONE`، و`account` قيمته `STRICT`.
يحتفظ الحقل الذي لم يُدرج بقيمته الافتراضية، ويُرفض بخطأ `400` أي حقل لا يقارنه نوع الكيان (فللشركة لا يوجد `date_of_birth`).

### الحدود حسب الولاية القضائية

يوجد `threshold_amount` لأن نطاق قاعدة Travel Rule يختلف من جهة تنظيمية إلى أخرى.
تستخدم Didit القيمة الافتراضية `0.00`، أي موقف الاتحاد الأوروبي، فتُتبادل كل معاملة ما لم ترفع الحد عمداً:

| النظام | الحد | ملاحظات |
| - | - | - |
| **الاتحاد الأوروبي**: لائحة نقل الأموال (EU) 2023/1113 | **بلا حد أدنى** | تقع كل معاملة عملات مشفرة بين CASP وCASP ضمن النطاق. يجب التحقق من ملكية المحفظة ذاتية الاستضافة للمعاملات التي تتجاوز EUR 1,000. |
| **توصية FATF 16** (الأساس العالمي) | USD/EUR 1,000 | دونه، تسمح FATF بمجموعة بيانات مخفّضة (الأسماء وعناوين المحافظ، دون تحقق). |
| **الولايات المتحدة**: BSA Travel Rule | USD 3,000 | حد FinCEN الراسخ لتحويلات الأموال، ويُطبَّق على العملات الافتراضية القابلة للتحويل. |
| **المملكة المتحدة** | ما يعادل EUR 1,000 | معلومات كاملة فوق الحد؛ ومجموعة بيانات مخفّضة دونه (MLRs Part 7A). |
| **سنغافورة**: MAS PSN02 | SGD 1,500 | متطلبات مخفّضة دون الحد. |
| **سويسرا**: FINMA | بلا حد أدنى | تُشترط المعلومات لجميع المعاملات؛ ويُتوقع دليل ملكية للمحافظ ذاتية الاستضافة. |

اضبط `threshold_amount` على الرقم الذي تحدده جهتك التنظيمية؛ فإن المعاملات دونه تُصنَّف على أنها `NOT_APPLICABLE` دون تبادل أي بيانات هوية.
تتغير الحدود بمرور الوقت، فتأكد من الرقم الحالي مع مستشارك في الامتثال، ولا تعتبر هذا الجدول نصيحة قانونية.

### نموذج بيانات IVMS 101

المعيار الصناعي للبيانات المتبادلة بموجب Travel Rule هو **IVMS 101** (interVASP Messaging Standard).
`travel_rule_details.originator_data` و`travel_rule_details.beneficiary_data` هما حمولتا شخص بنمط IVMS 101. يغلّف Didit كلًّا منهما داخل الغلاف الأصلي لكل قناة: تتبادل قناة TRP كتل `IVMS101` (`ivms101.2023`، ويُذكر في حقل `ivms_version` الخاص بالتحويل)، وتتبادل قناة Sygna نسختها من IVMS المشفّرة بـ ECIES، وتستخدم القنوات `GTR` و`TRUST` و`VERIFYVASP` أغلفتها المشفّرة الخاصة. وبذلك يصل شكل حمولة واحد إلى كل طرف مقابل بالصيغة التي يتوقعها بروتوكوله.

يقرأ Didit هذه المفاتيح من كل حمولة شخص عند بناء رسالة IVMS 101: `first_name` و`last_name` (أو `name` واحدًا أو `full_name`)، و`date_of_birth`، و`place_of_birth`، و`residence_country` (أو `country`)، و`vendor_data` (أو `customer_identification`)، و`wallet_address`.

قاعدتان عمليتان:

* **الكتابة باللاتينية.** يشترط IVMS 101 قيمًا بالحروف اللاتينية، لذا انقل الأسماء المكتوبة أصلًا بنظام كتابة آخر إلى الحروف اللاتينية. تقارن [مطابقة الأسماء](#صرامة-مطابقة-الأسماء) مجموعات الرموز بعد تطبيعها، فلا يُفشل اختلافُ ترتيب الكلمات أو حالة الأحرف التبادلَ، لكن اختلاف نظام الكتابة بين الطرفين يفعل ذلك.
* **أرسل بيانات تحققت منها.** عندما يكون الشخص الذي يخصّه `vendor_data` مستخدمًا لديه عملية تحقق KYC مقبولة في Didit، ينقل Didit الهوية الموثّقة لا القيم التي كتبتها: راجع [البيانات الموثّقة ومصدرها](#البيانات-الموثّقة-ومصدرها).
  في أي حالة أخرى، ينقل Didit `originator_data` كما أرسلتَه تمامًا، لذا ابنِه من الهوية التي تحققت منها عند التسجيل، لا من حقل نموذج غير موثّق.
  هذا ما يقتضيه نص FATF الذي يطلب «معلومات المُرسِل المطلوبة والدقيقة».
  على القناة `INTERNAL`، يتلقى تطبيقُ المستفيد أيضًا `subject` الذي أرسلتَه (الاسم و`vendor_data` وتاريخ الميلاد والدولة والعنوان) بوصفه الطرفَ المقابل في معاملته الواردة.

#### البيانات الموثّقة ومصدرها

عندما يكون موضوع التحويل أحد مستخدميك، أي فردًا لديه عملية تحقق KYC مقبولة، يبني Didit ذلك الجانب من التبادل من البيانات الموثّقة:

* المُرسِل في تحويل صادر تنشئه عبر `POST /v3/transactions/`؛
* المستفيد في تحويل وارد تبلّغ عنه عبر `POST /v3/transactions/`، أو عبر `POST /v3/travel-rule/inbound/` عندما يسمّي `holder_vendor_data` الخاص بالمحفظة المطابِقة ذلك المستخدم.

في `POST /v3/transactions/`، ينطبق الأمران على معاملة `transaction_category` فيها هو `travel_rule` ما دامت Travel Rule مفعّلة.

تتقدّم الأسماء الموثّقة وتاريخ الميلاد ومكانه ورقم الوثيقة ونوعها والعنوان ودولة الإقامة (المستمدة من العنوان) على القيم التي أرسلتها. يحتفظ الحقل الذي لا يتضمنه التحقق بقيمتك، وكذلك العنوان الكامل الذي أرسلتَه عندما لا يكون العنوان الموثّق مكتملًا بما يكفي للإرسال.

تسجّل `metadata` الخاصة بالتحويل، على كائن `travel_rule` المضمّن في المعاملة، مصدر كل حقل والمواضع التي اختلفت فيها قيمك:

```json theme={null}
{
  "metadata": {
    "originator_provenance": { "name": "verified", "date_of_birth": "verified", "customer_identification": "caller" },
    "originator_verified_differences": {
      "name": { "caller": "Jane Doe", "verified": "Jane Elizabeth Doe" }
    }
  }
}
```

يربط `*_provenance` كل حقل بـ `verified` أو `caller`، ويسرد `*_verified_differences` كل حقل أرسلتَ فيه قيمة تختلف عن القيمة الموثّقة، مع تجاهل حالة الأحرف والمسافات ورموز الدول المكوّنة من حرفين أو ثلاثة. وعندما تكون بيانات التحويل الوارد [مخفية](#بيانات-الطرف-المقابل-المقنّعة)، تُحذف الفروق. يحسب Didit هذين المفتاحين بنفسه، لذا تُسقَط النسخ التي ترسلها من هذه المفاتيح أو من `name_match` ضمن `travel_rule_details.metadata`.

#### إرسال IVMS 101 مباشرة

إضافةً إلى كائني `originator_data` و`beneficiary_data` المسطّحين، يقبل `travel_rule_details` (في `POST /v3/transactions/`) و`POST /v3/travel-rule/inbound/` كتل IVMS 101 الحقيقية:

* كتلة `originator` وكتلة `beneficiary`، يحمل كل منهما `originatorPersons` أو `beneficiaryPersons` يضم `naturalPerson` أو `legalPerson`، و`accountNumber`؛
* الكتلتين نفسيهما داخل كائن `ivms101` (أو `IVMS101`)؛
* شخص IVMS 101 واحد، أو كتلة كاملة واحدة، بوصف أيٍّ منهما `originator_data` أو `beneficiary_data`.

يأخذ كل جانب شخصًا واحدًا: إما `naturalPerson` وإما `legalPerson`، والأخير يجعل الطرف شركة. وإذا كان `originator_data` أو `beneficiary_data` المسطّح غير فارغ للجانب نفسه، فإنه يتقدم على الكتلة.

```json theme={null}
{
  "travel_rule_details": {
    "status": "AWAITING_COUNTERPARTY",
    "beneficiary": {
      "beneficiaryPersons": [
        {
          "naturalPerson": {
            "name": { "nameIdentifier": [{ "primaryIdentifier": "Ruiz", "secondaryIdentifier": "Carlos", "nameIdentifierType": "LEGL" }] }
          }
        }
      ],
      "accountNumber": ["0xBeneficiaryWallet01"]
    }
  }
}
```

تؤدي الكتلة غير الصحيحة إلى استجابة `400` يكون مفتاحها مسار الكتلة، على سبيل المثال `{"travel_rule_details": {"originator.originatorPersons": ["must be a non-empty list of originator persons."]}}`. وفي `POST /v3/travel-rule/inbound/` تظهر المفاتيح نفسها في المستوى الأعلى، تحت `ivms101.` إذا استخدمت الغلاف.

#### البيانات المطلوبة حسب النظام

ما دامت Travel Rule مفعّلة، يجب أن يحمل التحويل الصادر الذي يبلغ حدّك أو يتجاوزه ما يشترطه نظامه، وإلا أعاد الخطأ `400`. يُفحَص الجانبان اللذان أرسلتهما فقط، ويُحسب ما وُثّق ضمن المُرسِل، وتظهر الأخطاء تحت `travel_rule_details.originator_data` أو `travel_rule_details.beneficiary_data`، مثل `"EU TFR requires the originator name."` أو `"FATF Recommendation 16 requires the beneficiary wallet address."`:

| النظام | المُرسِل | المستفيد |
| - | - | - |
| EU TFR (إذا كان `jurisdiction` لديك دولة عضوًا في الاتحاد الأوروبي، أو آيسلندا، أو ليختنشتاين، أو النرويج، أو `EU` أو `EEA`؛ و`EU` هو الافتراضي) | الاسم، مع العنوان ورقم المستند الرسمي ورقم تعريف العميل معًا، أو تاريخ الميلاد ومكانه. لا يملك الكيان الاعتباري بديلًا من تاريخ الميلاد. | الاسم والعنوان |
| FATF Recommendation 16 (كل اختصاص آخر، بما في ذلك الاختصاص الفارغ) | الاسم، مع واحد من العنوان أو رقم المستند الرسمي أو رقم تعريف العميل، أو تاريخ الميلاد ومكانه معًا. لا يملك الكيان الاعتباري بديلًا من تاريخ الميلاد. | الاسم والعنوان |

بالنسبة إلى المُرسِل، يقرأ الفحص الحقول التي يشاركها تطبيقك في [`data_sharing_fields`](#مشاركة-البيانات)، لأنها كل ما ترسله القناة؛ ويُفحَص المستفيد كما أرسلتَه. وإذا لم يستوفِ التحويل النظام إلا بحقل لا تشاركه، فإن الخطأ `400` يذكر شرط النظام، ثم يذكر الحقول التي تشاركها إعداداتك.

رقم المستند الرسمي هو `national_id` (أو `document_number`)، ورقم تعريف العميل هو `customer_identification` (أو `vendor_data`)، وتاريخ الميلاد هو `date_of_birth`. يُملأ `beneficiary_data.wallet_address` الفارغ من `counterparty.payment_method.account_id` قبل الفحص، ويُعدّ سحب UTXO الذي استنتج Didit مخرج المستفيد فيه من `travel_rule_details.utxo` حاملًا للعنوان. ولا يُفحَص تحويل Lightning الذي لا تنطبق عليه Travel Rule.

### عناوين Travel Address

**Travel Address** سلسلة مشفّرة ومضغوطة تشير إلى endpoint استعلامات `TRP` الواردة الخاصة بـ VASP، ولا تكشف أبدًا عن أي رابط URL خام أو عنوان محفظة.
بعد تفعيل Travel Rule، ينشئ Didit لك `travel_address` الخاص بك (يُعاد للقراءة فقط في الإعدادات) لتتمكن من مشاركته مع VASPs الأخرى التي تصل إليك عبر قناة `TRP`.
كل محفظة من محافظ دفتر العناوين لديك تحصل أيضًا على `receiving_travel_address` خاص بها: الاستعلام المرسل إليها يحدد تلك المحفظة، فلا يضطر Didit إلى البحث عنها برقم الحساب أو اسم الحامل.
خادم TRP العام لدى Didit لا يستجيب لـ VASPs الأخرى بعد، لذلك لا يتوفر الاستقبال عبر `TRP` إلى أن يحدث ذلك: راجع [شبكات Travel Rule](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md).
عندما تعرف Travel Address الخاص بطرف مقابل، خزّنه في [إدخال دفتر عناوين المحفظة](#دفتر-عناوين-المحافظ) الخاص بالوجهة، ليوجّه Didit تحويلات ذلك المستفيد مباشرة عبر `TRP` بدلًا من الرجوع إلى البريد الإلكتروني.
يتحقق Didit من Travel Address الذي تخزنه في إدخال دفتر عناوين المحفظة أو ترسله في `originating_vasp`: يجب أن يبدأ كل عنوان بـ `ta` وأن يُفكّ ترميزه إلى رابط استعلام يحمل `t=i`، فالقيمة النائبة مثل `ta...` تُرجع `400`.
لا يخضع `beneficiary_data.travel_address` في المعاملة للتحقق: إذا تعذّر فك ترميزه يُتخطى مسار `TRP`.

يعتمد الترميز على Base58Check مع البادئة `ta`: مضيف endpoint ومساره (ويحمل دائمًا زوج الاستعلام `t=i`)، مع مجموع تحقق (checksum) من أربعة بايتات بخوارزمية SHA-256 المطبّقة مرتين، ثم يُرمَّز الناتج بـ base58. العنوان الحقيقي يبدو هكذا، ويبلغ طوله نحو 100 حرف:

```text theme={null}
ta2ih1MicegQ3JqiKz9xT89KsSuwaDJYw8DgzmeSEp1h9tduJcNDZ5SgKLEHeyGMcS1s2HgbM6undFrMQknhM5aTXw3G9KBzi16hx
```

عند تحقق Didit من Travel Address، فإن القيمة التي لا تكون عنوانًا سليم التكوين وصحيح مجموع التحقق تُرجع `400` مع `"Invalid travel address."`.
استخدم عنوانًا حقيقيًا من استجابة الإعدادات الخاصة بك، أو من الطرف المقابل نفسه.

## الاختبار دون بيانات اعتماد الشبكة

لا تحتاج إلى عضوية في GTR أو TRUST أو VerifyVASP أو Sygna لاختبار المسارات التي لا تتطلب عضوية. ما زلت تحتاج إلى مفتاح API الخاص بـ Didit للتطبيق قيد الاختبار.

* **الصادر في البيئة التجريبية:** أرسل معاملة `travelRule` من تطبيق في البيئة التجريبية. بعد فحوصات الحد والمحفظة ذاتية الاستضافة، يردّ [Didit Test VASP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) داخل Didit بالسيناريو الذي تختاره حسب محفظة المستفيد أو اسمه: القبول، أو الرفض، أو عدم تطابق الاسم، أو تعذر الوصول، أو انتهاء المهلة، أو ذاتية الاستضافة. لن يُرسل أي شيء إلى شبكة أو عبر البريد الإلكتروني، ولن يتلقى أي عميل آخر لدى Didit أي شيء.
* **الوارد في البيئة التجريبية:** اطلب من Test VASP أن يرسل إليك تحويلًا عبر [Trigger Test VASP Inbound Transfer](https://docs.didit.me/ar/management-api/travel-rule/trigger-test-vasp-inbound.md)، أو سجّل تحويلًا بنفسك عبر [Register Inbound Travel Rule Transfer](https://docs.didit.me/ar/management-api/travel-rule/register-inbound.md). اختبر محفظة غير معروفة، ومحفظة غير موثّقة، وعدم تطابق اسم المستفيد، ومحفظة موثّقة متطابقة. تختبر هذه الحالات قرارات حقيقية بشأن المعاملات الواردة دون الاتصال بأي شبكة.
* **تطبيقان حيان خاضعان للتحكم:** استخدم المسار `INTERNAL` بين تطبيقين حيين تملكهما، حيث يكون التطبيق المستقبِل قابلًا للاكتشاف ويثبت سيطرته على محفظة الوجهة برسالة موقّعة أو إيداع تجريبي. أو استخدم طرفًا مقابلًا خاضعًا للتحكم عبر TRP، لاختبار تبادل بين طرفين دون بيانات اعتماد تجارية للشبكة. قد تترتب على التطبيقات الحية رسوم وإشعارات عادية، لذا استخدم هويات وأطرافًا مقابلة تتحكم بها أنت.

راجع [اختبار Travel Rule في البيئة التجريبية](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) لكل السيناريوهات ونتيجة كل منها بدقة. لا تُثبت الاختبارات الناجحة في البيئة التجريبية أو اختبارات البروتوكول المحلي بيانات اعتماد شبكة تجارية أو عضويتها أو قابليتها للتشغيل البيني في بيئة الإنتاج. تتطلب هذه الأمور بيئة تجريبية لشبكة معتمدة، أو تبادلًا حيًا خاضعًا للتحكم مع بيانات اعتماد عضوية صالحة.

## إرسال تحويل

أدرِج التحويل في [`POST /v3/transactions/`](https://docs.didit.me/ar/transaction-monitoring/transactions) بضبط `transaction_category` على `travelRule` (أو `travel_rule`) وإرفاق كائن `travel_rule_details` (الاسم البديل: `travelRule`).

كتلة `travel_rule_details` نفسها اختيارية، لكن بمجرد إرفاقها يصبح `travel_rule_details.status` مطلوباً: الكتلة التي لا تتضمنه تعيد `400`.
عندما يكون Travel Rule **مفعّلاً** لتطبيقك، يتجاهل Didit قيمة `status` التي ترسلها ويدير تبادل المعلومات بنفسه:

1. إذا كان المبلغ أقل من `threshold_amount` المضبوط لديك، يُحسم التحويل فوراً على `NOT_APPLICABLE` ولا يُتفاوض على شيء.
2. إذا أعلنت وسيلة دفع الطرف المقابل أن الوجهة محفظة ذاتية الاستضافة (`payment_method.method_type: "unhosted_wallet"`)، فلا تُجرَّب أي قناة، ويذهب التحويل مباشرة إلى `UNCONFIRMED_OWNERSHIP` ويُنشأ أداة التحقق من ملكية المحفظة تلقائياً (انظر [المحافظ الذاتية الاستضافة المُعلنة](#المحافظ-ذاتية-الاستضافة-المُصرَّح-بها)).
3. وإلا تُشغَّل القنوات بحسب ترتيب الأولوية، وأول قناة تصل إلى الطرف المقابل تحمل التبادل:
   * `INTERNAL` - يوجد عميل آخر واحد فقط لدى Didit يملك إثباتاً بتوقيع رسالة أو بإيداع تجريبي للعنوان `beneficiary_data.wallet_address`، أُنجز بعد آخر تغيير في حائز المحفظة. لا يُحتسب تطبيقك أنت أبداً، وعندما يختار المستخدم النهائي عضواً في شبكة Didit ضمن [أداة التحقق من ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md)، يُحتسب إثبات ذلك العضو وحده. يعمل تطبيق ذلك العميل في بيئة الإنتاج (وليس البيئة التجريبية)، ومفعّل فيه Travel Rule مع ضبط `is_discoverable`، وهو الـ VASP الذي تسمّيه عند إرسال `counterparty_vasp_lei` أو `counterparty_vasp_name`. المحفظة المُعلنة ذاتياً فقط، أو المُثبَتة بلقطة شاشة، أو غير الموثّقة، أو المدرجة في دفتر العناوين فقط، لا تستلم شيئاً عبر `INTERNAL` أبداً.
   * `TRP` - للأصل المُحوَّل معرّف رمز رقمي وفق ISO 24165 (DTI) مطابق لشبكة التحويل (انظر [معرّفات أصول TRP](#معرّفات-أصول-trp))، والحمولة تتضمن `beneficiary_data.travel_address`، أو يخزّن إدخال دفتر العناوين الخاص بالوجهة عنواناً من هذا النوع، أو يُحلّ الطرف المقابل في [الدليل](#الدليل) (عبر `counterparty_vasp_lei` أو `counterparty_vasp_name`) ولديه نقطة نهاية TRP.
   * `GTR`، `TRUST`، `VERIFYVASP`، `SYGNA` - ربطت عضويتك الخاصة في تلك الشبكة من **Marketplace**، ويُحلّ الطرف المقابل إلى معرّف شبكة (حقل صريح أو إدخال في الدليل، انظر [حقول تحديد الطرف المقابل](#حقول-تحديد-الطرف-المقابل)).
     ولا تملك Didit حالياً عضوية منصة في هذه الشبكات (وهي في طور الانضمام كمزوّد)، لذلك لا يغيّر `disabled_networks` هذه الخطوة في الوقت الحالي.
   * `EMAIL` - وُفِّر `beneficiary_data.counterparty_vasp_email`، أو يُحلّ `counterparty_vasp_name` إلى إدخال في الدليل يحتوي على عنوان بريد إلكتروني للامتثال.
4. إذا لم تستطع أي قناة تحديد الطرف المقابل، تُشغّل Didit سلسلة [اكتشاف الطرف المقابل](#اكتشاف-الطرف-المقابل). مع تفعيل `vasp_attribution_enabled`، تتضمن هذه السلسلة [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين): تُحدَّد المحفظة الوجهة إلى الـ VASP المالك لها، ويُكتب الاسم المُسنَد إلى `beneficiary_data.counterparty_vasp_name` (إذا كان فارغاً) وإلى [الدليل](#الدليل)، وتُعاد تشغيل القنوات مرة واحدة. لذلك تُوجَّه المحفظة المُسنَدة إلى VASP يحمل إدخاله في الدليل نقطة نهاية TRP أو معرّف شبكة أو عنوان بريد إلكتروني للامتثال في هذه المرحلة الثانية.
5. إذا بقي الطرف المقابل غير محلول، ينتقل التحويل إلى `COUNTERPARTY_VASP_NOT_FOUND`. في التحويلات الصادرة يُنشئ Didit تلقائياً [أداة التحقق من ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) (عندما يكون `auto_wallet_verification` مفعّلاً) حتى يمكن إتمام التحويل كتحويل إلى محفظة ذاتية الاستضافة، ويمكنك إعادة تشغيل التوجيه لاحقاً باستخدام `action: "resend"` بعد توفر بيانات أفضل عن الطرف المقابل.

تحدث الخطوتان 1 و2 ضمن الطلب نفسه. وتعمل الخطوات من 3 إلى 5 مباشرة بعد الاستجابة: يعود التحويل بالحالة `AWAITING_COUNTERPARTY` مع `protocol: null`، ويصل كل نتيجة عبر webhook من نوع [`travel_rule.status.updated`](#webhooks).

### معرّفات أصول TRP

يسمّي `TRP` الأصل المُحوَّل بمعرّف الرمز الرقمي وفق ISO 24165 (DTI).
يحدد DTI رمزاً واحداً على بلوكتشين واحد، لذلك يملك الرمز متعدد السلاسل معرّف DTI لكل شبكة.

يرسل Didit التحويلات عبر `TRP` لهذه الأصول:

| الأصل | الشبكة | DTI |
| - | - | - |
| `BTC` | Bitcoin | `4H95J0R2X` |
| `ETH` | Ethereum | `X9J9K872S` |
| `USDC` | Ethereum | `CK9PW1MFH` |
| `USDC` | Celo | `2ZTG3NNVB` |
| `USDC` | Base | `CP6817N4B` |
| `USDC` | Optimism | `898NNTPZJ` |
| `USDC` | Arbitrum One | `4ZSZS1F4F` |
| `USDC` | Polygon PoS | `LS71LQK3L` |
| `USDC` | Avalanche C-Chain | `45J6XJX7H` |
| `USDC` | Solana | `5R3XFPZSM` |
| `USDC` | Plume | `N064ZKXDM` |

معرّفات `USDC` هي التي ينشرها مُصدر الرمز في ورقته البيضاء وفق MiCA.

بالنسبة إلى الرمز متعدد السلاسل، يجب أن يحدد التحويل شبكته في `transaction_details.crypto_params.crypto_chain` (مثل `CELO` أو `BASE` أو `OP` أو `ARB` أو `POL`).
فبدون شبكة، أو على شبكة لا يوجد لها ربط، لا يُرسل التحويل عبر `TRP`، ويجرّب Didit القنوات المتبقية: شبكات التشغيل البيني أولاً، ثم البريد الإلكتروني.

`USDT` غير مربوط بعد.
أما الرمز الذي لا يملك ربط DTI، مثل العملة المستقرة الخاصة بشركة، فيحتاج مُصدره إلى تسجيل DTI لدى جهة التسجيل وفق ISO 24165، واحد لكل رمز على كل بلوكتشين.
وبعد وجود معرّفات DTI، تواصل مع دعم Didit وأرسل كل DTI وبلوكتشينه وعدد الخانات العشرية للرمز، فيضيف Didit الربط.

تُسجَّل طلبات الاستعلام الواردة عبر `TRP` التي تحمل DTI مرتبطاً بكل سلسلة بعملة الرمز، والمبلغ بالخانات العشرية للرمز، والشبكة.

### اكتشاف الطرف المقابل

يصل التحويل الذي يحمل عنوان محفظة فقط إلى طرفه المقابل متى تمكّن أي أحد من تحديده.
قبل إعلان تعذّر توجيه تحويل صادر، يسأل Didit بهذا الترتيب، ويتوقف عند أول خطوة تسمّي VASP له مسار:

| الخطوة | ما الذي تفعله |
| - | - |
| `internal_address_book` | يثبت عميل آخر لدى Didit سيطرته على المحفظة (بتوقيع أو إيداع تجريبي)، فيسلّم مسار `INTERNAL` التحويل إليه. لا يُحتسب إدخال في دفتر العناوين لم يُثبَت أبداً. |
| `wallet_attribution` | إسناد المحفظة عبر تحليلات البلوكتشين، مطابَقاً مع VASP في الدليل له مسار. تُستخدم النتيجة المخزّنة مرة أخرى، وتُحصَّل رسومها مرة واحدة. يتطلب `vasp_attribution_enabled`. |
| `network_lookup` | شبكة Travel Rule تجيب عن سؤال "من يملك هذا العنوان"، عندما يملك تطبيقك الوصول إليها. لا تقدّم هذه الخدمة اليوم سوى GTR، وتعمل عندما تُرسل قناة GTR التحويل. وفي غير ذلك تُسجَّل الخطوة بالحالة `skipped` مع السبب. |
| `customer_hint` | اسم VASP أو LEI أو الولاية القضائية التي أرسلتها في `beneficiary_data`، ويُطابَق مع VASP في الدليل لديه مسار. أما `travel_address` أو بريد الامتثال فيُوصَل إليهما عبر قناته الخاصة. |
| `end_user` | لم يُسمِّ أحد الطرف المقابل، لذا يُسأل المستخدم النهائي. انظر أدناه. |

يسرد الحقل `discovery` في التحويل كل خطوة نُفِّذت مع `outcome` الخاص بها (`match` أو `miss` أو `skipped`)، و`reason` مقروءاً آلياً، و`vasp` و`rail` اللذين وجدتهما، والطابع الزمني.
يتقدّم VASP الذي اخترته أنت أو المستخدم النهائي على كل خطوة تلقائية، فلا يستبدله الاكتشاف أبداً بتخمينه الخاص.

عندما لا تسمّي أي خطوة طرفاً مقابلاً، ينتقل التحويل إلى `COUNTERPARTY_VASP_NOT_FOUND`، أو إلى `COUNTERPARTY_VASP_NOT_REACHABLE` إذا سُمّي VASP لكن لا يتوفر أيٌّ من مساراته لتطبيقك.
ثم يحمل التحويل `reason` (`awaiting_end_user` أو `no_directory_match` أو `directory_match_no_route` أو `picked_member_without_proven_wallet` عندما لم يثبت العضو الذي اختاره المستخدم النهائي ملكية المحفظة) وقائمة `next_actions`:

| `action` | المعنى |
| - | - |
| `select_counterparty_vasp` | يختار المستخدم النهائي VASP الوجهة في [أداة المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md)، أو تسمّيه أنت بنفسك باستخدام `{"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"}` في [endpoint التحويل](#إرسال-تحويل). يُوجَّه التحويل إلى ذلك VASP ويُرسل من جديد. |
| `declare_self_hosted` | يعلن المستخدم النهائي في الأداة نفسها أن المحفظة ذاتية الاستضافة. |
| `add_vasp_hint` | أرسل اسم VASP أو LEI أو `travel_address` في `beneficiary_data`، ثم أعد الإرسال. |
| `update_compliance_email` | أعطِ بريد الامتثال الخاص بالطرف المقابل مرة أخرى عندما رُفض البريد الأول؛ راجع [لماذا يتوقف التحويل](#لماذا-يتوقف-التحويل). |
| `resend` | أعد تشغيل الاكتشاف بما تغيّر. |

رابط الأداة هو `url` في الإجراءات التي يؤديها المستخدم النهائي.
عندما يكون إجراء إثبات ملكية المحفظة معلّقاً، يحمل قسم `action_required` في المعاملة (من النوع `wallet_ownership`) الـ`reason` نفسه و`next_actions` نفسها، فيعرض العميل الذي يتتبع `action_required` أصلاً أداة الاختيار دون أي عمل إضافي.

### حقول تحديد الطرف المقابل

تأتي كل المعلومات التي يعرفها Didit عن الطرف المقابل من `travel_rule_details.beneficiary_data`.
تُشغّل هذه الحقول تحديد المسار، وجميعها اختيارية:

| الحقل | ما يُشغّله |
| - | - |
| `wallet_address` | مطابقة `INTERNAL` مع دفتر العناوين، وبحث `TRP` في دفتر العناوين، وتدفقات إثبات ملكية المحفظة. عندما تحذفه يستخدم Didit القيمة `counterparty.payment_method.account_id`. |
| `chain` | يحدد نطاق البحثين في دفتر العناوين: لا يُطابَق المدخل إلا إذا كان `chain` الخاص به يساوي هذه القيمة (دون مراعاة حالة الأحرف) أو إذا لم يكن له `chain` أصلاً. عندما تحذفه يملؤه Didit من `transaction_details.crypto_params.crypto_chain` أو `custom_properties.crypto_chain` أو من عملة التحويل بعد تحويلها إلى أحرف كبيرة، لكن فقط إذا كانت هذه القيمة سلسلة يتعرف عليها Didit (مثل `ETH` و`BTC` و`SOL` و`TRX`)؛ وإلا فلا يحمل التحويل أي سلسلة ويُطابق المدخلات على أي سلسلة. أما تحويلات `USDT` أو `USDC` التي لا تحمل سلسلة صريحة، فيستنتج Didit سلسلتها من هاش المعاملة في `transaction_details.payment_reference_id` (الهاش الذي يبدأ بـ `0x` يعطي `ETH`). |
| `memo` | وسم الوجهة أو مذكرة `wallet_address` في الشبكات التي تستخدم المذكرات. ويُعد جزءاً من المحفظة كلما طُوبق `wallet_address` (راجع [المذكرات والوسوم في الشبكات](#شبكات-memo-والوسم)). الاسم البديل: `destinationTag`. |
| `travel_address` | يُوجَّه مباشرةً عبر `TRP`، وهو أقوى إشارة يمكنك تمريرها. |
| `counterparty_vasp_lei` | بحث في الدليل بواسطة LEI لأجل `TRP` و`GTR` و`TRUST` و`VERIFYVASP` و`SYGNA`. ويُتحقق منه أيضاً مقابل الهوية التي تبلّغ عنها endpoint الخاص بـ TRP؛ فعدم التطابق، أو هوية بلا LEI، يوقف التبادل بالحالة `COUNTERPARTY_VASP_NOT_REACHABLE`. |
| `counterparty_vasp_name` | بحث في الدليل لأجل `TRP` و`GTR` و`TRUST` و`VERIFYVASP` و`SYGNA` و`EMAIL`: الاسم الدقيق، ثم الاسم نفسه مكتوباً بطريقة أخرى (مثل `B.V.` بدلاً من `BV`، أو مع حرف بعلامة لهجة)، ثم اسم بديل لأحد المدخلات. ويُتحقق منه بمطابقة تقريبية مع هوية TRP عند توفر الاثنين. |
| `counterparty_vasp_jurisdiction` | رمز البلد وفق ISO 3166 للكيان المستلم عندما يكون VASP المسمّى علامة تجارية لها عدة كيانات منظّمة، أو عندما تشترك عدة مدخلات في الدليل في الاسم نفسه؛ راجع [العلامات التجارية وكياناتها](#العلامات-التجارية-وكياناتها). |
| `counterparty_gtr_vasp_code` | معرّف شبكة `GTR` الصريح؛ يتجاوز الدليل. |
| `counterparty_trust_membership_id` | معرّف شبكة `TRUST` الصريح؛ يتجاوز الدليل. |
| `counterparty_verifyvasp_id` | معرّف شبكة `VerifyVASP` الصريح؛ يتجاوز الدليل. |
| `counterparty_sygna_vasp_code` | رمز VASP الصريح لـ`Sygna Bridge`؛ يتجاوز الدليل. |
| `counterparty_vasp_email` | جهة الاتصال الصريحة للامتثال في قناة `EMAIL`؛ تتجاوز الدليل. |

### أشكال السلاسل

في سلسلة الحسابات (شبكات EVM وSolana وTron) ينقل التحويل الأموال من عنوان إلى آخر، ويقرأ Didit المحفظتين مباشرةً من المعاملة.
تحتاج ثلاثة أشكال أخرى إلى مزيد من البيانات، وما يحدده Didit لها يظهر في التحويل بوصفه `chain_details` (فارغاً، أي `{}`، في سلسلة الحسابات).
يحمل كلٌّ من `chain_details.originator` و`chain_details.beneficiary` الحقول `address` و`memo` و`source` الذي أتى منه، ويبدأ التوجيه والمطابقة بقراءة المحفظتين منهما أولاً.

#### تحويلات UTXO

تُنفق معاملة Bitcoin أو Litecoin أو Bitcoin Cash أو Dogecoin مدخلاتٍ من أي عدد من العناوين، وتدفع أي عدد من المخرجات، وبعضها يعود إلى المرسل كباقي المبلغ.
أرسل المدخلات والمخرجات في `travel_rule_details.utxo` (المبالغ بوحدة العملة نفسها، كسلاسل عشرية)، وسيستنتج Didit ما لا تصرّح به:

* **المرسل**: `originator_data.wallet_address` عندما ترسله، وإلا فعنوان المدخل الذي ساهم بأكبر قدر (`source: largest_input`).
* **المستفيد**: المحفظة المعلنة، وإلا فالمخرج الوحيد الذي لا يُعيد دفع مبلغ إلى عنوان مدخل كباقٍ (`only_non_change_output`)، وإلا فالمخرج الذي يدفع مبلغ التحويل (`amount_match`).

```bash theme={null}
curl -X POST https://verification.didit.me/v3/transactions/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "btc-withdrawal-0042",
    "transaction_category": "travelRule",
    "transaction_details": {
      "direction": "outbound",
      "amount": "0.25",
      "currency": "BTC",
      "currency_kind": "crypto"
    },
    "subject": { "vendor_data": "user-042", "full_name": "Ana Diaz" },
    "counterparty": { "full_name": "Luis Perez" },
    "travel_rule_details": {
      "status": "AWAITING_COUNTERPARTY",
      "beneficiary_data": { "name": "Luis Perez", "counterparty_vasp_name": "Destination Exchange" },
      "utxo": {
        "inputs": [
          { "address": "bc1qsenderhotwallet01", "amount": "0.30" },
          { "address": "bc1qsendercoldwallet02", "amount": "0.05" }
        ],
        "outputs": [
          { "address": "bc1qbeneficiarydeposit01", "amount": "0.25" },
          { "address": "bc1qsenderhotwallet01", "amount": "0.0999" }
        ]
      }
    }
  }'
```

يحمل التحويل بعد ذلك:

```json theme={null}
{
  "chain_details": {
    "chain": "BTC",
    "shape": "utxo",
    "originator": { "address": "bc1qsenderhotwallet01", "memo": "", "source": "largest_input" },
    "beneficiary": { "address": "bc1qbeneficiarydeposit01", "memo": "", "source": "only_non_change_output" },
    "utxo": {
      "inputs": [
        { "address": "bc1qsenderhotwallet01", "amount": "0.300000000000000000" },
        { "address": "bc1qsendercoldwallet02", "amount": "0.050000000000000000" }
      ],
      "outputs": [
        { "address": "bc1qbeneficiarydeposit01", "amount": "0.250000000000000000" },
        { "address": "bc1qsenderhotwallet01", "amount": "0.099900000000000000" }
      ],
      "change_output_indexes": [1],
      "beneficiary_output_index": 0
    }
  }
}
```

يُشير `chain_details.warnings` إلى ما لا يتطابق: `declared_originator_not_an_input` و`declared_beneficiary_not_an_output` و`beneficiary_output_ambiguous` (لم يكن بالإمكان تمييز مخرَج واحد بعينه) و`beneficiary_output_amount_differs`.
يُنتج إرسال `utxo` على أي سلسلة أخرى الخطأ `400`، ولا تحتوي كل قائمة على أكثر من 1,000 عنصر.
يأخذ الإيداع المُبلَّغ عنه الكائن `utxo` نفسه (راجع [تسجيل ما بعد الإيداع](#التسجيل-اللاحق-للإيداع)).

#### شبكات memo والوسم

في XRP وStellar (XLM) وEOS وCosmos (ATOM) وHedera (HBAR)، تستقبل المنصة كل عملائها عبر عنوان واحد مشترك، وتميّز بينهم بوسم الوجهة (destination tag) أو بالـ memo.
لذلك يُعدّ الـ memo جزءًا من المحفظة: أرسله بوصفه `payment_method.memo` على المشارك، أو بوصفه `memo` داخل `originator_data` / `beneficiary_data` (الاسم البديل `destinationTag`)، وتقارن Didit العنوان والـ memo معًا.

* يطابق إدخالُ دفتر العناوين الذي يحمل memo التحويلاتِ التي تذكر هذا الـ memo فقط. أما الإدخال الذي لا يحمل memo فيطابق العنوان كاملًا. ولا يصل أي تحويل لا يذكر memo إلى إدخال يحمل واحدًا: فعلى عنوان مشترك، الإيداع الذي لا وسم معه لا يخص أحدًا.
* عنوان X في XRP يحمل الوسم داخله: تفصله Didit إلى العنوان الكلاسيكي والوسم (`source: x_address`)، فتطابق المحفظة المسجّلة بأي من الصيغتين تحويلًا بالصيغة الأخرى.
* كل memo على عنوان مشترك يُعدّ وسيلة دفع مستقلة في المعاملة.
* ما تقبله كل شبكة: وسم الوجهة في XRP عدد صحيح من 0 إلى 4294967295 (يُقبل رقم JSON)؛ وmemo في Stellar نص يصل إلى 28 بايتًا، أو معرّف من 64 بت، أو تجزئة من 32 بايتًا بصيغة hex؛ وEOS يقبل حتى 256 بايتًا، وCosmos حتى 256 حرفًا، وHedera حتى 100 بايت. وأي memo على سلسلة لا تدعمه (Bitcoin وشبكات EVM وSolana وTron وLitecoin وBitcoin Cash وDogecoin وLightning) يُنتج الخطأ `400`.

#### Lightning

لا تملك دفعة Lightning عنوان مستفيد على السلسلة: فالدافع يحمل طلب دفع.
في تحويلات العملات المشفرة على bitcoin أو Lightning، يجوز أن يكون `payment_method.account_id` هذا الطلب، فتحدد Didit المستفيد منه دون الاتصال بأي شبكة:

| ما ترسله | المستفيد |
| - | - |
| فاتورة BOLT11 (`lnbc...`) | عقدة المستلم، المذكورة في الفاتورة أو المستخرجة من توقيعها. |
| عرض BOLT12 أو فاتورته (`lno1...`، `lni1...`) | عقدة المُصدِر، ما لم تكن مخفية خلف مسارات مُعمّاة. |
| عنوان Lightning (`name@domain`) | العنوان نفسه. |
| معرّف العقدة | العقدة نفسها. |
| LNURL (`lnurl1...`، `lnurlp://`) | لا شيء: فهو يسمّي خدمة وليس مستلمًا. |

يُخزَّن المستلم بوصفه الحساب وبوصفه `chain_details.beneficiary` (`source: invoice_payee`)، على السلسلة `LIGHTNING`، ويُحفظ ما يذكره الطلب في `chain_details.lightning`.
عندما لا يذكر الطلب مستلمًا، تكون التحويلة الصادرة `NOT_APPLICABLE` ويُسجَّل السبب في `chain_details.not_applicable_reason` وفي `timeline`: `LIGHTNING_NO_PAYEE_IDENTIFIER` أو `LIGHTNING_BOLT12_BLINDED_PAYEE` أو `LIGHTNING_LNURL_NAMES_NO_PAYEE`.
لا تُقرأ القيمة على أنها Lightning إلا على bitcoin، أو على `LIGHTNING`، أو عندما لا تُسمَّى سلسلة (ولا يُعامَل عنوان Lightning إلا على bitcoin أو `LIGHTNING`): على أي سلسلة أخرى تكون هذه القيمة عنوان تلك السلسلة نفسه.

> [!NOTE]
>
> لا يصل مسار `INTERNAL` إلى عميل Didit آخر إلا عبر محفظة أثبت ذلك العميل سيطرته عليها برسالة موقّعة أو بإيداع تجريبي، وهذه الإثباتات متاحة اليوم لـ Bitcoin وشبكات EVM وSolana وTron فقط.
> لذلك لا يصل التحويل أبدًا إلى عميل Didit آخر عبر `INTERNAL` على شبكات memo وLightning وLitecoin وBitcoin Cash وDogecoin.
> أما مطابقة الـ memo والوسم وLightning فتظل سارية على دفتر عناوينك أنت: التحويلات الواردة، والإيداعات المُبلَّغ عنها، واستفسارات `TRP` الموجهة إلى محافظك.

### تحديث محفظة المُرسِل

غالبًا ما يُصرَّح بالسحب من محفظة العميل الرئيسية، ويُبثّ من العناوين التي كانت تحتفظ بالعملات فعلًا.
سجّل المحفظة التي خرجت منها الأموال فعلًا باستخدام `PATCH /v3/transactions/{transaction_id}/travel-rule/`:

```bash theme={null}
curl -X PATCH "https://verification.didit.me/v3/transactions/$TRANSACTION_ID/travel-rule/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "action": "update_originator_wallet", "wallet_address": "bc1qsendercoldwallet02" }'
```

* التحويلات الصادرة فقط، ولا يجوز ذلك أبدًا لتحويل بالحالة `CANCELLED` أو `EXPIRED` (`409`).
* عندما تكون مدخلات UTXO الخاصة بالتحويل معروفة، يجب أن تكون المحفظة إحدى هذه المدخلات (وإلا فالخطأ `400`). أرسل `memo` أيضًا على شبكة تستخدم الـ memo.
* يغيّر ذلك السجل فقط: لا يُرسل أي شيء إلى الطرف المقابل مرة أخرى، وتبقى الحالة كما هي. يصبح `chain_details.originator` المحفظة الجديدة مع `source: updated`، ويسجّل `timeline` المحفظتين السابقة والجديدة، ويُحدَّث الطرف `INTERNAL` المقابل للتحويل بالطريقة نفسها.

### إسناد تحليلات البلوكتشين

عندما تمرّر عنوان محفظة وحده، تستطيع Didit مع ذلك أن تعرف من يقف على الطرف الآخر.
إذا لم يستطع أي مسار توجيه التحويل، تطابق Didit محفظة الوجهة مع بيانات إسناد تحليلات البلوكتشين، وهي التحليلات نفسها التي تقف خلف [فحص معاملات العملات المشفرة](https://docs.didit.me/ar/transaction-monitoring/aml-screening.md)، فتعرف المحافظ التي تنتمي إلى كل منصة تداول وكل حارس أصول.
يعمل الإسناد على التحويلات الصادرة التي تحمل محفظة وجهة و`chain` معًا (راجع [حقول تحديد الطرف المقابل](#حقول-تحديد-الطرف-المقابل))؛ وبدون السلسلة يُتخطّى.

عندما تُسنَد المحفظة إلى جهة معروفة، تقوم Didit بما يلي:

1. تسجّل الإسناد على التحويل: يُملأ `beneficiary_data.counterparty_vasp_name` إذا لم تكن قد زوّدتها أنت، وتحمل بيانات التحويل الوصفية كتلة `vasp_attribution` تضم اسم الجهة ونوعها وبلدها و`source: "blockchain_analytics"`.
2. تضيف الجهة إلى [دليل VASP](#الدليل) (أو تطابق الإدخال الموجود)، فيبقى الإسناد ثابتًا عبر التحويلات.
3. تعيد تشغيل المسارات مرة واحدة باسم الجهة المُسنَد: فالإدخال الموجود في الدليل الذي يحمل بالفعل TRP endpoint يجعل التحويل يُوجَّه فورًا بدلًا من أن ينتهي إلى `COUNTERPARTY_VASP_NOT_FOUND`.

يعمل استدعاء الإسناد أيضًا بوصفه فحصًا كاملًا للعملات المشفرة: تتلقى المعاملة المخرجات الكاملة للفحص، من درجة المخاطر وفئة مخاطر المحفظة ولقطة الشبكة، تمامًا كما لو كانت مراقبة العملات المشفرة قد أُجريت. ويُضبط `custom_values.aml_screening_trigger` للمعاملة على `travel_rule_attribution` حتى تعرف أن الفحص أُجري لأن توجيه Travel Rule استوجبه.
وإذا كانت مراقبة العملات المشفرة قد فحصت المحفظة نفسها في هذه المعاملة من قبل، أُعيد استخدام النتيجة المخزَّنة: فلا استدعاء ثانٍ للتحليلات ولا رسوم ثانية.
ولا يمنع الإسناد أبدًا إنشاء المعاملة: فإذا فشل بحث التحليلات أو لم يغطِّ رصيدك تكلفته، يمضي التحويل إلى `COUNTERPARTY_VASP_NOT_FOUND` دون أي رسوم على المحاولة.
وعند `action: "resend"`، يُعاد استخدام الإسناد المسجّل سابقًا بدلًا من إعادة الاستعلام عنه.

عطّل الخطوة كاملة باستخدام `vasp_attribution_enabled: false` في [الإعدادات](#الإعداد).
راجع [الأسعار](#الأسعار) لمعرفة طريقة فوترة استدعاء الإسناد.

عندما تكون Travel Rule **معطّلة**، تُسجَّل `travel_rule_details` (بما فيها `status` الذي يحدده المستدعي، سواء كان القديم أو الحالي) على المعاملة، ولكن بشكل سلبي، دون إرسال أي مسار.
استخدم هذا لاستكمال بيانات الامتثال التي سبق أن تتبعتها بعمليتك الخاصة.
التحويل الصادر السلبي لا يبدأ أي تبادل، لذلك يُحتسب كـ Transaction Screening، وليس على [بند Travel Rule](#الأسعار).

عند تفعيل Travel Rule، يُوجَّه هذا الطلب عبر المسار `EMAIL`، لأنه يتضمن البريد الإلكتروني للامتثال لدى الطرف المقابل، ولا يستطيع أي مسار سابق الوصول إلى المستفيد:

```bash theme={null}
curl -X POST https://verification.didit.me/v3/transactions/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "trv-2026-07-05-001",
    "transaction_category": "travelRule",
    "transaction_details": {
      "direction": "outbound",
      "action_type": "transfer",
      "amount": "0.25",
      "currency": "ETH",
      "currency_kind": "crypto"
    },
    "subject": {
      "entity_type": "individual",
      "vendor_data": "user-042",
      "full_name": "Jane Doe"
    },
    "travel_rule_details": {
      "status": "AWAITING_COUNTERPARTY",
      "originator_data": {
        "first_name": "Jane",
        "last_name": "Doe",
        "date_of_birth": "1990-04-12",
        "residence_country": "ES",
        "customer_identification": "user-042",
        "wallet_address": "0x135908330861442a814796ae99feac507925782a"
      },
      "beneficiary_data": {
        "wallet_address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
        "name": "Ana Diaz",
        "counterparty_vasp_email": "compliance@bene-casp.example"
      }
    }
  }'
```

الاستجابة، مختصرة لتقتصر على الحقول المهمة هنا:

```json theme={null}
{
  "uuid": "22222222-3333-4444-5555-666666666666",
  "txn_id": "trv-2026-07-05-001",
  "transaction_type": "travelRule",
  "direction": "OUTBOUND",
  "status": "APPROVED",
  "amount": "0.25",
  "currency": "ETH",
  "currency_type": "crypto",
  "travel_rule": {
    "uuid": "33333333-4444-5555-6666-777777777777",
    "status": "AWAITING_COUNTERPARTY",
    "protocol": null,
    "required": true,
    "obligations_count": 0,
    "originator_data": {
      "first_name": "Jane",
      "last_name": "Doe",
      "date_of_birth": "1990-04-12",
      "residence_country": "ES",
      "customer_identification": "user-042",
      "wallet_address": "0x135908330861442a814796ae99feac507925782a"
    },
    "beneficiary_data": {
      "wallet_address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
      "name": "Ana Diaz",
      "counterparty_vasp_email": "compliance@bene-casp.example",
      "chain": "ETH"
    },
    "metadata": {
      "compliance_email_source": "caller_supplied"
    }
  },
  "action_required": null
}
```

* `originator_data` هي ما أرسلته، لأن المستخدم في المثال ليس لديه تحقق KYC معتمد؛ بالنسبة إلى مستخدم موثّق يبنيها Didit من البيانات الموثّقة (انظر [البيانات الموثّقة ومصدرها](#البيانات-الموثّقة-ومصدرها)).
  يعرض المسار `EMAIL` للمستلم حقول المُرسِل التي تشاركها في [`data_sharing_fields`](#مشاركة-البيانات) فقط.
* `beneficiary_data.chain` هي `ETH` لأن الطلب لم يحدد أي شبكة، فأخذها Didit من العملة.
* `status` هي `APPROVED` لأن أي قاعدة لم تتخذ إجراءً على المعاملة؛ قد تحدد قواعدك الخاصة حالة أخرى.
* تتلقى جهة اتصال الامتثال رابط الاستلام، ويكتمل التحويل، أو يفشل في مطابقة الاسم، أو يُرفض عند ردها، أو تنتهي صلاحيته إن لم تردّ (انظر [استلام البريد الإلكتروني](#استلام-البريد-الإلكتروني-للأطراف-المقابلة-غير-القابلة-للوصول)).

`protocol` ما زال `null` لأن المسار يُختار بعد الاستجابة (مثلاً `EMAIL` عندما تزوّد `counterparty_vasp_email`): يعرضه [الحصول على المعاملة](https://docs.didit.me/ar/management-api/transactions/get.md) بعد اختياره، وكل webhook لاحق من نوع `travel_rule.status.updated` يحمله في `rail`.
إذا كانت محفظة المستفيد تنتمي إلى عميل آخر في Didit أثبت سيطرته عليها، يُسوّي مسار `INTERNAL` التبادل كله فور الاستجابة، وذلك الـ webhook يُبلغ بالفعل `COMPLETED` (أو `COUNTERPARTY_MISMATCHED_DATA`). عندما لا يتطابق الاسم، يصبح تحويلك `COUNTERPARTY_MISMATCHED_DATA` ولا يتلقى العميل الآخر أي شيء.
من دون `counterparty_vasp_email`، وعندما لا تستطيع المسارات ولا [الإسناد](#إسناد-تحليلات-البلوكتشين) الوصول إلى المستفيد، ينتهي التحويل لاحقاً بالحالة `COUNTERPARTY_VASP_NOT_FOUND` مع إجراء `wallet_ownership` على المعاملة.

> [!NOTE]
>
> تحمل كتلة `travel_rule` المضمّنة في المعاملة حقول التحويل نفسه (`uuid` و`status` و`protocol` و`required` و`obligations_count` و`originator_data` و`beneficiary_data` و`metadata`)، وما حدّده Didit وقارنه (`chain_details` و`name_match` و`data_match` و`mismatched_fields`، وحقلي [الإخفاء](#بيانات-الطرف-المقابل-المقنّعة) `data_masked` و`data_unmasked`)، والحقول التي توضح أين يقف التحويل: `direction` و`rail` و`counterparty_vasp` و`delivery` و`discovery` و`reason` و`next_actions` (انظر [لماذا يتوقف التحويل](#لماذا-يتوقف-التحويل)).
> تحمل كل صف من [`GET /v3/transactions/`](https://docs.didit.me/ar/management-api/transactions/list) الكتلة نفسها، أو `null` للمعاملة التي لا تحتوي على تحويل.
> تُرجع endpoints التحويل المخصصة أدناه تلك الحقول أيضاً، إضافة إلى `ivms_version` و`ownership_confirmed` و`deadline_at` و`timeline` و`created_at`، لكنها لا تتضمن `obligations_count` أو `metadata`.

لإغلاق تحويل صادر بحالة `COMPLETED` بعد بثه على السلسلة:

```bash theme={null}
curl -X PATCH https://verification.didit.me/v3/transactions/22222222-3333-4444-5555-666666666666/travel-rule/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"payment_txn_id": "0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060"}'
```

يتطلب ذلك أن يكون التحويل من نوع **صادر** بحالة `COMPLETED`، وإلا يُرجع API الرمز `409`.
عند النجاح ينتقل كل من التحويل الصادر ونظيره على مسار `INTERNAL` إلى `FINISHED`، وتُضبط `payment_txn_id` للمعاملة على التجزئة التي أرسلتها. على مسار `TRP`، يرسل Didit التجزئة أيضاً إلى رابط استدعاء التأكيد لدى الطرف المقابل.

لإلغاء تحويل لم يصل بعد إلى حالة نهائية، أرسل `{"action": "cancel"}` إلى الـendpoint نفسه بدلاً من ذلك.
يُلغى أيضاً نظيره على مسار `INTERNAL`، وعلى مسار `TRP`، بعد أن يوافق الطرف المقابل على الاستعلام، يرسل Didit الإلغاء إلى رابط استدعاء التأكيد.
التحويل الذي بلغ `FINISHED` أو `CANCELLED` أو `EXPIRED` يُرجع `409`.
الطلب الذي لا يتضمن `payment_txn_id` ولا `action` مدعوماً يُرجع `400`.

على تحويل مرّ عبر `GTR` أو `VERIFYVASP` أو `SYGNA`، يُبلغ Didit الشبكة بالتجزئة على السلسلة (أو بالإلغاء) بعد الاستجابة، مع [إعادات المحاولة نفسها](#التسليم-وإعادة-المحاولة)؛ ويُظهر `delivery` في الاستجابة تلك الرسالة.

لإعادة محاولة تحويل صادر لم يصل إلى طرفه المقابل، أي تحويل في `COUNTERPARTY_VASP_NOT_FOUND` أو `COUNTERPARTY_VASP_NOT_REACHABLE` أو `NOT_ENOUGH_COUNTERPARTY_DATA`، حسّن أولاً بيانات الطرف المقابل، مثلاً بإضافة `travel_address` إلى إدخال المحفظة الوجهة، أو [جهة اتصال](#جهات-الاتصال) لإدخال الطرف المقابل في الدليل، أو بإضافة VASP إلى [الدليل](#الدليل).
ثم أرسل `{"action": "resend"}` إلى الـendpoint نفسه. يعيد Didit ضبط مهلة التأكيد، ويعيد وضع سلّم التوجيه في الطابور من البداية، مستخدماً البيانات المخزنة في التحويل: تُظهر الاستجابة التحويل عائداً إلى `AWAITING_COUNTERPARTY` (مع `resend queued` في `timeline`)، ويصل النتيجة عبر webhook من نوع `travel_rule.status.updated`.
طلب إعادة الإرسال الذي يُرسل أثناء تشغيل محاولة سابقة يُرسل بعد انتهائها.
أي حالة أخرى، أو تحويل وارد، يُرجع `409`.

```bash theme={null}
curl -X PATCH https://verification.didit.me/v3/transactions/22222222-3333-4444-5555-666666666666/travel-rule/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "resend"}'
```

لتسمية الطرف المقابل بنفسك عندما تعذر [الاكتشاف](#اكتشاف-الطرف-المقابل)، أرسل `{"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"}` (وهو `id` من `GET /v3/travel-rule/vasps/`).
يُوجَّه التحويل إلى ذلك VASP ويُعاد إرساله.
لا يقبل ذلك إلا تحويل صادر في `COUNTERPARTY_VASP_NOT_FOUND` أو `COUNTERPARTY_VASP_NOT_REACHABLE` أو `NOT_ENOUGH_COUNTERPARTY_DATA`؛ أي حالة أخرى تُرجع `409`، والمعرّف غير المعروف يُرجع `404`.

### لماذا يتوقف التحويل

يوضح التحويل في `COUNTERPARTY_VASP_NOT_FOUND` أو `COUNTERPARTY_VASP_NOT_REACHABLE` سبب توقفه وما يدفعه إلى الأمام، وذلك في كل قراءة لمعاملته.
تحمل كتلة `travel_rule` في [`GET /v3/transactions/{transaction_id}/`](https://docs.didit.me/ar/management-api/transactions/get) وفي استجابة `201` من [`POST /v3/transactions/`](https://docs.didit.me/ar/management-api/transactions/create) وفي كل صف من [`GET /v3/transactions/`](https://docs.didit.me/ar/management-api/transactions/list) هذه المعلومات، وكذلك كائن التحويل الذي تُرجعه [endpoint التحويل](https://docs.didit.me/ar/management-api/travel-rule/update-transfer.md):

* `reason` هو السبب المقروء آليًا، و`""` لأي حالة أخرى.
* `next_actions` يسرد الإجراءات التي تُحرّك التحويل إلى الأمام، و`[]` لأي حالة أخرى.
* `delivery` هو أحدث رسالة يدين بها التحويل للطرف الآخر، ويتضمن `kind` و`status` (وهي `QUEUED` أو `SENDING` أو `RETRYING` أو `DELIVERED` أو `FAILED`) و`rail` و`attempts` و`last_error` و`next_attempt_at` و`delivered_at`، أو `null` عندما لا يكون مدينًا بأي رسالة.
* `discovery` يبيّن أين بحثت Didit عن الطرف المقابل، بإدخال واحد لكل خطوة نفّذتها، ويتضمن `step` و`outcome` (وهي `match` أو `miss` أو `skipped`) و`reason` و`vasp` و`rail` و`at`.

لا تظهر `email_undeliverable` و`delivery_failed` إلا عند `COUNTERPARTY_VASP_NOT_REACHABLE`، وتنتجان عن تسليم فاشل.
يُحدِّد التسليم الفاشل قيمة `reason` أولًا، لذلك لا يُبلَّغ أبدًا عن طرف مقابل وجدته Didit على أنه طرف لم تتمكن من العثور عليه.
أما الأسباب الأربعة الأخرى فتأتي من سجل الاكتشاف، في أي من الحالتين.

| `reason` | ما الذي حدث | `next_actions` |
| - | - | - |
| `email_undeliverable` | رفض مزوّد البريد بريد الامتثال الإلكتروني، ولم يبقَ أي عنوان لتجربته: عند الإرسال، أو في التذكير، أو كارتداد دائم أُبلغ عنه لاحقًا. | `update_compliance_email`، ثم `resend` |
| `delivery_failed` | فشلت القناة التي كانت تُسلّم الرسالة فشلًا نهائيًا: رفضت قناة شبكة الرسالة، أو استنفدت إعادة المحاولات، أو لم يستجب مضيف هوية `TRP`، أو لم يقبل مضيف `TRP` الخاص بالطرف المقابل الاستفسار. | `resend` |
| `awaiting_end_user` | لم تُسمِّ أي خطوة اكتشاف طرفًا مقابلًا تستطيع Didit الوصول إليه، لذلك يُطلب من المستخدم النهائي تسميته. | `select_counterparty_vasp`، و`declare_self_hosted`، و`add_vasp_hint`، و`resend` |
| `directory_match_no_route` | سمّت إحدى الخطوات إدخالًا في [الدليل](#الدليل)، لكن هذا الإدخال لا يملك مسارًا تستطيع Didit استخدامه لأجلك. | كما في `awaiting_end_user` |
| `picked_member_without_proven_wallet` | اختار المستخدم النهائي عميلًا آخر لدى Didit طرفًا مقابلًا، لكن ذلك العميل لم يُثبت سيطرته على المحفظة. | كما في `awaiting_end_user` |
| `no_directory_match` | لا يقدّم سجل الاكتشاف سببًا آخر. | كما في `awaiting_end_user` |

| الإجراء التالي | ما الذي يجب فعله |
| - | - |
| `update_compliance_email` | أعطِ بريد الامتثال الإلكتروني للطرف المقابل مرة أخرى، باستخدام `{"action": "update_compliance_email", "compliance_email": "..."}` على نقطة نهاية التحويل. |
| `resend` | أعد تشغيل التوجيه باستخدام `{"action": "resend"}` بعد تغيّر شيء ما. |
| `select_counterparty_vasp` | يختار المستخدم النهائي VASP الوجهة في [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md). يكون `url` رابط الأداة ما دامت للتحويل جلسة أداة مفتوحة. |
| `declare_self_hosted` | يُصرّح المستخدم النهائي في الأداة بأن المحفظة ذاتية الاستضافة، عند نفس `url`. |
| `add_vasp_hint` | أخبِر Didit من هو الطرف المقابل، باسم VASP أو LEI أو Travel Address (مثل `travel_address` في [إدخال دفتر العناوين](#دفتر-عناوين-المحافظ) الخاص بمحفظة الوجهة)، ثم أعد الإرسال. |

يُحرّك إعادةُ الإرسال التحويلَ إلى الأمام، فتُمسح قيمة `reason`.
يحمل إدخال الجدول الزمني لأي انتقال تسبب فيه تسليم فاشل القيمةَ نفسها ضمن `reason`.

إذا رفض مزوّد البريد بريد الامتثال الإلكتروني الخاص بـ[مثال التحويل أعلاه](#إرسال-تحويل)، فإن كتلة `travel_rule` في معاملته تقرأ، مختصرة:

```json theme={null}
{
  "uuid": "33333333-4444-5555-6666-777777777777",
  "status": "COUNTERPARTY_VASP_NOT_REACHABLE",
  "protocol": "EMAIL",
  "direction": "OUTBOUND",
  "rail": "EMAIL",
  "counterparty_vasp": null,
  "delivery": {
    "kind": "SEND",
    "status": "FAILED",
    "rail": "EMAIL",
    "attempts": 1,
    "last_error": "email undeliverable",
    "next_attempt_at": null,
    "delivered_at": null
  },
  "reason": "email_undeliverable",
  "next_actions": [
    { "action": "update_compliance_email" },
    { "action": "resend" }
  ]
}
```

هنا تتفق `delivery` مع `reason`، لأن الإرسال نفسه قد رُفض.
أما الرفض في التذكير، أو الارتداد المُبلَّغ عنه لاحقًا، فيُبقي `delivery.status` على `DELIVERED`، لأن الرسالة الإلكترونية الأولى قد أُرسلت بالفعل.
اقرأ `reason` لا `delivery` لتعرف سبب تعطّل التحويل.

لإصلاح ذلك، أعطِ بريد الامتثال الإلكتروني للطرف المقابل مرة أخرى، ثم أعد الإرسال:

```bash theme={null}
curl -X PATCH https://verification.didit.me/v3/transactions/22222222-3333-4444-5555-666666666666/travel-rule/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "update_compliance_email", "compliance_email": "desk@bene-casp.example"}'

curl -X PATCH https://verification.didit.me/v3/transactions/22222222-3333-4444-5555-666666666666/travel-rule/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action": "resend"}'
```

يحتفظ `update_compliance_email` بالعنوان في `beneficiary_data.counterparty_vasp_email` الخاص بهذا التحويل: إنه يخص هذا التحويل وحده، ولا يُضاف إلى أي إدخال في الدليل أو إلى أي قائمة جهات اتصال.
لا تتغير الحالة، ويضيف الجدول الزمني السطر `compliance email updated`، ويحتفظ التحويل بـ`reason: email_undeliverable` حتى تُرسل إعادةُ الإرسال الطلبَ إلى العنوان الجديد.
لا يقبل هذا الإجراء إلا تحويل صادر في `COUNTERPARTY_VASP_NOT_FOUND` أو `COUNTERPARTY_VASP_NOT_REACHABLE` أو `NOT_ENOUGH_COUNTERPARTY_DATA`؛ وأي تحويل آخر يُجيب بالرمز `409`، وتؤدي قيمة `compliance_email` المفقودة أو غير الصحيحة إلى استجابة بالرمز `400`.

### المحافظ ذاتية الاستضافة المُصرَّح بها

عندما يخبرك عميلك أن الوجهة هي محفظته الذاتية الاستضافة (غير المستضافة) الخاصة به، فصرّح بها في المعاملة بدلًا من ترك التوجيه يكتشف أنه لا توجد VASP خلفها: اضبط نوع طريقة الدفع للطرف المقابل على `unhosted_wallet`.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/transactions/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transaction_id": "trv-2026-07-07-002",
    "transaction_category": "travelRule",
    "transaction_details": {
      "direction": "outbound",
      "action_type": "transfer",
      "amount": "0.25",
      "currency": "ETH",
      "currency_kind": "crypto"
    },
    "subject": {
      "entity_type": "individual",
      "vendor_data": "user-042",
      "full_name": "Jane Doe"
    },
    "counterparty": {
      "entity_type": "external",
      "full_name": "Jane Doe",
      "payment_method": {
        "method_type": "unhosted_wallet",
        "account_id": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9"
      }
    },
    "travel_rule_details": {
      "status": "AWAITING_COUNTERPARTY",
      "beneficiary_data": {
        "wallet_address": "0xd3b62acb76fb27a7f8961ec40fa11746b113aca9",
        "name": "Jane Doe"
      }
    }
  }'
```

يتجاوز التصريح التوجيه بالكامل:

* لا تُجرَّب أي قناة، إذ لا توجد VASP مقابلة للتبادل معها، ويُنشأ التحويل مباشرةً في `UNCONFIRMED_OWNERSHIP`.
* عند تفعيل `auto_wallet_verification` (وهو الافتراضي)، تُنشئ Didit تلقائيًا جلسة [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) مرتبطة بالمعاملة، وتعيدها في كتلة `action_required` الخاصة بالمعاملة، وتشغّلها حزم SDK تلقائيًا عند [الإرسال من جانب العميل](https://docs.didit.me/ar/transaction-monitoring/sdk-transaction-submission.md).
* بمجرد أن يُثبت العميل سيطرته على المحفظة، يُجري التحويل مطابقة اسم المستفيد ويتقدم إلى `COMPLETED`، أو إلى `COUNTERPARTY_MISMATCHED_DATA` عند فشل المطابقة.

هذا هو الالتزام الخاص بالمحافظ ذاتية الاستضافة في لائحة نقل الأموال الأوروبية (EU TFR) في صورة واجهة برمجية: التحقق من ملكية المحفظة غير المستضافة، بدلًا من تبادل البيانات مع VASP مقابلة.
يُقرأ التصريح من طريقة الدفع في جهة **الوجهة** للتحويل الصادر، وفي جهة **المصدر** للتحويل الوارد، وفي الحالتين يكون الطرف المقابل هو المشارك المعني.
يسير التحويل المُصرَّح فيه بأنه غير مستضاف بالفعل على مساره النهائي الخالي من القنوات، لذلك فإن `UNCONFIRMED_OWNERSHIP` ليست حالة قابلة لإعادة الإرسال؛ أكمل إثبات الملكية (أو ألغِ التحويل) بدلًا من استدعاء `action: "resend"`.

## الاستلام

### تأكيد ملكية المحفظة

ينتظر التحويل في حالة `UNCONFIRMED_OWNERSHIP` في حالتين:

* يُحل تحويل وارد إلى إدخال في [دفتر العناوين](#دفتر-عناوين-المحافظ) لم تُتحقق ملكيته بعد.
* أُعلن أن محفظة الطرف المقابل ذاتية الاستضافة (`counterparty.payment_method.method_type: "unhosted_wallet"`)، في سحب صادر أو إيداع وارد. راجع [المحافظ ذاتية الاستضافة المُعلنة](#المحافظ-ذاتية-الاستضافة-المُصرَّح-بها).

يؤكد تطبيقك التحويل أو يرفضه:

```bash theme={null}
curl -X POST https://verification.didit.me/v3/transactions/{transaction_uuid}/travel-rule/ownership/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"confirmed": true}'
```

يقبل الجسم `confirmed` (مطلوب، قيمة منطقية) و`wallet_address` اختياري.

تقبل نقطة النهاية تحويلاً في أي من هذه الحالات، وتُعيد `409` مع `{"detail": "Transfer is not awaiting ownership confirmation."}` لأي حالة أخرى:

* `UNCONFIRMED_OWNERSHIP`، في أي من الاتجاهين.
* `ON_HOLD` في تحويل وارد.
* `UNCONFIRMED_OWNERSHIP` أو `ON_HOLD` أو `COUNTERPARTY_MISMATCHED_DATA` في تحويل `TRP` وارد، حتى يتمكن مسؤول الامتثال من حل استفسار الطرف المقابل يدوياً.

في تحويل أنشأه Didit بنفسه (مسار `INTERNAL`، أو تسجيل Sunrise، أو محفظة ذاتية الاستضافة مُعلنة):

* `confirmed: true` يضع علامة التحقق من الملكية على إدخال عنوان المحفظة المطابق في دفتر العناوين، ثم يُجري مطابقة الاسم مع `holder_name` لذلك الإدخال: `COMPLETED` إذا نجحت، و`COUNTERPARTY_MISMATCHED_DATA` إذا لم تنجح.
  يحصل الطرف المقابل في مسار `INTERNAL`، إن وُجد، على النتيجة نفسها.
  بالنسبة إلى محفظة ذاتية الاستضافة مُعلنة، يسجل `confirmed: true` أن عميلك تحقق ممن يتحكم في محفظة الطرف المقابل، ويُكمل التحويل (`COMPLETED`)، صادراً كان أو وارداً.
  أما التحويل الوارد الذي سُوّي إيداعه بالفعل فينتقل مباشرة إلى `FINISHED`.
* `confirmed: false` ينقل طرفي التحويل كليهما إلى `COUNTERPARTY_VASP_GENERAL_DECLINE`.
* يُبحث عن الإدخال المطابق في دفتر عناوينك بعنوان المحفظة وحده، دون السلسلة.
  حل تحويل وارد في حالة `ON_HOLD` دون إدخال مطابق ينشئ الإدخال من `beneficiary_data.wallet_address` ويعلّمه كمتحقق منه.
  المحفظة ذاتية الاستضافة المُعلنة هي الاستثناء: تُسجل المحفظة في دفتر عناوينك بوصفها متحققة الملكية، كما هو موضح أدناه.
  في كل الحالات الأخرى، يُعيد الطلب `409` عند عدم العثور على الإدخال مع `{"detail": "wallet address entry no longer available"}`، وهو الرد نفسه الذي يُعيده الإدخال المحذوف.

على تحويل `TRP` وارد، يجيب الاستدعاء نفسه عن استفسار الطرف المقابل:

* `confirmed: true` يحتاج إلى عنوان دفع لإعادته، ويُؤخذ من `wallet_address` في الطلب، ثم من الإدخال المطابق، ثم من `beneficiary_data.wallet_address`.
  إذا لم يتوفر أي من الثلاثة، يُعيد الطلب `400` مع `{"wallet_address": ["wallet_address is required to approve."]}`.
  ينشئ Didit الإدخال أو يتحقق منه، ويرسل استدعاء حل الاستفسار إلى الطرف المقابل، ويضبط `ownership_confirmed`، وينقل التحويل إلى `COMPLETED`.
* `confirmed: false` يرسل ردّ رفض الاستفسار، وينقل التحويل إلى `COUNTERPARTY_VASP_GENERAL_DECLINE`.
* إذا تعذر الوصول إلى نقطة نهاية الطرف المقابل، يُعيد الطلب `502` ويحتفظ التحويل بحالته الحالية.
  عند الموافقة، يُنشأ إدخال عنوان المحفظة أو يُعلَّم بأنه متحقق منه.

بالنسبة إلى محفظة ذاتية الاستضافة مُعلنة، المحفظة التي تتحقق منها هي محفظة الطرف المقابل: وجهة السحب الصادر، أو مصدر الإيداع الوارد (محفظة المُرسِل).
يضيف Didit المحفظة إلى دفتر عناوين المحفظة بوصفها متحققة الملكية باسم الطرف المقابل، فتُطابَق المحفظة مع اسم الطرف المقابل (المُرسِل في حالة الإيداع).
إذا كان دفتر العناوين يحمل تلك المحفظة باسم حامل مختلف، ينتقل التحويل بدلاً من ذلك إلى `COUNTERPARTY_MISMATCHED_DATA`.

إذا لم يذكر التحويل محفظة للطرف المقابل إطلاقاً، مرّر `wallet_address` في جسم الطلب.
إذا لم يوفّر التحويل ولا الطلب عنوان محفظة، يُرفض الطلب بالرمز `400`.

```json theme={null}
{"confirmed": true, "wallet_address": "0xCounterpartyWallet01"}
```

* تحويل من شبكة أُجيب عليه بالفعل عبر شبكته (تحويل VerifyVASP، أو تحويل GTR أو Sygna Bridge قُرّر بالفعل) يُعيد `409` (راجع [التحويلات من شبكة](#التحويلات-من-شبكة)).

الاستجابة هي كائن التحويل الأوسع الموصوف أعلاه.
لا ينتظر تحويل `INTERNAL` جديد هنا أبداً، إذ لا يصل إلا إلى عميل أثبت سيطرته على المحفظة من قبل. أما تحويل `INTERNAL` أقدم ما زال ينتظر من قبل تطبيق تلك القاعدة، فيُبقي تفاصيل المُرسِل مخفية حتى تُثبت سيطرتك على المحفظة (بتوقيع رسالة أو إيداع تجريبي)، ويؤدي تأكيده إلى إرجاع `409` حتى تفعل ذلك. الرفض لا يزال يعمل.
عندما يجيب الطرف المقابل بأن المحفظة ذاتية الاستضافة (حالياً يقدّم [Didit Test VASP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) هذه الإجابة في بيئة الاختبار)، يضيف التأكيد المحفظة إلى دفتر عناوينك باسم المستفيد، ويُجري مطابقة الاسم: المطابقة الناجحة تُكمل التحويل وتعلّم المحفظة كمتحققة الملكية.

### التحويلات من شبكة

يمكن لـ Didit أيضاً استلام تحويلات Travel Rule يرسلها طرف مقابل عبر `GTR` أو `VERIFYVASP` أو `SYGNA`.
يفعّل Didit الاستلام لكل شبكة على حدة، و**لا توجد شبكة مفعّلة حالياً**: يتطلب ذلك أيضاً تسجيل كل شبكة لنقاط endpoint الخاصة بـ Didit، وليس لدى Didit عضوية في هذه الشبكات بعد.
لا يمكن استلام تحويلات `TRUST`.

بمجرد تفعيل شبكة، تُعالج الرسالة التي تسلّمها كما يلي:

* **التوجيه.** تصل الرسالة إلى تطبيقك عندما تذكر رمز المشارك لعضويتك المتصلة في تلك الشبكة. لا تصل الرسالة الموجهة إلى عضوية Didit نفسها إلا إذا كنت عميل Didit الوحيد في بيئة الإنتاج الذي أثبت السيطرة على محفظة المستفيد. أي رسالة أخرى تُرفض، فلا يتلقى عميل أبداً تحويلاً لعميل آخر.
* **القرار.** ينشئ Didit التحويل الوارد في تطبيقك ويقرره كما يُقرَّر [استفسار TRP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-interoperability.md#endpoints-trp): مطابقة المحفظة، والملكية، ومطابقة الأسماء، و`inbound_auto_accept`.
* **مرة واحدة.** تعيد الشبكات إرسال الرسالة حتى تُجاب. تحصل المحاولة المكررة على الإجابة التي حصلت عليها النسخة الأولى، ولا يُنشأ شيء أو يُقرَّر مرتين.
* **مراجعتك، عبر `GTR` و`SYGNA`.** التحويل الذي ينتظرك (`UNCONFIRMED_OWNERSHIP` أو `ON_HOLD` أو `COUNTERPARTY_MISMATCHED_DATA`) يُقرَّر عبر [`POST .../travel-rule/ownership/`](#تأكيد-ملكية-المحفظة): يوافق `confirmed: true` عليه (مرّر `wallet_address` عندما لا يذكر التحويل محفظة)، ويرفضه `confirmed: false`. يرد Didit على الشبكة بعد الاستجابة، مع [إعادة المحاولة نفسها](#التسليم-وإعادة-المحاولة). التحويل الذي أُجيب عليه بالفعل يُعيد `409`.
* **لا إجابة لاحقة عبر `VERIFYVASP`.** يأخذ VerifyVASP إجابته لحظة سؤاله، لذلك يُرفض التحويل الذي كان سيحتاج إلى مراجعتك فوراً، ولا يمكن تقريره لاحقاً (`409`).

### بيانات الطرف المقابل المقنّعة

إلى حين تأكيد ملكية المحفظة، تعود البيانات الشخصية للطرف المقابل في التحويل الوارد مقنّعةً لا محذوفةً.
يُبقى الحرف الأول من كل كلمة، وتظل المحفظة والسلسلة وتوجيه VASP مقروءةً.
قيمة `data_masked` هي `true`، ويُقنَّع الطرف المقابل في تفاصيل المعاملة وقائمتها وتصدير CSV بالطريقة نفسها.

بعد تأكيد الملكية تظهر القيم الحقيقية ويسجّل `data_unmasked` قيد التدقيق:

```json theme={null}
{
  "data_masked": false,
  "data_unmasked": { "at": "2026-10-17T10:00:00Z", "reason": "wallet_proof", "actor": "" }
}
```

قيمة `reason` إحدى القيم التالية: `ownership_confirmed` و`wallet_proof` و`address_book_match` و`own_verified_wallet` و`inquiry_approved` (أي وافقت على استفسار `TRP` أو على رسالة `GTR` أو `Sygna`)، و`known_payment_method` (ردّت محفظة المستخدم النهائي المسجّلة في سجلاتك)، أو `travel_address` (حدّد Travel Address الخاص بكل محفظة تلك المحفظة).
يحمل التحويل الوارد من نوع `INTERNAL` السجل `data_unmasked` بالقيمة `reason: wallet_proof` منذ لحظة إنشائه، لأن المستلم الذي أثبت ملكية المحفظة وحده يتلقاه.
الحقل `actor` هو البريد الإلكتروني لمستخدم وحدة التحكم أو تسمية مفتاح API، ويبقى فارغاً في القرار التلقائي.
يُقنّع تقريرُ **سجل تحويلات Travel Rule** (CSV وPDF) أسماءَ التحويل الوارد بالطريقة نفسها إلى حين تأكيد الملكية. أما التقارير التي تقدّمها إلى جهة تنظيمية، مثل ملف goAML XML وتقرير PDF التنظيمي، فتحمل البيانات الحقيقية للطرف المقابل.

### ملاحظات عدم التطابق

يذكر تحويلُ `COUNTERPARTY_MISMATCHED_DATA` الآن الحقولَ المختلفة.
يحتوي `data_match` على المقارنة، ويسرد `mismatched_fields` الحقول.
يتضمن الحقلان أسماء الحقول والنتائج فقط دون القيم، فيبقيان مقروءين أثناء إخفاء البيانات:

```json theme={null}
{
  "status": "COUNTERPARTY_MISMATCHED_DATA",
  "mismatched_fields": ["date_of_birth"],
  "data_match": {
    "matched": false,
    "mismatched_fields": ["date_of_birth"],
    "fields": {
      "name": { "result": "matched", "strictness": "DEFAULT" },
      "date_of_birth": { "result": "mismatched", "strictness": "STRICT" },
      "address": { "result": "not_compared", "strictness": "NONE" },
      "account": { "result": "matched", "strictness": "STRICT" }
    }
  }
}
```

يذكر إدخال الجدول الزمني الحقول، مثلاً «تاريخ ميلاد المستفيد لا يطابق صاحب المحفظة».
يُخبر رفضُ `TRP` بعد عدم التطابق الـVASP المُرسِل بالحقول المختلفة، مثلاً «بيانات المستفيد لا تطابق صاحب المحفظة: الاسم».
ما يعرفه الـVASP الآخر محدودٌ عن قصد: ما دام الاسم خاطئاً، يكون الاسم الحقلَ الوحيد المُبلَّغ عنه (`mismatched_fields: ["name"]`، وتُعدّ كل الحقول الأخرى `not_compared`)، وبعد أن يتطابق الاسم تُذكر كل الحقول المختلفة. ينطبق هذا على جانب المُرسِل في تبادل `INTERNAL` وعلى رفض `TRP`.
يظهر الاسم الغائب من الطرفين بالقيمة `not_compared` ولا يُعدّ عدم تطابق، وتتطابق الدولة بحسب الرمز الذي يحدّدها، ولذلك تتفق `ES` و`ESP`.

#### درجة مطابقة الاسم

يحمل كل تحويل قورن اسمُه الكائنَ `name_match`، ويحمل إدخالُ الجدول الزمني الذي حسم النتيجة الكائنَ نفسه بجانب `detail` الخاص به:

```json theme={null}
{
  "name_match": {
    "score": 90,
    "matched": false,
    "method": "sequence_ratio",
    "strictness": "FUZZY",
    "compared_with": "wallet_holder",
    "transfer_name": "Ana Diaz",
    "compared_name": "Ana Diaz Garcia",
    "matched_names": ["Ana", "Diaz"],
    "mismatched_names": ["Garcia"]
  }
}
```

* `score` هي درجة التشابه بين الاسمين الكاملين، من 0 إلى 100، وتكون `0` إذا كان أيٌّ منهما فارغاً. `matched` هي النتيجة عند `strictness`، لذا قد تختلف النتيجتان: إذ يحكم `FUZZY` بنسبة تشابهه الخاصة البالغة `0.85`.
* `matched_names` هي كلمات اسم التحويل الموجودة في الاسم الآخر، أما `mismatched_names` فهي الكلمات التي يملكها أحد الطرفين ويفتقر إليها الآخر.
* `method` هي إحدى القيم `none` أو `exact_token` أو `token_subset` أو `token_containment` أو `sequence_ratio`، وتقابل `NONE` و`STRICT` و`DEFAULT` و`CONTAINS` و`FUZZY`.
* `compared_with` هي `wallet_holder` (صاحب المحفظة المسجّل لها) أو `counterparty_vasp` (الاسم الذي ردّ به الطرف المقابل في صفحة الرد عبر البريد الإلكتروني، أو ردّ Didit Test VASP).
* تتبع نتيجة التحويل `data_match` الذي يقارن كل الحقول، لذا قد يكون التحويل `COUNTERPARTY_MISMATCHED_DATA` بينما تكون قيمة `name_match.matched` هي `true`.
* يوجد `name_match` في كائن التحويل الذي تعيده endpoints الخاصة بـTravel Rule، وفي الحقل `travel_rule` المضمَّن في المعاملة، وتكون قيمته `null` إلى أن يُقارَن اسم. لا تتضمنه قائمة التحويلات ولا الـwebhooks.
* تُخفى الأسماء ما دام الطرفان [مقنّعَين](#بيانات-الطرف-المقابل-المقنّعة)، وفي نسخة العميل الآخر من تبادل `INTERNAL`.

### الرسائل وطلبات المستندات

يمكن لـVASPين حلّ تحويل متنازع عليه داخل Didit بدلاً من البريد الإلكتروني.
يعرض `GET` و`POST /v3/transactions/{transaction_id}/travel-rule/messages/` الرسائل على التحويل ويرسلانها:

```bash theme={null}
curl -X POST https://verification.didit.me/v3/transactions/{transaction_uuid}/travel-rule/messages/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind": "DOCUMENT_REQUEST", "body": "Please confirm the beneficiary date of birth.", "requested_documents": ["Proof of address"]}'
```

* قيمة `kind` هي `MESSAGE` (الافتراضية) أو `DOCUMENT_REQUEST`. يحتاج طلب المستند إلى عنصر واحد على الأقل في `requested_documents` (بحدّ أقصى 10)، وتحتاج الرسالة إلى `body` (بحدّ أقصى 5000 حرف) أو ملف.
* يشير `reply_to` إلى رسالة سابقة من التحويل نفسه. يُلبّي الردُّ من الطرف الآخر الذي يحمل مستنداً طلبَ المستند الذي يجيب عنه، ويُضبط عليه `fulfilled_at`. ولا يُلبّي ردُّك أنت طلبَك أبداً.
* أرسل الطلب بصيغة multipart مع `files` لإرفاق حتى 5 ملفات بحجم 10 MB لكل منها، بصيغ PDF أو PNG أو JPEG أو WebP. يفحص Didit محتوى كل ملف لا نوعه المُعلَن فقط، ويردّ أي ملف آخر بالرمز `400` على `files` مع الرسالة «أرفق ملفات PDF أو PNG أو JPEG أو WebP فقط.»
* يتسع التحويل لما يصل إلى 100 رسالة، منها 20 رسالة كحدّ أقصى تحمل مرفقات (كل منها حتى 5 ملفات)، مع احتساب الطرفين معاً؛ وتجاوُز أيٍّ من الحدّين يردّ الطلب بالرمز `400`. لا تُحتسب مرفقات الرسائل ضمن مستندات المعاملة نفسها.
* تعمل الرسائل عبر مساري `INTERNAL` و`EMAIL`. في `INTERNAL` يرى العميل الآخر في Didit الرسالة على جانبه من هذا التبادل. وفي `EMAIL` يُرسل بريد إلكتروني إلى الطرف المقابل، فيردّ عبر بوابة الاستلام. وإن تعذّر إرسال بريد الإشعار، تُحفظ الرسالة على أي حال ويردّ الطلب بالرمز `201`.
* يردّ الطلب بالرمز `409` مع سبب في `detail` في الحالات التالية: تحويل عبر `TRP` أو `GTR` أو `TRUST` أو `VerifyVASP` أو `Sygna` (هذه البروتوكولات لا تحمل رسائل)، وتحويل ليس له طرف مقابل بعد، وتحويل `INTERNAL` لم تطابق بياناته صاحب المحفظة (فلم يصل شيء إلى المستلم)، وتحويل `INTERNAL` لم يثبت فيه المستلم سيطرته على المحفظة بعد (على الطرفين إلى أن يثبت ذلك)، وتحويل `EMAIL` لم يعد للطرف المقابل فيه عنوان بريد إلكتروني للامتثال، وتحويل `EMAIL` انتهت صلاحية رابط استلامه أو أُغلق التحويل.
* لا يُطلق أي webhook عندما يكتب الطرف المقابل رداً. اقرأ endpoint الرسائل.
* يُرسل البريد الذي يُعلم الطرف المقابل برسالة جديدة باللغة الإنجليزية.

### دفتر عناوين المحافظ

سجّل المحافظ التي تتحكم فيها كي تتمكن التحويلات الواردة (مسار `INTERNAL` واستفسارات `TRP` الواردة و[التسجيلات بعد الإيداع](#التسجيل-اللاحق-للإيداع)) من المطابقة معها، باستخدام `POST`/`GET /v3/travel-rule/wallet-addresses/` و`PATCH`/`DELETE /v3/travel-rule/wallet-addresses/{entry_uuid}/`.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/wallet-addresses/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
    "chain": "ETH",
    "holder_name": "Ana Diaz",
    "holder_vendor_data": "user-042",
    "self_declared": true
  }'
```

| الحقل | النوع | الوصف |
| - | - | - |
| `address` | string | عنوان المحفظة. فريد لكل تطبيق و`chain` و`memo` (تُقارن العناوين دون حساسية لحالة الأحرف)، ويؤدي التكرار إلى إرجاع الاستجابة `400`. يُخزَّن عنوان X-address في XRP بعنوانه الكلاسيكي وعلامته. يكون فارغاً في السجل [المستورد بواسطة هاشه](#استيراد-المحافظ-دفعةً-واحدة). |
| `address_hash` | string | للقراءة فقط. قيمة SHA-256 للعنوان بعد تحويله إلى أحرف صغيرة، بترميز hex بأحرف صغيرة. |
| `memo` | string | اختياري. علامة الوجهة أو الـ memo الذي يشكل جزءاً من المحفظة على [شبكة memo](#شبكات-memo-والوسم)؛ يكون فارغاً للعنوان الكامل. الاسم البديل: `destinationTag`. |
| `chain` | string | معرّف سلسلة اختياري، بحد أقصى 32 حرفاً. استخدم الرمز نفسه الذي تحمله تحويلاتك (مثل `ETH` أو `BTC`)، أو اتركه فارغاً لمطابقة التحويلات على أي سلسلة، انظر الملاحظة أدناه. يُخزَّن مستلم Lightning (معرّف العقدة أو Lightning Address) المسجَّل على bitcoin بأحرف صغيرة على `LIGHTNING`، وهي السلسلة التي تُطابَق فيها تحويلات [Lightning](#lightning). |
| `holder_name` | string | اسم صاحب المحفظة، ويُستخدم لمطابقة اسم المستفيد. |
| `holder_vendor_data` | string | معرّفك الداخلي لصاحب المحفظة. |
| `entity_type` | string | نص حر بحد أقصى 16 حرفاً، والقيمة الافتراضية `"individual"`. |
| `travel_address` | string | اختياري. عنوان Travel Address الخاص بـ VASP الطرف المقابل لهذه المحفظة، إن كنت تعرفه. يتيح لـ Didit توجيه التحويلات إلى هذا المستفيد عبر المسار `TRP` بدلاً من البريد الإلكتروني. |
| `receiving_travel_address` | string | للقراءة فقط. عنوان Travel Address الخاص بك لهذه المحفظة. أعطه لـ VASP يرسل إلى هذه المحفظة، فيذكر استعلام TRP الخاص به المحفظة مباشرةً. يكون فارغاً للمحفظة المسجلة كمحفظة تابعة لـ VASP آخر، وعندما تكون Travel Rule متوقفة، وقبل حفظ ملف VASP الخاص بك. يتوقف عن الاستجابة بعد حذف المحفظة. |
| `is_ownership_verified` | boolean | للقراءة فقط. يحدد ما إذا كانت ملكية هذا العنوان قد أُثبتت (عبر [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) أو بالتصريح الذاتي). |
| `self_declared` | boolean | للكتابة فقط، مع `POST` فقط. عند `true` يُنشأ السجل محققاً مسبقاً عبر إثبات `SELF_DECLARATION`، فتتجاوز التحويلات الواردة إلى هذا العنوان `UNCONFIRMED_OWNERSHIP` تماماً وتنتقل مباشرةً إلى مطابقة الاسم. يُرجع `400` عندما يكون `allow_self_declaration` متوقفاً في إعداداتك. |

يقبل `PATCH` الحقول `holder_name` و`holder_vendor_data` و`entity_type` و`travel_address`، ويُرجع هذه الحقول الأربعة فقط.
يحذف `DELETE` السجل (`204`)، فيصبح عنوانه متاحاً لإعادة التسجيل، ويتوقف فوراً عن مطابقة التحويلات الجديدة.

> [!NOTE]
>
> تتم المطابقة دون حساسية لحالة الأحرف في العنوان، وتتضمن `memo` على شبكات memo، وتُحصر بـ`chain`.
> عندما يحمل التحويل سلسلة، لا يُطابِق السجل إلا إذا كانت `chain` الخاصة به القيمة نفسها (دون حساسية لحالة الأحرف) أو كانت فارغة.
> تُقارن أسماء السلاسل كنص ولا تُترجم، فالسجل المخزَّن باسم `ethereum` لا يطابق تحويلاً سلسلته `ETH`.
> تأخذ التحويلات الصادرة سلسلتها من `beneficiary_data.chain`، ثم من `transaction_details.crypto_params.crypto_chain`، ثم من `custom_properties.crypto_chain`، ثم من العملة (مثل `ETH`، أو بالنسبة لـ`USDT` و`USDC` السلسلة المستنتجة من `payment_reference_id`)، ولا تُعتمد إلا إذا كانت سلسلة يتعرف عليها Didit. أما التسجيلات بعد الإيداع فتأخذها من حقل `chain` بأحرف صغيرة.
> لا تأخذ استعلامات `TRP` الواردة السلسلة في الحسبان: فهي تطابق بالعنوان، أو، إذا لم يذكر الاستعلام محفظة، باسم المستفيد مقارنةً بسجلاتك المحققة.
> تطابق [`POST .../travel-rule/ownership/`](#تأكيد-ملكية-المحفظة) بالعنوان وحده أيضاً.
> عندما تطابق عدة سجلات، يفضّل مسار `INTERNAL` والتسجيلات بعد الإيداع السجلَّ المثبت الملكية، ثم الأقدم، بينما يأخذ البحث الصادر عبر `TRP` أقدم سجل يخزّن عنوان Travel Address.
> تأخذ استعلامات `TRP` الواردة وendpoint الملكية أيّاً من السجلات المطابقة، لذا احتفظ بسجل واحد لكل عنوان حيثما أمكن.
> لا يطابق مسار `INTERNAL` أي سجل إطلاقاً عندما توجد سجلات محققة للعنوان في أكثر من تطبيق آخر لديك.

#### استيراد المحافظ دفعةً واحدة

استورد حتى 10,000 محفظة في استدعاء واحد عبر [`POST /v3/travel-rule/wallet-addresses/import/`](https://docs.didit.me/ar/management-api/travel-rule/import-wallet-addresses)، بصيغة JSON (`{"entries": [...]}` أو مصفوفة مباشرة)، أو كملف CSV بترميز UTF-8 لا يتجاوز 5 MB ويحتوي على صف رأس.
يُعرّف الصف المحفظةَ بعنوانها `address`، أو بـ`address_hash` (هاش SHA-256 للعنوان بعد تحويله إلى أحرف صغيرة، ويكون 64 حرفاً سداسي عشري أو 44 حرفاً بترميز base64)، أو بهما معاً، مع أي من حقول السجل أعلاه. أرسل الهاش وحده لتسجيل محفظة دون الكشف عن عنوانها: فهي تطابق التحويلات إلى ذلك العنوان كأي سجل آخر، ويمكن إثبات ملكيتها عبر [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md).

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/wallet-addresses/import/ \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@wallets.csv;type=text/csv"
```

```text theme={null}
address,address_hash,chain,memo,holder_name,holder_vendor_data
0xBeneficiaryWallet01,,ethereum,,Ana Diaz,user-042
,4f7d2e1c9b8a7f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e,bitcoin,,,user-043
rExchangeSharedAddress01,,XRP,104729,Ana Diaz,user-042
```

الاستيراد قابل للتكرار بأمان، ويُبلغ عن كل صف بالترتيب الذي أُرسل به: `created` (أُنشئ)، و`existing` (المحفظة والسلسلة والـ memo نفسها موجودة في الدفتر وتُركت دون تغيير)، و`duplicate` (يكرر صفاً سابقاً، ويُذكر في `duplicate_of_row`)، أو `failed` مع `errors` الخاصة به.
لا يُفشل صفٌّ سيئ الصفوفَ الأخرى: تكون الاستجابة `200` إذا لم يفشل أي صف، و`207` إذا فشل صف واحد على الأقل، مع الأعداد في `total` و`created` و`existing` و`duplicate` و`failed`.
تُعد الخلية الفارغة في CSV غير مُرسلة، وتُتجاهل الأعمدة التي لا يقرؤها الاستيراد، فيُستورد ملف مُصدَّر من أداة أخرى كما هو.

في `GET /v3/travel-rule/transfers/`، يحمل كل صف `originator_memo` و`beneficiary_memo` إلى جانب المحفظتين.

### استلام البريد الإلكتروني للأطراف المقابلة غير القابلة للوصول

عندما لا يستطيع أي مسار بروتوكول الوصول إلى الطرف المقابل، يلجأ Didit إلى `EMAIL`: يرسل رابط استلام لمرة واحدة إلى `beneficiary_data.counterparty_vasp_email` (أو إلى بريد إلكتروني يُستخرج من `beneficiary_data.counterparty_vasp_name` بالبحث في سجل دليل VASP).
لا يحتاج المستلم إلى حساب Didit أو مفتاح API، فرمز الرابط هو وسيلة المصادقة.
وإليك كيفية إرسال الطلب:

* **إلى العناوين الصحيحة.** `counterparty_vasp_email` الذي تمرّره هو المستلم الوحيد. وإلا يكتب Didit إلى ثلاثة عناوين كحد أقصى: [جهات اتصال](#جهات-الاتصال) الطرف المقابل التي لم تتعرض رسائلها للارتداد (أولاً جهة اتصالك، ثم جهات اتصال المنصة، ثم جهات الاتصال التي سبق أن ردّت، بهذا الترتيب)، ثم بريد الامتثال في سجل الدليل إذا بقيت خانة. يتلقى كل عنوان بريداً خاصاً به.
* **باسمك.** يُرسل البريد من عنوان Didit باسم "*اسمك القانوني* عبر Didit"، بلغة الولاية القضائية للطرف المقابل (الإنجليزية إذا لم تكن معروفة)، ويفتح الرابط صفحة الرد بتلك اللغة. لا تُرسل لك نسخة، فتابع الجدول الزمني للتحويل.
* **مع التذكيرات.** إلى أن يرد الطرف المقابل، يذكّره Didit قبل الموعد النهائي بـ72 و24 و6 ساعات، بعد 12 ساعة على الأقل من الطلب أو من آخر تذكير، ولا يذكّره بعد الموعد النهائي أبداً.
* **مع معالجة الارتدادات.** يُعلِّم الارتداد أو شكوى البريد المزعج جهةَ الاتصال التي وصلها بأنها غير صالحة مع سببها، ويسجل الجدول الزمني للتحويل ذلك. فجهة اتصال المنصة تصبح غير صالحة لكل عملاء Didit، أما جهة اتصال تطبيقك فتكون غير صالحة لتطبيقك وحده. وعندما يتوقف تسليم بريد Didit إلى عنوان ما نهائياً (بعد ارتداد دائم أو شكوى بريد مزعج أو إلغاء اشتراك)، تُعلَّم كل جهات الاتصال على ذلك العنوان بأنها غير صالحة (`suppressed`)، وتعود صالحة حين يُستأنف الإرسال إلى العنوان. وعندما لا يبقى عنوان يُكتب إليه، تنتقل حالة التحويل إلى `COUNTERPARTY_VASP_NOT_REACHABLE` مع سبب خادم البريد المستلم في جدوله الزمني. ويؤدي الارتداد الدائم أو شكوى البريد المزعج على `counterparty_vasp_email` الذي مررته إلى ذلك فوراً، لأنه المستلم الوحيد. أما الارتداد المؤقت (`soft_bounce`) عليه، أو على بريد الامتثال في سجل الدليل، فيُبقي الطلب مفتوحاً للتذكيرات.

يفتح الرابط صفحة مستضافة تعرض التحويل المعلّق، وتستدعي endpointين العامين التاليين الخاصين بالمستلم.
بالنسبة إلى [تحويل المثال أعلاه](#إرسال-تحويل)، تكون تفاصيل الاستلام كما يلي:

```bash theme={null}
curl https://verification.didit.me/v3/travel-rule/pickup/{token}/
```

```json theme={null}
{
  "reference": "33333333-4444-5555-6666-777777777777",
  "requested_at": "2026-07-05T10:00:00Z",
  "originator_vasp_name": "Origin CASP SL",
  "originator_vasp_lei": "529900EXAMPLEORIG001",
  "recipient_vasp_name": "Example Counterparty VASP",
  "language": "es",
  "amount": "0.250000000000000000",
  "currency": "ETH",
  "fiat_amount": "",
  "fiat_currency": "",
  "chain": "ETH",
  "beneficiary_wallet": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
  "status": "AWAITING_COUNTERPARTY",
  "ivms_version": "ivms101.2023",
  "deadline_at": "2026-07-07T10:00:00Z",
  "reminders_sent": 0,
  "contact": "",
  "decline_reasons": ["data_mismatch", "not_our_customer", "wallet_not_hosted", "sanctions", "risk_appetite", "jurisdiction", "insufficient_data", "other"],
  "join_invitation": { "eligible": false, "url": "" },
  "originator_data": { "name": "Jane Doe", "wallet_address": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7" },
  "beneficiary_data": { "name": "Ana Diaz", "wallet_address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb" },
  "ivms_request": {
    "originator": {
      "originatorPersons": [{ "naturalPerson": { "name": { "nameIdentifier": [{ "primaryIdentifier": "Doe", "secondaryIdentifier": "Jane", "nameIdentifierType": "LEGL" }] } } }],
      "accountNumber": ["0x77ccff0cc624a53cd8b8d8703ced826710211ec7"]
    },
    "beneficiary": {
      "beneficiaryPersons": [{ "naturalPerson": { "name": { "nameIdentifier": [{ "primaryIdentifier": "Diaz", "secondaryIdentifier": "Ana", "nameIdentifierType": "LEGL" }] } } }],
      "accountNumber": ["0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb"]
    }
  },
  "data_masked": false
}
```

`reference` هو `uuid` الخاص بالتحويل. يحتوي `originator_data` وحقل `ivms_request` المبني منه وفق معيار IVMS 101 على حقول المُرسِل التي تشاركها فقط في [`data_sharing_fields`](#مشاركة-البيانات)، أما الاسم والمحفظة فيُدرجان دائمًا. يكون `fiat_amount` و`fiat_currency` فارغين إذا لم ترسل قيمة محوّلة، ويعيد `contact` القيمة الموجودة في المعامل `?contact=` الخاص بالرابط، ويسرد `decline_reasons` القيم التي يقبلها `decline_reason`. تكون قيمة `join_invitation.eligible` مساوية لـ `true` طالما أن الطرف المقابل لديه دعوة نشطة للانضمام إلى Didit، أما رابط الدعوة نفسه فيُرسل عبر البريد الإلكتروني فقط.

يُعيد endpoint هذا المبلغ المخزّن كما هو، فيتضمن جميع المنازل العشرية البالغ عددها 18، بدلًا من الصيغة المختصرة التي يعرضها كائن تفاصيل المعاملة.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/pickup/{token}/respond/ \
  -H "Content-Type: application/json" \
  -d '{"decision": "accept", "beneficiary_name": "Ana Diaz"}'
```

القيمة `decision` هي `accept` أو `decline`.
عند `accept`، يُقارَن `beneficiary_name` المُرسَل مع `beneficiary_data.name` الخاص بالتحويل وفق قاعدة الأسماء لديك: تكون النتيجة `COMPLETED` عند التطابق، و`COUNTERPARTY_MISMATCHED_DATA` بخلاف ذلك. يمكن للطرف المقابل أن يرسل استجابة IVMS 101 كاملة في `ivms_response` بدلًا من ذلك، فيكون اسم المستفيد الوارد فيها هو المعتمد بدلًا من `beneficiary_name`.
عند `decline`، ينتقل التحويل إلى `COUNTERPARTY_VASP_GENERAL_DECLINE`. يمكن للطرف المقابل أن يذكر `decline_reason` من بين `decline_reasons`، مع `decline_detail` (بحد أقصى 512 حرفًا، ويكون مطلوبًا عند القيمة `other`)، ويسجّل الجدول الزمني للتحويل ذلك، مثلًا: `counterparty declined: The beneficiary is not our customer`.
تكون الاستجابة هي `{"status": "..."}` الناتجة، مع `decline_reason` بعد الرفض. وبعد أن يرد الطرف المقابل، تُعيد كلتا النقطتين الاستجابة `410`. وتُعيد النقطتان الاستجابة `404` عند استخدام رمز غير معروف، والاستجابة `410` بعد إغلاق النافذة، أي عندما يغادر التحويل الحالة `AWAITING_COUNTERPARTY`، أو عندما تنتهي مهلة التأكيد (`confirmation_timeout_hours` بعد الإنشاء أو بعد آخر إعادة إرسال).

يقرأ الطرف المقابل ويجيب عبر رابط الاستلام باستخدام `GET` و`POST /v3/travel-rule/pickup/{token}/messages/`. لا يحتاج إلى مفتاح API، ويقبل مرفقات بصيغة PDF أو PNG أو JPEG أو WebP فقط، ويُعيد الاستجابة `410` بعد انتهاء صلاحية الرابط أو إغلاق التحويل.
وتُظهر الرسالة التي أرسلتها اسم VASP الخاص بك كقيمة لـ`author` وكقيمة لـ`uploaded_by` في المرفق، ولا تُظهر أبدًا الشخص أو مفتاح API الذي يقف وراءها.

### الإيداعات غير المطابقة

قد يصل إيداع وارد قبل وصول بيانات Travel Rule الخاصة بـ VASP المُرسِل.
يبقى هذا الإيداع في `AWAITING_COUNTERPARTY` أو `NOT_ENOUGH_COUNTERPARTY_DATA` إلى أن تصل البيانات.
اسرد الإيداعات التي ما زالت تنتظر باستخدام مفتاح API يملك صلاحية المعاملات:

```bash theme={null}
curl "https://verification.didit.me/v3/travel-rule/unmatched/" \
  -H "x-api-key: YOUR_API_KEY"
```

تستخدم الاستجابة الصفوف نفسها الموجودة في `GET /v3/travel-rule/transfers/`، مقصورةً على الإيداعات الواردة التي تنتظر بيانات VASP المُرسِل.

عندما تصل البيانات في رسالة مستلمة منفصلة، فاقرن بين الاثنين بنفسك:

```bash theme={null}
curl -X POST "https://verification.didit.me/v3/travel-rule/unmatched/{transaction_uuid}/match/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"transaction_id": "<uuid of the received message transaction>"}'
```

`{transaction_uuid}` هو الإيداع.
`transaction_id` هو المعاملة الخاصة برسالة Travel Rule المستلمة.
يعيد الاستدعاء `{ "deposit": ..., "message": ... }`.
تُعيد الاستجابة `404` إذا لم تعد أي من المعاملتين موجودة، وتُعيد `409` مع `travel_rule_match_conflict` ("This deposit can no longer be matched.") إذا كان أحد الطرفين قد انتقل إلى حالة أخرى.

### التسجيل اللاحق للإيداع

عندما تُسوّى عملية إيداع للعملات الرقمية على السلسلة **قبل** أن تجري أي عملية تبادل لـ Travel Rule، سواء لأن VASP المُرسِل كان غير قابل للوصول، أو لأنك تُسجّل الإيداعات التاريخية بأثر رجعي، فسجّلها لاحقًا باستخدام `POST /v3/travel-rule/inbound/`.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/inbound/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "chain": "eth",
    "txid": "0xf103cfc37f6d390b61827987b9dc631b5e1d2bfeb008a780c1e38047ae5d557b",
    "wallet_address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb",
    "amount": "500.00",
    "currency": "USDC",
    "originator_data": { "name": "Carlos Ruiz", "wallet_address": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7" },
    "beneficiary_data": { "name": "Ana Diaz" },
    "originating_vasp": {
      "name": "Northwind Digital Assets Ltd",
      "lei": "5493001KJTIIGC8Y1R12",
      "travel_address": "tareGfwAzkySLkFzcqr7AKno3K4VsT3jayMwPvj3ovbFZHzpayHLmgCrAMoLqjfCYRPpvLqr9dSr2VVTFAncwChcMjL4AheNuHCJM8NRcUg"
    }
  }'
```

يجب أن يكون `originating_vasp.travel_address` عنوان [Travel Address](#عناوين-travel-address) حقيقيًا وصحيح المجموع الاختباري، فإن كان عنصرًا نائبًا أعادت النقطة الاستجابة `400` مع `"Invalid travel address."`.
يجب أن يكون `originating_vasp.lei` فارغًا أو مكوّنًا من 20 حرفًا بصيغة LEI (18 حرفًا أو رقمًا، يليها رقمان)، وأي قيمة أخرى تُعيد الاستجابة `400` مع `"Invalid LEI: expected 20 alphanumeric characters (ISO 17442)."`.
تتحقق Didit من هذه الصيغة فقط، لا من أرقام التحقق في ISO 17442.

| الحقل | النوع | الوصف |
| - | - | - |
| `chain` | string | السلسلة التي سُوّي عليها الإيداع، بحد أقصى 32 حرفًا. تحوّلها Didit إلى أحرف صغيرة وتستخدمها لمطابقة مدخلات [دفتر العناوين](#دفتر-عناوين-المحافظ) لديك، لذا استخدم الرمز نفسه المستخدم في مدخلاتك (يطابق `eth` مدخلًا مخزّنًا بالصيغة `ETH`). كما تحدد إمكانية فحص الإيداع: `bitcoin`/`btc` و`ethereum`/`eth` و`solana`/`sol` و`tron`/`trx` و`polygon`/`matic` و`bsc`/`bnb` و`litecoin`/`ltc` و`ripple`/`xrp` و`bitcoin-cash`/`bch` و`dogecoin`/`doge`. |
| `txid` | string | هاش المعاملة على السلسلة. يُستخدم لإزالة التكرار: إذا تطابق نفس `txid` و`wallet_address`، تُعيد الاستدعاء التحويلَ الموجود بدلًا من إنشاء نسخة مكررة. |
| `wallet_address` | string | عنوان المحفظة الوجهة التي استلمت عليها الإيداع. يُقسَّم عنوان XRP من نوع X-address إلى العنوان الكلاسيكي والعلامة (tag). |
| `memo` | string | اختياري. علامة الوجهة للإيداع أو المذكرة على [شبكة تستخدم المذكرات](#شبكات-memo-والوسم). في عنوان إيداع مشترك، تحدد هذه القيمة العميل الذي ينتمي إليه الإيداع. |
| `amount` | string (decimal) | مبلغ الإيداع. |
| `currency` | string | أصل الإيداع. |
| `originator_data` | object | تفاصيل المُرسِل من VASP المُرسِل، إن كانت معروفة، ككائن مسطّح: تقرأ Didit الحقول `name` (أو `full_name`)، و`first_name`، و`last_name`، و`vendor_data`. |
| `beneficiary_data` | object | تفاصيل المستفيد (عميلك)، ككائن مسطّح: تطابق Didit الحقل `name` مع `holder_name` في مدخل دفتر العناوين المطابق، وتضيف إليه `wallet_address` و`chain`. |
| `utxo` | object | اختياري، ويُستخدم فقط مع [سلاسل UTXO](#تحويلات-utxo). يحتوي على `inputs` و`outputs` الخاصة بمعاملة الإيداع: محفظة المُرسِل هي `originator_data.wallet_address` إذا أعلنتها، وإلا فهي أكبر مدخل. |
| `originating_vasp` | object | اختياري، كائن `{ name, lei, travel_address }` يصف المُرسِل. يجب أن يطابق `lei` صيغة LEI أعلاه، ويجب أن يكون `travel_address` عنوان Travel Address صالحًا، وإلا أعادت الاستدعاء `400`. يُحفظ هذا الكائن في التحويل بوصفه `metadata.originating_vasp`، ولا ينشئ أو يغيّر أبدًا مدخلًا مشتركًا في [الدليل](#كيف-تدخل-الإدخالات-إلى-الدليل). |

يُنشئ Didit معاملة `travelRule` واردة (أو يعيد استخدام إيداع وارد أرسلته سابقاً بالتجزئة نفسها والمحفظة نفسها، إذا لم يكن له تحويل Travel Rule بعد) ويعالج التحويل بالرجوع إلى [دفتر عناوين محافظك](#دفتر-عناوين-المحافظ)، بحسب العنوان والملاحظة (memo) الخاصة به:

* لا يوجد إدخال مطابق -> `ON_HOLD`.
  احلّه باستخدام [`POST .../travel-rule/ownership/`](#تأكيد-ملكية-المحفظة): تؤدي قيمة `confirmed: true` إلى إضافة المحفظة إلى دفتر عناوينك كعنوان متحقَّق منه، ويُجري مطابقة الاسم. عند التطابق ينتقل التحويل إلى `COMPLETED`، ثم إلى `FINISHED`.
* يوجد إدخال لكن ملكية العنوان غير مُثبتة -> `UNCONFIRMED_OWNERSHIP`.
* لا يطابق اسم المستفيد قيمة `holder_name` في الإدخال -> `COUNTERPARTY_MISMATCHED_DATA`.
* إدخال متحقَّق منه والاسم مطابق -> `COMPLETED`، ثم `FINISHED` فوراً (الإيداع مُسوّى بالفعل).

مع إدخال دفتر العناوين المتحقَّق منه المُسجَّل في [المثال أعلاه](#دفتر-عناوين-المحافظ)، تكون الاستجابة:

```json theme={null}
{
  "transaction_id": "44444444-5555-6666-7777-888888888888",
  "txn_id": "tr-in-0xf103cfc37f6d390b61827987b9dc631b5e1d2bfeb008a780c1e38047ae5d557b-6151d81b366e",
  "created": true,
  "travel_rule": {
    "uuid": "55555555-6666-7777-8888-999999999999",
    "status": "FINISHED",
    "direction": "INBOUND",
    "rail": null,
    "protocol": null,
    "ivms_version": "ivms101.2023",
    "required": true,
    "ownership_confirmed": true,
    "deadline_at": null,
    "timeline": [
      { "status": "COMPLETED", "at": "2026-07-06T10:15:02.114208+00:00", "detail": "matched verified wallet address book entry" },
      { "status": "FINISHED", "at": "2026-07-06T10:15:02.131544+00:00", "detail": "on-chain deposit already settled" }
    ],
    "counterparty_vasp": null,
    "originator_data": { "name": "Carlos Ruiz", "wallet_address": "0x77ccff0cc624a53cd8b8d8703ced826710211ec7" },
    "beneficiary_data": { "name": "Ana Diaz", "wallet_address": "0xede2d7e4f5b097e6391ab6bbcf2f47a53f4778cb", "chain": "eth" },
    "created_at": "2026-07-06T10:15:02.087412Z"
  }
}
```

يكون `txn_id` للمعاملة الجديدة هو `tr-in-`، وأول 80 حرفاً من `txid`، وتجزئة من 12 حرفاً لـ`txid` والمحفظة.
تكون قيمة `created` هي `true` (HTTP `201`) عندما يسجّل هذا الاستدعاء الإيداع، وتكون `false` (HTTP `200`) عندما يكون `txid` و`wallet_address` نفسهما مسجَّلين من قبل، وفي هذه الحالة يُعاد التحويل الموجود دون تغيير.
في مسار الإدخال المتحقَّق منه يحدث الانتقالان قبل أن ترد نقطة النهاية، لذا تُظهر الاستجابة المتزامنة الحالة النهائية `FINISHED` مباشرة، أما خطوة `COMPLETED` الوسيطة فما تزال مسجّلة في `timeline` الخاص بالتحويل.
يُطلق كل انتقال حدث webhook باسم `travel_rule.status.updated` (ويُطلق كلٌّ من `COMPLETED` و`FINISHED` حدثاً واحداً).
عندما ينشئ Didit معاملة جديدة، يرسل أولاً [`transaction.created`](https://docs.didit.me/ar/integration/webhooks#أنواع-الأحداث) ثم هذه الأحداث بعده.
لا تترتب على التسجيل أي رسوم لـ Travel Rule أو للمراقبة.
عند تفعيل مراقبة العملات المشفّرة، وكانت `chain` من السلاسل التي يستطيع Didit فحصها، يُفحص الإيداع الجديد المنشأ أيضاً ويُحتسب مرة واحدة بسعر Wallet Verification & Screening.

### أداة ملكية المحفظة

لنقل تحويل من `UNCONFIRMED_OWNERSHIP`، أو للتحقق مسبقاً من محفظة قبل وصول أي تحويل، أنشئ أداة إثبات ملكية المحفظة المستضافة عبر `POST /v3/travel-rule/widget-session/` ووجّه عميلك إلى `url` المُعاد.
تُثبت الأداة سيطرة العميل على المحفظة عبر توقيع الرسائل (بما فيها حسابات العقود الذكية في EVM من خلال ERC-1271 وERC-6492)، أو اختبار Satoshi، أو لقطة شاشة، أو الإقرار الذاتي، ثم تُعلّم إدخال دفتر العناوين المطابق بأنه متحقَّق منه حتى تتمكن البورصة من المتابعة.
لقطة الشاشة هي الاستثناء: فهي لا تُثبت ملكية المحفظة بمفردها أبداً، لذا يراجعها فريق الامتثال لديك ويؤكد التحويل في `UNCONFIRMED_OWNERSHIP` باستخدام [`POST .../travel-rule/ownership/`](#تأكيد-ملكية-المحفظة).

راجع [أداة ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md) للاطلاع على التدفق الكامل وطرق الإثبات، والملاحظة المهمة بأن الأداة يجب أن تُفتح في متصفح حقيقي، وليس أبداً داخل عرض الويب المضمّن في SDK الجوال.

## الدليل

`GET /v3/travel-rule/vasps/` يبحث في دليل VASP، وهو يضم إدخالات الدليل المشتركة إلى جانب أعضاء [شبكة Didit](#شبكة-didit). يُظهر كل صف الطريقة التي يمكن لتطبيقك بها الوصول إلى ذلك VASP اليوم.

```bash theme={null}
curl "https://verification.didit.me/v3/travel-rule/vasps/?search=counterparty" \
  -H "x-api-key: YOUR_API_KEY"
```

```json theme={null}
{
  "count": 1,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91",
      "kind": "directory",
      "name": "Example Counterparty VASP",
      "lei": "529900EXAMPLECPTY001",
      "jurisdiction": "DE",
      "domains": ["counterparty.example"],
      "reachable": true,
      "aliases": [{ "name": "Example Counterparty", "kind": "trading_name" }],
      "networks": [
        {
          "network": "GTR",
          "code": "EXAMPLE01",
          "listed_name": "Example Counterparty VASP",
          "country": "DE",
          "verified_at": "2026-10-12T09:30:00Z",
          "last_seen_at": "2026-10-12T09:30:00Z",
          "source": "staff"
        }
      ],
      "routes": [
        { "rail": "GTR", "status": "unavailable", "reason": "no_membership", "via": "" },
        { "rail": "EMAIL", "status": "available", "reason": "", "via": "contact" }
      ],
      "umbrella": null,
      "entities": [],
      "contacts": [
        {
          "id": "6c1f9b8e-2d4a-4f7e-8b3c-5a9d0e1f2a3b",
          "email": "travelrule@counterparty.example",
          "name": "Travel Rule desk",
          "source": "staff",
          "scope": "platform",
          "verified_at": null
        }
      ],
      "dd_status": "NOT_STARTED",
      "dd_score": 62,
      "dd_score_breakdown": {
        "jurisdiction": { "points": 25.0, "max": 25, "reason": "jurisdiction_not_high_risk", "detail": "DEU is not on the high-risk jurisdiction list" },
        "verification": { "points": 3.8, "max": 15, "reason": "dd_status_not_started", "detail": "due diligence status NOT_STARTED" },
        "protocol": { "points": 6.0, "max": 15, "reason": "email_only", "detail": "reachable over the email fallback only" },
        "lei": { "points": 10.0, "max": 10, "reason": "lei_valid", "detail": "valid LEI on record" },
        "history": { "points": 5.0, "max": 10, "reason": "no_history", "detail": "no exchange history" },
        "essentials": { "points": 7.5, "max": 15, "reason": "no_essential_checks", "detail": "no decided essential check yet" },
        "responsiveness": { "points": 5.0, "max": 10, "reason": "responsiveness_unknown", "detail": "0 decided recent requests, too few to judge" }
      },
      "dd_assessed_at": "2026-10-12T09:30:00Z",
      "dd_score_semantic": "higher_is_safer",
      "risk_level": "MEDIUM",
      "responsiveness": { "status": "UNKNOWN", "answered": 0, "total": 0, "computed_at": "2026-10-12T09:30:00Z" },
      "essential_checks": {},
      "reachable_rails": ["GTR", "EMAIL"],
      "is_didit_customer": false,
      "decision": {
        "decision": "APPROVED",
        "reason": "Licensed in DE",
        "decided_by": "",
        "updated_at": "2026-10-14T10:05:00Z",
        "inherited_from": null
      },
      "entity_screening": {
        "id": "7a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
        "status": "Approved",
        "total_hits": 0,
        "score": null,
        "screened_at": "2026-10-14T09:58:00Z",
        "fresh": true,
        "flagged": false
      },
      "questionnaires": []
    }
  ]
}
```

يطابق `search` جزءاً من اسم أو اسم مستعار، أو رقم LEI دقيقاً، أو نطاقاً (`counterparty.example` أو عنواناً URL ضمنه). لتضييق النتائج استخدم:

| المعامل | التأثير |
| - | - |
| `network` | `GTR` أو `TRUST` أو `VERIFYVASP` أو `SYGNA` أو `TRISA`: الإدخالات الموجودة فقط في دليل أعضاء تلك الشبكة كما هو مُدرج حالياً. |
| `jurisdiction` | رمز الدولة وفق ISO 3166 بالحرف الثنائي (alpha-2) أو الثلاثي (alpha-3). |
| `reachable` | `true`: الـVASP الذي يتوفر لتطبيقك مسار إليه فقط. `false`: الإدخالات التي لا يستطيع تطبيقك الوصول إليها اليوم فقط. |
| `kind` | `directory` للإدخالات المشتركة، و`didit` لأعضاء شبكة Didit. |
| `risk` | `LOW` أو `MEDIUM` أو `HIGH`: فقط إدخالات الدليل التي يقع فيها `risk_level` ضمن هذه الفئة. راجع [الدرجة ومستوى المخاطر](#الدرجة-ومستوى-المخاطر). |
| `responsiveness` | `RESPONSIVE` أو `UNRESPONSIVE` أو `UNKNOWN`: فقط إدخالات الدليل التي تحمل `responsiveness.status` بهذه القيمة. راجع [سرعة الاستجابة](#مدى-الاستجابة). |

أعضاء شبكة Didit غير مُقيَّمين، لذا تُعيد `risk` و`responsiveness` إدخالات الدليل فقط. تُرتَّب النتائج حسب الاسم، ويُقسَّم الناتج إلى صفحات بالمعاملين `limit` (القيمة الافتراضية `50`) و`offset`. أي شبكة أو رمز دولة أو فئة مخاطر أو حالة استجابة غير معروفة يُعيد الرد `400` مع ذكر الحقل المعني. يعيد `GET /v3/travel-rule/vasps/{vasp_id}/` صفاً واحداً بحسب `id` الخاص به. ولا يظهر ملف VASP الخاص بك أبداً ضمن نتائجك.

تحمل الحقول `dd_status` و`dd_score` و`dd_score_breakdown` و`dd_assessed_at` و`dd_score_semantic` و`risk_level` و`responsiveness` و`essential_checks` التقييم المشترك للعناية الواجبة لإدخال في الدليل. أما `decision` و`entity_screening` و`questionnaires` فهي سجلات تطبيقك الخاصة عن الـVASP، ولا يطّلع عليها أي عميل آخر. راجع [العناية الواجبة للطرف المقابل](#العناية-الواجبة-تجاه-الطرف-المقابل) لمعرفة معنى كل منها، واعتمد عليها عبر [حقول قاعدة الطرف المقابل](#حقول-القواعد-والإعدادات-المسبقة) بدلاً من التفرع عليها مباشرة في الكود. أعضاء شبكة Didit غير مُقيَّمين: إذ تكون قيمة `dd_status` هي `COMPLETED`، و`dd_score` هي `null`، و`risk_level` فارغة، والتفصيل فارغ.

### المسارات

يسرد `routes` الطرق التي يستطيع تطبيقك بها التسليم إلى الـVASP، وفق الترتيب الذي يجربه سلم المسارات، ويكون `reachable` بقيمة `true` عندما يكون مسار واحد على الأقل `available`:

* `TRP` عندما يحمل الإدخال endpoint لـ TRP تحقق منه الدليل.
* `GTR` أو `TRUST` أو `VERIFYVASP` أو `SYGNA` عندما تُدرج شبكة الـVASP تحت رمز. لا يكون المسار `available` إلا إذا كان بوسع تطبيقك الإرسال عبر تلك الشبكة اليوم (`via: own_membership` لعضويتك المتصلة، و`via: didit_membership` لعضوية Didit). وإلا يكون `unavailable` مع `reason: no_membership` أو `reason: network_switched_off`، ولا يُعرض أبداً كطريقة للوصول إلى الـVASP. عضويات Didit في شبكاتها غير مفعّلة بعد، لذا فإن مسار الشبكة لا يكون متاحاً اليوم إلا عبر عضوية ربطتها أنت في Marketplace.
* `EMAIL` عندما توجد جهة اتصال للامتثال للإدخال.
* `INTERNAL` لعضو في شبكة Didit.

يظهر إدراج `TRISA` ضمن `networks` ويخبرك بهوية الـVASP على TRISA، لكن Didit لا تملك قناة TRISA، لذا لا يكون أبداً مساراً.

لا يتاح أي مسار من الدليل لتطبيق في البيئة التجريبية، لأنه يرسل إلى [Didit Test VASP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) فقط. لذلك يكون كل مسار `unavailable` مع `reason: sandbox_application`، ويكون `reachable: false` في كل صف، ويعيد `reachable=true` صفر صفوف.

### العلامات التجارية وكياناتها

العلامة التجارية التي تعمل عبر عدة كيانات قانونية تُمثَّل بصف واحد، وتكون `entities` فيه هي الكيانات القانونية التي تستقبل تحويلاتها. ويشير الكيان إلى علامته التجارية في `umbrella`. يُرسَل التحويل الذي يسمّي العلامة التجارية إلى أحد كياناتها، ويُختار من بينها جميعاً: الكيان الموجود في الولاية القضائية المذكورة في `beneficiary_data.counterparty_vasp_jurisdiction`، وإلا فالكيان الذي ربطه [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) بالمحفظة المستلمة، وإلا فالكيان الوحيد للعلامة التجارية عندما لا تُذكر أي ولاية قضائية. وعندئذ فقط يجب أن يكون ذلك الكيان قابلاً للوصول؛ فإذا لم يكن كذلك، لا يُرسَل التحويل أبداً إلى كيان آخر ولا إلى العلامة التجارية نفسها. وعندما لا يناسب أي كيان (إذا تساوى اثنان في الملاءمة، أو كانت الولاية القضائية المذكورة لا تنتمي إلى أي منها)، يُستخدم مسار العلامة التجارية نفسها، وإن لم يوجد لها مسار فيكون التحويل `COUNTERPARTY_VASP_NOT_FOUND`. ولا يُترك تحديد الكيان القانوني الذي يستقبل بيانات المُرسِل للتخمين أبداً، ولا يُحدَّد بحسب الكيان الذي يتوفر له جهة اتصال.

تُميَّز الإدخالات المتعددة التي تحمل الاسم نفسه، مثل شركات المجموعة التي تشترك في اسم تجاري واحد، بالقاعدة ذاتها: الإدخال الموجود في الولاية القضائية المذكورة، وإلا الإدخال الذي ربطه إسناد تحليلات البلوكتشين. وإذا لم تحدد أي من القاعدتين إدخالاً واحداً، فلا يُستخدم أي إدخال، وتُحسب التفاصيل كأنها لا تسمّي أي إدخال في الدليل.

### جهات الاتصال

`contacts` هي العناوين التي يكتب إليها مسار `EMAIL`. يخدم `scope: platform` كل عملاء Didit: إذ تنتقيها Didit (`source: staff`)، أو يجيب عنوان على نطاق VASP الخاص بالجهة عبر رابط الرد الخاص به (`source: learned`). أما `scope: application` فهي خاصة بتطبيقك: وهي التي تضيفها أنت (`source: application`)، وعنوان خارج نطاقات الـVASP الخاصة أجاب على أحد طلباتك (`source: learned`). يرسل التحويل بريداً إلكترونياً أولاً إلى جهة الاتصال الخاصة بتطبيقك، ثم إلى جهة اتصال من المنصة سبق أن أجابت (مع تعيين `verified_at`)، ثم إلى الباقي.

أدِر جهات الاتصال الخاصة بتطبيقك عبر واجهة برمجة جهات اتصال الطرف المقابل:

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/counterparty-contacts/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"counterparty": "0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91", "email": "compliance@counterparty.example", "name": "Compliance desk"}'
```

* يسرد `GET /v3/travel-rule/counterparty-contacts/` كل جهة اتصال يحق لتطبيقك الإرسال إليها، بما فيها جهات اتصال المنصة وتلك التي ارتدت، وترتيبها من الأحدث إلى الأقدم، ويُقسَّم الناتج إلى صفحات بالمعاملين `limit` و`offset`. صفِّ النتائج بـ`?counterparty=` ومعرّف إدخال الدليل `id`؛ والقيمة التي ليست UUID تُعيد `400`.
* يضيف `POST` جهة اتصال خاصة (`counterparty` و`email` واختيارياً `name`) ويعيد `201`. وإضافة عنوان يملكه الإدخال بالفعل ضمن جهات اتصالك الخاصة تُعيد جهة الاتصال تلك. ويُعيد إدخال غير معروف الرد `400` (`"No directory entry with this id."`).
* يحذف `DELETE /v3/travel-rule/counterparty-contacts/{contact_uuid}/` إحدى جهات اتصالك الخاصة (`204`). ولا يمكن حذف جهات اتصال المنصة، فتُعيد `404`.

تحمل جهة الاتصال التي ارتدّت رسالتها أو قدّمت شكوى علامة `is_invalid: true`، مع `invalid_reason` (`hard_bounce` أو `soft_bounce` أو `spam_complaint` أو `suppressed`) و`invalid_detail` و`invalid_at`، ويتخطاها مسار `EMAIL`. يكون `created_by` فارغاً في جهات اتصال المنصة وفي جهات الاتصال التي أضافها مفتاح API.

### كيف تدخل الإدخالات إلى الدليل

* سجل ESMA المؤقت لمقدّمي خدمات الأصول المشفّرة بموجب MiCA، ويُقرأ كل أسبوع: اسم كل مزوّد وLEI الخاص به والدولة العضو الأصلية لمقدّم الخدمة.
* دليل TRISA العام، ويُقرأ كل أسبوع: هوية كل عضو وبلده وإدراجه في TRISA. يُحذف الإدراج الذي يتوقف الدليل عن عرضه لمدة ثلاثة أسابيع.
* سجل LEI العالمي يملأ LEI والأسماء القانونية الأخرى وبلد الإدخال، ويعثر على LEI الخاص بالإدخال عبر اسمه القانوني الدقيق في بلده.
* [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) يضيف VASP الذي يملك محفظة الوجهة أو يطابقه، ويحتفظ بالاسم المنسوب كاسم بديل.
* يتولى فريق Didit تنظيم الإدخالات: معرّفات التوجيه التي تحقّقوا منها وإدراجات الشبكات التي تحقّقوا منها، وجهات اتصال الامتثال، والأسماء البديلة، والعلامات التجارية وكياناتها، والإدخالات المكررة المدموجة، والإدخالات المخفية.

البيانات التي يبلغ عنها العميل بشأن طرف مقابل، مثل `originating_vasp` الوارد أو Travel Address، تبقى على معاملة ذلك العميل ولا تغيّر أي إدخال مشترك أبداً. تُطابَق الإدخالات أولاً بواسطة LEI، ثم بالاسم الدقيق أو الاسم البديل، وتُثرى ولا تُكرَّر.

### شبكة Didit

ملفك الشخصي كـ VASP عضو في شبكة Didit، فيجده عملاء Didit الآخرون في الدليل وفي منتقي VASP الخاص بالمستخدم النهائي، فقط عندما تتحقق كل الشروط التالية:

* تطبيقك في بيئة الإنتاج (وليس البيئة التجريبية) وقاعدة Travel Rule مفعّلة؛
* `is_discoverable` قيمته `true` و`legal_name` مضبوط؛
* `compliance_email` مضبوط ومؤكَّد: أرسل التأكيد باستخدام `POST /v3/travel-rule/settings/compliance-email/confirmation/` وافتح الرابط المرسل إلى بريدك. يتطلب تغيير العنوان تأكيداً جديداً؛
* لم تُعلّم Didit التطبيق كتطبيق اختبار أو تجريبي أو داخلي.

يعمل مسار `INTERNAL` نفسه على محفظة أثبتّ ملكيتها، كما هو موضح في [الإرسال عبر التحويل](#إرسال-تحويل): يحتاج إلى أن يكون تطبيقك في بيئة الإنتاج وأن تكون Travel Rule مفعّلة و`is_discoverable`، لا بقية القائمة.

يعيد `GET /v3/travel-rule/settings/` الحقل `didit_network` الذي يتضمن `listed` و`compliance_email_confirmed`، وفي `missing` كل شرط ما زال غير محقَّق (`travel_rule_off`، `sandbox_application`، `not_discoverable`، `legal_name_missing`، `compliance_email_missing`، `compliance_email_unconfirmed`، `excluded_by_staff`، `internal_organization`).

### معرّفات التوجيه

يستعلم التوجيه الصادر إدخالاً في الدليل كلما سمّى تحويلك الطرف المقابل عبر `counterparty_vasp_lei` أو `counterparty_vasp_name` (والاسم البديل يعمل أيضاً). يحمل الإدخال معرّفاً واحداً لكل شبكة يمكن الوصول إلى الإدخال عبرها، وendpoint محقَّقاً لـ TRP وجهات اتصال الامتثال الخاصة به، ويبيّن `routes` أيّاً منها يمكن لتطبيقك استخدامه. يمكنك دائماً تجاوز الدليل في تحويل واحد بتمرير الحقول الصريحة الموضحة في [حقول تحديد الطرف المقابل](#حقول-تحديد-الطرف-المقابل).

## العناية الواجبة تجاه الطرف المقابل

قبل أن تصل أموال عملائك إلى VASP آخر، عليك أن تعرف من هو هذا الـ VASP، وما إذا كنت تقبله. تتكون العناية الواجبة تجاه الطرف المقابل من طبقتين:

* **التقييم المشترك.** يحمل كل إدخال في الدليل درجة العناية الواجبة ومستوى مخاطره وحالة استجابته وتقرير الفحوصات الأساسية. يحسب Didit هذه القيم من بيانات المنصة نفسها، فيرى كل عميل القيم ذاتها.
* **سجلاتك الخاصة.** قرارك بشأن الـ VASP، وفحص العقوبات والأخبار السلبية الذي تجريه عليه، واستبيانات العناية الواجبة التي تبادلتها معه تخص تطبيقك وحده. لا يراها عميل آخر، ولا تغيّر الإدخال المشترك أبداً.

تعمل سجلاتك الخاصة مع الإدخال في الدليل ومع عضو في [شبكة Didit](#شبكة-didit) على حد سواء: استخدم `id` الذي يعرضه [الدليل](#الدليل) للإشارة إلى أيٍّ منهما.

| endpoint | ما تفعله |
| - | - |
| `GET` / `PUT` / `DELETE /v3/travel-rule/vasps/{vasp_id}/decision/` | قراءة [قرارك](#قرارك-بشأن-الطرف-المقابل) أو تعيينه أو إلغاؤه بشأن الطرف المقابل. |
| `GET` / `POST /v3/travel-rule/vasps/{vasp_id}/screening/` | قراءة أحدث [فحص للطرف المقابل](#فحص-الطرف-المقابل) لديك، أو تشغيل فحص جديد. |
| `GET` / `POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/` | عرض [استبيانات العناية الواجبة](#استبيان-العناية-الواجبة) التي لديك مع الطرف المقابل، أو إرسال استبيان. |
| `GET /v3/travel-rule/transfers/?counterparty={vasp_id}` | [تحويلاتك مع ذلك الطرف المقابل](#المعاملات-مع-طرف-مقابل-واحد). |

### الدرجة ومستوى المخاطر

يتراوح `dd_score` من 0 إلى 100، و**كلما ارتفعت الدرجة، زاد الأمان**. تذكر كل نتيجة ذلك في `dd_score_semantic`، وقيمته دائماً `higher_is_safer`. أما `risk_level` فهو النطاق الذي تقع فيه الدرجة:

| `risk_level` | `dd_score` |
| - | - |
| `LOW` | 70 أو أكثر |
| `MEDIUM` | من 40 إلى 69 |
| `HIGH` | أقل من 40 |

الدرجة مجموع سبعة مكوّنات. يعرض `dd_score_breakdown` كل مكوّن بالشكل `{points, max, reason, detail}`: إذ تمثل `max` وزن المكوّن، و`reason` رمزاً قابلاً للقراءة الآلية يمكنك ترجمته، و`detail` شرحاً إنجليزياً من سطر واحد.

| المكوّن | الوزن | طريقة الاحتساب | رموز `reason` |
| - | - | - | - |
| `jurisdiction` | 25 | كامل عندما لا تكون دولة الإدخال في قائمة الولايات القضائية عالية المخاطر الافتراضية (`IRN`, `PRK`, `SYR`, `AFG`, `RUS`, `MMR`)، وصفر عندما تكون فيها، ونصف الدرجة عندما تكون الدولة غير معروفة. | `jurisdiction_not_high_risk`، `jurisdiction_high_risk`، `jurisdiction_unknown` |
| `verification` | 15 | كامل لـ `COMPLETED`، ونصف لـ `IN_PROGRESS`، وربع لـ `NOT_STARTED`، وصفر لـ `REJECTED`، وذلك وفق حالة التحقق في Didit للإدخال (`dd_status`). | `dd_status_completed`، `dd_status_in_progress`، `dd_status_not_started`، `dd_status_rejected` |
| `protocol` | 15 | كامل عندما يصل مسار بروتوكول أصلي إلى الإدخال (endpoint الخاص بـ TRP أو المسار `INTERNAL`)، و40 في المائة عندما يصل إليه البريد الإلكتروني الاحتياطي وحده، وصفر دون مسار قابل للوصول. | `native_rail`، `email_only`، `no_rail` |
| `lei` | 10 | كامل مع LEI صالح في السجل، وصفر دونه. | `lei_valid`، `lei_missing` |
| `history` | 10 | نسبة عمليات التبادل المحسومة للإدخال التي نجحت، ونصف الدرجة دون أي عملية محسومة. | `history`، `no_history` |
| `essentials` | 15 | نسبة [الفحوصات الأساسية](#الفحوصات-الأساسية) المحسومة التي تجتاز، ونصف الدرجة ما دام لم يُحسم أي فحص. | `essential_checks`، `no_essential_checks` |
| `responsiveness` | 10 | كامل لـ `RESPONSIVE`، وصفر لـ `UNRESPONSIVE`، ونصف لـ `UNKNOWN`. راجع [مدى الاستجابة](#مدى-الاستجابة). | `responsive`، `unresponsive`، `responsiveness_unknown` |

تُقرَّب النقاط إلى رقم عشري واحد، ويُقرَّب المجموع إلى عدد صحيح. يقرأ `history` الطلبات نفسها التي يقرأها [مدى الاستجابة](#مدى-الاستجابة)، دون نافذة زمنية: تُعد عملية `COMPLETED` أو `FINISHED` نجاحاً، وتُعد `EXPIRED` أو `COUNTERPARTY_MISMATCHED_DATA` أو `COUNTERPARTY_VASP_GENERAL_DECLINE` فشلاً. ولا يُحتسب الإلغاء أبداً، لأنه فعل صادر عن المرسل نفسه.

يعيد Didit احتساب التقييم عندما تكتمل عملية تبادل مع الإدخال أو تنتهي أو تنتهي مهلتها أو يحدث فيها عدم تطابق في البيانات أو يتم رفضها، وعندما يحدّث الإدخال أو يتولى تنظيمه، وفي كل إدخال ضمن التحديث الأسبوعي للدليل. يبيّن `dd_assessed_at` موعد آخر تشغيل له. أما الإدخال الذي لم يُقيَّم بعد فلا يملك `dd_assessed_at`، ودرجته `dd_score` تساوي `0`، ومستوى مخاطره `risk_level` فارغ، لذا اقرأ `risk_level` ولا تعتمد على الدرجة الخام. لا تُقيَّم أعضاء شبكة Didit: فدرجتهم `dd_score` قيمتها `null`، ومستوى مخاطرهم `risk_level` فارغ، و`dd_score_breakdown` فارغ.

### الفحوصات الأساسية

`essential_checks` تقرير موجز عن أربعة فحوصات يجريها Didit على كل إدخال في الدليل، من المصادر التي تحققت منها المنصة فقط، ولا يُعتمد أبداً على بيانات أبلغ عنها العميل:

| `id` الفحص | يجتاز عندما |
| - | - |
| `registration` | يُدرج سجل رسمي الـ VASP: السجل المؤقت لمقدمي خدمات الأصول المشفرة بموجب MiCA التابع للاتحاد الأوروبي، أو دليل TRISA العام، أو سجل LEI العالمي مع LEI مُصدَر. |
| `licence` | يسجّل سجل MiCA ترخيصاً للـ VASP لم ينته بعد. |
| `domain` | يتطابق نطاق الإدخال مع endpoint TRP الخاص به، أو مع الموقع الذي يذكره سجله. |
| `lei` | سجل LEI الخاص بالإدخال نشط ومُصدَر، ويتطابق اسمه القانوني وبلده مع الإدخال. |

يعرض كل فحص في `checks` حالته `status` (`pass` أو `fail` أو `unknown` عندما لا يستطيع أي مصدر مسجل حسمه)، و`reason` رمزاً قابلاً للقراءة الآلية، و`detail` شرحاً إنجليزياً من سطر واحد. تحسب `passed` و`failed` و`unknown` و`total` عدد الفحوصات، و`level` قيمته `essential`، و`checked_at` يبيّن وقت بناء التقرير. يحتسب مكوّن `essentials` نسبة الفحوصات المحسومة التي تجتاز، فلا يُحتسب الفحص `unknown` لا له ولا عليه. ويبقى التقرير فارغاً حتى يفحص أول تحديث أسبوعي للدليل الإدخال، ويبقى فارغاً دائماً لعضو في شبكة Didit.

### مدى الاستجابة

`responsiveness` يبيّن ما إذا كان الـ VASP يردّ على طلبات Travel Rule:

```json theme={null}
{ "status": "UNRESPONSIVE", "answered": 0, "total": 6, "computed_at": "2026-10-12T09:30:00Z" }
```

يحسب `total` الطلبات التي بدأها عملاء Didit نحو الـ VASP خلال آخر 90 يوماً، والتي حُسمت نتيجتها، ويحسب `answered` الطلبات التي ردّ عليها:

* **تُحتسب:** الطلبات المرسلة عبر شبكة أو مسار بروتوكول، والطلبات المرسلة بالبريد الإلكتروني إلى عنوان مشترك، وهو عنوان الامتثال في الإدخال أو عنوان جهة اتصال للمنصة.
* **لا تُحتسب أبداً:** طلب أُرسل بالبريد الإلكتروني إلى عنوان كتبه عميل واحد، أو إلى عنوان جهة اتصال خاصة بالعميل. تبقى هذه العملية في سجل تحويلات العميل وحده، ولا تصنّف الـ VASP لدى الآخرين أبداً.
* **تُعد ردّاً:** `COMPLETED` أو `FINISHED` أو `COUNTERPARTY_VASP_GENERAL_DECLINE` أو `COUNTERPARTY_MISMATCHED_DATA`. فالرفض أو عدم تطابق البيانات ردّ، لأن الـ VASP تفاعل مع الطلب.
* **بلا ردّ:** `EXPIRED`.
* **خارج الحساب:** كل حالة أخرى. فالطلب `CANCELLED` فعل صادر عن المرسل نفسه، و`COUNTERPARTY_VASP_NOT_REACHABLE` قد يكون إخفاقاً من جهة المرسل، والطلب الذي ما زال قيد التنفيذ لم يُحسم بعد.

| `status` | متى |
| - | - |
| `UNKNOWN` | أقل من 5 طلبات مُبتّ فيها خلال النافذة الزمنية، حتى لا يُصنّف طلبٌ منتهٍ واحد أي VASP. |
| `UNRESPONSIVE` | ردّ الـVASP على أقل من 10 في المئة من طلباته المُبتّ فيها. |
| `RESPONSIVE` | في غير ذلك. |

يردّ أعضاء شبكة Didit داخل Didit، ويظهرون دائماً بالحالة `UNKNOWN` مع أعداد صفرية. تصرّف تجاه طرف مقابل غير مستجيب عبر [سياسة عدم الاستجابة](#سياسات-sunrise-وعدم-الاستجابة) أو عبر [الإعداد المسبق](#حقول-القواعد-والإعدادات-المسبقة) `travel-rule-counterparty-unresponsive`.

### قرارك بشأن الطرف المقابل

سجّل قرار فريق الامتثال لديك بشأن طرف مقابل باستخدام `PUT /v3/travel-rule/vasps/{vasp_id}/decision/`:

```bash theme={null}
curl -X PUT https://verification.didit.me/v3/travel-rule/vasps/0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91/decision/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"decision": "BLOCKED", "reason": "Unlicensed in its home jurisdiction"}'
```

```json theme={null}
{
  "decision": {
    "decision": "BLOCKED",
    "reason": "Unlicensed in its home jurisdiction",
    "decided_by": "",
    "updated_at": "2026-10-14T10:05:00Z",
    "inherited_from": null
  }
}
```

| `decision` | المعنى | الإعداد المسبق الذي يطبّقه |
| - | - | - |
| `APPROVED` | وافق فريقك على الطرف المقابل. | لا شيء |
| `RESTRICTED` | يجوز المضي في التحويلات إليه بعد المراجعة. | `travel-rule-counterparty-restricted` يحتجزها للمراجعة. |
| `BLOCKED` | رفض فريقك الطرف المقابل. | `travel-rule-counterparty-blocked` يرفضها. |

* القرار خاص بتطبيقك: لا يراه عميل آخر، ولا يغيّر الإدخال المشترك أبداً.
* لا يُحدث القرار أي تغيير بمفرده، ولا يغيّر أبداً طريقة توجيه التحويل. يصل إلى معاملاتك عبر [حقل القاعدة](#حقول-القواعد-والإعدادات-المسبقة) `counterparty_dd_status`: ثبّت الإعدادات المسبقة، أو اكتب قاعدتك الخاصة التي تعتمد عليه.
* ينطبق القرار على العلامة التجارية على كل [كيان](#العلامات-التجارية-وكياناتها) تابع لها ليس له قرار خاص به، ويُظهر الكيان العلامة التجارية في `inherited_from`. ويتجاوز قرار الكيان قرار العلامة التجارية لذلك الكيان.
* يعيد `GET` القرار المنطبق، أو `{"decision": null}`. ويمسح `DELETE` قرارك الخاص ويعيد ما ينطبق بعد ذلك: قرار العلامة التجارية للكيان، وإلا `null`. ويعيد `404` عندما لا يكون لتطبيقك قرار خاص به على الطرف المقابل.
* `reason` اختياري، ويصل إلى 255 حرفاً، وكل `PUT` يستبدله. و`decided_by` هو مستخدم وحدة التحكم الذي اتخذ القرار أو عدّله آخر مرة، ويكون فارغاً عندما يتم ذلك عبر مفتاح API.

### فحص الطرف المقابل

يتحقق فحص الطرف المقابل من VASP الطرف المقابل نفسه، بصفته شركة، مقابل العقوبات والأخبار السلبية. وهو **اختياري وخاضع للفوترة**: فعّله بالمعامل `counterparty_screening_enabled` في [الإعدادات](#الإعداد). وما دام متوقفاً، لا يُفحص شيء ولا يُحتسب شيء.

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/vasps/0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91/screening/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"refresh": false}'
```

```json theme={null}
{
  "outcome": "screened",
  "screening": {
    "id": "7a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
    "status": "In Review",
    "total_hits": 2,
    "score": 85.0,
    "screened_at": "2026-10-14T09:58:00Z",
    "fresh": true,
    "flagged": true
  }
}
```

* **الفوترة.** يكلّف كل فحص جديد مؤسستك وفق [سعر](https://docs.didit.me/ar/getting-started/pricing.md) فحص AML للشركات. يعيد `GET /v3/travel-rule/vasps/{vasp_id}/screening/` هذا `price` و`fresh_days` وما إذا كان الفحص `enabled`، دون أي رسوم. الفحص الذي عمره أقل من 30 يوماً يُعدّ حديثاً: يعيده `POST` مرة أخرى بالحالة `200` و`outcome: reused` دون أن يُحتسب شيء، إلا إذا أرسلت `refresh: true`. ويجيب الفحص الجديد بالحالة `201` مع `outcome: screened`. لا تخضع تطبيقات البيئة التجريبية للفحص أو الفوترة أبداً.
* **الفحص التلقائي.** عند تفعيل الفحص، يفحص Didit أيضاً الطرف المقابل الذي يصل إليه التبادل الصادر عند بدئه، قبل أن تقيّم قواعدك المعاملة، بنفس إعادة الاستخدام والفوترة. ولا يؤدي الرفض أو الفشل هنا أبداً إلى فشل التحويل.
* **النتيجة.** تكون `status` بقيمة `Approved` عندما لا يحتاج أي تطابق محتمل إلى اهتمام، وبقيمة `In Review` أو `Declined` عند وجود تطابق محتمل مع العقوبات أو الأخبار السلبية. وتكون `flagged` بقيمة `true` طالما كان الفحص الحديث بحالة `In Review` أو `Declined`.
* **الأثر.** طالما كان آخر فحص لديك للطرف المقابل مُعلَّماً والفحص مفعّلاً، تكون `counterparty_risk_level` بقيمة `HIGH` في قواعدك، فيحتجز الإعداد المسبق `travel-rule-counterparty-high-risk`، بعد تثبيته، معاملاته. ولا يتغير `risk_level` المشترك في الدليل.
* **الخصوصية.** الفحص خاص بتطبيقك: لا يراه عميل آخر، ولا يغيّر الإدخال المشترك أبداً. ويعرض الدليل آخر فحص لديك باسم `entity_screening`.
* **الرفض.** يعيد `409` عندما يكون الفحص متوقفاً، أو عندما يكون التطبيق في البيئة التجريبية، أو أثناء تشغيل فحص آخر للطرف المقابل نفسه. ويعيد `403` مع `code: insufficient_credits` عندما لا يغطي رصيدك السعر. ويعيد `502` عندما يتعذر إكمال الفحص. ولا تُفرض رسوم على أيٍّ منها.

### استبيان العناية الواجبة

اطلب من الطرف المقابل إجاباته عن العناية الواجبة عبر استبيان Didit القياسي. يرسل `POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/` الاستبيان بالبريد الإلكتروني إلى عنوان امتثال مسجّل للطرف المقابل، مع رابط لمرة واحدة إلى صفحة الإجابة:

```bash theme={null}
curl -X POST https://verification.didit.me/v3/travel-rule/vasps/0d6f3c2a-6a1e-4c55-9a39-1f2b0c7d8e91/questionnaires/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sent_to": "travelrule@counterparty.example"}'
```

```json theme={null}
{
  "id": "3f9e8d7c-6b5a-4c3d-9e2f-1a0b9c8d7e6f",
  "status": "SENT",
  "form_version": "1",
  "sent_to": "travelrule@counterparty.example",
  "sent_at": "2026-10-14T10:00:00Z",
  "expires_at": "2026-11-13T10:00:00Z",
  "answered_at": null,
  "valid_until": null,
  "current": false,
  "answers": {}
}
```

* **الوجهة.** يجب أن تكون `sent_to` عنوان امتثال مسجّلاً: بالنسبة إلى إدخال في الدليل، عنوان امتثاله أو جهة اتصال يراها تطبيقك في `contacts`؛ وبالنسبة إلى عضو في شبكة Didit، بريده الإلكتروني للامتثال المؤكد. لا تُدرجها لاستخدام العنوان الذي يُرسل إليه بريد Travel Rule إلى الطرف المقابل: جهة اتصالك أولاً، ثم جهة اتصال المنصة، ثم عنوان الامتثال للإدخال. ولا يرسل Didit الاستبيان إلى أي جهة أخرى أبداً، ويعيد `400` عندما لا يكون لدى الطرف المقابل عنوان امتثال مسجّل.
* **الإجابة.** يفتح الرابط `/v3/travel-rule/questionnaires/{token}/`، وهي صفحة موجهة لشخص لدى الطرف المقابل، لا يحتاج إلى حساب أو مفتاح API. يجيب عن كل سؤال، بما لا يتجاوز 2,000 حرف لكل منها (`N/A` حيث لا ينطبق السؤال)، ويرسل مرة واحدة. ويمكن للطرف المقابل أيضاً أن يرسل `{"answers": {"<question id>": "<answer>"}}` إلى الرابط نفسه. ويعرض الرابط الذي استُخدم أو استُبدل أو تجاوز موعده صفحة انتهاء صلاحية بدلاً من ذلك. يُترجم البريد والصفحة، أما الأسئلة نفسها فتبقى دائماً بالإنجليزية، حتى لا يتغير معناها بين اللغات.
* **المواعيد.** لدى الطرف المقابل 30 يوماً للرد (`expires_at`). تبقى الإجابات سارية لمدة 365 يوماً (`valid_until`)، ويكون `current` بقيمة `true` حتى ذلك الحين. ويصبح الاستبيان غير المُجاب عنه بعد موعده، وتصبح الإجابات بعد انتهاء صلاحيتها، بحالة `EXPIRED`.
* **استبيان مفتوح واحد لكل طرف مقابل.** يحل الإرسال الجديد محل استبيانك السابق غير المُجاب عنه إلى الطرف المقابل نفسه: يصبح بحالة `EXPIRED` ويتوقف رابطه عن العمل. ولا يُرسل أكثر من بريد واحد في الدقيقة إلى العنوان نفسه، ويعيد الإرسال الأسرع `429`.
* **قراءة الإجابات.** يسرد `GET /v3/travel-rule/vasps/{vasp_id}/questionnaires/` استبياناتك مع الطرف المقابل، من الأحدث إلى الأقدم، مع `answers` مفهرسة بمعرّف السؤال بعد الإجابة. ويعرضها الدليل باسم `questionnaires`. وهي خاصة بتطبيقك.

يطرح الإصدار `1` من النموذج هذه الأسئلة الاثني عشر:

| معرّف السؤال | السؤال |
| - | - |
| `legal_name` | الاسم القانوني للكيان والولاية القضائية للتأسيس. |
| `licensing` | التراخيص أو التسجيلات الحاصلة عليها لخدمات الأصول الافتراضية: الجهة التنظيمية، ورقم الترخيص، وحالته في كل ولاية قضائية. |
| `jurisdictions` | الولايات القضائية التي تعمل فيها، وأي ولاية قضائية تكون مستبعدًا أو مقيّدًا فيها. |
| `aml_program` | ملخص برنامج AML/CFT الخاص بك: السياسات والإجراءات وتاريخ آخر تدقيق أو مراجعة مستقلة. |
| `compliance_officer` | اسم مسؤول الامتثال لديك ودوره، وكيفية التواصل معه. |
| `sanctions_screening` | كيفية فحص العملاء والأطراف المقابلة مقابل العقوبات والأخبار السلبية: المزوّد أو القوائم، والتكرار، والتصعيد. |
| `transaction_monitoring` | كيفية مراقبة المعاملات لاكتشاف النشاط المشبوه: الأدوات، والحدود، وممارسة الإبلاغ. |
| `travel_rule` | كيفية امتثالك لـ Travel Rule: البروتوكولات والشبكات المستخدمة، ووقت استجابتك المعتاد للطلب. |
| `custody` | ترتيبات حفظ أصول العملاء: أمين الحفظ المؤهل، والتأمين، والفصل. |
| `ownership` | المستفيدون الحقيقيون الذين يمتلكون 25 بالمئة أو أكثر، وأي كيان أم أو كيان مظلة. |
| `record_keeping` | ممارسة حفظ السجلات ومدة الاحتفاظ ببيانات Travel Rule والمعاملات. |
| `data_protection` | كيفية حماية البيانات الشخصية المشتركة لأغراض الامتثال، ومكان تخزينها. |

### المعاملات مع طرف مقابل واحد

يسرد [`GET /v3/travel-rule/transfers/?counterparty={vasp_id}`](https://docs.didit.me/ar/management-api/travel-rule/list-transfers) تحويلات Travel Rule الخاصة بتطبيقك مع طرف مقابل واحد، مرتبةً من الأحدث إلى الأقدم، وذلك بحسب `id` الذي يعرضه الدليل: تحويلاتك التي يكون طرفها المقابل إدخال الدليل ذاك، أو عمليات التبادل `INTERNAL` التي تمّت مع عضو شبكة Didit ذاك. القيمة التي ليست معرّفاً صالحاً تُعيد الاستجابة `400`.
يحمل كل صف الحقل `reason` مباشرةً بعد `status`: وهو [`reason`](#لماذا-يتوقف-التحويل) الخاص بالتحويل نفسه، بحيث توضّح القائمة أن بريد الامتثال ارتدّ بسبب عدم وجود مسار لدى الطرف المقابل، دون فتح كل تحويل على حدة.

### سياسات Sunrise وعدم الاستجابة

عندما ينتهي تحويل (أي تجاوز `confirmation_timeout_hours` وهو في حالة `AWAITING_COUNTERPARTY`)، يحدد `timeout_outcome` ما يحدث لمعاملته. يتيح لك إعدادان معاملة سببين شائعين لانتهاء المهلة بشكل مختلف:

| الإعداد | ينطبق عندما يكون الطرف المقابل إدخالاً في الدليل |
| - | - |
| `sunrise_policy` | يقع في دولة مدرجة في `sunrise_jurisdictions`: دولة لا تُطبّق Travel Rule بعد، لذا لا يكون VASP ملزماً بالرد. |
| `non_responsive_policy` | يملك `responsiveness.status` بقيمة `UNRESPONSIVE`. |

يقبل كلا الإعدادين القيم `HOLD` أو `REJECT` أو `PROCEED`، بالمعنى نفسه المستخدم في `timeout_outcome`، أو سلسلة نصية فارغة لاتباع `timeout_outcome`. وكلاهما فارغ افتراضياً، لذا لا يتغير شيء حتى تضبط أحدهما:

```bash theme={null}
curl -X PUT https://verification.didit.me/v3/travel-rule/settings/ \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sunrise_policy": "PROCEED", "non_responsive_policy": "HOLD"}'
```

الإعداد الأول الذي ينطبق يحدد النتيجة:

1. `sunrise_policy`، إذا كان مضبوطاً ودولة الطرف المقابل مدرجة في `sunrise_jurisdictions`.
2. `non_responsive_policy`، إذا كان مضبوطاً والطرف المقابل `UNRESPONSIVE`.
3. `timeout_outcome` في كل الحالات الأخرى، بما في ذلك التحويل إلى عضو شبكة Didit أو إلى طرف مقابل لا يملك إدخالاً في الدليل.

`sunrise_jurisdictions` للقراءة فقط، وقيمتها الحالية `["CO", "KH", "VN"]`. تُحسب هذه الدول وحدها ضمن فترة Sunrise: أي دولة أخرى، وكذلك الولاية القضائية الفارغة أو غير المعروفة، تتبع `timeout_outcome`، حتى لا يحصل طرف مقابل على سياسة Sunrise الخاصة بك بالخطأ. يذكر الجدول الزمني للتحويل المنتهي النتيجة التي طُبّقت، مثل `sunrise_policy=PROCEED (counterparty jurisdiction CO does not enforce the Travel Rule yet)`. تستمر قواعدك في العمل بعد انتهاء المهلة، لذا قد تنقل قاعدة مثل `tr_eu_expired_review` من حزمة EU TFR المعاملة إلى المراجعة تحت `PROCEED`.

### حقول القواعد والإعدادات المسبقة

تحمل أربعة حقول من حقول [القاعدة](https://docs.didit.me/ar/transaction-monitoring/rules.md) ما يعرفه تطبيقك عن الطرف المقابل الذي وصل إليه تبادل Travel Rule الخاص بالمعاملة: إدخاله في الدليل، أو، في حالة التبادل `INTERNAL`، عميل Didit الذي استلمه. يكون كل حقل فارغاً عندما لا يصل التبادل إلى أي طرف مقابل معروف.

| الحقل | القيمة |
| - | - |
| `counterparty_dd_status` | [قرارك](#قرارك-بشأن-الطرف-المقابل): `APPROVED` أو `RESTRICTED` أو `BLOCKED`، وتتبع الجهة قرار علامتها التجارية. يكون فارغاً إذا لم تتخذ قراراً. ولا يكون أبداً قرار عميل آخر. |
| `counterparty_risk_level` | القيمة `risk_level` للإدخال (`LOW` أو `MEDIUM` أو `HIGH`)، أو `HIGH` إذا كان [فحصك](#فحص-الطرف-المقابل) للطرف المقابل يحمل علامة تنبيه. يكون فارغاً للإدخال الذي لم يُقيَّم بعد، ولعضو شبكة Didit ما لم يحمل فحصك له علامة تنبيه. |
| `counterparty_jurisdiction` | دولة الطرف المقابل، من إدخال الدليل أو من ملف عضو شبكة Didit. تُقارَن رموز ISO-2 وISO-3 معاً، كما في حقول الدول الأخرى. |
| `counterparty_responsiveness` | القيمة `responsiveness.status` للإدخال: `RESPONSIVE` أو `UNRESPONSIVE` أو `UNKNOWN`. يكون فارغاً لعضو شبكة Didit. |

تعمل خمسة إعدادات مسبقة في حزمة `travel_rule` على هذه الحقول. ثبّتها من **Transactions → Rules → Library** في Business Console أو باستخدام [واجهة API لمكتبة القواعد](https://docs.didit.me/ar/management-api/transactions/rules-install.md):

| `library_key` | المُشغِّل | الإجراء الافتراضي |
| - | - | - |
| `travel-rule-counterparty-blocked` | `counterparty_dd_status` تساوي `BLOCKED` | +90 درجة، `DECLINED` |
| `travel-rule-counterparty-restricted` | `counterparty_dd_status` تساوي `RESTRICTED` | +50 درجة، `IN_REVIEW` |
| `travel-rule-counterparty-high-risk` | `counterparty_risk_level` تساوي `HIGH` | +40 درجة، `IN_REVIEW` |
| `travel-rule-counterparty-high-risk-jurisdiction` | `counterparty_jurisdiction` موجودة في قائمة الدول عالية المخاطر الافتراضية (`IRN`, `PRK`, `SYR`, `AFG`, `RUS`, `MMR`) | +60 درجة، `IN_REVIEW` |
| `travel-rule-counterparty-unresponsive` | `counterparty_responsiveness` تساوي `UNRESPONSIVE` | +30 درجة، `IN_REVIEW` |

تنطبق الإعدادات الخمسة جميعها على معاملات Travel Rule فقط.

## Webhooks

اربط وجهة webhook بـ `travel_rule.status.updated` لتتلقى إشعارًا عند كل تغيير في الحالة لكل تحويل في تطبيقك، الصادر والوارد، بما في ذلك أجزاء مسار `INTERNAL`.
يبدأ التوجيه بعد أن تُرجع عملية إنشاء المعاملة استجابتها، لذلك تصلك نتائج مثل `COUNTERPARTY_VASP_NOT_FOUND` و`COUNTERPARTY_VASP_NOT_REACHABLE`، أو تبادل `INTERNAL` تتم تسويته فورًا، عبر هذا الحدث لا في استجابة الإنشاء.

```json theme={null}
{
  "event_id": "9c0c8b8a-1111-4222-9333-666666666666",
  "webhook_type": "travel_rule.status.updated",
  "timestamp": 1774970000,
  "created_at": 1774970000,
  "application_id": "11111111-2222-3333-4444-555555555555",
  "environment": "live",
  "transaction_id": "22222222-3333-4444-5555-666666666666",
  "txn_id": "trv-2026-07-05-001",
  "travel_rule_status": "COMPLETED",
  "rail": "INTERNAL",
  "direction": "OUTBOUND"
}
```

يبقى الحقل `rail` فارغًا حتى يُختار مسار.
بالنسبة لمعاملة واحدة، يرسل Didit الحدث `travel_rule.status.updated` بعد `transaction.created`: عندما ينشئ Didit المعاملة (طلب `POST /v3/transactions/` منك، أو تسجيل sunrise، أو استعلام `TRP` وارد، أو الجزء الوارد عبر مسار `INTERNAL`)، يرسل `transaction.created` أولًا.
يُسلَّم كل حدث ويُعاد إرساله بشكل مستقل، لذلك قد يصل حدث `transaction.created` الذي احتاج إلى إعادة محاولة بعد حدث الحالة: اجعل معالج الأحداث يعتمد على `transaction_id`، واقرأ المعاملة عندما يذكر حدث حالة معرّفًا لم تره من قبل.
لا يصل حدث `COMPLETED` للتحويل المرسل عبر `TRUST`: إذ لا يعيد TRUST أي شيء يستطيع Didit قراءته، لذلك ما لم يفشل الإرسال أو تلغيه، يكون آخر حدث له `EXPIRED`. أما عبر `GTR` و`VERIFYVASP` و`SYGNA`، فيتبع الحدث الرد الذي يقرؤه Didit من الشبكة.
تُرسل تطبيقات البيئة التجريبية هذا الحدث أيضًا، مع `"environment": "sandbox"`؛ والتحويل الذي ردّ عليه [Didit Test VASP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) يحمل `rail: "TEST_VASP"` و`test_vasp: true` و`test_vasp_scenario`.

راجع [دليل webhook](https://docs.didit.me/ar/integration/webhooks.md#أنواع-الأحداث) للاطلاع على كتالوج الأحداث الكامل، والتحقق من التوقيع، وسياسة إعادة المحاولة.

## الأسعار

رسم Travel Rule هو **\$0.02 لكل تبادل صادر يبدأ**، يُحتسب مرة واحدة عند إنشاء المعاملة، بغض النظر عن عدد تغييرات الحالة التي يمر بها التبادل لاحقًا. ولا يُحتسب `resend` مرة أخرى أبدًا.

* ينطبق على معاملة `travelRule` صادرة في تطبيق فعّلت فيه Travel Rule، وكان مبلغها يساوي `threshold_amount` لديك أو يتجاوزه، فيبدأ Didit لها تبادلًا مُدارًا. ويُحتسب التحويل إلى محفظة ذاتية الاستضافة، أو إلى محفظة موثّقة تعود لمستخدمك، بالطريقة نفسها: إثبات الملكية هو التبادل الخاص بها.
* تُحتسب كل معاملة صادرة أخرى تحمل بيانات Travel Rule كفحص معاملات قياسي، تشمله خطتك حتى [حد المعاملات الشهري](https://docs.didit.me/ar/getting-started/pricing.md#مراقبة-المعاملات-kyt) ويُسعَّر بـ \$0.001 بعده: تحويل أقل من الحد لديك، ودفعة Lightning لا تنطبق عليها Travel Rule، وتحويل يُسجَّل بشكل سلبي والـ Travel Rule متوقف. وتُحتسب المعاملة على أحد البندين فقط، لا على كليهما أبدًا.
* لا تحمل معاملات `travelRule` الواردة أي رسوم Travel Rule أو مراقبة: الجزء الوارد الذي ينشئه Didit في تطبيق المستفيد عبر مسار `INTERNAL`، واستعلامات `TRP` الواردة، و[تسجيلات ما بعد الإيداع](#التسجيل-اللاحق-للإيداع).
* لا يدفع التطبيق الذي انضم إلى Travel Rule مجانًا أيًّا من الرسمين على معاملات `travelRule` الصادرة، إلى أن يفعّل الفوترة الصادرة عبر `POST /v3/travel-rule/workspace/billing/`؛ أما الاستلام فيبقى مجانيًا.
* لا تُحتسب تطبيقات البيئة التجريبية أبدًا.
* يُدرج رسم Travel Rule بسعر $0.02، ويُدرج Transaction Screening بسعر $0.001 بعد حدك. وتُحتسب كل معاملة بسعر البند الذي تُحتسب عليه.
* إذا أُجري فحص AML للعملات الرقمية أو فحص المحافظ على المعاملة نفسها أيضًا (مثلًا إيداع وارد بـ `currency_kind: "crypto"` والمراقبة مفعّلة)، فيُحتسب ذلك بشكل منفصل وفق سعر Wallet Verification & Screening القياسي، ولا يُدمج في رسم Travel Rule.
* [فحص الطرف المقابل](#فحص-الطرف-المقابل) اختياري ويُحتسب بشكل منفصل، بسعر فحص AML للشركات عن كل فحص؛ ويُعاد استخدام الفحص الذي يقل عمره عن 30 يومًا دون رسوم. القرارات والاستبيانات وتقييم العناية الواجبة في الدليل لا تكلّف شيئًا.

### تسعير الإسناد

يحتاج [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) إلى استعلام واحد عن المحفظة لدى مزوّد التحليلات، وتحصل دائمًا على القيمة الكاملة لذلك الاستعلام:

* **كانت مراقبة العملات الرقمية قد فحصت المحفظة في هذه المعاملة بالفعل** - تُعاد استخدام النتيجة المخزّنة. استدعاء واحد للتحليلات، ورسم واحد لـ Wallet Verification & Screening (الرسم نفسه الذي احتُسب بالفعل لمراقبة العملات الرقمية). ولا يضيف الإسناد شيئًا.
* **لم تعمل مراقبة العملات الرقمية** - يُجري Didit استدعاء التحليلات المطلوب مرة واحدة، ويمرّر قيمته الكاملة: تُحتسب المعاملة بسعر Wallet Verification & Screening القياسي (\$0.15 مع التحليلات المُدارة من Didit)، وتحصل في المقابل على مخرجات فحص العملات الرقمية كاملة: درجة المخاطر، وفئة مخاطر المحفظة، ولقطة الشبكة، لا اسم VASP فقط. يُوسم بند الاستخدام بالمُشغِّل `travel_rule_attribution` حتى يكون الرسم قابلًا للتفسير.
* **مفتاح تحليلات خاص بك** - ينطبق هنا رسم المنصة نفسه الذي ينطبق على مراقبة العملات الرقمية بمفتاحك الخاص (\$0.02 لكل استدعاء). ويُحاسبك مزوّدك على الاستعلام الأساسي مباشرة.
* **لا تُحتسب الاستعلامات الفاشلة أبدًا**، وتستخدم عمليات إعادة الإرسال الإسناد المسجّل دون استدعاء جديد أو رسم جديد، ولا تُحتسب تطبيقات البيئة التجريبية أبدًا.

إذن، يكلّف التحويل الصادر الذي احتاج إلى إسناد \$0.02 (Travel Rule) + رسم واحد لـ Wallet Verification & Screening، وعندما يكون المنتجان مفعّلين معًا، يُجرى استدعاء التحليلات وتُحتسب رسومه مرة واحدة فقط.

## حزمة قواعد EU TFR

تتضمن حزمة `travel_rule_eu_tfr` أربع قواعد جاهزة، صُمّمت خصيصاً لالتزامات EU TFR.
مثل كل [حزمة قواعد جاهزة](https://docs.didit.me/ar/transaction-monitoring/rules-library.md) أخرى، فعّلها من Business Console ضمن **Transactions → Rules → Library**.

| القاعدة (`library_key`) | المُشغِّل | الإجراء |
| - | - | - |
| `tr_eu_mismatch_hold` | حالة التحويل هي `COUNTERPARTY_MISMATCHED_DATA` | `+50` درجة، وتُعيَّن المعاملة إلى `IN_REVIEW` |
| `tr_eu_unverified_selfhosted_review` | حالة التحويل هي `UNCONFIRMED_OWNERSHIP` ومبلغ العملة الافتراضية لا يقل عن `1000` | تُعيَّن المعاملة إلى `IN_REVIEW` |
| `tr_eu_vasp_not_found_score` | حالة التحويل هي `COUNTERPARTY_VASP_NOT_FOUND` | `+25` درجة، ووسم `travel-rule-sunrise` |
| `tr_eu_expired_review` | حالة التحويل هي `EXPIRED` | تُعيَّن المعاملة إلى `IN_REVIEW` |

تُفعَّل هذه القواعد عند كل انتقال ذي صلة، أي عند إنشاء التحويل، وعند تأكيد الملكية، وعند استجابة التقاط البريد الإلكتروني، ومن خلال مهمة فحص انتهاء الصلاحية. وبذلك يظل التحويل الذي لا يُحسم أبداً ظاهراً لمراجعة الامتثال، بدلاً من أن يُسوّى بصمت.

## لماذا يعمل هذا بشكل أفضل على منصة واحدة

الامتثال لـ Travel Rule مشكلة هوية في ثوب مدفوعات، وDidit يحتفظ بالهوية بالفعل:

* **بيانات موثّقة في متناول يدك.** يُربط الطرف المعني بكل تحويل بملف KYC الذي تحقّقت منه Didit أثناء التسجيل (استخراج المستند بالتعرف الضوئي على الحروف، وكشف الحيوية، ومطابقة الوجه) عبر `vendor_data`، لذا يمكنك بناء `originator_data` من حقول موثّقة على المنصة نفسها.
  بالنسبة إلى مستخدم لديه عملية تحقق KYC مقبولة، ترسل Didit الهوية الموثّقة بدلاً من القيم التي أدخلتها (راجع [البيانات الموثّقة والمصدر](#البيانات-الموثّقة-ومصدرها)).
* **قياسات بيومترية إضافية للتحويلات عالية المخاطر.** يمكن لـ[قاعدة](https://docs.didit.me/ar/transaction-monitoring/rules.md) أن توقف أي تحويل عالي القيمة إلى أن يجتاز المستخدم فحصاً بيومترياً إضافياً مقارنةً بالوجه الذي التُقط أثناء التسجيل، وهو أقوى رد ممكن على الاستيلاء على الحساب لحظة السحب. راجع [المثال التطبيقي](https://docs.didit.me/ar/transaction-monitoring/sdk-transaction-submission.md#مثال-التحقق-البيومتري-الإضافي-لسحب-عالي-القيمة).
* **مخطط واحد للأجهزة.** تحمل التحويلات المُرسلة عبر SDK معلومات الجهاز نفسها المتاحة في جلسات KYC، لذلك تصبح قاعدة "جهاز جديد + مبلغ مرتفع + مستفيد لأول مرة" قاعدة واحدة، لا عملية ربط في مستودع البيانات.
* **الفحص والقواعد والحالات وتبادل البيانات في مكان واحد.** فحص المحافظ الذي يحدد VASP للطرف المقابل هو الفحص نفسه الذي تراه قواعدك ومحللوك، فتدفع رسماً واحداً، وتعمل من لوحة واحدة، وتحتفظ بسجل تدقيق واحد.
* **أسعار منشورة.** [\$0.02 لكل تبادل صادر](#الأسعار)، دون مستويات حسب الحجم، ودون الحاجة إلى مكالمة مبيعات.

## الأسئلة الشائعة

### كيف يعمل التبادل

> [accordion] هل تُشغّل Didit تبادل VASP إلى VASP بنفسها، أم أنها تسجّل بيانات Travel Rule فقط بعد أن تُكمل شبكة أخرى المصافحة؟
>
> تُشغّل Didit التبادل بنفسها.
> عند إرسال تحويل `travelRule`، تنفّذ Didit اكتشاف الطرف المقابل مباشرةً، وترسل بيانات المُرسِل والمستفيد إلى VASP المستلم عبر قنوات الشبكات التي تنقلها، ولا تُعلّم التحويل `COMPLETED` إلا بعد أن يؤكد الطرف المقابل ذلك. إنها مصافحة مُدارة وليست سجلاً يُكتب بعد التسوية.
> تُعالَج إجابة الطرف المقابل على كل شبكة ما عدا `TRUST`، الذي يرسل فقط، لذلك تنتهي صلاحية التحويل عبره بدلاً من اكتماله. وعبر `GTR` و`VERIFYVASP` و`SYGNA`، تقرأ Didit الإجابة من استجابة الشبكة أو من خلال الاستعلام عنها كل 5 دقائق، ولم يكتمل أي تبادل عبرها مع شبكة عاملة حتى الآن. وعبر `TRP`، تحتاج الإجابة التي لا يقدمها الطرف المقابل فورًا إلى مضيف TRP العام التابع لـ Didit، وهو غير مفعّل بعد (انظر [شبكات Travel Rule](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md)).
> كما تحتفظ Didit بالسجل الكامل وحالة الامتثال لكل تبادل: دورة حياة من 13 حالة ([دورة الحياة](#دورة-الحياة))، و[webhooks](#webhooks)، وسجل التدقيق.
> إذا كنت تفضّل تشغيل Travel Rule عبر عمليتك الخاصة، يمكن لـ Didit بدلاً من ذلك أن تسجّل البيانات بشكل سلبي بوصفها نظام السجل الوحيد لديك (انظر السؤال عن التسجيل السلبي أدناه).
> كلا الوضعين متاح: يعمل التبادل النشط بعد أن تضبط `is_enabled: true` في [الإعدادات](#الإعداد) (القيمة الافتراضية `false`)، وحتى ذلك الحين تسجّل Didit البيانات بشكل سلبي.

> [accordion] هل التبادل أصلي في Didit، أم أنه يعتمد على مزود خارجي للتشغيل البيني (Notabene أو Sygna أو VerifyVASP أو TRP)؟
>
> إنه أصلي. تشغّل Didit تطبيقها الخاص لبروتوكول Travel Rule (TRP)، ويُقدَّم عبر `trp.didit.me` بمجرد تفعيل المضيف العام (وهو لا يستجيب بعد، لذا لا يمكن للأطراف المقابلة الوصول إليك عبر TRP اليوم)، وتطبّق بروتوكولات شبكات القطاع مباشرة: `GTR` (Global Travel Rule)، و`TRUST`، و`VerifyVASP`، و`Sygna Bridge` (تُطبَّق أصلاً، بما في ذلك IVMS 101 المشفّر بـ ECIES لدى Sygna وطلبات الإذن الموقّعة). Didit ليست وسيطًا لطبقة تشغيل بيني واحدة لطرف ثالث. والوصول إلى طرف مقابل موجود على شبكة عضوية محددة يتم بالضرورة عبر تلك الشبكة، فليس هناك قناة عالمية واحدة في Travel Rule، لكن الاكتشاف والمصافحة والتحقق وحفظ السجلات تنفّذها Didit جميعًا.
> اليوم، تحتاج كل شبكة إلى عضويتك الخاصة، و`TRUST` يرسل فقط: انظر [نظرة عامة](#نظرة-عامة).

> [accordion] ما شبكات وبروتوكولات Travel Rule التي تدعمها Didit؟
>
> مطبّقة أصلاً، وتُجرَّب بترتيب أولوية صارم: `INTERNAL` (كلا VASPَين على Didit)، و`TRP` (بروتوكول OpenVASP Travel Rule)، و`GTR`، و`TRUST`، و`VerifyVASP`، و`Sygna Bridge`، وقناة احتياطية `EMAIL` للأطراف المقابلة التي لا تملك أدوات مناسبة.
> تحتاج قنوات الشبكات إلى عضويتك الخاصة اليوم، و`TRUST` يرسل فقط، ولم يُفعَّل الاستلام عبر أي شبكة بعد: انظر [شبكات Travel Rule](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md).
> تظهر CODE وTRISA وNotabene وVeriscope في Marketplace لدى Didit كبطاقات طلب وصول، دون تكامل حتى الآن.
> انظر [كيف توجّه Didit التبادل](https://docs.didit.me/ar/transaction-monitoring/travel-rule-interoperability.md#كيف-يوجّه-didit-التحويل) للاطلاع على جدول التوجيه الكامل، و[شبكات Travel Rule](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md) لمعرفة ما تصل إليه كل شبكة اليوم.

> [accordion] أي شبكة يجب أن أستخدم، وهل أحتاج إلى عضويات خاصة بي؟
>
> `TRP` هو الخيار الأساسي الذي نوصي به: فهو لا يتطلب عضوية مشتركة، ومشاركة [Travel Address](#عناوين-travel-address) الخاص بك تتيح لأي مزود يتحدث TRP الوصول إليك. وعندما لا يُعرف الطرف المقابل إلا بعنوان المحفظة، فإن [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين) يوجّهه عبر TRP فقط إذا كان إدخال الدليل المُسنَد يملك endpoint لـ TRP بالفعل.
> عند الإرسال، ترسل Didit الأصول المدرجة ضمن [معرّفات أصول TRP](#معرّفات-أصول-trp) عبر TRP، والطرف المقابل الذي لا يجيب فورًا يحتاج إلى مضيف TRP العام التابع لـ Didit، وهو غير مفعّل بعد.
> بالنسبة إلى الشبكات التي تتطلب عضوية، اختر وفق مكان عمل أطرافك المقابلة: تقدم GTR تغطية عالمية واسعة، وTRUST موجّهة إلى VASPs في الولايات المتحدة، وVerifyVASP (الذي يدير الآن Sygna Bridge أيضًا) تغطيته قوية في آسيا.
> نعم، تحتاج اليوم إلى عضويتك الخاصة: لا تملك Didit عضوية منصة على هذه الشبكات بعد، وهي تخضع حاليًا لعملية التسجيل بصفتها مزودًا.
> اربط عضويتك في **Marketplace**، فأنت لست مقيّدًا بشبكة واحدة.
> تذكّر أن `TRUST` يرسل فقط، وأن التحويل عبره لا يكتمل، وأن أي تبادل عبر شبكة لم يكتمل مع شبكة عاملة حتى الآن.

> [accordion] كيف تجد Didit الـ VASP المقابل عندما يكون لديّ عنوان المحفظة فقط؟
>
> عبر سلسلة حلّ: عميل آخر لدى Didit أثبت سيطرته على المحفظة (مسار `INTERNAL`)، ثم [دفتر عناوين المحافظ](#دفتر-عناوين-المحافظ) الخاص بك لعنوان Travel Address مخزّن، ثم مسارات البروتوكولات والشبكات، وأخيرًا [إسناد تحليلات البلوكتشين](#إسناد-تحليلات-البلوكتشين).
> إذا حمل التحويل محفظة وجهة واحدة فقط، تحلّها Didit مقابل بيانات تحليلات البلوكتشين لإسناد خدمة البورصة أو الحفظ المقابلة، وتسجّلها في [دليل VASP](#الدليل).
> لا يُوجَّه التحويل تلقائيًا إلا إذا كان إدخال الدليل يملك مسارًا بالفعل، مثل endpoint لـ`TRP`. وإلا فإنه ينتهي بالحالة `COUNTERPARTY_VASP_NOT_FOUND` مع تسجيل اسم الطرف المقابل، ويمكنك إعادة الإرسال بمجرد وجود مسار، مثلاً بعد تخزين `travel_address` الخاص بالطرف المقابل في إدخال دفتر العناوين لتلك المحفظة (للأصول المدرجة ضمن [معرّفات أصول TRP](#معرّفات-أصول-trp)).

### الأسعار والترخيص

> [accordion] كم تكلفة Travel Rule، وهل تُدرج ضمن خطة KYC أو التحقق لديّ؟
>
> Travel Rule منتج منفصل قائم على الاستخدام.
> لا يُضمّ إلى التحقق من الهوية.
> يكلّف \*\*$0.02 لكل تبادل صادر يبدأ** ([الأسعار المنشورة](#الأسعار)، دون شرائح حجم، ودون مكالمة مبيعات).
>         عندما يحتاج التوجيه إلى بحث تحليلات البلوكتشين لتحديد الـ VASP المقابل، يُحتسب ذلك البحث مرة واحدة بسعر [الإسناد](#تسعير-الإسناد): بدءًا من $0.15 للاستعلام المُدار، أو \$0.02 مع مفتاح مزود موجود لديك.
> لا يُحتسب مرة أخرى إذا كانت مراقبة العملات المشفرة قد فحصت المحفظة نفسها.
> يُفوتَر التحويل الذي يقل عن حدّك، أو الذي يُسجَّل والـ Travel Rule متوقف، كفحص المعاملات؛ أما التحويلات الواردة، مثل الأرجل التي تُنشئها Didit على جانب المستفيد، فلا تُحتسب عليها رسوم Travel Rule.

> [accordion] هل سأُحاسَب مرتين عندما يعمل Travel Rule والمراقبة للعملات المشفرة معًا؟
>
> لا.
> تُفوتَر معاملة `travelRule` في سطر واحد: رسوم Travel Rule (\$0.02) عندما تبدأ تبادلاً صادرًا، وفحص المعاملات المعتاد في غير ذلك. يُحتسب بحث تحليلات البلوكتشين مرة واحدة: إذا كانت مراقبة العملات المشفرة قد فحصت محفظة الوجهة للمعاملة، فإن [الإسناد](#إسناد-تحليلات-البلوكتشين) يعيد استخدام تلك النتيجة المخزّنة دون تكلفة إضافية.
> لا تُحتسب أبدًا رسوم Travel Rule على الأرجل الواردة التي تُنشئها Didit على جانب المستفيد.

> [accordion] هل تستطيع Didit تقديم توثيق أو بيان قدرات لملف ترخيصي أو ملفي لدى الجهة التنظيمية كـ VASP؟
>
> نعم. قدرات KYT ومراقبة المعاملات، وفحص AML والعقوبات، وتقييم مخاطر المحافظ بتحليلات البلوكتشين، وقدرات Travel Rule موثّقة كلها علنًا على docs.didit.me، ويحق لك الاستشهاد بهذه الصفحات في أي ملف تنظيمي. أما بيان قدرات منتج رسمي مخصّص لتقديم محدد، مثل طلب ترخيص AIFC/AFSA أو MiCA أو أي ترخيص آخر لـ VASPs، فتواصل مع فريق حسابك في Didit بالصيغة التي تشترطها جهتك التنظيمية.

### العمليات والبيانات

> [accordion] ماذا يحدث للتحويلات التي تقل عن الحد المحدد لي؟
>
> تنتقل فوراً إلى `NOT_APPLICABLE`: لا يتم تجربة أي مسار، ولا تغادر أي بيانات هوية منصة Didit.
> تُحتسب المعاملة كفحص معاملات قياسي (Transaction Screening)، لا كرسوم Travel Rule.
> تقارن Didit الحد بالمبلغ بعد تحويله إلى العملة الافتراضية لتطبيقك.
> إذا تعذّر على Didit تحويل المبلغ، لا يُطبَّق الحد ويُجرى التبادل.
> لا يوجد حد أدنى في لائحة نقل الأموال الأوروبية (EU TFR)، لذا ينبغي لمزودي خدمات الأصول المشفّرة (CASPs) في الاتحاد الأوروبي الإبقاء على `threshold_amount` عند `0.00`.

> [accordion] ماذا لو لم يستجب الطرف المقابل أبداً؟
>
> يبقى التحويل في `AWAITING_COUNTERPARTY` حتى تنقضي `confirmation_timeout_hours`، ثم تنقله مهمة تنظيف دورية إلى `EXPIRED` وتطبّق `timeout_outcome` على المعاملة الأساسية: `HOLD` للمراجعة، أو `REJECT` للرفض، أو `PROCEED` لتركها دون تغيير. كما تعرض القاعدة الجاهزة `tr_eu_expired_review` كل حالة انتهاء على محلليك. أما الطرف المقابل الذي لا يستلم الرسالة إطلاقاً فالأمر مختلف: تعيد Didit المحاولة، وبعد المحاولة السادسة الفاشلة ينتقل التحويل إلى `COUNTERPARTY_VASP_NOT_REACHABLE` (راجع [التسليم وإعادة المحاولات](#التسليم-وإعادة-المحاولة)).

> [accordion] ليست لدى الطرف المقابل أي أدوات Travel Rule. هل يمكنني الامتثال؟
>
> نعم، وذلك عبر مسار `EMAIL`. تتلقى جهة الامتثال لدى الطرف المقابل رابط استلام لمرة واحدة، ويمكنها تأكيد التبادل أو رفضه من صفحة مستضافة دون حساب في Didit ودون مفتاح API ودون أي تكامل. أما الإيداعات التي تمّت تسويتها قبل أن يصبح أي تبادل ممكناً، فاستخدم [تسجيل Sunrise بعد الإيداع](#التسجيل-اللاحق-للإيداع).

> [accordion] كيف تعمل عمليات السحب إلى محفظة المستخدم الخاصة؟
>
> صرّح بالوجهة على أنها ذاتية الاستضافة (`payment_method.method_type: "unhosted_wallet"`). تتجاوز Didit توجيه VASP، وبدلاً من ذلك تجمع دليلاً على أن عميلك يتحكم في المحفظة: توقيع الرسالة، أو اختبار Satoshi، أو لقطة شاشة، أو إقرار ذاتي، وذلك عبر [أداة إثبات ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md). وهذا هو التزام المحافظ ذاتية الاستضافة في لائحة نقل الأموال الأوروبية (EU TFR) في صورة واجهة API.

> [accordion] هل بيانات الطرف المقابل الشخصية محمية أثناء التبادل؟
>
> نعم.
> إلى أن تتأكد ملكية المحفظة من جهتك، تُخفى البيانات الشخصية للطرف المقابل في التحويل الوارد، سواءً في كائن التحويل أو في جزء الطرف المقابل من المعاملة (راجع [بيانات الطرف المقابل المخفية](#بيانات-الطرف-المقابل-المقنّعة)).
> لا تعرض صفحات الاستلام عبر البريد الإلكتروني إلا ملخص التحويل (اسم VASP المُرسِل، والمبلغ، ومحفظة الوجهة)، ولا تعرض أبداً payload الخاصة بالأشخاص.
> تعمل تبادلات المسارات عبر HTTPS، وتقوم شبكات المسارات (`GTR`، `TRUST`، `VERIFYVASP`، `SYGNA`) إضافةً إلى ذلك بتشفير payload الخاص بـ IVMS بالمفتاح العام لـ VASP المستقبِل.

> [accordion] أنا أتتبع امتثال Travel Rule بعملياتي الخاصة. هل يمكنني تسجيله فقط؟
>
> نعم. مع تعطيل Travel Rule، يُسجَّل بشكل سلبي على المعاملة أي `travel_rule_details` ترسله، بما في ذلك `status` الذي تحدده بنفسك سواءً كان الحالي أو القديم، ولا يُستدعى أي مسار، ولا يُتفاوض على شيء. استخدم ذلك للتعبئة الرجعية أو لتشغيل عمليتك الخاصة مع الحفاظ على نظام سجل واحد.

> [accordion] كيف أختبر هذا قبل الإطلاق؟
>
> استخدم تطبيقاً في البيئة التجريبية مع تفعيل Travel Rule. تتجاوز البيئة التجريبية القواعد والفوترة وwebhook الخاصة بـ `transaction.created` و`transaction.status.updated`، وتُوجَّه كل عملية تبادل **صادرة** إلى [Didit Test VASP](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md) عبر مسار `TEST_VASP`، الذي يجيب داخل Didit بالسيناريو الذي تختاره: قبول، أو رفض، أو عدم تطابق الاسم، أو عدم الوصول، أو انتهاء المهلة، أو محفظة ذاتية الاستضافة. تتلقى webhook من نوع `travel_rule.status.updated` معلَّمة بـ `environment: sandbox`، ولا تصل أي رسالة إلى طرف مقابل حقيقي.
> أما التحويلات **الواردة**، فاطلب من VASP الاختبار إرسال تحويل إليك عبر [تشغيل تحويل وارد من Test VASP](https://docs.didit.me/ar/management-api/travel-rule/trigger-test-vasp-inbound.md)، أو سجّل واحداً باستخدام `POST /v3/travel-rule/inbound/`. يُبتّ في الحالتين استناداً إلى دفتر عناوين محافظك: `ON_HOLD`، أو `UNCONFIRMED_OWNERSHIP`، أو `COUNTERPARTY_MISMATCHED_DATA`، أو `COMPLETED` ثم `FINISHED`.
> أما التبادل بين طرفين مع تطبيق حقيقي آخر، فاستخدم تطبيقين من تطبيقاتك **في بيئة الإنتاج** على مسار `INTERNAL`: يجب أن يكون التطبيق المستقبِل قابلاً للاكتشاف، وأن يثبت سيطرته على محفظة الوجهة بتوقيع رسالة أو بإيداع تجريبي.

## الخطوات التالية

> [card] [أداة ملكية المحفظة](https://docs.didit.me/ar/transaction-monitoring/wallet-ownership-widget.md)
>
> أثبت أن العميل يتحكم في محفظة عبر التوقيع، أو اختبار Satoshi، أو لقطة شاشة، أو إقرار ذاتي.

> [card] [قابلية التشغيل البيني](https://docs.didit.me/ar/transaction-monitoring/travel-rule-interoperability.md)
>
> endpoint الموجهة للطرف المقابل التي تستخدمها VASPs الأخرى للوصول إليك: TRP، وعمليات الاستدعاء، واستلام البريد الإلكتروني، وSunrise.

> [card] [الشبكات](https://docs.didit.me/ar/transaction-monitoring/travel-rule-networks.md)
>
> ما يصل إليه كل مسار وكل شبكة اليوم، وما ينتظر عضوية.

> [card] [الاختبار في البيئة التجريبية](https://docs.didit.me/ar/transaction-monitoring/travel-rule-sandbox.md)
>
> اختبر كل نتيجة مقابل Didit Test VASP قبل الإطلاق.

> [card] [إرسال المعاملات](https://docs.didit.me/ar/transaction-monitoring/transactions.md)
>
> كيفية تضمين بيانات Travel Rule في payload الخاص بـ Create Transaction.

> [card] [مكتبة القواعد](https://docs.didit.me/ar/transaction-monitoring/rules-library.md)
>
> كتالوج القواعد الجاهزة كاملاً، بما في ذلك حزمة Travel Rule.

> [card] [webhook](https://docs.didit.me/ar/integration/webhooks.md)
>
> اشترك في travel\_rule.status.updated وفي كل عائلة أحداث أخرى.

> [card] [دليل وحدة التحكم](https://docs.didit.me/ar/transaction-monitoring/console.md)
>
> عرض حالة Travel Rule في عرض تفاصيل المعاملة.


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