Zum Hauptinhalt springen
Didit führt den Austausch von Auftraggeber- und Begünstigtendaten nach FATF und der EU-Verordnung über Geldtransfers (TFR) für Transfers virtueller Vermögenswerte durch. Das System sucht einen Kanal, der den VASP der Gegenpartei erreicht, verhandelt darüber die erforderlichen Daten, verfolgt den Austausch über einen Lebenszyklus mit 13 Zuständen und informiert Sie, sobald der Austausch abgeschlossen ist, damit Sie die Mittel On-Chain freigeben können.

Überblick

Die FATF-Travel-Rule (Empfehlung 16), in der EU als Transfer-of-Funds-Verordnung umgesetzt, verpflichtet einen sendenden Virtual Asset Service Provider (den Auftraggeber-VASP), Auftraggeber- und Begünstigtendaten zu erheben und vor der Abwicklung eines Kryptowerte-Transfers an den empfangenden VASP (den Begünstigten-VASP) zu übermitteln. Anders als in den meisten Rechtsräumen gilt die EU-TFR ohne Mindestbetrag: Jeder Krypto-Transfer fällt in den Anwendungsbereich, nicht nur Transfers oberhalb einer Meldeschwelle. Das Travel-Rule-Produkt von Didit ist ein verwalteter Austausch und nicht nur ein Datenfeld:
  • Sie reichen einen Transfer mit transaction_category: "travelRule" ein.
  • Didit probiert die Wege in fester Prioritätsreihenfolge, um den Gegen-VASP zu erreichen, führt den Austausch über den ersten Weg durch, der ihn erreicht, und gleicht den Namen des Begünstigten, sofern die Gegenseite einen zurückgibt, mit dem von Ihnen übermittelten Namen ab.
  • Erst wenn der Austausch COMPLETED erreicht, sollten Sie den Transfer on-chain übertragen.
  • Anschließend melden Sie den On-Chain-Transaktions-Hash an Didit zurück, um den Austausch als FINISHED abzuschließen.
In diesem Release sind sieben Wege verfügbar, die in strikter Prioritätsreihenfolge probiert werden. Der erste Weg, der den Gegenpart erreichen kann, gewinnt: Die Netzwerkwege (GTR, TRUST, VERIFYVASP, SYGNA) setzen auf der sendenden Seite eine Netzwerkmitgliedschaft voraus, und derzeit muss diese Ihre eigene sein. Hinterlegen Sie Ihre Mitgliedschaftsdaten in der Konsole unter Marketplace (Kategorie Travel-Rule-Netzwerke), dann laufen Ihre Transfers unter Ihrer eigenen Netzwerkidentität. Didit besitzt derzeit für keines der vier Netzwerke eine Plattformmitgliedschaft und befindet sich im Onboarding als Provider. Bis dieses Onboarding abgeschlossen ist, ist platform_available für alle vier false, der Einstellungsmodus didit (Routing über die Plattformmitgliedschaft von Didit) ist für kein Netzwerk verfügbar, und disabled_networks hat nichts, was es abzuschalten gilt. Eine eigene Mitgliedschaft, die Sie hinterlegen, hat immer Vorrang vor einer Plattformmitgliedschaft. Keine Netzwerkmitgliedschaft ist standardmäßig enthalten, auch GTR nicht. Die Aktivierung von Travel Rule aktiviert GTR, TRUST, VerifyVASP oder Sygna nicht. Prüfen Sie in Travel-Rule-Einstellungen abrufen die wirksamen networks-Modi Ihrer Anwendung und Travel-Rule-Netzwerke, um zu sehen, was jedes Netzwerk heute erreicht. Wenn alle vier unavailable melden, kann keines einen Austausch routen. Hinterlegen Sie dann Ihre eigene Mitgliedschaft unter Marketplace oder verwenden Sie einen erreichbaren Gegenpart für INTERNAL, TRP oder EMAIL. Wenn Sie eine Mitgliedschaft speichern, muss der Teilnehmercode Ihr eigener sein: Das Speichern schlägt mit 400 fehl, wenn der Code der eigene Code von Didit in diesem Netzwerk ist oder ein Code, den bereits die Mitgliedschaft einer anderen Anwendung belegt. Eine GTR-Mitgliedschaft benötigt ihren privaten ed25519-Schlüssel (Base64), also den Schlüssel, dessen öffentlicher Schlüssel im GTR-Portal registriert ist. Mit ihm werden die personenbezogenen Daten verschlüsselt, die Sie senden, und die Daten entschlüsselt, die Sie empfangen. Eine VerifyVASP-Mitgliedschaft verweist auf Ihr eigenes VerifyVASP-Enclave: Ihre URL ist die Ihres Enclaves, und ihr Token ist dasjenige, das Ihr Enclave gegenüber Didit vorlegt. Auch mit einer eigenen Mitgliedschaft routet ein Netzwerkweg einen Transfer nur dann, wenn die beneficiary_data des Transfers die ID des Gegenparts in diesem Netzwerk enthält (counterparty_gtr_vasp_code, counterparty_trust_membership_id, counterparty_verifyvasp_id oder counterparty_sygna_vasp_code), oder wenn der Verzeichniseintrag des Gegenparts diese ID für dieses Netzwerk auflistet (siehe Routen). platform_available zeigt an, ob eine Plattformmitgliedschaft konfiguriert ist, und ist keine Live-Prüfung des Netzwerkstatus. Ebenso bedeutet connected, dass Ihre Mitgliedschaftsdaten gespeichert sind und die lokale Validierung bestanden haben. Der erste Live-Austausch prüft sie dann gegen das Netzwerk. Ein Modus didit oder own garantiert weder, dass der Gegenpart erreichbar ist, noch, dass die Zustellung gelingt. Mit Ihrer eigenen Mitgliedschaft liest Didit die Antwort der Gegenpartei über GTR, VERIFYVASP und SYGNA aus der Antwort des Netzwerks oder durch Abfrage des Netzwerks alle 5 Minuten. Dadurch wird der Transfer abgeschlossen oder abgelehnt. TRUST ist nur sendend: Ein darüber gesendeter Transfer bleibt in AWAITING_COUNTERPARTY, bis confirmation_timeout_hours abgelaufen ist. Danach wechselt er zu EXPIRED, und Ihr timeout_outcome gilt. Der Empfang eines Transfers, den ein anderer VASP über ein Netzwerk an Sie sendet, ist noch nicht aktiviert. Ein Austausch über ein Netzwerk wurde mit einem Live-Netzwerk noch nicht abgeschlossen: siehe Travel-Rule-Netzwerke. Weitere Netzwerke - CODE (die koreanische Allianz), TRISA, Notabene und Veriscope - sind in der Marketplace-Konsole als Kacheln mit Zugriffsanfrage aufgeführt. Didit hat noch keine Integration mit ihnen, daher kann heute kein Transfer über sie geroutet werden. Wenn keine der sieben Rails eine Gegenpartei ermitteln kann, führt Didit vor dem Aufgeben noch einen weiteren Auflösungsschritt aus: die Zuordnung über Blockchain-Analytics. Das Ziel-Wallet wird anhand von Blockchain-Analytics-Daten abgefragt. Gehört das Wallet zu einer bekannten Börse oder einem bekannten Verwahrer, zeichnet Didit den zugeordneten VASP für den Transfer auf, fügt ihn dem Verzeichnis hinzu und führt die Rails einmal erneut mit dem neuen Namen aus. Das vollständige Verhalten und die Preise finden Sie unter Zuordnung über Blockchain-Analytics. Ein Transfer, dessen Ziel als selbstverwahrte Wallet deklariert ist, umgeht alle sieben Rails - es gibt keinen Gegenpartei-VASP, mit dem ein Austausch möglich wäre - und geht direkt zum Nachweis der Wallet-Inhaberschaft durch den Endbenutzer.
Didit betreibt außerdem die der Gegenpartei zugewandte Seite des Austauschs: öffentliche TRP-Identitäts- und Anfrage-Endpoints, die andere VASPs aufrufen, um Sie zu erreichen, Callback-Endpoints und den E-Mail-Abholablauf. Diese rufen Sie nie selbst auf - sie sind verwaltete Infrastruktur. Die Seite Travel-Rule-Interoperabilität dokumentiert aber jeden einzelnen davon, damit Gegenpartei-VASPs sich mit Ihnen verbinden können. Mit Travel Rule interagieren Sie nur über die auf dieser Seite beschriebenen /v3/-Endpoints.

Was beim Einreichen eines Transfers ausgeführt wird

Die Prüfungen laufen innerhalb des einen POST /v3/transactions/-Aufrufs ab: Bis Sie die Antwort erhalten, ist das Screening abgeschlossen, der Transfer gespeichert und die Regeln sind ausgewertet. Der Austausch selbst beginnt nach der Antwort: Didit wählt die Rail und kontaktiert die Gegenpartei außerhalb Ihrer Anfrage, sodass kein Netzwerk und keine Gegenpartei das Anlegen verlangsamen oder zum Scheitern bringen können. Jede spätere Statusänderung kommt als travel_rule.status.updated-Webhook, der die Rail nennt. Das Transfer-Objekt, das die Travel-Rule-Transfer-Endpoints zurückgeben, enthält ein delivery-Feld, das zeigt, ob die Nachricht angekommen ist. Es gibt keine Pipeline, die Sie abfragen müssten; die asynchronen Teile sind der Austausch, die Antwort der Gegenpartei und alle Aktionen des Endnutzers. Schritt für Schritt:
  1. Validierung und Zuordnung des Subjekts. Die Payload wird validiert. Eine transaction_id, die in Ihrer Anwendung bereits verwendet wurde, wird mit 400 abgelehnt. Wenn zwei Anfragen mit derselben ID gleichzeitig eintreffen, erhält eine davon 409. Das subject wird über vendor_data mit Ihrem Benutzer- oder Unternehmensprofil verknüpft, damit der Transfer für das Monitoring auf diesem Profil erscheint. Ein auf einer Sperrliste stehendes Subjekt oder ein gesperrter vendor_data-Wert der Gegenpartei wird mit 400 abgelehnt, und es wird keine Transaktion angelegt. Auf Sperrlisten stehende Wallets, Bankkonten, IP-Adressen und Geräte werden in Schritt 6 geprüft und führen dort zur Ablehnung der Transaktion, nachdem das Routing gelaufen ist.
  2. Geräte- und Netzwerkanreicherung. IP-Adressen der Parteien werden geo-angereichert. Jeder Gerätekontext (automatisch bei der SDK-Übermittlung) wird in den Geräte-Graphen normalisiert, denselben Graphen, den auch KYC-Sitzungen füllen. So funktioniert „nach Gerät verknüpft“ über Onboarding und Transaktionen hinweg.
  3. Krypto-Screening. Bei Krypto-Transfers mit aktiviertem Monitoring wird die relevante Wallet (oder der On-Chain-Hash) vor jedem Austausch gegen Blockchain-Analysen geprüft: Sanktionsrisiko, Nähe zu Mixern, gestohlene Gelder. Siehe Krypto- und Wallet-Screening.
  4. Travel-Rule-Transfer. Die Austausch-Engine prüft den Schwellenwert und berücksichtigt eine Erklärung zur selbstverwahrten Wallet. Danach speichert sie den Transfer: NOT_APPLICABLE unterhalb Ihres Schwellenwerts, UNCONFIRMED_OWNERSHIP für eine erklärte selbstverwahrte Wallet, COMPLETED, wenn die andere Wallet Ihre eigene verifizierte Wallet ist, und sonst AWAITING_COUNTERPARTY, wobei die Rail dann noch leer ist. Jede Statusänderung reiht ein travel_rule.status.updated-Ereignis in die Warteschlange ein. Didit sendet es nach dem transaction.created der Transaktion (Schritt 7).
  5. Erzeugung der Wallet-Eigentumsprüfung. Wenn der Transfer einen Nachweis der Kontrolle durch den Endnutzer erfordert und auto_wallet_verification aktiviert ist, wird eine Widget-Sitzung zur Wallet-Eigentumsprüfung erzeugt und in action_required zurückgegeben.
  6. Regelauswertung. Jede aktive Regel wird ausgeführt. Das EU-TFR-Regelpaket reagiert auf den Transferstatus aus Schritt 4, Ihre eigenen Regeln sehen die Screening-Ergebnisse aus Schritt 3. Eine Regel kann die Transaktion zurückhalten (IN_REVIEW), sie ablehnen oder eine Step-up-Verifizierung verlangen (AWAITING_USER).
  7. Abrechnung und Benachrichtigung. Eine ausgehende Transaktion wird über eine Position abgerechnet: den Travel-Rule-Posten, wenn sie einen Austausch gestartet hat, andernfalls Transaction Screening. Ein eingehender Transfer fällt keine Gebühr an, und eine Sandbox-Anwendung wird nie berechnet. Die Antwort wird zurückgegeben, und transaction.created wird an Ihre Webhook-Ziele ausgelöst, gefolgt von den travel_rule.status.updated-Ereignissen aus Schritt 4.
  8. Routing nach der Antwort. Didit durchläuft die sieben Rails in Prioritätsreihenfolge. Wenn keine Rail eine Lösung liefert, identifiziert die Zuordnung über Blockchain-Analysen die Gegenpartei, und die Rails werden ein einziges Mal erneut durchlaufen. Über die erste erreichbare Rail wird der Austausch abgewickelt: Der Transfer bleibt auf dieser Rail im Status AWAITING_COUNTERPARTY, während die Gegenpartei antwortet. Er wird sofort abgeschlossen, wenn eine INTERNAL-Gegenpartei gefunden wird (COMPLETED oder COUNTERPARTY_MISMATCHED_DATA). Er wird COUNTERPARTY_VASP_NOT_FOUND, wenn keine Rail die Gegenpartei erreicht. Jede Änderung löst travel_rule.status.updated aus, und Ihre Regeln laufen erneut, wenn sich der Status oder die Rail geändert hat. Ein Transfer, den das Routing in COUNTERPARTY_VASP_NOT_FOUND belässt, erhält an dieser Stelle seine Sitzung zur Wallet-Eigentumsprüfung (wenn auto_wallet_verification aktiviert ist). Lesen Sie sie mit Transaktion abrufen aus action_required der Transaktion aus.

Wie jeder Schritt Ihre Pflichten erfüllt

Hinweis zum Testen. Sandbox-Anwendungen überspringen die Regelauswertung und die Abrechnung und senden keine transaction.created- oder transaction.status.updated-Webhooks. Sandbox-Transaktionen bleiben APPROVED, außer wenn ein ablaufender Travel-Rule-Transfer Ihr timeout_outcome anwendet. Es wird nichts berechnet. Die Travel-Rule-Austausch-Engine läuft auf Sandbox-Anwendungen, wenn Travel Rule aktiviert ist, und zwar gegen nur eine Gegenpartei: Jeder ausgehende Austausch geht an die Didit Test VASP auf der Rail TEST_VASP. Sie antwortet innerhalb von Didit mit dem von Ihnen gewählten Szenario. Der Transfer wird also abgeschlossen, abgelehnt, weist nicht übereinstimmende Daten auf, ist nicht erreichbar, läuft ab oder wartet auf die Wallet-Eigentumsprüfung. Keine Compliance-Nachricht erreicht jemals eine echte Gegen-VASP, und travel_rule.status.updated-Webhooks werden mit environment: sandbox zugestellt. Eingehend: Die Test-VASP kann Ihnen einen Transfer senden (Eingehenden Test-VASP-Transfer auslösen). Die Registrierung (POST /v3/travel-rule/inbound/) wird gegen Ihr Wallet-Adressbuch abgeglichen, wie bei einer Live-Anwendung: ON_HOLD, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_MISMATCHED_DATA oder COMPLETED, danach FINISHED. Siehe Travel Rule in der Sandbox testen.

Lebenszyklus

Jeder Transfer hat einen status aus 13 Werten. Der Austausch beginnt im Normalfall mit AWAITING_COUNTERPARTY, bei einem Betrag unter Ihrem threshold_amount oder wenn eine Lightning-Zahlungsanfrage keinen Empfänger nennt (siehe Lightning), mit NOT_APPLICABLE. Ist das Ziel als selbstverwahrte Wallet deklariert, beginnt er mit UNCONFIRMED_OWNERSHIP. Er endet in einem der Endzustände FINISHED, CANCELLED oder EXPIRED. Der Transfer hat eine eigene Zustandsmaschine, getrennt vom Prüfstatus der zugrunde liegenden Transaktion. Ein Austauschstatus ändert den Transaktionsstatus nicht von selbst, mit einer Ausnahme: Bei einem Ablauf wird Ihr konfiguriertes timeout_outcome angewendet (oder eine Sunrise- oder Nicht-Antwort-Richtlinie, sofern eine zutrifft). Ihre Regeln werden stattdessen bei jedem Übergang erneut ausgeführt. Dadurch können die EU-TFR-Regeln oder jede Regel mit Bezug auf travel_rule_status die Transaktion verschieben, etwa auf IN_REVIEW. Eine Transaktion, die einen Nachweis der Wallet-Kontrolle durch den Endnutzer erfordert, erhält einen Block action_required, ihr status bleibt jedoch so, wie Ihre Regeln ihn belassen haben. Lesen Sie den Austauschstatus aus travel_rule.status, die Entscheidung über Freigabe, Zurückhalten oder Ablehnung aus dem eigenen status der Transaktion. Jeder Übergang (und jeder passiv gemeldete Status) wird außerdem in die benutzerdefinierten Werte der Transaktion gespiegelt, damit Regeln darauf basieren können bzw. den Wert als Auslöser verwenden können: custom_values.travel_rule_status (kanonischer Status), custom_values.travel_rule_rail (die Rail, über die der Austausch lief; leer, bis eine Rail ausgewählt ist) und custom_values.travel_rule_regime (abgeleitet aus dem jurisdiction Ihrer Einstellungen: SG wird zu singapore, GB zu uk, jeder Ländercode eines EU- oder EWR-Mitglieds wie DE oder FR zu eu; nicht zugeordnete Codes werden in Kleinbuchstaben übernommen, z. B. US zu us. Ein props.travel_rule_regime, das Sie selbst übermitteln, hat immer Vorrang vor dem abgeleiteten Wert).
Broadcasten Sie niemals vor COMPLETED. Die Freigabe von Mitteln on-chain, während ein Transfer AWAITING_COUNTERPARTY, UNCONFIRMED_OWNERSHIP oder sich in einem Abweichungs- oder Ablehnungsstatus befindet, untergräbt den Zweck des Austauschs. Machen Sie Ihren Broadcast-Schritt von status == "COMPLETED" abhängig, und rufen Sie dann PATCH .../travel-rule/ mit der resultierenden payment_txn_id auf, um auf FINISHED zu wechseln.
Die Übergänge auf einen Blick (CANCELLED ist zusätzlich aus jedem nicht endgültigen Status mit action: "cancel" erreichbar):

Zustellung und Wiederholungsversuche

Didit sendet jede Nachricht, die ein Transfer senden muss, außerhalb der Anfrage, die sie ausgelöst hat, und wiederholt den Versuch, bis die Gegenseite sie annimmt. Das Transferobjekt, das von Abschließen, Abbrechen oder Erneut senden, Eigentümerschaft bestätigen und Sunrise-Registrierung zurückgegeben wird, enthält die neueste davon im Feld delivery, ebenso das eingebettete Objekt travel_rule der Transaktion; es ist null, wenn der Transfer nie eine erfordert hat. Ein Fehler, von dem sich das Netzwerk möglicherweise noch erholen kann (keine rechtzeitige Antwort, eine fehlgeschlagene Verbindung, HTTP 408, 429 oder 5xx), wird nach 30 Sekunden, 2 Minuten, 10 Minuten, 30 Minuten und 1 Stunde wiederholt. Wenn eine erste Nachricht endgültig fehlschlägt - das Netzwerk hat sie abgelehnt, oder auch der sechste Versuch ist gescheitert -, wechselt der Transfer zu COUNTERPARTY_VASP_NOT_REACHABLE, wobei last_error in seiner timeline steht, und Sie können ihn mit action: "resend" erneut versuchen. Jede andere Nachricht, die endgültig fehlschlägt, wird in der timeline vermerkt. delivery ersetzt nie den status des Transfers: Den Stand des Austauschs lesen Sie aus status, und mit delivery sehen Sie, warum ein Transfer noch wartet.

Veraltete Statuswerte

Wenn Sie vor diesem Release bereits travel_rule_details.status übermittelt haben, funktionieren diese Werte weiterhin und werden automatisch zugeordnet. camelCase-Schreibweisen eines beliebigen Status (zum Beispiel counterpartyVaspNotFound) werden ebenfalls akzeptiert, sowohl bei der Übermittlung als auch in Bedingungswerten einer Regel, und auf die kanonische Form normalisiert:

Einrichtung

Konfigurieren Sie Ihr VASP-Profil und die Verhandlungsrichtlinie einmalig pro Anwendung mit GET/PUT /v3/travel-rule/settings/.
PUT ist ein partielles Update. Senden Sie nur die Felder, die Sie ändern möchten.

Strenge des Namensabgleichs

Modi der Eigentumsvalidierung

ownership_validation_mode legt fest, wie viel Nachweis für das Eigentum an einer Wallet erforderlich ist, bevor sich eine Transaktion darauf stützt: Eine Wallet wird pro Endbenutzer gespeichert, sobald sie verifiziert ist. In FULL und SIMPLIFIED verwendet eine spätere Transaktion sie nur dann erneut, wenn ein für diese Transaktion nach dem Modus akzeptierter Nachweis sie stützt. Wenn inbound_auto_accept keine Adressbuch-Wallet zum Abgleich findet, identifiziert eine Krypto-Wallet, die Sie bei genau einem Endbenutzer in dessen Transaktionen erfasst haben, den Inhaber. Didit fügt diese Wallet dem Adressbuch des Endbenutzers als Ihre Selbstauskunft hinzu und verifiziert sie, außer im Modus FULL. Didit fügt niemals eine Wallet hinzu, die das Adressbuch bereits unter einem anderen Namen derselben Chain führt (eth und ethereum), auch keine, die als Wallet eines anderen VASP erfasst wurde. Die Adressprüfungen, die andere VASPs vor dem Senden durchführen (über GTR, Sygna und VerifyVASP), folgen ebenfalls dem Modus: Unter FULL wird eine Wallet, die der Endbenutzer nur selbst angegeben hat, nicht als Ihre gemeldet.

Datenweitergabe

data_sharing_fields legt fest, welche Felder Didit über Ihre eigenen Benutzer an die Gegenpartei übermittelt, getrennt für natürliche Personen und Unternehmen:
  • Natürliche Personen können name, wallet_address, address, national_id, customer_identification, date_of_birth und place_of_birth freigeben. Unternehmen teilen die ersten fünf.
  • name und wallet_address werden immer übermittelt.
  • Ein Entitätstyp, den Sie nie gewählt haben, gibt jedes Feld frei. Eine leere Liste ist ebenfalls eine Wahl: Sie gibt nur den Namen und die Wallet frei.
  • Ein PUT wird pro Entitätstyp zusammengeführt, sodass das Senden von individual die gespeicherte Auswahl für company unberührt lässt.
  • Eine Auswahl, die die Pflichten des Auftraggebers nach dem Regime Ihrer jurisdiction (EU TFR oder FATF Recommendation 16) nicht erfüllen kann, wird einschließlich einer leeren Liste mit 400 abgelehnt. Die Fehler stehen unter data_sharing_fields, geschlüsselt nach Entitätstyp.

Abgleich pro Feld

matching_rules legt fest, wie streng jedes Feld der Daten der Gegenpartei mit Ihren eigenen Daten verglichen wird:
Jeder Wert ist NONE, STRICT, CONTAINS, DEFAULT oder FUZZY. Standardwerte: name folgt name_matching_strictness, date_of_birth und address sind NONE, und account ist STRICT. Ein weggelassenes Feld behält seinen Standardwert. Ein Feld, das der Entitätstyp nicht vergleicht (ein Unternehmen hat kein date_of_birth), wird mit 400 abgelehnt.

Schwellenwerte nach Rechtsraum

threshold_amount gibt es, weil der Anwendungsbereich der Travel Rule je nach Aufsichtsbehörde variiert. Didit verwendet standardmäßig 0.00 – die EU-Position –, sodass für jede Transaktion Daten ausgetauscht werden, sofern Sie den Wert nicht bewusst anheben: Legen Sie threshold_amount auf den Wert Ihrer Aufsichtsbehörde fest. Transaktionen darunter werden zu NOT_APPLICABLE aufgelöst, ohne dass Identitätsdaten ausgetauscht werden. Schwellenwerte ändern sich. Bestätigen Sie den aktuellen Wert mit Ihrem Compliance-Rechtsberater, statt diese Tabelle als Rechtsberatung zu behandeln.

IVMS-101-Datenmodell

Der Industriestandard für die Daten, die im Rahmen der Travel Rule ausgetauscht werden, ist IVMS 101 (interVASP Messaging Standard). travel_rule_details.originator_data und travel_rule_details.beneficiary_data sind Personen-Payloads im IVMS-101-Stil. Didit verpackt sie in den nativen Umschlag jeder Rail: Die TRP-Rail tauscht IVMS101-Blöcke aus (ivms101.2023, angegeben im Feld ivms_version des Transfers), die Sygna-Rail deren ECIES-verschlüsselte IVMS-Variante und die Rails GTR, TRUST und VERIFYVASP ihre eigenen verschlüsselten Umschläge. So erreicht eine einzige Payload-Struktur jede Gegenpartei in dem Format, das ihr Protokoll erwartet. Didit liest diese Schlüssel aus jeder Personen-Payload, wenn es die IVMS-101-Nachricht erstellt: first_name und last_name (oder ein einzelnes name bzw. full_name), date_of_birth, place_of_birth, residence_country (oder country), vendor_data (oder customer_identification) und wallet_address. Zwei praktische Regeln:
  • Lateinische Schrift. IVMS 101 verlangt Werte in lateinischer Schrift. Transliterieren Sie Namen, die in einer anderen Schrift geschrieben sind. Der Namensabgleich von Didit vergleicht normalisierte Tokenmengen, daher scheitert ein Austausch nicht an Unterschieden bei Reihenfolge oder Groß- und Kleinschreibung. Unterschiedliche Schriften auf beiden Seiten führen allerdings zum Fehler.
  • Verifizierte Daten senden. Wenn die Person, auf die sich vendor_data bezieht, ein Benutzer mit einer genehmigten KYC-Verifizierung bei Didit ist, überträgt Didit die verifizierte Identität und nicht die Werte, die Sie eingegeben haben. Siehe Verifizierte Daten und Herkunft. Für jede andere Person überträgt Didit genau das originator_data, das Sie senden. Erstellen Sie es deshalb aus der Identität, die Sie beim Onboarding verifiziert haben, und nicht aus einem nicht verifizierten Formularfeld. Genau das verlangt die FATF mit der Formulierung „required and accurate originator information“. Auf der INTERNAL-Rail erhält die Anwendung des Begünstigten zusätzlich das subject, das Sie gesendet haben (Name, vendor_data, Geburtsdatum, Land und Adresse), als Gegenpartei ihrer eingehenden Transaktion.

Verifizierte Daten und Herkunft

Wenn die betroffene Person eines Transfers einer Ihrer Benutzer ist, also eine Person mit einer genehmigten KYC-Verifizierung, erstellt Didit diese Seite des Austauschs aus den verifizierten Daten:
  • der Auftraggeber eines ausgehenden Transfers, den Sie mit POST /v3/transactions/ anlegen;
  • der Begünstigte eines eingehenden Transfers, den Sie mit POST /v3/transactions/ melden, oder mit POST /v3/travel-rule/inbound/, wenn das holder_vendor_data der zugeordneten Wallet diesen Benutzer nennt.
Bei POST /v3/transactions/ gilt beides für eine Transaktion, deren transaction_category travel_rule ist, während Travel Rule aktiviert ist. Die verifizierten Namen, Geburtsdatum und Geburtsort, Dokumentnummer und Dokumenttyp, Adresse und Wohnsitzland (abgeleitet aus dieser Adresse) haben Vorrang vor den Werten, die Sie gesendet haben. Ein Feld, das die Verifizierung nicht enthält, behält Ihren Wert. Gleiches gilt für eine vollständige Adresse, die Sie gesendet haben, wenn die verifizierte Adresse nicht vollständig genug für die Übermittlung ist. Die metadata des Transfers im eingebetteten Objekt travel_rule der Transaktion halten fest, woher jedes Feld stammt und wo sich Ihre Werte unterschieden haben:
*_provenance ordnet jedem Feld verified oder caller zu. *_verified_differences listet jedes Feld auf, in dem Sie einen Wert gesendet haben, der vom verifizierten Wert abweicht. Dabei bleiben Groß- und Kleinschreibung, Leerzeichen sowie zwei- oder dreistellige Ländercodes unberücksichtigt. Solange die Daten eines eingehenden Transfers maskiert sind, werden die Abweichungen weggelassen. Didit berechnet beide Werte selbst. Kopien dieser Schlüssel oder von name_match, die Sie in travel_rule_details.metadata senden, werden deshalb verworfen.

IVMS 101 direkt senden

Neben den flachen Objekten originator_data und beneficiary_data akzeptieren travel_rule_details (bei POST /v3/transactions/) und POST /v3/travel-rule/inbound/ echtes IVMS 101:
  • einen Block originator und einen Block beneficiary, wobei originatorPersons bzw. beneficiaryPersons eine naturalPerson oder eine legalPerson sowie accountNumber enthalten;
  • dieselben Blöcke innerhalb eines Objekts ivms101 (oder IVMS101);
  • eine IVMS-101-Person oder einen ganzen Block als originator_data oder beneficiary_data.
Jede Seite nimmt genau eine Person auf: eine naturalPerson oder eine legalPerson, wodurch die Gegenpartei zu einem Unternehmen wird. Ein nicht leeres flaches originator_data oder beneficiary_data hat Vorrang vor einem Block für dieselbe Seite.
Ein fehlerhafter Block wird mit 400 beantwortet und unter seinem Pfad angegeben, zum Beispiel {"travel_rule_details": {"originator.originatorPersons": ["must be a non-empty list of originator persons."]}}. Bei POST /v3/travel-rule/inbound/ stehen dieselben Schlüssel auf oberster Ebene, unter ivms101., wenn Sie den Wrapper verwendet haben.

Erforderliche Daten nach Regelwerk

Solange Travel Rule aktiviert ist, muss ein ausgehender Transfer ab Ihrem Schwellenwert die Angaben enthalten, die sein Regelwerk verlangt, andernfalls antwortet er mit 400. Geprüft werden nur die Parteien, deren Daten Sie gesendet haben, und verifizierte Daten zählen für den Auftraggeber. Die Fehler stehen unter travel_rule_details.originator_data bzw. travel_rule_details.beneficiary_data, zum Beispiel "EU TFR requires the originator name." oder "FATF Recommendation 16 requires the beneficiary wallet address.": Für den Auftraggeber liest die Prüfung die Felder, die Ihre Anwendung in data_sharing_fields freigibt, denn nur diese Felder überträgt eine Rail. Der Begünstigte wird so geprüft, wie Sie ihn gesendet haben. Erfüllt ein Transfer das Regelwerk nur mit einem Feld, das Sie nicht freigeben, nennt das 400 die Anforderung des Regelwerks und anschließend die Felder, die Ihre Einstellungen freigeben. Die amtliche Dokumentnummer ist national_id (oder document_number), die Kundenidentifikationsnummer ist customer_identification (oder vendor_data), und das Geburtsdatum ist date_of_birth. Ein leeres beneficiary_data.wallet_address wird vor der Prüfung aus counterparty.payment_method.account_id gefüllt. Eine UTXO-Auszahlung, deren Empfänger-Output Didit aus travel_rule_details.utxo abgeleitet hat, gilt als Angabe der Adresse. Ein Lightning-Transfer, auf den die Travel Rule nicht zutrifft, wird nicht geprüft.

Travel Addresses

Eine Travel Address ist eine kompakte, kodierte Zeichenfolge, die auf den eingehenden TRP-Anfrage-Endpoint einer VASP zeigt. Sie gibt niemals eine rohe URL oder eine Wallet-Adresse preis. Sobald Travel Rule aktiviert ist, leitet Didit Ihre eigene travel_address ab (in den Einstellungen schreibgeschützt abrufbar), damit Sie sie an andere VASPs weitergeben können, die Sie über die TRP-Schiene erreichen. Jede Ihrer Wallets im Adressbuch erhält außerdem eine wallet-spezifische receiving_travel_address: Eine Anfrage, die an sie gesendet wird, nennt diese Wallet, sodass Didit sie nicht über Kontonummer oder Kontoinhabernamen finden muss. Der öffentliche TRP-Host von Didit beantwortet derzeit noch keine Anfragen anderer VASPs. Der Empfang über TRP ist daher erst verfügbar, wenn dies der Fall ist: siehe Travel-Rule-Netzwerke. Wenn Sie die Travel Address einer Gegenpartei kennen, speichern Sie sie im Eintrag im Wallet-Adressbuch der Zielwallet. Didit leitet Transaktionen an diesen Begünstigten dann direkt über TRP, statt auf E-Mail zurückzugreifen. Didit validiert die Travel Addresses, die Sie in einem Eintrag im Wallet-Adressbuch speichern oder in originating_vasp senden: Jede muss mit ta beginnen und sich in eine Anfrage-URL mit t=i dekodieren lassen. Ein Platzhalter wie ta... gibt daher 400 zurück. Ein beneficiary_data.travel_address in einer Transaktion wird nicht validiert. Lässt er sich nicht dekodieren, wird die TRP-Schiene übersprungen. Die Kodierung ist Base58Check mit dem Präfix ta: Host und Pfad des Endpoints (der immer das Abfrage-Paar t=i enthält) plus eine vierbytige Doppel-SHA-256-Prüfsumme, base58-kodiert. Eine echte Adresse sieht daher so aus und hat etwa 100 Zeichen:
Wenn Didit eine Travel Address validiert, gibt ein Wert, der keine korrekt aufgebaute Adresse mit gültiger Prüfsumme ist, 400 mit "Invalid travel address." zurück. Nehmen Sie eine echte Adresse aus Ihrer eigenen Einstellungsantwort oder direkt von der Gegenpartei.

Testen ohne Netzwerk-Zugangsdaten

Sie benötigen keine Mitgliedschaft bei GTR, TRUST, VerifyVASP oder Sygna, um die Pfade ohne Mitgliedschaft zu testen. Sie benötigen weiterhin einen Didit-API-Schlüssel für die getestete Anwendung.
  • Sandbox ausgehend: Senden Sie eine travelRule-Transaktion aus einer Sandbox-Anwendung. Nach der Schwellenwertprüfung und den Prüfungen selbstverwahrter Wallets beantwortet der Didit Test VASP sie innerhalb von Didit mit dem Szenario, das Sie über die Wallet oder den Namen des Begünstigten auswählen: akzeptieren, ablehnen, Namensabweichung, nicht erreichbar, Zeitüberschreitung oder selbstverwahrte Wallet. Es wird weder ein Netzwerk kontaktiert noch eine E-Mail versendet, und kein anderer Didit-Kunde erhält etwas.
  • Sandbox eingehend: Lassen Sie den Test-VASP Ihnen mit Eingehende Transaktion des Test-VASP auslösen eine Transaktion senden, oder registrieren Sie selbst eine mit Eingehende Travel-Rule-Transaktion registrieren. Testen Sie eine unbekannte Wallet, eine nicht verifizierte Wallet, eine Abweichung beim Namen des Begünstigten und eine verifizierte, übereinstimmende Wallet. Mit diesen Tests werden echte Entscheidungen für eingehende Transaktionen getroffen, ohne ein Netzwerk zu kontaktieren.
  • Zwei kontrollierte Live-Anwendungen: Verwenden Sie die Schiene INTERNAL zwischen zwei Ihrer eigenen Live-Anwendungen. Die empfangende Anwendung ist auffindbar und weist die Kontrolle über die Zielwallet mit einer signierten Nachricht oder einer Testeinzahlung nach. Alternativ können Sie eine kontrollierte TRP-Gegenpartei verwenden, um einen Austausch zwischen zwei Parteien ohne kommerzielle Netzwerk-Zugangsdaten zu testen. Live-Anwendungen können übliche Gebühren und Benachrichtigungen auslösen. Verwenden Sie deshalb nur Testidentitäten und Gegenparteien, die Sie kontrollieren.
Siehe Travel-Rule-Tests in der Sandbox für jedes Szenario und dessen genaues Ergebnis. Erfolgreiche Sandbox- oder lokale Protokolltests bestätigen weder die Zugangsdaten noch die Mitgliedschaft oder die Interoperabilität in der Produktionsumgebung eines kommerziellen Netzwerks. Dafür sind eine autorisierte Netzwerk-Sandbox oder ein kontrollierter Live-Austausch mit gültigen Zugangsdaten für die Mitgliedschaft erforderlich.

Einen Transfer senden

Nehmen Sie den Transfer über POST /v3/transactions/ auf, indem Sie transaction_category auf travelRule (oder travel_rule) setzen und ein Objekt travel_rule_details (Alias: travelRule) anhängen. Der Block travel_rule_details selbst ist optional. Sobald Sie ihn anhängen, ist travel_rule_details.status jedoch erforderlich: Ein Block ohne dieses Feld gibt 400 zurück. Wenn Travel Rule für Ihre Anwendung aktiviert ist, ignoriert Didit den von Ihnen gesendeten status-Wert und steuert den Austausch selbst:
  1. Liegt der Betrag unter Ihrem konfigurierten threshold_amount, wird der Transfer sofort auf NOT_APPLICABLE gesetzt, und es wird nichts verhandelt.
  2. Deklariert die Zahlungsmethode der Gegenpartei das Ziel als selbstverwahrte Wallet (payment_method.method_type: "unhosted_wallet"), wird kein Übertragungsweg versucht. Der Transfer geht direkt in UNCONFIRMED_OWNERSHIP, und das Widget zur Wallet-Eigentumsprüfung wird automatisch erstellt (siehe Deklarierte selbstverwahrte Wallets).
  3. Andernfalls werden die Übertragungswege in Prioritätsreihenfolge ausgeführt, und der erste Weg, der die Gegenpartei erreichen kann, übernimmt den Austausch:
    • INTERNAL: Genau ein anderer Didit-Kunde hält einen Nachweis einer signierten Nachricht oder einer Testeinzahlung für beneficiary_data.wallet_address, der erstellt wurde, nachdem die Wallet zuletzt den Besitzer gewechselt hat. Ihre eigene Anwendung zählt nie. Wenn Ihr Endbenutzer im Widget zur Wallet-Eigentumsprüfung ein Mitglied des Didit-Netzwerks gewählt hat, zählt nur der Nachweis dieses Mitglieds. Die Anwendung dieses Kunden ist live (nicht Sandbox), hat Travel Rule aktiviert und is_discoverable gesetzt und ist das VASP, das Sie bei der Angabe von counterparty_vasp_lei oder counterparty_vasp_name genannt haben. Eine Wallet, die nur selbst deklariert ist, durch einen Screenshot belegt ist, nicht verifiziert ist oder nur im Adressbuch steht, erhält über INTERNAL niemals etwas.
    • TRP: Für das Asset des Transfers gibt es für das Transfernetzwerk eine Zuordnung zu einem Digital Token Identifier (siehe TRP-Asset-Kennungen), und die Payload enthält beneficiary_data.travel_address. Alternativ speichert der eigene Adressbucheintrag des Ziels eine solche Adresse, oder die Gegenpartei lässt sich im Verzeichnis auflösen (über counterparty_vasp_lei oder counterparty_vasp_name) und hat einen TRP-Endpoint.
    • GTR, TRUST, VERIFYVASP, SYGNA: Sie haben Ihre eigene Mitgliedschaft für dieses Netzwerk unter Marketplace verbunden, und die Gegenpartei wird auf eine Netzwerk-ID aufgelöst (explizites Feld oder Verzeichniseintrag, siehe Felder zur Auflösung der Gegenpartei). Didit besitzt in diesen Netzwerken noch keine Plattformmitgliedschaft, da es sich derzeit als Anbieter im Onboarding befindet. Daher ändert disabled_networks an diesem Schritt derzeit nichts.
    • EMAIL: beneficiary_data.counterparty_vasp_email wurde angegeben, oder counterparty_vasp_name wird auf einen Verzeichniseintrag mit einer Compliance-E-Mail aufgelöst.
  4. Kann kein Übertragungsweg die Gegenpartei auflösen, führt Didit die Ermittlung der Gegenpartei aus. Ist vasp_attribution_enabled aktiviert, gehört dazu auch die Blockchain-Analyse-Attribution: Die Ziel-Wallet wird dem zugehörigen VASP zugeordnet. Der zugeordnete Name wird in beneficiary_data.counterparty_vasp_name (falls leer) und im Verzeichnis eingetragen, und die Übertragungswege werden einmal erneut ausgeführt. Eine Wallet, die einem VASP zugeordnet ist, dessen Verzeichniseintrag einen TRP-Endpoint, eine Netzwerk-ID oder eine Compliance-E-Mail enthält, wird so bereits beim zweiten Durchlauf geroutet.
  5. Bleibt die Gegenpartei unaufgelöst, wechselt der Transfer in COUNTERPARTY_VASP_NOT_FOUND. Bei ausgehenden Transfers erstellt Didit automatisch das Widget zur Wallet-Eigentumsprüfung (wenn auto_wallet_verification aktiviert ist), damit der Transfer trotzdem als Transfer an eine selbstverwahrte Wallet abgeschlossen werden kann. Sie können das Routing später mit action: "resend" erneut ausführen, sobald Sie bessere Daten zur Gegenpartei haben.
Die Schritte 1 und 2 finden innerhalb der Anfrage statt. Die Schritte 3 bis 5 laufen direkt nach der Antwort ab: Der Transfer kommt mit AWAITING_COUNTERPARTY und protocol: null zurück, und jedes Ergebnis wird als travel_rule.status.updated-Webhook übermittelt.

TRP-Asset-Kennungen

TRP benennt das übertragene Asset anhand seines Digital Token Identifiers (DTI) nach ISO 24165. Ein DTI identifiziert einen Token auf einer einzelnen Blockchain. Daher hat ein Multi-Chain-Token pro Netzwerk einen eigenen DTI. Didit sendet Transfers für diese Assets über TRP: Die USDC-Kennungen sind diejenigen, die der Emittent des Tokens in seinem MiCA-White-Paper veröffentlicht. Bei einem Multi-Chain-Token muss der Transfer sein Netzwerk in transaction_details.crypto_params.crypto_chain angeben (zum Beispiel CELO, BASE, OP, ARB oder POL). Ohne Netzwerk oder bei einem Netzwerk ohne Zuordnung wird der Transfer nicht über TRP gesendet. Didit versucht dann die übrigen Übertragungswege: zuerst die Interoperabilitätsnetzwerke, danach E-Mail. USDT ist noch nicht zugeordnet. Ein Token ohne DTI-Zuordnung, etwa ein eigener Stablecoin eines Unternehmens, benötigt einen DTI. Dafür muss der Emittent bei der Registrierungsstelle nach ISO 24165 einen DTI registrieren, und zwar einen pro Token und pro Blockchain. Sobald die DTIs vorliegen, kontaktieren Sie den Didit-Support mit jedem DTI, seiner Blockchain und den Dezimalstellen des Tokens. Didit ergänzt dann die Zuordnung. Eingehende TRP-Anfragen, die einen zugeordneten, chainspezifischen DTI enthalten, werden mit der Währung des Tokens, dem Betrag unter Verwendung der Dezimalstellen des Tokens und dem Netzwerk erfasst.

Ermittlung der Gegenpartei

Ein Transfer, der nur eine Adresse enthält, erreicht seine Gegenpartei immer dann, wenn jemand sie identifizieren kann. Bevor ein ausgehender Transfer als nicht routbar gilt, fragt Didit in dieser Reihenfolge ab. Es hält beim ersten Schritt an, der einen VASP mit einer Route benennt: Das Feld discovery des Transfers listet jeden Schritt auf, der gelaufen ist, mit seinem outcome (match, miss oder skipped), einem maschinenlesbaren reason, dem vasp und der rail, die er gefunden hat, sowie einem Zeitstempel. Ein VASP, den Sie oder der Endbenutzer ausgewählt haben, hat Vorrang vor jedem automatischen Schritt: Die Erkennung ersetzt ihn nie durch eine eigene Vermutung. Wenn kein Schritt eine Gegenpartei nennt, wechselt der Transfer zu COUNTERPARTY_VASP_NOT_FOUND, oder zu COUNTERPARTY_VASP_NOT_REACHABLE, wenn ein VASP benannt wurde, aber keine seiner Routen für Ihre Anwendung verfügbar ist. Der Transfer enthält dann einen reason (awaiting_end_user, no_directory_match, directory_match_no_route oder picked_member_without_proven_wallet, wenn das vom Endbenutzer ausgewählte Mitglied die Wallet nicht nachgewiesen hat) sowie eine Liste next_actions: Bei den Aktionen, die der Endbenutzer ausführt, befindet sich der Widget-Link unter url. Wenn eine Wallet-Eigentümerschafts-Aktion aussteht, enthält der Block action_required der Transaktion (Typ wallet_ownership) denselben reason und dieselben next_actions, sodass ein Client, der action_required bereits auswertet, die Auswahl ohne weiteren Aufwand anzeigt.

Felder zur Auflösung der Gegenpartei

Alles, was Didit über die Gegenpartei weiß, stammt aus travel_rule_details.beneficiary_data. Diese Felder steuern die Ermittlung des Übertragungswegs; alle sind optional:

Chain-Strukturen

Auf einer Account-Chain (EVM-Chains, Solana, Tron) bewegt ein Transfer Mittel von einer Adresse zur anderen, und Didit liest beide Wallets direkt aus der Transaktion. Drei andere Strukturen brauchen mehr, und was Didit für sie aufgelöst hat, steht im Transfer als chain_details (leer, {}, auf einer Account-Chain). chain_details.originator und chain_details.beneficiary enthalten jeweils die address, ihr memo und die source, aus der die Adresse stammt. Abgleich und Routing lesen die Wallets zuerst von dort.

UTXO-Transfers

Eine Bitcoin-, Litecoin-, Bitcoin-Cash- oder Dogecoin-Transaktion verbraucht Inputs von beliebig vielen Adressen und zahlt an beliebige Outputs, von denen einige als Wechselgeld an den Absender zurückgehen. Senden Sie die Inputs und Outputs als travel_rule_details.utxo (Beträge in der eigenen Einheit des jeweiligen Coins als Dezimalstrings), und Didit leitet ab, was Sie nicht angeben:
  • Auftraggeber: originator_data.wallet_address, wenn Sie es senden, andernfalls die Input-Adresse, die am meisten beigetragen hat (source: largest_input).
  • Begünstigter: die angegebene Wallet, andernfalls der einzige Output, an den keine Input-Adresse als Wechselgeld zurückgeht (only_non_change_output), andernfalls der eine Output, auf den der Transferbetrag entfällt (amount_match).
Der Transfer enthält dann:
chain_details.warnings markiert Unstimmigkeiten: declared_originator_not_an_input, declared_beneficiary_not_an_output, beneficiary_output_ambiguous (kein einzelner Output ließ sich eindeutig zuordnen) und beneficiary_output_amount_differs. utxo auf einer anderen Chain ergibt einen 400-Fehler, und jede Liste enthält höchstens 1.000 Einträge. Eine gemeldete Einzahlung verwendet dasselbe utxo-Objekt (siehe Sunrise-Registrierung nach der Einzahlung).

Memo- und Tag-Netzwerke

Bei XRP, Stellar (XLM), EOS, Cosmos (ATOM) und Hedera (HBAR) empfängt eine Börse Einzahlungen für alle Kunden über eine gemeinsame Adresse und unterscheidet sie anhand des Destination-Tags oder Memos. Das Memo ist daher Teil der Wallet: Übermitteln Sie es als payment_method.memo am Teilnehmer oder als memo in originator_data / beneficiary_data (Alias destinationTag). Didit vergleicht dann Adresse und Memo gemeinsam.
  • Ein Adressbuch-Eintrag mit Memo trifft nur Transfers, die genau dieses Memo angeben. Ein Eintrag ohne Memo trifft die gesamte Adresse. Ein Transfer ohne Memo erreicht nie einen Eintrag mit Memo: Auf einer gemeinsamen Adresse gehört eine Einzahlung ohne ihren Tag niemandem.
  • Eine XRP-X-Adresse enthält ihren Tag: Didit zerlegt sie in die klassische Adresse und den Tag (source: x_address). So trifft eine Wallet, die in einer der beiden Formen registriert ist, einen Transfer in der anderen Form.
  • Jedes Memo auf einer gemeinsamen Adresse ist auf der Transaktion eine eigene Zahlungsmethode.
  • Was die einzelnen Netzwerke akzeptieren: Ein XRP-Destination-Tag ist eine ganze Zahl von 0 bis 4294967295 (eine JSON-Zahl wird akzeptiert). Ein Stellar-Memo ist Text mit bis zu 28 Byte, eine 64-Bit-ID oder ein 32-Byte-Hash in Hex. EOS akzeptiert bis zu 256 Byte, Cosmos bis zu 256 Zeichen und Hedera bis zu 100 Byte. Ein Memo auf einer Chain ohne Memo-Feld (Bitcoin, EVM-Chains, Solana, Tron, Litecoin, Bitcoin Cash, Dogecoin, Lightning) ergibt einen 400-Fehler.

Lightning

Eine Lightning-Zahlung hat keine On-Chain-Adresse des Begünstigten: Der Zahler hält eine Zahlungsanforderung. Bei einem Bitcoin- oder Lightning-Krypto-Transfer kann payment_method.account_id diese Anforderung enthalten. Didit ermittelt den Begünstigten daraus, ohne ein Netzwerk zu kontaktieren: Der Zahlungsempfänger wird als Konto und als chain_details.beneficiary (source: invoice_payee) auf der Chain LIGHTNING gespeichert. Was die Zahlungsanforderung angibt, steht in chain_details.lightning. Nennt die Anforderung keinen Zahlungsempfänger, hat ein ausgehender Transfer den Status NOT_APPLICABLE. Der Grund steht in chain_details.not_applicable_reason und in seiner timeline: LIGHTNING_NO_PAYEE_IDENTIFIER, LIGHTNING_BOLT12_BLINDED_PAYEE oder LIGHTNING_LNURL_NAMES_NO_PAYEE. Ein Wert wird nur dann als Lightning gelesen, wenn die Chain Bitcoin oder LIGHTNING ist oder keine Chain angegeben wurde (eine Lightning Address nur auf Bitcoin oder LIGHTNING). Auf jeder anderen Chain ist er die eigene Adresse dieser Chain.
Die INTERNAL-Rail erreicht einen anderen Didit-Kunden nur über eine Wallet, deren Kontrolle dieser Kunde mit einer signierten Nachricht oder einer Testeinzahlung nachgewiesen hat. Solche Nachweise gibt es derzeit für Bitcoin, EVM-Chains, Solana und Tron. In Memo-Netzwerken, bei Lightning, Litecoin, Bitcoin Cash und Dogecoin erreicht ein Transfer daher nie einen anderen Didit-Kunden über INTERNAL. Der Memo-, Tag- und Lightning-Abgleich gilt weiterhin für Ihr eigenes Adressbuch: eingehende Transfers, gemeldete Einzahlungen und TRP-Anfragen an Ihre Wallets.

Auftraggeber-Wallet aktualisieren

Eine Auszahlung wird oft als von der Hauptwallet Ihres Kunden stammend angegeben und von den Adressen aus gesendet, auf denen die Coins tatsächlich lagen. Erfassen Sie die Wallet, von der die Mittel tatsächlich abgeflossen sind, mit PATCH /v3/transactions/{transaction_id}/travel-rule/:
  • Nur ausgehende Transfers, niemals CANCELLED- oder EXPIRED-Transfers (409).
  • Sind die UTXO-Inputs des Transfers bekannt, muss die Wallet eine davon sein (sonst 400). Senden Sie auch memo in einem Memo-Netzwerk.
  • Es ändert nur den Datensatz: Nichts wird erneut an die Gegenpartei gesendet, und der Status bleibt unverändert. chain_details.originator wird zur neuen Wallet mit source: updated. Die timeline hält die vorherige und die neue Wallet fest, und das INTERNAL-Gegenstück des Transfers wird auf die gleiche Weise aktualisiert.

Blockchain-Analytics-Zuordnung

Wenn Sie nur eine Adresse übergeben, kann Didit trotzdem ermitteln, wer auf der Gegenseite steht. Kann kein Rail den Transfer routen, gleicht Didit die Ziel-Wallet mit den Daten zur Blockchain-Analytics-Zuordnung ab. Dieselbe Analyse, die das Krypto-Transaktionsscreening antreibt, weiß, welche Wallets zu welchen Börsen und Verwahrern gehören. Die Zuordnung läuft nur bei ausgehenden Transfers, die sowohl eine Ziel-Wallet als auch eine chain enthalten (siehe Felder zur Auflösung der Gegenpartei). Ohne Chain wird sie übersprungen. Wird die Wallet einer bekannten Stelle zugeordnet, geht Didit wie folgt vor:
  1. Hält die Zuordnung am Transfer fest: beneficiary_data.counterparty_vasp_name wird befüllt (sofern Sie keinen Wert angegeben haben), und die Metadaten des Transfers enthalten einen Block vasp_attribution mit dem Namen, dem Entitätstyp und dem Land der Entität sowie source: "blockchain_analytics".
  2. Fügt die Stelle dem VASP-Verzeichnis hinzu (oder gleicht sie mit dem vorhandenen Eintrag ab), damit die Zuordnung über alle Transfers hinweg stabil bleibt.
  3. Führt die Rails einmal mit dem zugeordneten Namen erneut aus. Verfügt ein Verzeichniseintrag bereits über einen TRP-Endpoint, wird der Transfer sofort geroutet, statt bei COUNTERPARTY_VASP_NOT_FOUND zu landen.
Der Zuordnungsaufruf dient zugleich als vollständiges Krypto-Screening: Die Transaktion erhält die vollständige Screening-Ausgabe, also Risiko-Score, Wallet-Risikokategorie und Netzwerk-Snapshot, genau so, als wäre das Krypto-Monitoring gelaufen. Außerdem wird custom_values.aml_screening_trigger der Transaktion auf travel_rule_attribution gesetzt, damit Sie sehen, dass das Screening wegen des Travel-Rule-Routings lief. Hat das Krypto-Monitoring dieselbe Wallet bei dieser Transaktion bereits geprüft, wird das gespeicherte Ergebnis wiederverwendet: kein zweiter Analytics-Aufruf und keine zweite Belastung. Die Zuordnung blockiert nie die Anlage der Transaktion. Schlägt die Analytics-Abfrage fehl oder reicht Ihr Guthaben nicht, läuft der Transfer einfach mit COUNTERPARTY_VASP_NOT_FOUND weiter, und für den Versuch wird nichts berechnet. Bei action: "resend" wird eine zuvor erfasste Zuordnung wiederverwendet, statt erneut abgefragt zu werden. Deaktivieren Sie den gesamten Schritt mit vasp_attribution_enabled: false in den Einstellungen. Unter Preise finden Sie, wie der Attribution-Aufruf abgerechnet wird. Ist Travel Rule deaktiviert, wird travel_rule_details (einschließlich eines vom Aufrufer übergebenen status, in älterer oder aktueller Form) trotzdem an der Transaktion gespeichert, allerdings passiv: Es wird kein Rail angestoßen. Verwenden Sie dies, um Compliance-Daten nachträglich zu erfassen, die Sie bereits mit Ihrem eigenen Prozess erhoben haben. Ein passiver ausgehender Transfer startet keinen Austausch und wird daher als Transaction Screening abgerechnet, nicht über den Travel-Rule-Posten. Bei aktivierter Travel Rule leitet diese Anfrage über das Rail EMAIL, weil sie die Compliance-E-Mail der Gegenpartei nennt und kein früheres Rail den Begünstigten erreichen kann:
Die Antwort, gekürzt auf die relevanten Felder:
  • originator_data ist das, was Sie gesendet haben, da dem Beispiel-Subjekt keine genehmigte KYC-Verifizierung zugeordnet ist. Bei einem verifizierten Benutzer erstellt Didit es aus den verifizierten Daten (siehe Verifizierte Daten und Herkunft). Das Rail EMAIL zeigt dem Empfänger nur die Auftraggeber-Felder, die Sie in data_sharing_fields freigeben.
  • beneficiary_data.chain ist ETH, weil die Anfrage kein Netzwerk nannte und Didit es aus der Währung abgeleitet hat.
  • status ist APPROVED, weil keine Regel auf die Transaktion angewendet wurde. Ihre eigenen Regeln können einen anderen Status setzen.
  • Der Compliance-Kontakt erhält den Abholungslink. Der Transfer wird abgeschlossen, schlägt beim Namensabgleich fehl oder wird abgelehnt, sobald der Kontakt antwortet, oder er läuft ab, wenn der Kontakt nicht antwortet (siehe E-Mail-Abholung).
protocol bleibt null, weil das Rail erst nach der Antwort gewählt wird (zum Beispiel EMAIL, wenn Sie counterparty_vasp_email angegeben haben). Transaktion abrufen zeigt es, sobald es gewählt ist, und jeder spätere Webhook travel_rule.status.updated enthält es in rail. Gehört die Begünstigten-Wallet einem anderen Didit-Kunden, der deren Kontrolle nachgewiesen hat, schließt das Rail INTERNAL den gesamten Austausch direkt nach der Antwort ab, und dieser Webhook meldet bereits COMPLETED (oder COUNTERPARTY_MISMATCHED_DATA). Stimmt der Name nicht überein, hat Ihr Transfer den Status COUNTERPARTY_MISMATCHED_DATA, und der andere Kunde erhält nichts. Ohne counterparty_vasp_email und wenn weder die Rails noch die Attribution den Begünstigten erreichen können, endet der Transfer später in COUNTERPARTY_VASP_NOT_FOUND mit einer Aktion wallet_ownership für die Transaktion.
Der eingebettete Block travel_rule der Transaktion enthält die eigenen Felder des Transfers (uuid, status, protocol, required, obligations_count, originator_data, beneficiary_data, metadata), das, was Didit aufgelöst und verglichen hat (chain_details, name_match, data_match, mismatched_fields sowie die Felder zur Maskierung data_masked und data_unmasked), und die Felder, die den Stand angeben: direction, rail, counterparty_vasp, delivery, discovery, reason und next_actions (siehe Warum ein Transfer blockiert ist). Jede Zeile von GET /v3/transactions/ enthält denselben Block, oder null für eine Transaktion ohne Transfer. Die dedizierten Transfer-Endpoints unten liefern diese Felder ebenfalls zurück, dazu ivms_version, ownership_confirmed, deadline_at, timeline und created_at, aber kein obligations_count und kein metadata.
Um einen ausgehenden Transfer im Status COMPLETED abzuschließen, nachdem Sie ihn On-Chain gesendet haben:
Dafür muss der Transfer ein ausgehender Transfer im Status COMPLETED sein. Andernfalls gibt die API 409 zurück. Bei Erfolg wechseln sowohl der ausgehende Transfer als auch sein Gegenstück auf dem Rail INTERNAL in den Status FINISHED, und payment_txn_id der Transaktion wird auf den von Ihnen angegebenen Hash gesetzt. Auf dem Rail TRP sendet Didit den Hash außerdem an den Bestätigungs-Callback der Gegenpartei. Um einen Transfer zu stornieren, der noch keinen Endstatus erreicht hat, senden Sie stattdessen {"action": "cancel"} an denselben Endpoint. Das Gegenstück auf dem Rail INTERNAL wird ebenfalls storniert. Auf dem Rail TRP sendet Didit die Stornierung an den Bestätigungs-Callback, sobald die Gegenpartei die Anfrage genehmigt hat. Ein Transfer, der bereits FINISHED, CANCELLED oder EXPIRED ist, gibt 409 zurück. Eine Anfrage ohne payment_txn_id und ohne unterstützte action gibt 400 zurück. Bei einem Transfer über GTR, VERIFYVASP oder SYGNA meldet Didit den On-Chain-Hash (oder die Stornierung) nach der Antwort an das Netzwerk, mit denselben Wiederholungsversuchen. Das Feld delivery der Antwort zeigt diese Nachricht. Um einen ausgehenden Transfer erneut zu versuchen, der seine Gegenpartei nicht erreichen konnte (er befindet sich im Status COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE oder NOT_ENOUGH_COUNTERPARTY_DATA), verbessern Sie zuerst die Daten der Gegenpartei. Fügen Sie zum Beispiel dem Ziel-Wallet-Eintrag eine travel_address hinzu, ergänzen Sie einen Kontakt für den Verzeichniseintrag der Gegenpartei, oder nehmen Sie das VASP im Verzeichnis auf. Senden Sie danach {"action": "resend"} an denselben Endpoint. Didit startet die Bestätigungsfrist neu und reiht die Routing-Stufenfolge erneut von Anfang an in die Warteschlange ein, auf Basis der im Transfer gespeicherten Daten. Die Antwort zeigt den Transfer wieder im Status AWAITING_COUNTERPARTY (mit resend queued in seiner timeline), und das Ergebnis kommt als Webhook travel_rule.status.updated an. Ein erneuter Versuch, der gesendet wird, während ein früherer Versuch noch läuft, wird übermittelt, sobald dieser Versuch abgeschlossen ist. Jeder andere Status oder ein eingehender Transfer gibt 409 zurück.
Um die Gegenpartei selbst zu benennen, wenn die Ermittlung sie nicht finden konnte, senden Sie {"action": "beneficiary_vasp", "beneficiary_vasp": "<directory VASP id>"} (die id aus GET /v3/travel-rule/vasps/). Der Transfer wird an dieses VASP geleitet und erneut gesendet. Nur ein ausgehender Transfer im Status COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE oder NOT_ENOUGH_COUNTERPARTY_DATA akzeptiert das. Jeder andere Status gibt 409 zurück, und eine unbekannte ID gibt 404 zurück.

Warum ein Transfer blockiert ist

Ein Transfer im Status COUNTERPARTY_VASP_NOT_FOUND oder COUNTERPARTY_VASP_NOT_REACHABLE nennt bei jedem Abruf seiner Transaktion den Grund, warum er blockiert ist, und was ihn weiterbringt. Der Block travel_rule von GET /v3/transactions/{transaction_id}/, des 201 von POST /v3/transactions/ und jeder Zeile von GET /v3/transactions/ enthält diese Informationen, ebenso das Transfer-Objekt, mit dem der Transfer-Endpoint antwortet:
  • reason ist die maschinenlesbare Ursache, "" bei jedem anderen Status.
  • next_actions listet auf, was den Transfer weiterbringt, [] bei jedem anderen Status.
  • delivery ist die neueste Nachricht, die der Transfer der Gegenseite schuldet: kind, status (QUEUED, SENDING, RETRYING, DELIVERED oder FAILED), rail, attempts, last_error, next_attempt_at und delivered_at, oder null, wenn er keine Nachricht schuldet.
  • discovery zeigt, wo Didit nach der Gegenpartei gesucht hat, mit einem Eintrag pro ausgeführtem Schritt: step, outcome (match, miss oder skipped), reason, vasp, rail und at.
email_undeliverable und delivery_failed stammen aus einem fehlgeschlagenen Versand und erscheinen nur bei COUNTERPARTY_VASP_NOT_REACHABLE. Ein fehlgeschlagener Versand bestimmt zuerst reason, sodass eine Gegenpartei, die Didit gefunden hat, nie als nicht auffindbar gemeldet wird. Die anderen vier stammen aus dem Ermittlungsverlauf, bei beiden Status. Ein erneuter Versand bringt den Transfer weiter, daher wird sein reason leer. Der Zeitleisteneintrag eines Übergangs, der durch einen fehlgeschlagenen Versand ausgelöst wurde, trägt denselben Wert unter reason. Lehnt der Mail-Provider die Compliance-E-Mail des oben genannten Beispieltransfers ab, lautet der Block travel_rule der Transaktion verkürzt:
Hier stimmt delivery mit reason überein, weil der Versand selbst abgelehnt wurde. Eine Ablehnung bei einer Erinnerung oder ein später gemeldeter Bounce lässt delivery.status auf DELIVERED: Die erste E-Mail wurde tatsächlich versendet. Lesen Sie reason, nicht delivery, um zu erfahren, warum ein Transfer hängt. Um das zu beheben, geben Sie die Compliance-E-Mail der Gegenpartei erneut an und senden Sie dann erneut:
update_compliance_email speichert die Adresse als beneficiary_data.counterparty_vasp_email dieses Transfers: Sie gehört nur zu diesem Transfer und wird weder einem Verzeichniseintrag noch einer Kontaktliste hinzugefügt. Der Status ändert sich nicht, die Zeitleiste erhält den Eintrag compliance email updated, und der Transfer behält reason: email_undeliverable, bis das erneute Senden die Anfrage an die neue Adresse schickt. Nur ein ausgehender Transfer in COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE oder NOT_ENOUGH_COUNTERPARTY_DATA akzeptiert dies; jeder andere Transfer antwortet mit 409, und ein fehlendes oder fehlerhaftes compliance_email wird mit 400 beantwortet.

Deklarierte selbstverwahrte Wallets

Wenn Ihr Kunde Ihnen mitteilt, dass das Ziel seine eigene selbstverwahrte (nicht verwahrte) Wallet ist, deklarieren Sie dies in der Transaktion, statt das Routing herausfinden zu lassen, dass kein VASP dahintersteht: Setzen Sie den Zahlungsmethodentyp der Gegenpartei auf unhosted_wallet.
Die Deklaration umgeht das Routing vollständig:
  • Es wird kein Rail verwendet - es gibt keinen Gegenpartei-VASP, mit dem ausgetauscht werden könnte - und der Transfer wird direkt in UNCONFIRMED_OWNERSHIP angelegt.
  • Ist auto_wallet_verification aktiviert (Standardeinstellung), erstellt Didit automatisch eine Widget-Sitzung zur Wallet-Eigentumsprüfung, die an die Transaktion gebunden ist, und gibt sie im Block action_required der Transaktion zurück; die SDKs starten sie bei der clientseitigen Übermittlung automatisch.
  • Sobald der Kunde die Kontrolle über die Wallet nachweist, führt der Transfer den Abgleich des Begünstigten-Namens aus und wechselt zu COMPLETED (oder zu COUNTERPARTY_MISMATCHED_DATA bei einem fehlgeschlagenen Abgleich).
Dies ist die Verpflichtung gemäß der EU-TFR zu selbstverwahrten Wallets in API-Form: Sie prüfen das Eigentum an der nicht verwahrten Wallet, statt Daten mit einem Gegenpartei-VASP auszutauschen. Die Deklaration wird aus der Zahlungsmethode auf der Ziel-Seite eines ausgehenden Transfers und auf der Quelle-Seite eines eingehenden Transfers gelesen - in beiden Fällen ist es der Teilnehmer der Gegenpartei. Ein deklarierter Transfer mit nicht verwahrter Wallet befindet sich bereits auf seinem finalen Pfad ohne Rail, daher ist UNCONFIRMED_OWNERSHIP kein Zustand, der erneut gesendet werden kann - schließen Sie den Eigentumsnachweis ab (oder brechen Sie ab), statt action: "resend" aufzurufen.

Empfangen

Bestätigung des Wallet-Eigentums

Ein Transfer wartet in zwei Fällen im Status UNCONFIRMED_OWNERSHIP:
  • Ein eingehender Transfer wird einem Eintrag im Adressbuch zugeordnet, dessen Eigentum noch nicht verifiziert ist.
  • Die Wallet der Gegenpartei wurde als selbstverwahrt angegeben (counterparty.payment_method.method_type: "unhosted_wallet"), bei einer ausgehenden Auszahlung oder einer eingehenden Einzahlung. Siehe Angegebene selbstverwahrte Wallets.
Ihre Anwendung bestätigt oder lehnt den Transfer ab:
Der Body akzeptiert confirmed (erforderlich, boolesch) und optional wallet_address. Der Endpoint akzeptiert einen Transfer in jedem der folgenden Status. Für alle anderen Status gibt er 409 mit {"detail": "Transfer is not awaiting ownership confirmation."} zurück:
  • UNCONFIRMED_OWNERSHIP, in beiden Richtungen.
  • ON_HOLD bei einem eingehenden Transfer.
  • UNCONFIRMED_OWNERSHIP, ON_HOLD oder COUNTERPARTY_MISMATCHED_DATA bei einem eingehenden TRP-Transfer, damit ein Compliance-Beauftragter eine Anfrage der Gegenpartei manuell klären kann.
Bei einem Transfer, den Didit selbst angelegt hat (INTERNAL-Rail, Sunrise-Registrierung oder eine angegebene selbstverwahrte Wallet), gilt Folgendes:
  • confirmed: true markiert den passenden Eintrag im Wallet-Adressbuch als eigentumsverifiziert und führt anschließend den Namensabgleich gegen den holder_name dieses Eintrags aus. Das Ergebnis ist COMPLETED, wenn der Abgleich besteht, und COUNTERPARTY_MISMATCHED_DATA, wenn nicht. Das Gegenstück auf der INTERNAL-Rail erhält, sofern es existiert, dasselbe Ergebnis. Bei einer angegebenen selbstverwahrten Wallet hält confirmed: true fest, dass Ihr Kunde die Kontrolle über die Wallet der Gegenpartei verifiziert hat, und schließt den Transfer ab (COMPLETED), ausgehend oder eingehend. Ein eingehender Transfer, dessen Einzahlung bereits gebucht wurde, geht direkt in FINISHED über.
  • confirmed: false setzt beide Seiten des Transfers auf COUNTERPARTY_VASP_GENERAL_DECLINE.
  • Der passende Eintrag wird in Ihrem Adressbuch allein anhand der Adresse gesucht, ohne Berücksichtigung der Chain. Wenn Sie ein eingehendes ON_HOLD ohne passenden Eintrag auflösen, wird der Eintrag aus beneficiary_data.wallet_address des Transfers angelegt und als verifiziert markiert. Eine angegebene selbstverwahrte Wallet ist die Ausnahme: Die Wallet wird, wie unten beschrieben, als eigentumsverifiziert in Ihrem Adressbuch registriert. In allen anderen Fällen gibt ein fehlender Eintrag 409 mit {"detail": "wallet address entry no longer available"} zurück. Dieselbe Antwort erhalten Sie für einen gelöschten Eintrag.
Bei einem eingehenden TRP-Transfer beantwortet derselbe Aufruf die Anfrage der Gegenpartei:
  • confirmed: true benötigt eine Zahlungsadresse für die Rückgabe. Sie wird zunächst aus der wallet_address der Anfrage, dann aus dem passenden Eintrag und zuletzt aus beneficiary_data.wallet_address entnommen. Sind alle drei leer, gibt die Anfrage 400 mit {"wallet_address": ["wallet_address is required to approve."]} zurück. Didit legt den Eintrag an oder verifiziert ihn, sendet den Callback zur Anfrageklärung an die Gegenpartei, setzt ownership_confirmed und verschiebt den Transfer nach COMPLETED.
  • confirmed: false sendet eine abgelehnte Klärung und setzt den Transfer auf COUNTERPARTY_VASP_GENERAL_DECLINE.
  • Ist der Callback-Endpoint der Gegenpartei nicht erreichbar, gibt die Anfrage 502 zurück, und der Transfer behält seinen aktuellen Status. Bei einer Genehmigung wird der Eintrag im Wallet-Adressbuch trotzdem angelegt oder als verifiziert markiert.
Bei einer angegebenen selbstverwahrten Wallet ist die Wallet, die Sie verifizieren, die Wallet der Gegenpartei: das Ziel einer ausgehenden Auszahlung oder die Quelle einer eingehenden Einzahlung (die Wallet des Auftraggebers). Didit nimmt sie als eigentumsverifiziert unter dem Namen der Gegenpartei in das Wallet-Adressbuch auf. Deshalb wird die Wallet mit dem Namen der Gegenpartei abgeglichen, bei einer Einzahlung mit dem Namen des Auftraggebers. Enthält das Adressbuch diese Wallet bereits unter einem anderen Inhabernamen, wechselt der Transfer stattdessen in COUNTERPARTY_MISMATCHED_DATA. Nennt der Transfer keine Wallet der Gegenpartei, übergeben Sie wallet_address im Request-Body. Fehlt eine Adresse sowohl im Transfer als auch in der Anfrage, wird die Anfrage mit 400 abgelehnt.
  • Ein Netzwerktransfer, der bereits über sein Netzwerk beantwortet wurde (ein VerifyVASP-Transfer oder ein bereits entschiedener GTR- oder Sygna-Bridge-Transfer), gibt 409 zurück (siehe Transfers aus einem Netzwerk).
Die Antwort ist das oben beschriebene, umfassendere Transferobjekt. Ein neuer INTERNAL-Transfer wartet hier nie: Er erreicht nur einen Kunden, der die Wallet bereits nachgewiesen hat. Ein älterer INTERNAL-Transfer, der noch aus der Zeit vor dieser Regel wartet, hält die Absenderdaten verborgen, bis Sie die Kontrolle über die Wallet nachweisen (eine signierte Nachricht oder eine Test-Einzahlung). Bis dahin gibt die Bestätigung 409 zurück. Die Ablehnung funktioniert weiterhin. Hat die Gegenpartei angegeben, dass die Wallet selbstverwahrt ist (derzeit gibt der Didit Test VASP diese Antwort in der Sandbox), fügt die Bestätigung die Wallet unter dem Namen des Begünstigten Ihrem Adressbuch hinzu und führt den Namensabgleich aus. Bei einer Übereinstimmung wird der Transfer abgeschlossen und die Wallet als verifiziert markiert.

Transfers aus einem Netzwerk

Didit kann außerdem Travel-Rule-Transfers empfangen, die eine Gegenpartei über GTR, VERIFYVASP oder SYGNA sendet. Den Empfang schaltet Didit für jedes Netzwerk einzeln frei. Derzeit ist keines freigeschaltet. Dafür muss zusätzlich jedes Netzwerk die Endpoints von Didit registrieren, und Didit besitzt noch keine Mitgliedschaft in diesen Netzwerken. TRUST-Transfers können nicht empfangen werden. Sobald ein Netzwerk freigeschaltet ist, wird eine von ihm gelieferte Nachricht wie folgt verarbeitet:
  • Routing. Die Nachricht erreicht Ihre Anwendung, wenn sie den Teilnehmercode Ihrer eigenen verbundenen Mitgliedschaft in diesem Netzwerk nennt. Eine an die Mitgliedschaft von Didit adressierte Nachricht erreicht Sie nur, wenn Sie der einzige aktive Didit-Kunde sind, der die Kontrolle über die Begünstigten-Wallet nachgewiesen hat. Alles andere wird abgelehnt, sodass kein Kunde jemals den Transfer eines anderen Kunden erhält.
  • Entscheidung. Didit legt den eingehenden Transfer in Ihrer Anwendung an und behandelt ihn wie eine TRP-Anfrage: Wallet-Abgleich, Eigentum, Namensabgleich und inbound_auto_accept.
  • Einmalig. Netzwerke senden eine Nachricht erneut, bis sie beantwortet ist. Eine Wiederholung erhält dieselbe Antwort wie die erste Kopie, und nichts wird ein zweites Mal angelegt oder entschieden.
  • Ihre Prüfung, über GTR und SYGNA. Ein Transfer, der auf Sie wartet (UNCONFIRMED_OWNERSHIP, ON_HOLD oder COUNTERPARTY_MISMATCHED_DATA), entscheiden Sie mit POST .../travel-rule/ownership/: confirmed: true genehmigt ihn (übergeben Sie wallet_address, wenn der Transfer keine nennt), und confirmed: false lehnt ihn ab. Didit antwortet dem Netzwerk nach Ihrer Antwort, mit denselben Wiederholungsversuchen. Ein bereits beantworteter Transfer gibt 409 zurück.
  • Keine spätere Antwort über VERIFYVASP. VerifyVASP erwartet seine Antwort bereits bei der Anfrage. Ein Transfer, der Ihre Prüfung bräuchte, wird deshalb sofort abgelehnt und kann später nicht mehr entschieden werden (409).

Maskierte Daten der Gegenpartei

Bis die Inhaberschaft der Wallet bestätigt ist, werden die personenbezogenen Daten der Gegenpartei bei einer eingehenden Überweisung maskiert und nicht weggelassen. Der erste Buchstabe jedes Wortes bleibt erhalten, und die Wallet, die Chain und das Routing über den VASP bleiben lesbar. data_masked ist true, und die Gegenpartei im Transaktionsdetail, in der Liste und im CSV-Export wird auf dieselbe Weise maskiert. Sobald die Inhaberschaft bestätigt ist, erscheinen die echten Werte, und data_unmasked protokolliert den Audit-Eintrag:
reason ist ownership_confirmed, wallet_proof, address_book_match, own_verified_wallet, inquiry_approved (Sie haben eine TRP-Anfrage oder eine GTR- oder Sygna-Nachricht genehmigt), known_payment_method (die Wallet des Endbenutzers in Ihren eigenen Unterlagen hat geantwortet) oder travel_address (die Travel Address pro Wallet hat die Wallet zugeordnet). Eine eingehende INTERNAL-Überweisung trägt data_unmasked mit reason: wallet_proof ab dem Zeitpunkt ihrer Erstellung, weil nur ein Empfänger, der die Wallet nachgewiesen hat, einen solchen Eintrag erhält. actor ist die E-Mail-Adresse des Konsolenbenutzers oder das Label des API-Schlüssels und bleibt leer bei einer automatischen Entscheidung. Der Bericht Protokoll der Travel-Rule-Überweisungen (CSV und PDF) maskiert die Namen einer eingehenden Überweisung auf dieselbe Weise, bis die Inhaberschaft bestätigt ist. Berichte, die Sie bei einer Aufsichtsbehörde einreichen, etwa das goAML-XML und der Regulierungsbericht als PDF, enthalten die echten Daten der Gegenpartei.

Rückmeldung bei Abweichungen

Eine Überweisung mit COUNTERPARTY_MISMATCHED_DATA nennt jetzt die Felder, die voneinander abweichen. data_match enthält den Vergleich, und mismatched_fields listet die Felder auf. Beide enthalten nur Feldnamen und Ergebnisse, niemals Werte, sodass sie lesbar bleiben, während die Daten maskiert sind:
Der Zeitleisten-Eintrag nennt die Felder, zum Beispiel “beneficiary date of birth does not match wallet holder”. Eine TRP-Ablehnung nach einer Abweichung teilt dem ursprünglichen VASP mit, welche Felder abweichen, zum Beispiel “Beneficiary data does not match the wallet holder: name”. Was der andere VASP erfährt, ist bewusst begrenzt: Solange der Name falsch ist, wird nur der Name gemeldet (mismatched_fields: ["name"], alle anderen Felder not_compared). Sobald der Name übereinstimmt, wird jedes abweichende Feld genannt. Dies gilt für die Senderseite eines INTERNAL-Austauschs und für eine TRP-Ablehnung. Ein Name, der auf beiden Seiten fehlt, wird als not_compared ausgewiesen und ist keine Abweichung. Ein Land wird anhand seiner Bezeichnung verglichen, sodass ES und ESP übereinstimmen.

Übereinstimmungswert des Namens

Jede Überweisung, deren Name verglichen wurde, enthält name_match. Der Zeitleisten-Eintrag, der die Entscheidung getroffen hat, enthält dasselbe Objekt neben seinem detail:
  • score ist die Ähnlichkeit der beiden vollständigen Namen, von 0 bis 100, und 0, wenn einer der beiden Namen leer ist. matched ist das Ergebnis bei strictness, daher können beide voneinander abweichen: FUZZY entscheidet anhand seiner eigenen Ähnlichkeitsquote von 0.85.
  • matched_names sind die Wörter des Namens der Überweisung, die im anderen Namen gefunden wurden. mismatched_names sind die Wörter, die eine Seite hat und die andere nicht.
  • method ist none, exact_token, token_subset, token_containment oder sequence_ratio, für NONE, STRICT, DEFAULT, CONTAINS und FUZZY.
  • compared_with ist wallet_holder (der für die Wallet hinterlegte Inhaber) oder counterparty_vasp (der Name, den die Gegenpartei auf der E-Mail-Antwortseite angegeben hat, oder die Antwort des Didit Test-VASPs).
  • Das Ergebnis der Überweisung folgt data_match, das jedes Feld vergleicht. Daher kann eine Überweisung COUNTERPARTY_MISMATCHED_DATA sein, während name_match.matched true ist.
  • name_match steht am Überweisungsobjekt, das die Travel-Rule-Endpunkte zurückgeben, und am eingebetteten travel_rule der Transaktion. Es ist null, bis ein Name verglichen wurde. Die Überweisungsliste und die Webhooks enthalten es nicht.
  • Die Namen sind ausgeblendet, solange die Parteien maskiert sind, und in der Ansicht des anderen Kunden bei einem INTERNAL-Austausch.

Nachrichten und Dokumentenanfragen

Zwei VASPs können eine strittige Überweisung innerhalb von Didit klären, statt per E-Mail. GET und POST /v3/transactions/{transaction_id}/travel-rule/messages/ listen Nachrichten zu einer Überweisung auf und senden sie:
  • kind ist MESSAGE (Standard) oder DOCUMENT_REQUEST. Eine Dokumentenanfrage braucht mindestens einen Eintrag in requested_documents (bis zu 10). Eine Nachricht braucht einen body (bis zu 5000 Zeichen) oder eine Datei.
  • reply_to verweist auf eine frühere Nachricht derselben Überweisung. Eine Antwort der anderen Seite, die ein Dokument enthält, erfüllt die Dokumentenanfrage, auf die sie antwortet, und fulfilled_at wird darauf gesetzt. Ihre eigene Antwort erfüllt niemals Ihre eigene Anfrage.
  • Senden Sie eine Multipart-Anfrage mit files, um bis zu 5 Dateien mit je 10 MB anzuhängen, als PDF, PNG, JPEG oder WebP. Didit prüft den Inhalt jeder Datei, nicht nur den angegebenen Typ. Bei jedem anderen Dateityp antwortet die Anfrage auf files mit 400 (“Attach PDF, PNG, JPEG or WebP files only.”).
  • Eine Überweisung umfasst bis zu 100 Nachrichten, davon bis zu 20 mit Anhängen (jeweils mit bis zu 5 Dateien), beide Seiten zusammengerechnet. Wird eine dieser Grenzen überschritten, antwortet die Anfrage mit 400. Nachrichtenanhänge zählen nicht zu den eigenen Dokumenten einer Transaktion.
  • Nachrichten funktionieren über die Rails INTERNAL und EMAIL. Bei INTERNAL sieht der andere Didit-Kunde die Nachricht auf seiner Seite des Paars. Bei EMAIL wird die Gegenpartei per E-Mail benachrichtigt und antwortet im Abholportal. Kann diese Benachrichtigungs-E-Mail nicht gesendet werden, wird die Nachricht trotzdem gespeichert und die Anfrage antwortet mit 201.
  • Die Anfrage antwortet mit 409 und einem Grund in detail bei einer Überweisung über TRP, GTR, TRUST, VerifyVASP oder Sygna (diese Protokolle übertragen keine Nachrichten), bei einer Überweisung ohne Gegenpartei, bei einer INTERNAL-Überweisung, deren Daten nicht mit dem Wallet-Inhaber übereinstimmten (der Empfänger hat nichts erhalten), bei einer INTERNAL-Überweisung, deren Empfänger die Kontrolle über die Wallet noch nicht nachgewiesen hat (auf beiden Seiten, bis er es tut), bei einer EMAIL-Überweisung, deren Gegenpartei keine Compliance-E-Mail-Adresse mehr hat, und bei einer EMAIL-Überweisung, deren Abhol-Link abgelaufen oder deren Überweisung geschlossen ist.
  • Wenn die Gegenpartei zurückschreibt, wird kein Webhook ausgelöst. Rufen Sie den Nachrichten-Endpunkt ab.
  • Die E-Mail, die die Gegenpartei über eine neue Nachricht informiert, wird auf Englisch versendet.

Wallet-Adressbuch

Registrieren Sie die Wallets, die Sie kontrollieren, damit eingehende Überweisungen (über den INTERNAL-Weg, eingehende TRP-Anfragen und Registrierungen nach der Einzahlung) mit ihnen abgeglichen werden können, mit POST/GET /v3/travel-rule/wallet-addresses/ und PATCH/DELETE /v3/travel-rule/wallet-addresses/{entry_uuid}/.
PATCH akzeptiert holder_name, holder_vendor_data, entity_type und travel_address und gibt nur diese vier Felder zurück. DELETE löscht den Eintrag (204). Seine Adresse wird wieder frei für eine erneute Registrierung und der Eintrag wird bei neuen Transfers sofort nicht mehr berücksichtigt.
Der Abgleich ist bei der Adresse nicht case-sensitiv, berücksichtigt memo in einem Memo-Netzwerk und ist auf chain begrenzt. Trägt ein Transfer eine Chain, stimmt ein Eintrag nur dann, wenn seine chain denselben Wert hat (ohne Beachtung der Groß- und Kleinschreibung) oder leer ist. Chain-Namen werden als Text verglichen, nicht übersetzt. Ein Eintrag, der als ethereum gespeichert ist, stimmt daher nicht mit einem Transfer überein, dessen Chain ETH ist. Ausgehende Transfers übernehmen ihre Chain aus beneficiary_data.chain, dann aus transaction_details.crypto_params.crypto_chain, dann aus custom_properties.crypto_chain, dann aus der Währung (zum Beispiel ETH oder bei USDT und USDC die aus payment_reference_id abgeleitete Chain). Dabei wird nur eine Chain gesetzt, die Didit erkennt. Registrierungen nach der Einzahlung übernehmen ihre Chain aus dem Feld chain, kleingeschrieben. Eingehende TRP-Anfragen ignorieren die Chain: Sie stimmen über die Adresse überein oder, wenn die Anfrage keine Wallet nennt, über den Begünstigtennamen mit Ihren verifizierten Einträgen. POST .../travel-rule/ownership/ stimmt ebenfalls nur über die Adresse überein. Stimmen mehrere Einträge überein, bevorzugen die Schiene INTERNAL und Registrierungen nach der Einzahlung einen Eintrag mit nachgewiesenem Eigentum, dann den ältesten. Die ausgehende TRP-Suche nimmt den ältesten Eintrag, der eine Travel Address speichert. Eingehende TRP-Anfragen und der Endpunkt für das Eigentum nehmen einen beliebigen der übereinstimmenden Einträge. Behalten Sie deshalb nach Möglichkeit einen Eintrag pro Adresse. Die Schiene INTERNAL findet überhaupt keinen Eintrag, wenn in mehr als einer anderen Anwendung verifizierte Einträge für die Adresse existieren.

Wallets in großen Mengen importieren

Importieren Sie bis zu 10.000 Wallets in einem Aufruf mit POST /v3/travel-rule/wallet-addresses/import/, als JSON ({"entries": [...]} oder ein einfaches Array) oder als UTF-8-CSV-Datei mit höchstens 5 MB und einer Kopfzeile. Eine Zeile nennt eine Wallet über ihre address, über address_hash (der SHA-256 der kleingeschriebenen Adresse, 64 Hexadezimal- oder 44 Base64-Zeichen) oder über beide, zusammen mit beliebigen Eintragsfeldern von oben. Senden Sie nur den Hash, um eine Wallet zu registrieren, ohne ihre Adresse offenzulegen. Sie ordnet Transfers an diese Adresse wie jeder andere Eintrag zu und kann mit dem Widget zur Wallet-Eigentumsprüfung nachgewiesen werden.
Der Import ist idempotent und meldet jede Zeile in der gesendeten Reihenfolge: created, existing (dieselbe Wallet, Chain und Memo sind bereits im Verzeichnis und wurden unverändert gelassen), duplicate (wiederholt eine frühere Zeile, benannt in duplicate_of_row) oder failed mit seinen errors. Eine fehlerhafte Zeile beeinträchtigt die anderen nicht: Die Antwort ist 200, wenn keine Zeile fehlgeschlagen ist, und 207, wenn eine fehlgeschlagen ist. Die Zählwerte stehen in total, created, existing, duplicate und failed. Eine leere CSV-Zelle gilt als nicht gesendet, und Spalten, die der Import nicht liest, werden ignoriert. Ein Export aus einem anderen Tool lässt sich daher unverändert importieren. Bei GET /v3/travel-rule/transfers/ enthält jede Zeile originator_memo und beneficiary_memo neben den beiden Wallets.

E-Mail-Abholung für nicht erreichbare Gegenparteien

Wenn keine Protokollschiene die Gegenpartei erreichen kann, greift Didit auf EMAIL zurück. Dabei sendet Didit einen einmaligen Abholungslink an beneficiary_data.counterparty_vasp_email (oder an eine E-Mail-Adresse, die aus beneficiary_data.counterparty_vasp_name im VASP-Verzeichnis ermittelt wird). Der Empfänger braucht weder ein Didit-Konto noch einen API-Schlüssel. Das Token im Link dient als Authentifizierung. So wird die Anfrage versendet:
  • An die richtigen Adressen. Eine übergebene counterparty_vasp_email ist der einzige Empfänger. Andernfalls schreibt Didit an bis zu drei Adressen: an die Kontakte der Gegenpartei, bei denen kein Bounce aufgetreten ist (zuerst Ihre eigenen, dann die Plattform-Kontakte, und zwar jene, die zuerst geantwortet haben), und danach an die Compliance-E-Mail des Verzeichniseintrags, sofern noch ein Platz frei ist. Jede Adresse erhält eine eigene E-Mail.
  • In Ihrem Namen. Die E-Mail kommt von der Adresse von Didit mit dem Absender „Ihr rechtlicher Name via Didit“, in der Sprache der Jurisdiktion der Gegenpartei (Englisch, wenn keine bekannt ist). Der Link öffnet die Antwortseite in dieser Sprache. Sie erhalten keine Kopie. Verfolgen Sie den Verlauf des Transfers in der Zeitleiste.
  • Mit Erinnerungen. Bis die Gegenpartei antwortet, erinnert Didit sie 72, 24 und 6 Stunden vor der Frist, mindestens 12 Stunden nach der Anfrage oder der letzten Erinnerung, und niemals nach der Frist.
  • Umgang mit Bounces. Ein Bounce oder eine Spam-Beschwerde markiert den erreichten Kontakt als ungültig und vermerkt den Grund, und die Zeitleiste des Transfers vermerkt dies. Ein Plattform-Kontakt ist dann für jeden Didit-Kunden ungültig, Ihr eigener Anwendungskontakt nur für Ihre Anwendung. Stellt der E-Mail-Versand von Didit an eine Adresse ganz ein (nach einem dauerhaften Bounce, einer Spam-Beschwerde oder einer Abmeldung), wird jeder Kontakt an dieser Adresse als ungültig markiert (suppressed). Diese Kontakte sind wieder gültig, sobald der Versand an die Adresse wieder aufgenommen wird. Ist keine Adresse mehr übrig, an die geschrieben werden kann, wechselt der Transfer zu COUNTERPARTY_VASP_NOT_REACHABLE, und seine Zeitleiste enthält den Grund des empfangenden Mailservers. Ein dauerhafter Bounce oder eine Spam-Beschwerde an die übergebene counterparty_vasp_email führt sofort dazu, weil sie der einzige Empfänger ist. Ein vorübergehender Bounce (soft_bounce) an diese Adresse oder an die Compliance-E-Mail des Verzeichniseintrags lässt die Anfrage dagegen für die Erinnerungen offen.
Der Link öffnet eine gehostete Seite, die den ausstehenden Austausch anzeigt und für den Empfänger diese beiden öffentlichen Endpoints aufruft. Für den oben genannten Beispieltransfer lauten die Abholdaten:
reference ist die uuid des Transfers. originator_data und das daraus erstellte IVMS-101-ivms_request enthalten nur die Angaben zum Auftraggeber, die Sie in data_sharing_fields freigeben; der Name und die Wallet sind immer enthalten. fiat_amount und fiat_currency sind leer, wenn Sie keinen umgerechneten Wert gesendet haben. contact gibt den Wert von ?contact= aus dem Link zurück, und decline_reasons listet die Werte auf, die decline_reason akzeptiert. join_invitation.eligible ist true, solange die Gegenpartei eine gültige Einladung zum Beitritt zu Didit hat; der Einladungslink selbst wird nur per E-Mail übermittelt. Dieser Endpoint gibt den gespeicherten Betrag unverändert zurück. Er enthält daher alle 18 Dezimalstellen und nicht die gekürzte Form, die das Transaktionsdetailobjekt verwendet.
decision ist accept oder decline. Bei accept wird der übermittelte beneficiary_name nach Ihrer Namensregel mit dem beneficiary_data.name des Transfers verglichen: COMPLETED bei Übereinstimmung, andernfalls COUNTERPARTY_MISMATCHED_DATA. Die Gegenpartei kann stattdessen eine vollständige IVMS-101-Antwort als ivms_response senden. Der darin enthaltene Name des Begünstigten hat dann Vorrang vor beneficiary_name. Bei decline wechselt der Transfer in COUNTERPARTY_VASP_GENERAL_DECLINE. Die Gegenpartei kann einen decline_reason aus decline_reasons angeben, zusammen mit einem decline_detail (bis zu 512 Zeichen, bei other erforderlich). Die Zeitleiste Ihres Transfers hält dies fest, zum Beispiel counterparty declined: The beneficiary is not our customer. Die Antwort ist das resultierende {"status": "..."}, nach einer Ablehnung zusätzlich decline_reason. Sobald die Gegenpartei geantwortet hat, geben beide Endpoints 410 zurück. Beide Endpoints geben 404 für ein unbekanntes Token zurück und 410, sobald das Zeitfenster geschlossen ist. Das ist der Fall, wenn der Transfer AWAITING_COUNTERPARTY verlassen hat oder die Bestätigungsfrist (confirmation_timeout_hours nach der Erstellung oder dem letzten erneuten Senden) abgelaufen ist. Die Gegenpartei liest und antwortet über den Abholungslink mit GET und POST /v3/travel-rule/pickup/{token}/messages/. Sie benötigt keinen API-Schlüssel und akzeptiert ausschließlich Anhänge im Format PDF, PNG, JPEG oder WebP. Sie antwortet mit 410, sobald der Link abläuft oder der Transfer geschlossen ist. Eine Nachricht, die Sie gesendet haben, zeigt Ihren VASP-Namen als author und als uploaded_by des Anhangs, niemals die Person oder den API-Schlüssel dahinter.

Nicht zugeordnete Einzahlungen

Eine eingehende Einzahlung kann eintreffen, bevor die Travel-Rule-Daten des absendenden VASP vorliegen. Eine solche Einzahlung bleibt in AWAITING_COUNTERPARTY oder NOT_ENOUGH_COUNTERPARTY_DATA, bis die Daten eintreffen. Lassen Sie sich die Einzahlungen, die noch warten, mit einem API-Schlüssel auflisten, der die Berechtigung für Transaktionen besitzt:
Die Antwort verwendet dieselben Zeilen wie GET /v3/travel-rule/transfers/, beschränkt auf eingehende Einzahlungen, die auf die Daten des absendenden VASP warten. Wenn die Daten als separate empfangene Nachricht eingetroffen sind, ordnen Sie beide selbst einander zu:
{transaction_uuid} ist die Einzahlung. transaction_id ist die Transaktion der empfangenen Travel-Rule-Nachricht. Der Aufruf gibt { "deposit": ..., "message": ... } zurück. Er antwortet mit 404, wenn eine der beiden Transaktionen nicht mehr existiert. Er antwortet mit 409 und travel_rule_match_conflict (“This deposit can no longer be matched.”), wenn eine Seite bereits einen anderen Status erreicht hat.

Nachträgliche Sunrise-Registrierung nach der Einzahlung

Wenn eine Krypto-Einzahlung On-Chain abgewickelt wird, bevor ein Travel-Rule-Austausch stattgefunden hat, etwa weil der sendende VASP nicht erreichbar war oder Sie historische Einzahlungen nachtragen, registrieren Sie sie nachträglich mit POST /v3/travel-rule/inbound/.
originating_vasp.travel_address muss eine echte, prüfsummengültige Travel Address sein. Ein Platzhalter gibt 400 mit "Invalid travel address." zurück. originating_vasp.lei muss leer sein oder 20 Zeichen im LEI-Format haben (18 Buchstaben oder Ziffern, danach 2 Ziffern). Alles andere gibt 400 mit "Invalid LEI: expected 20 alphanumeric characters (ISO 17442)." zurück. Didit prüft nur dieses Format, nicht die Prüfziffern nach ISO 17442. Didit legt eine eingehende travelRule-Transaktion an (oder verwendet eine eingehende Einzahlung wieder, die Sie bereits mit demselben Hash und Wallet eingereicht haben, sofern diese noch keinen Travel-Rule-Transfer hat) und gleicht den Transfer über die Adresse und das Memo mit Ihrem Wallet-Adressbuch ab:
  • Kein passender Eintrag -> ON_HOLD. Lösen Sie ihn mit POST .../travel-rule/ownership/: confirmed: true fügt die Wallet als verifiziert zu Ihrem Adressbuch hinzu und führt den Namensabgleich durch. Bei einer Übereinstimmung wechselt der Transfer zu COMPLETED und danach zu FINISHED.
  • Eintrag vorhanden, aber die Eigentümerstruktur ist nicht nachgewiesen -> UNCONFIRMED_OWNERSHIP.
  • Name des Begünstigten stimmt nicht mit dem holder_name des Eintrags überein -> COUNTERPARTY_MISMATCHED_DATA.
  • Verifizierter Eintrag und Name stimmen überein -> COMPLETED, danach sofort FINISHED (die Einzahlung ist bereits abgewickelt).
Mit dem verifizierten Adressbuch-Eintrag, der im obigen Beispiel registriert wurde, lautet die Antwort:
Die txn_id der neuen Transaktion setzt sich aus tr-in-, den ersten 80 Zeichen der txid und einem 12-stelligen Hash aus txid und Wallet zusammen. created ist true (HTTP 201), wenn dieser Aufruf die Einzahlung registriert hat, und false (HTTP 200), wenn dieselbe txid und dieselbe wallet_address bereits registriert waren. In diesem Fall wird der bestehende Transfer unverändert zurückgegeben. Beim Pfad mit verifiziertem Eintrag finden beide Übergänge statt, bevor der Endpoint antwortet. Die synchrone Antwort zeigt daher bereits den endgültigen Status FINISHED. Der Zwischenschritt COMPLETED wird dennoch in der timeline des Transfers festgehalten. Jeder Übergang löst ein Webhook-Ereignis travel_rule.status.updated aus (COMPLETED und FINISHED lösen jeweils ein Ereignis aus). Wenn Didit eine neue Transaktion angelegt hat, sendet Didit zuerst transaction.created und danach diese Ereignisse. Die Registrierung verursacht keine Gebühr für Travel Rule oder Monitoring. Wenn die Krypto-Überwachung aktiviert ist und die chain von Didit geprüft werden kann, wird eine neu angelegte Einzahlung zusätzlich geprüft und einmal zum Tarif für Wallet Verification & Screening abgerechnet.

Widget zur Wallet-Eigentümerstruktur

Um einen Transfer aus UNCONFIRMED_OWNERSHIP herauszuholen oder eine Wallet vorab zu verifizieren, bevor ein Transfer eingeht, erstellen Sie mit POST /v3/travel-rule/widget-session/ ein gehostetes Widget zur Wallet-Eigentümerstruktur und leiten Sie Ihren Kunden zur zurückgegebenen url weiter. Das Widget weist die Kontrolle über die Wallet nach, durch Nachrichtensignatur (einschließlich EVM-Smart-Contract-Konten über ERC-1271 und ERC-6492), einen Satoshi-Test, einen Screenshot oder eine Selbstauskunft. Anschließend markiert es den passenden Adressbuch-Eintrag als verifiziert, damit die Börse fortfahren kann. Ein Screenshot ist die Ausnahme: Er verifiziert die Wallet nie allein. Ihr Compliance-Team prüft ihn daher und bestätigt einen Transfer in UNCONFIRMED_OWNERSHIP mit POST .../travel-rule/ownership/. Siehe Widget zur Wallet-Eigentümerstruktur für den vollständigen Ablauf, die Nachweismethoden und den wichtigen Hinweis, dass das Widget in einem echten Browser geöffnet werden muss, niemals innerhalb einer mobilen SDK-Webview.

Verzeichnis

GET /v3/travel-rule/vasps/ durchsucht das VASP-Verzeichnis: die gemeinsamen Verzeichniseinträge sowie die Mitglieder des Didit-Netzwerks. Jede Zeile zeigt, wie Ihre Anwendung diesen VASP derzeit erreichen kann.
search gleicht einen Namens- oder Aliasbestandteil, eine exakte LEI oder eine Domain ab (counterparty.example oder eine URL darauf). Schränken Sie die Ergebnisse mit folgenden Parametern ein: Mitglieder des Didit-Netzwerks werden nicht bewertet. Daher liefern risk und responsiveness nur Verzeichniseinträge zurück. Die Ergebnisse werden nach Name sortiert und mit limit (Standard 50) und offset paginiert. Ein unbekanntes Netzwerk, ein unbekannter Ländercode, eine unbekannte Risikostufe oder ein unbekannter Reaktionsfähigkeitsstatus führt zu einer Antwort 400 mit Nennung des Feldes. GET /v3/travel-rule/vasps/{vasp_id}/ gibt eine Zeile anhand ihrer id zurück. Ihr eigenes VASP-Profil erscheint nie in Ihren eigenen Ergebnissen. dd_status, dd_score, dd_score_breakdown, dd_assessed_at, dd_score_semantic, risk_level, responsiveness und essential_checks enthalten die gemeinsame Due-Diligence-Bewertung eines Verzeichniseintrags. decision, entity_screening und questionnaires sind die eigenen Datensätze Ihrer Anwendung zu dem VASP, und kein anderer Kunde kann sie einsehen. Was jedes davon bedeutet, erfahren Sie unter Due Diligence für Gegenparteien. Steuern Sie Entscheidungen über diese Felder mit den Regelfeldern für Gegenparteien, statt direkt in der Anwendung Verzweigungen anhand dieser Werte vorzunehmen. Mitglieder des Didit-Netzwerks werden nicht bewertet: dd_status ist COMPLETED, dd_score ist null, risk_level ist leer und die Aufschlüsselung ist leer.

Routen

routes listet die Wege auf, über die Ihre Anwendung an den VASP zustellen kann, in der Reihenfolge, in der die Routing-Stufen sie durchprobieren. reachable ist true, wenn mindestens eine davon available ist:
  • TRP, wenn der Eintrag einen TRP-Endpoint enthält, den das Verzeichnis verifiziert hat.
  • GTR, TRUST, VERIFYVASP, SYGNA, wenn ein Netzwerk den VASP unter einem Code führt. Die Route ist nur available, wenn Ihre Anwendung heute über dieses Netzwerk senden kann (via: own_membership für Ihre eigene verbundene Mitgliedschaft, via: didit_membership für die Mitgliedschaft von Didit). Andernfalls ist sie unavailable mit reason: no_membership oder reason: network_switched_off und wird niemals als Weg zum VASP angezeigt. Die eigenen Netzwerkmitgliedschaften von Didit sind noch nicht aktiv. Daher ist eine Netzwerkroute derzeit nur über eine Mitgliedschaft verfügbar, die Sie im Marketplace verbunden haben.
  • EMAIL, wenn für den Eintrag ein Compliance-Kontakt vorhanden ist.
  • INTERNAL für ein Mitglied des Didit-Netzwerks.
Ein TRISA-Eintrag erscheint unter networks und zeigt, welcher VASP auf TRISA gelistet ist. Didit hat jedoch keinen TRISA-Kanal, daher ist er niemals eine Route. Eine Sandbox-Anwendung sendet nur an die Didit Test VASP. Daher ist ihr keine Verzeichnisroute verfügbar: Jede Route ist unavailable mit reason: sandbox_application, jede Zeile hat reachable: false, und reachable=true liefert keine Zeilen zurück.

Marken und ihre Rechtsträger

Eine Marke, die über mehrere regulierte Rechtsträger tätig ist, ist eine einzige Zeile, deren entities die Rechtsträger sind, die ihre Transfers empfangen. Ein Rechtsträgerdatensatz verweist über umbrella auf seine Marke zurück. Ein Transfer, der die Marke nennt, geht an einen ihrer Rechtsträger, der aus allen ausgewählt wird: derjenige in der Jurisdiktion, die in beneficiary_data.counterparty_vasp_jurisdiction angegeben ist, andernfalls der Rechtsträger, dem die Blockchain-Analytics-Zuordnung die Ziel-Wallet zuordnet, andernfalls der einzige Rechtsträger der Marke, wenn keine Jurisdiktion angegeben ist. Erst dann muss dieser Rechtsträger erreichbar sein. Ist er es nicht, geht der Transfer niemals stattdessen an einen anderen Rechtsträger oder an die Marke. Passt kein Rechtsträger (zwei passen gleich gut, oder eine angegebene Jurisdiktion ist bei keinem von ihnen vertreten), wird die eigene Route der Marke verwendet. Ohne diese trägt der Transfer den Status COUNTERPARTY_VASP_NOT_FOUND. Welcher Rechtsträger die Daten des Auftraggebers erhält, wird niemals geraten und niemals davon bestimmt, welcher Rechtsträger zufällig einen Kontakt hat. Mehrere Einträge mit demselben Namen, etwa Konzerngesellschaften mit gleichem Handelsnamen, werden nach derselben Regel unterschieden: derjenige in der angegebenen Jurisdiktion, andernfalls derjenige, den die Blockchain-Analytics-Zuordnung verknüpft hat. Wenn keine der beiden Regeln einen auswählt, wird keiner verwendet, und die Angaben gelten als Nennung keines Verzeichniseintrags.

Kontakte

contacts sind die Adressen, an die der EMAIL-Kanal schreibt. scope: platform-Kontakte stehen allen Didit-Kunden zur Verfügung: Didit pflegt sie (source: staff), oder eine Adresse unter einer eigenen Domain des VASP hat über ihren Antwortlink auf eine Anfrage geantwortet (source: learned). scope: application-Kontakte sind nur für Ihre Anwendung privat: diejenigen, die Sie hinzufügen (source: application), sowie eine Adresse außerhalb der eigenen Domains des VASP, die eine Ihrer Anfragen beantwortet hat (source: learned). Ein Transfer sendet E-Mails zuerst an den eigenen Kontakt Ihrer Anwendung, dann an einen Plattformkontakt, der bereits geantwortet hat (verified_at gesetzt), und danach an die übrigen. Verwalten Sie die eigenen Kontakte Ihrer Anwendung mit der API für Gegenparteikontakte:
  • GET /v3/travel-rule/counterparty-contacts/ listet jeden Kontakt, an den Ihre Anwendung senden darf, einschließlich Plattformkontakte und unzustellbarer Kontakte, neueste zuerst. Die Paginierung erfolgt mit limit und offset. Filtern Sie mit ?counterparty= und einer id eines Verzeichniseintrags. Ein Wert, der keine UUID ist, führt zu einer Antwort 400.
  • POST fügt einen privaten Kontakt hinzu (counterparty, email, optional name) und antwortet mit 201. Wenn die Adresse unter Ihren eigenen Kontakten für diesen Eintrag bereits vorhanden ist, wird dieser Kontakt zurückgegeben. Ein unbekannter Eintrag führt zu einer Antwort 400 ("No directory entry with this id.").
  • DELETE /v3/travel-rule/counterparty-contacts/{contact_uuid}/ löscht einen Ihrer eigenen Kontakte (204). Plattformkontakte können nicht gelöscht werden und führen zu einer Antwort 404.
Ein Kontakt, der einen Bounce ausgelöst oder sich beschwert hat, erhält is_invalid: true mit invalid_reason (hard_bounce, soft_bounce, spam_complaint oder suppressed), invalid_detail und invalid_at, und der Kanal EMAIL überspringt ihn. created_by ist bei Plattformkontakten leer und ebenso bei Kontakten, die über einen API-Schlüssel angelegt wurden.

So gelangen Einträge in das Verzeichnis

  • Das ESMA-Zwischenregister der MiCA-Anbieter von Krypto-Dienstleistungen, das wöchentlich eingelesen wird: Name, LEI und Heimatmitgliedstaat jedes Anbieters.
  • Das öffentliche TRISA-Verzeichnis, das wöchentlich eingelesen wird: wer jedes Mitglied ist, in welchem Land es ansässig ist und welchen TRISA-Eintrag es hat. Ein Eintrag, den das Verzeichnis drei Wochen lang nicht mehr anzeigt, wird entfernt.
  • Das globale LEI-Register ergänzt bei einem Eintrag die LEI, weitere amtliche Firmennamen und das Land und findet die LEI eines Eintrags über dessen exakten amtlichen Namen in dessen Land.
  • Zuordnung durch Blockchain-Analytics ergänzt oder gleicht den VASP ab, dem eine Ziel-Wallet gehört, und behält den zugeordneten Namen als Alias.
  • Didit-Mitarbeitende pflegen Einträge: verifizierte Routing-Kennungen und Netzwerkeinträge, Compliance-Kontakte, Aliase, Marken und deren Gesellschaften, zusammengeführte Duplikate und ausgeblendete Einträge.
Daten, die ein Kunde zu einer Gegenpartei meldet, etwa ein eingehender originating_vasp oder eine Travel Address, bleiben bei dem Transfer dieses Kunden und verändern nie einen gemeinsamen Eintrag. Einträge werden zuerst über die LEI abgeglichen, danach über den exakten Namen oder Alias. Sie werden angereichert statt dupliziert.

Das Didit-Netzwerk

Ihr VASP-Profil ist Mitglied des Didit-Netzwerks, sodass andere Didit-Kunden es im Verzeichnis und in der VASP-Auswahl des Endbenutzers finden. Dies gilt nur, solange alle der folgenden Bedingungen erfüllt sind:
  • Ihre Anwendung befindet sich in der Produktion (nicht in der Sandbox) und die Travel Rule ist aktiviert;
  • is_discoverable ist true und legal_name ist gesetzt;
  • compliance_email ist gesetzt und bestätigt: Senden Sie die Bestätigung mit POST /v3/travel-rule/settings/compliance-email/confirmation/ und öffnen Sie den E-Mail-Link. Bei einer Änderung der Adresse ist eine neue Bestätigung erforderlich;
  • Didit hat die Anwendung nicht als Test-, Demo- oder interne Anwendung markiert.
Der Kanal INTERNAL selbst liefert an eine Wallet, deren Besitz Sie nachgewiesen haben, wie unter Transfer senden beschrieben. Dafür muss Ihre Anwendung produktiv sein, die Travel Rule aktiviert sein und die Auffindbarkeit (is_discoverable) aktiviert sein. Die übrigen Punkte der Liste gelten dafür nicht. GET /v3/travel-rule/settings/ liefert didit_network mit listed und compliance_email_confirmed. In missing stehen alle Bedingungen, die noch nicht erfüllt sind (travel_rule_off, sandbox_application, not_discoverable, legal_name_missing, compliance_email_missing, compliance_email_unconfirmed, excluded_by_staff, internal_organization).

Routing-Kennungen

Beim ausgehenden Routing wird ein Verzeichniseintrag abgefragt, wenn Ihr Transfer die Gegenpartei über counterparty_vasp_lei oder counterparty_vasp_name benennt (ein Alias funktioniert ebenso). Ein Eintrag enthält je Netzwerk, über das er erreichbar ist, eine Kennung, einen verifizierten TRP-Endpoint und seine Compliance-Kontakte. routes zeigt, welche davon Ihre Anwendung nutzen kann. Sie können das Verzeichnis bei einem einzelnen Transfer immer umgehen, indem Sie die expliziten Felder übergeben, die unter Felder zur Auflösung der Gegenpartei beschrieben sind.

Due-Diligence für Gegenparteien

Bevor Gelder Ihrer Kunden eine andere VASP erreichen, müssen Sie wissen, wer diese VASP ist und ob Sie sie akzeptieren. Die Due-Diligence für eine Gegenpartei umfasst zwei Ebenen:
  • Die gemeinsame Bewertung. Jeder Verzeichniseintrag enthält einen Due-Diligence-Score, seine Risikostufe, einen Reaktionsstatus und einen Bericht über wesentliche Prüfungen. Didit berechnet diese Werte aus den eigenen Daten der Plattform, sodass jeder Kunde dieselben Werte sieht.
  • Ihre eigenen Unterlagen. Ihre Entscheidung über die VASP, Ihre Sanktionsprüfung und Ihr Screening auf negative Medienberichte sowie die Due-Diligence-Fragebögen, die Sie mit ihr ausgetauscht haben, gehören ausschließlich zu Ihrer Anwendung. Kein anderer Kunde sieht sie, und sie verändern nie den gemeinsamen Eintrag.
Ihre eigenen Unterlagen funktionieren sowohl für einen Verzeichniseintrag als auch für ein Mitglied des Didit-Netzwerks. Adressieren Sie beide über die id, die das Verzeichnis anzeigt.

Score und Risikostufe

dd_score reicht von 0 bis 100, und ein höherer Wert ist sicherer. Jedes Ergebnis weist in dd_score_semantic darauf hin; dieser Wert ist immer higher_is_safer. risk_level ist die Stufe, in die der Score fällt: Der Score ist die Summe von sieben Komponenten. dd_score_breakdown zeigt jede davon als {points, max, reason, detail}: max ist das Gewicht der Komponente, reason ein maschinenlesbarer Code, den Sie übersetzen können, und detail eine einzeilige englische Erläuterung. Punkte werden auf eine Dezimalstelle gerundet, die Summe auf eine ganze Zahl. history berücksichtigt dieselben Anfragen wie die Reaktionsfähigkeit, ohne Zeitfenster: Ein Austausch mit COMPLETED oder FINISHED gilt als erfolgreich, ein Austausch mit EXPIRED, COUNTERPARTY_MISMATCHED_DATA oder COUNTERPARTY_VASP_GENERAL_DECLINE gilt als fehlgeschlagen. Eine Stornierung ist eine eigene Handlung des Absenders und zählt nie. Didit berechnet die Bewertung neu, wenn ein Austausch mit dem Eintrag abgeschlossen oder beendet wird, abläuft, nicht übereinstimmende Daten aufweist oder abgelehnt wird, wenn der Eintrag aktualisiert oder kuratiert wird und für jeden Eintrag bei der wöchentlichen Aktualisierung des Verzeichnisses. dd_assessed_at zeigt, wann sie zuletzt lief. Ein Eintrag, der noch nicht bewertet wurde, hat kein dd_assessed_at, einen dd_score von 0 und eine leere risk_level. Lesen Sie daher risk_level statt des rohen Scores. Mitglieder des Didit-Netzwerks werden nicht bewertet: Ihr dd_score ist null, ihre risk_level ist leer und ihr dd_score_breakdown ist leer.

Wesentliche Prüfungen

essential_checks ist ein kurzer Bericht über vier Prüfungen, die Didit bei jedem Verzeichniseintrag durchführt. Grundlage sind ausschließlich die verifizierten Quellen der Plattform, niemals Daten, die ein Kunde gemeldet hat. Jede Prüfung in checks meldet ihren status (pass, fail oder unknown, wenn keine gespeicherte Quelle eine Entscheidung darüber zulässt), einen maschinenlesbaren reason und eine einzeilige englische detail. passed, failed, unknown und total zählen die Prüfungen, level ist essential, und checked_at zeigt, wann der Bericht erstellt wurde. Die Komponente essentials bewertet den Anteil der entschiedenen Prüfungen, die bestanden werden. Eine unknown-Prüfung zählt daher weder für noch gegen den Eintrag. Der Bericht bleibt leer, bis die wöchentliche Aktualisierung des Verzeichnisses einen Eintrag zum ersten Mal prüft, und er ist für ein Mitglied des Didit-Netzwerks immer leer.

Reaktionsfähigkeit

responsiveness zeigt, ob die VASP auf Travel-Rule-Anfragen antwortet:
total zählt die Anfragen, die Didit-Kunden an die VASP in den letzten 90 Tagen gestellt haben und deren Ergebnis feststeht. answered zählt diejenigen, die sie beantwortet hat.
  • Wird gezählt: Anfragen über einen Netzwerk- oder Protokollkanal sowie Anfragen, die an eine gemeinsam genutzte Adresse per E-Mail gesendet wurden. Dazu gehören die Compliance-Adresse des Eintrags oder ein Plattformkontakt.
  • Wird nie gezählt: Eine Anfrage, die per E-Mail an eine von einem Kunden selbst eingegebene Adresse gesendet wurde, oder an einen privaten Kontakt eines Kunden. Ein solcher Austausch bleibt im Transferverlauf des Kunden und kennzeichnet die VASP nie für alle anderen.
  • Beantwortet: COMPLETED, FINISHED, COUNTERPARTY_VASP_GENERAL_DECLINE oder COUNTERPARTY_MISMATCHED_DATA. Eine Ablehnung oder eine Nichtübereinstimmung ist eine Antwort: Die VASP hat reagiert.
  • Unbeantwortet: EXPIRED.
  • Weder noch: jeder andere Status. Eine CANCELLED-Anfrage ist eine eigene Handlung des Absenders. COUNTERPARTY_VASP_NOT_REACHABLE kann auf Seiten des Absenders ein Fehler sein. Eine Anfrage, die noch läuft, ist noch nicht entschieden.
Mitglieder des Didit-Netzwerks antworten innerhalb von Didit und werden immer mit UNKNOWN und Zählern von null angezeigt. Um auf eine nicht reagierende Gegenpartei zu reagieren, verwenden Sie die Richtlinie für nicht reagierende Gegenparteien oder das Preset travel-rule-counterparty-unresponsive.

Ihre Entscheidung zu einer Gegenpartei

Halten Sie das Urteil Ihres Compliance-Teams zu einer Gegenpartei mit PUT /v3/travel-rule/vasps/{vasp_id}/decision/ fest:
  • Die Entscheidung ist nur für Ihre Anwendung sichtbar: Ein anderer Kunde sieht sie nie, und sie ändert nie den gemeinsamen Eintrag.
  • Eine Entscheidung allein bewirkt nichts und ändert nie, wie ein Transfer geroutet wird. Sie wirkt sich auf Ihre Transaktionen über das Regelfeld counterparty_dd_status aus: Installieren Sie die Presets oder schreiben Sie eigene Regeln darauf.
  • Eine Entscheidung zu einer Marke gilt für jede ihrer Entitäten, die keine eigene Entscheidung hat, und die Entität zeigt die Marke in inherited_from an. Eine Entscheidung zur Entität überschreibt die der Marke für diese Entität.
  • GET liefert die Entscheidung, die gilt, oder {"decision": null}. DELETE löscht Ihre eigene Entscheidung und liefert zurück, was danach gilt: die Entscheidung der Marke für eine Entität, andernfalls null. Die Anfrage liefert 404 zurück, wenn Ihre Anwendung zu der Gegenpartei keine eigene Entscheidung hat.
  • reason ist optional, bis zu 255 Zeichen lang, und jedes PUT ersetzt es. decided_by ist der Konsolenbenutzer, der die Entscheidung getroffen oder zuletzt geändert hat, und ist leer, wenn sie über einen API-Schlüssel getroffen wurde.

Screening der Gegenpartei

Das Screening der Gegenpartei prüft das VASP der Gegenpartei als Unternehmen selbst auf Sanktionen und negative Medienberichte. Es ist optional und kostenpflichtig: Aktivieren Sie es mit counterparty_screening_enabled in Ihren Einstellungen. Solange es deaktiviert ist, wird nichts geprüft und nichts abgerechnet.
  • Abrechnung. Jedes neue Screening kostet den Preis für das AML-Screening von Unternehmen Ihrer Organisation. GET /v3/travel-rule/vasps/{vasp_id}/screening/ liefert diesen price, fresh_days und ob das Screening enabled ist, kostenlos. Ein Screening, das jünger als 30 Tage ist, ist aktuell: POST liefert es mit 200 und outcome: reused erneut zurück und rechnet nichts ab, es sei denn, Sie senden refresh: true. Bei einem neuen Screening wird 201 mit outcome: screened zurückgegeben. Sandbox-Anwendungen werden niemals geprüft oder abgerechnet.
  • Automatisches Screening. Ist das Screening aktiviert, prüft Didit außerdem die Gegenpartei eines ausgehenden Austauschs, sobald der Austausch beginnt, bevor Ihre Regeln die Transaktion auswerten, unter denselben Bedingungen für Wiederverwendung und Abrechnung. Eine Ablehnung oder ein Fehler an dieser Stelle lässt den Transfer nie scheitern.
  • Ergebnis. status ist Approved, wenn kein möglicher Treffer Aufmerksamkeit erfordert, und In Review oder Declined bei einem möglichen Treffer bei Sanktionen oder negativen Medienberichten. flagged ist true, solange ein aktuelles Screening In Review oder Declined ist.
  • Auswirkung. Solange Ihr letztes Screening einer Gegenpartei markiert ist und das Screening aktiviert bleibt, ist counterparty_risk_level in Ihren Regeln HIGH. Damit hält das Preset travel-rule-counterparty-high-risk nach der Installation ihre Transfers zurück. Das gemeinsame risk_level im Verzeichnis ändert sich nicht.
  • Datenschutz. Das Screening ist nur für Ihre Anwendung sichtbar: Ein anderer Kunde sieht es nie, und es ändert nie den gemeinsamen Eintrag. Das Verzeichnis zeigt Ihr letztes Screening als entity_screening an.
  • Ablehnungen. 409, wenn das Screening deaktiviert ist, bei einer Sandbox-Anwendung oder während bereits ein Screening derselben Gegenpartei läuft. 403 mit code: insufficient_credits, wenn Ihr Guthaben den Preis nicht deckt. 502, wenn das Screening nicht abgeschlossen werden konnte. In keinem dieser Fälle wird etwas abgerechnet.

Fragebogen zur Sorgfaltsprüfung

Bitten Sie eine Gegenpartei mit dem Standardfragebogen von Didit um ihre Antworten zur Sorgfaltsprüfung. POST /v3/travel-rule/vasps/{vasp_id}/questionnaires/ sendet ihn per E-Mail an eine hinterlegte Compliance-Adresse der Gegenpartei, zusammen mit einem Einmal-Link zu einer Antwortseite:
  • Empfänger. sent_to muss eine hinterlegte Compliance-Adresse sein: bei einem Verzeichniseintrag deren Compliance-Adresse oder ein Kontakt, den Ihre Anwendung in contacts sieht; bei einem Mitglied des Didit-Netzwerks deren bestätigte Compliance-E-Mail. Lassen Sie das Feld weg, um die Adresse zu verwenden, an die eine Travel-Rule-E-Mail an die Gegenpartei geht: zuerst Ihr eigener Kontakt, dann ein Plattformkontakt, dann die Compliance-Adresse des Eintrags. Didit sendet den Fragebogen nie an eine andere Stelle und antwortet mit 400, wenn die Gegenpartei keine Compliance-Adresse hinterlegt hat.
  • Beantwortung. Der Link öffnet /v3/travel-rule/questionnaires/{token}/, eine Seite für eine Person bei der Gegenpartei, die dafür kein Konto und keinen API-Schlüssel benötigt. Sie beantwortet jede Frage, bis zu 2.000 Zeichen je Frage (N/A, wenn eine Frage nicht zutrifft), und reicht sie einmal ein. Eine Gegenpartei kann außerdem {"answers": {"<question id>": "<answer>"}} an denselben Link senden. Ein Link, der bereits verwendet oder ersetzt wurde oder dessen Gültigkeitsfrist abgelaufen ist, zeigt stattdessen eine Seite mit abgelaufenem Link. Die E-Mail und die Seite sind übersetzt; die Fragen selbst stehen immer auf Englisch, damit ihre Bedeutung in allen Sprachen gleich bleibt.
  • Fristen. Die Gegenpartei hat 30 Tage Zeit zu antworten (expires_at). Antworten bleiben 365 Tage gültig (valid_until), und current ist bis dahin true. Ein unbeantworteter Fragebogen nach Ablauf der Frist und Antworten nach Ablauf ihrer Gültigkeit werden EXPIRED.
  • Ein offener Fragebogen pro Gegenpartei. Ein neuer Versand ersetzt Ihren früheren unbeantworteten Fragebogen an dieselbe Gegenpartei: Er wird EXPIRED, und sein Link funktioniert nicht mehr. An eine Adresse kann nur eine E-Mail pro Minute gehen; ein schnellerer Versand führt zu 429.
  • Antworten abrufen. GET /v3/travel-rule/vasps/{vasp_id}/questionnaires/ listet Ihre Fragebögen zu der Gegenpartei auf, neueste zuerst, wobei answers nach Frage-ID als Schlüssel strukturiert ist, sobald beantwortet. Das Verzeichnis zeigt sie als questionnaires an. Sie sind nur für Ihre Anwendung sichtbar.
Formularversion 1 stellt diese zwölf Fragen:

Transfers mit einer Gegenpartei

GET /v3/travel-rule/transfers/?counterparty={vasp_id} listet die Travel-Rule-Transfers Ihrer Anwendung mit einer Gegenpartei auf, die neuesten zuerst, anhand der id, die das Verzeichnis anzeigt: Ihre Transfers, deren Gegenpartei dieser Verzeichniseintrag ist, oder Ihre INTERNAL-Austausche mit diesem Didit-Netzwerkmitglied. Ein Wert, der keine gültige ID ist, liefert 400. Jede Zeile enthält reason direkt nach status: die eigene reason des Transfers. So erkennen Sie in der Liste eine unzustellbare Compliance-E-Mail oder eine Gegenpartei ohne Route, ohne jeden Transfer einzeln zu öffnen.

Sunrise-Richtlinie und Richtlinie für nicht reagierende Gegenparteien

Wenn ein Transfer abläuft (confirmation_timeout_hours verstrichen, während er AWAITING_COUNTERPARTY war), entscheidet timeout_outcome, was mit seiner Transaktion geschieht. Zwei Einstellungen erlauben es Ihnen, zwei häufige Gründe für ein Timeout unterschiedlich zu behandeln: Beide akzeptieren HOLD, REJECT oder PROCEED mit derselben Bedeutung wie bei timeout_outcome oder einen leeren String, um timeout_outcome zu übernehmen. Beide sind standardmäßig leer, sodass sich nichts ändert, bis Sie eine festlegen:
Die erste dieser Richtlinien, die zutrifft, entscheidet über das Ergebnis:
  1. sunrise_policy, wenn sie gesetzt ist und die Rechtsordnung der Gegenpartei in sunrise_jurisdictions enthalten ist.
  2. non_responsive_policy, wenn sie gesetzt ist und die Gegenpartei UNRESPONSIVE ist.
  3. timeout_outcome in allen anderen Fällen, einschließlich eines Transfers an ein Didit-Netzwerkmitglied oder an eine Gegenpartei ohne Verzeichniseintrag.
sunrise_jurisdictions ist schreibgeschützt und derzeit ["CO", "KH", "VN"]. Nur diese Länder gelten als in einer Sunrise-Phase: Jede andere Rechtsordnung sowie eine leere oder unbekannte folgen timeout_outcome, sodass eine Gegenpartei niemals versehentlich Ihre Sunrise-Richtlinie erhält. Die Zeitleiste des abgelaufenen Transfers nennt das angewandte Ergebnis, zum Beispiel sunrise_policy=PROCEED (counterparty jurisdiction CO does not enforce the Travel Rule yet). Ihre Regeln laufen auch nach dem Ablauf weiter, sodass eine Regel wie die EU-TFR-Regel tr_eu_expired_review die Transaktion unter PROCEED dennoch in die Prüfung verschieben kann.

Regelfelder und Vorlagen

Vier Regel-Felder enthalten, was Ihre Anwendung über die Gegenpartei weiß, die der Travel-Rule-Austausch einer Transaktion erreicht hat: ihren Verzeichniseintrag oder bei einem INTERNAL-Austausch den Didit-Kunden, der die Transaktion empfangen hat. Jedes Feld ist leer, wenn der Austausch keine bekannte Gegenpartei erreicht hat. Fünf Vorlagen im travel_rule-Bundle wirken auf diese Felder. Installieren Sie sie unter Transactions → Rules → Library in der Business Console oder mit der Regelbibliotheks-API: Alle fünf gelten nur für Travel-Rule-Transaktionen.

Webhooks

Registrieren Sie ein Webhook-Ziel für travel_rule.status.updated, um bei jedem Statuswechsel jedes ausgehenden und eingehenden Transfers in Ihrer Anwendung benachrichtigt zu werden, einschließlich der Transaktionsabschnitte auf der INTERNAL-Schiene. Das Routing läuft erst, nachdem die Anfrage zum Erstellen der Transaktion eine Antwort zurückgegeben hat. Ergebnisse wie COUNTERPARTY_VASP_NOT_FOUND, COUNTERPARTY_VASP_NOT_REACHABLE oder ein über INTERNAL abgewickelter Austausch, der sofort abgeschlossen wird, erreichen Sie daher über dieses Ereignis und nicht in der Antwort auf die Erstellung.
rail ist leer, bis eine Schiene ausgewählt ist. Für eine Transaktion sendet Didit travel_rule.status.updated nach transaction.created: Wenn Didit die Transaktion erstellt (über Ihr POST /v3/transactions/, eine Sunrise-Registrierung, eine eingehende TRP-Anfrage oder der eingehende Transaktionsabschnitt auf der INTERNAL-Schiene), sendet es zuerst transaction.created. Jedes Ereignis wird einzeln zugestellt und einzeln wiederholt. Daher kann ein transaction.created, das einen Wiederholungsversuch benötigte, nach einem Statusereignis eintreffen. Verwenden Sie transaction_id als Schlüssel in Ihrem Handler, und rufen Sie die Transaktion ab, wenn ein Statusereignis eine Transaktion nennt, die Sie noch nicht kennen. Ein über TRUST gesendeter Transfer erhält kein COMPLETED-Ereignis: TRUST sendet nichts zurück, das Didit lesen kann. Sofern das Senden nicht fehlschlägt oder Sie den Transfer abbrechen, ist daher das letzte Ereignis EXPIRED. Bei GTR, VERIFYVASP und SYGNA richtet sich das Ereignis nach der Antwort, die Didit aus dem Netzwerk liest. Sandbox-Anwendungen senden dieses Ereignis ebenfalls, mit "environment": "sandbox". Ein Transfer, den der Didit Test VASP beantwortet hat, trägt rail: "TEST_VASP", test_vasp: true und test_vasp_scenario. Den vollständigen Ereigniskatalog, die Signaturprüfung und die Wiederholungsrichtlinie finden Sie im Webhooks-Leitfaden.

Preise

Die Travel-Rule-Gebühr beträgt $0.02 pro ausgehendem Austausch, der startet. Sie wird einmal bei der Erstellung der Transaktion berechnet, unabhängig davon, wie viele Statuswechsel der Austausch danach durchläuft. Ein resend berechnet sie nie erneut.
  • Sie gilt für eine ausgehende travelRule-Transaktion in einer Anwendung mit aktivierter Travel Rule, deren Betrag mindestens Ihrem threshold_amount entspricht, sodass Didit dafür einen verwalteten Austausch startet. Ein Transfer an eine selbstverwahrte Wallet oder an die eigene verifizierte Wallet Ihres Benutzers zählt ebenfalls: Der Eigentumsnachweis ist dessen Austausch.
  • Jede andere ausgehende Transaktion, die Travel-Rule-Daten enthält, wird als standardmäßiges Transaction Screening abgerechnet. Das ist in Ihrem Tarif bis zu dessen monatlichem Transaktionskontingent enthalten und kostet darüber hinaus $0.001. Dazu gehören ein Transfer unterhalb Ihres Schwellenwerts, eine Lightning-Zahlung, auf die die Travel Rule nicht angewendet wird, und ein passiv erfasster Transfer, wenn Travel Rule ausgeschaltet ist. Eine Transaktion wird über genau eine der beiden Positionen abgerechnet, niemals über beide.
  • Eingehende travelRule-Transaktionen verursachen keine Gebühr für Travel Rule oder Monitoring. Das gilt für den eingehenden Transaktionsabschnitt, den Didit in der Anwendung des Begünstigten über die INTERNAL-Schiene erstellt, für eingehende TRP-Anfragen und für Registrierungen nach der Einzahlung.
  • Eine Anwendung, die dem kostenlosen Travel-Rule-Angebot beigetreten ist, zahlt bei ausgehenden travelRule-Transaktionen keine der beiden Gebühren, bis sie die ausgehende Abrechnung mit POST /v3/travel-rule/workspace/billing/ aktiviert. Der Empfang bleibt kostenlos.
  • Sandbox-Anwendungen werden nie berechnet.
  • Die Travel-Rule-Gebühr ist mit $0.02 angesetzt, Transaction Screening mit $0.001 jenseits Ihres Kontingents. Jede Transaktion wird zum Preis der Position berechnet, über die sie abgerechnet wird.
  • Wenn auf derselben Transaktion auch Krypto-AML-/Wallet-Screening läuft (zum Beispiel bei einer eingehenden Einzahlung mit currency_kind: "crypto" und aktiviertem Monitoring), wird das separat zum Standardpreis für Wallet Verification & Screening berechnet. Es ist nicht in der Travel-Rule-Gebühr enthalten.
  • Gegenpartei-Screening muss ausdrücklich aktiviert werden und wird separat berechnet, zum Preis für Company AML Screening pro Screening. Ein Screening, das jünger als 30 Tage ist, wird ohne Kosten wiederverwendet. Entscheidungen, Fragebögen und die Due-Diligence-Bewertung im Verzeichnis kosten nichts.

Attribution-Preise

Für die Blockchain-Analytics-Attribution ist eine Wallet-Abfrage beim Analytics-Anbieter nötig, und Sie erhalten immer den vollen Wert dieser Abfrage:
  • Das Krypto-Monitoring hat die Wallet bei dieser Transaktion bereits geprüft: Das gespeicherte Ergebnis wird wiederverwendet. Es fällt ein Analytics-Aufruf und eine Abrechnung für Wallet Verification & Screening an (dieselbe, die das Krypto-Monitoring bereits erzeugt hat). Die Attribution fügt nichts hinzu.
  • Das Krypto-Monitoring lief nicht: Didit führt den erforderlichen Analytics-Aufruf einmal aus und gibt dessen vollen Wert weiter. Die Transaktion wird zum Standardpreis für Wallet Verification & Screening abgerechnet ($0.15 mit von Didit verwalteter Analytics) und erhält dafür die vollständige Krypto-Screening-Ausgabe zurück: Risiko-Score, Risikokategorie der Wallet, Netzwerk-Snapshot, nicht nur den VASP-Namen. Die Nutzungsposition ist mit dem Auslöser travel_rule_attribution markiert, damit die Abrechnung nachvollziehbar ist.
  • Eigener Analytics-Schlüssel: Hier gilt dieselbe Plattformgebühr wie für das Krypto-Monitoring mit Ihrem eigenen Schlüssel ($0.02 pro Aufruf). Ihr Anbieter stellt Ihnen die zugrunde liegende Abfrage direkt in Rechnung.
  • Fehlgeschlagene Abfragen werden nie berechnet. Wiederholungen verwenden die gespeicherte Attribution ohne neuen Aufruf und ohne neue Abrechnung. Sandbox-Anwendungen werden nie berechnet.
Ein ausgehender Transfer, der eine Attribution benötigte, kostet also $0.02 (Travel Rule) plus eine Abrechnung für Wallet Verification & Screening. Wenn beide Produkte aktiviert sind, finden der Analytics-Aufruf und seine Abrechnung nur einmal statt.

Regelpaket EU TFR

Vier vordefinierte Regeln sind im Bundle travel_rule_eu_tfr enthalten, speziell für die Pflichten nach der EU-TFR entwickelt. Wie jedes andere vordefinierte Bundle aktivieren Sie es in der Business Console unter Transactions → Rules → Library. Diese Regeln greifen bei jedem relevanten Statuswechsel: bei der Erstellung des Transfers, bei der Bestätigung des Eigentums, bei der Antwort nach dem Abruf der E-Mail und im Ablaufprozess (Ablaufbereinigung). So bleibt ein Transfer, der nie abgeschlossen wird, für die Compliance-Prüfung sichtbar, statt stillschweigend abgewickelt zu werden.

Warum das auf einer Plattform besser funktioniert

Die Einhaltung der Travel Rule ist ein Identitätsproblem im Zahlungsgewand, und Didit verfügt bereits über die Identitätsdaten:
  • Verifizierte Daten bereits vorhanden. Die betroffene Person jedes Transfers ist über vendor_data mit dem KYC-Profil verknüpft, das Didit beim Onboarding verifiziert hat (Dokument-OCR, Liveness-Erkennung, Gesichtsabgleich). So können Sie originator_data auf derselben Plattform aus verifizierten Feldern aufbauen. Bei einem Benutzer mit genehmigter KYC-Verifizierung übermittelt Didit die verifizierte Identität und nicht die von Ihnen eingegebenen Werte (siehe Verifizierte Daten und Herkunftsnachweis).
  • Biometrische Step-up-Prüfung für riskante Transfers. Eine Regel kann jeden Transfer mit hohem Betrag zurückhalten, bis der Benutzer eine biometrische Nachprüfung gegen das beim Onboarding erfasste Gesicht bestanden hat, die wirksamste Antwort auf eine Kontoübernahme im Moment der Auszahlung. Siehe das Praxisbeispiel.
  • Ein einheitlicher Gerätegraph. Über das SDK übermittelte Transfers enthalten dieselben Geräteinformationen und -signale wie KYC-Sitzungen. Damit ist „neues Gerät + hoher Betrag + erstmaliger Begünstigter“ eine einzige Regel und keine Data-Warehouse-Verknüpfung.
  • Screening, Regeln, Fälle und Exchange an einem Ort. Das Wallet-Screening, das die VASP der Gegenpartei zuordnet, ist dasselbe Screening, das Ihre Regeln und Analysten sehen. Das bedeutet eine Abrechnung, eine Konsole und einen Audit-Trail.
  • Veröffentlichte Preise. $0.02 pro ausgehendem Exchange, keine Volumenstufen, kein Verkaufsgespräch.

FAQ

Wie der Austausch funktioniert

Didit führt den Austausch selbst durch. Wenn Sie eine travelRule-Transaktion übermitteln, ermittelt Didit live die Gegenpartei, sendet die Daten des Auftraggebers und des Begünstigten über die Kanäle, die sie transportieren, an den empfangenden VASP und setzt die Transaktion erst dann auf COMPLETED, wenn die Seite der Gegenpartei sie bestätigt. Es handelt sich um einen verwalteten Handshake, kein Protokoll, das nach der Abwicklung geführt wird. Eine Antwort der Gegenpartei wird auf jedem Kanal verarbeitet, außer auf TRUST, der nur sendet. Eine Transaktion darüber läuft daher ab, statt abgeschlossen zu werden. Über GTR, VERIFYVASP und SYGNA liest Didit die Antwort aus der Antwort des Netzwerks oder fragt sie alle 5 Minuten ab. Über keines dieser Netzwerke ist bisher ein Austausch gegen ein Live-Netzwerk abgeschlossen worden. Über TRP benötigt eine Antwort, die die Gegenpartei nicht sofort gibt, den öffentlichen TRP-Host von Didit, der noch nicht live ist (siehe Travel-Rule-Netzwerke). Didit speichert außerdem den vollständigen Datensatz und den Compliance-Status jedes Austauschs (einen Lebenszyklus mit 13 Zuständen, Webhooks und ein Audit-Trail). Wenn Sie Travel Rule lieber über Ihren eigenen Prozess abwickeln, kann Didit die Daten stattdessen passiv aufzeichnen, als Ihr einziges führendes Aufzeichnungssystem (siehe die Frage zur passiven Aufzeichnung weiter unten). Beide Modi sind verfügbar: Der aktive Austausch läuft, sobald Sie is_enabled: true in den Einstellungen setzen (standardmäßig ist es false). Bis dahin zeichnet Didit die Daten passiv auf.
Er ist nativ implementiert. Didit betreibt seine eigene Implementierung des Travel Rule Protocol (TRP), die unter trp.didit.me bereitgestellt wird, sobald dieser öffentliche Host live ist. Bis dahin antwortet er noch nicht, sodass Gegenparteien Sie heute nicht über TRP erreichen können. Didit implementiert außerdem die Netzwerkprotokolle der Branche direkt: GTR (Global Travel Rule), TRUST, VerifyVASP und Sygna Bridge (nativ unterstützt, einschließlich der ECIES-verschlüsselten IVMS-101-Daten von Sygna und signierter Berechtigungsanfragen). Didit ist kein Wiederverkäufer einer einzelnen Interoperabilitätsschicht eines Drittanbieters. Eine Gegenpartei, die in einem bestimmten Mitgliedsnetzwerk angesiedelt ist, erreicht man zwangsläufig über dieses Netzwerk. Es gibt im Travel Rule keinen einzigen universellen Kanal. Die Ermittlung, der Handshake, die Verifizierung und die Aufzeichnung führt jedoch Didit vollständig aus. Heute benötigt jeder Netzwerkkanal Ihre eigene Mitgliedschaft, und TRUST sendet nur. Siehe Übersicht.
Nativ implementiert und in strikter Prioritätsreihenfolge ausprobiert: INTERNAL (beide VASPs bei Didit), TRP (OpenVASP Travel Rule Protocol), GTR, TRUST, VerifyVASP, Sygna Bridge und ein EMAIL-Fallback für Gegenparteien ohne Tools. Die Netzwerkkanäle benötigen heute Ihre eigene Mitgliedschaft. TRUST sendet nur, und der Empfang über ein Netzwerk ist noch nicht freigeschaltet. Siehe Travel-Rule-Netzwerke. CODE, TRISA, Notabene und Veriscope erscheinen im Marketplace von Didit als Kacheln mit Zugriffsanfrage, ohne bestehende Integration. Die vollständige Routing-Tabelle finden Sie unter So leitet Didit einen Austausch weiter. Was jedes Netzwerk heute erreicht, steht unter Travel-Rule-Netzwerke.
TRP ist die Grundlage, die wir empfehlen. Es erfordert keine gemeinsame Mitgliedschaft. Wenn Sie Ihre Travel Address teilen, kann jede VASP, die TRP spricht, Sie erreichen. Ist eine Gegenpartei nur über eine Wallet-Adresse bekannt, leitet die Zuordnung über Blockchain-Analyse sie nur dann über TRP weiter, wenn der zugeordnete Verzeichniseintrag bereits einen TRP-Endpunkt hat. Bei ausgehenden Transaktionen sendet Didit die unter TRP-Asset-Kennungen aufgeführten Assets darüber. Eine Gegenpartei, die nicht sofort antwortet, benötigt den öffentlichen TRP-Host von Didit, der noch nicht live ist. Bei den Mitgliedsnetzwerken wählen Sie nach dem Ort, an dem Ihre Gegenparteien tätig sind: GTR bietet eine breite globale Abdeckung, TRUST richtet sich an VASPs in den USA, und VerifyVASP (das nun auch Sygna Bridge betreibt) hat eine starke Abdeckung in Asien. Ja, heute benötigen Sie eine eigene Mitgliedschaft. Didit hat auf diesen Netzwerken noch keine Plattformmitgliedschaft und wird gerade als Anbieter aufgenommen. Verbinden Sie Ihre Mitgliedschaft im Marketplace. Sie sind nicht auf ein einziges Netzwerk festgelegt. Denken Sie daran, dass TRUST nur sendet. Eine Transaktion darüber wird daher nicht abgeschlossen. Außerdem ist über kein Netzwerk bisher ein Austausch gegen ein Live-Netzwerk abgeschlossen worden.
Über eine Auflösungskette: zuerst ein anderer Didit-Kunde, der die Kontrolle über die Wallet nachgewiesen hat (der INTERNAL-Kanal), dann Ihr eigenes Wallet-Adressbuch für eine gespeicherte Travel Address, anschließend die Protokoll- und Netzwerkkanäle und schließlich die Zuordnung über Blockchain-Analyse. Wenn die Transaktion nur eine Zieladresse enthält, gleicht Didit diese mit Daten der Blockchain-Analyse ab, ordnet die Börse oder den Verwahrdienst der Gegenpartei zu und katalogisiert diesen im VASP-Verzeichnis. Die Transaktion wird nur dann automatisch weitergeleitet, wenn der Verzeichniseintrag bereits einen Pfad hat, etwa einen TRP-Endpunkt. Andernfalls endet sie mit COUNTERPARTY_VASP_NOT_FOUND, wobei der Name der Gegenpartei gespeichert wird. Sie können die Transaktion erneut senden, sobald ein Pfad existiert. Das ist zum Beispiel der Fall, wenn Sie die travel_address der Gegenpartei im Adressbuch-Eintrag für diese Wallet speichern (für die unter TRP-Asset-Kennungen aufgeführten Assets).

Preise und Lizenzierung

Travel Rule ist ein separates, nutzungsabhängiges Produkt. Es ist nicht in der Identitätsverifizierung enthalten. Es kostet **$0.02 pro ausgehendem Austausch, der startet** ([veröffentlichte Preise](#preise), keine Volumenstufen, kein Verkaufsgespräch). Wenn das Routing eine Abfrage der Blockchain-Analyse benötigt, um die Gegen-VASP zu identifizieren, wird diese Abfrage einmalig zum [Zuordnungstarif](#attribution-preise) berechnet: ab $0.15 bei verwaltetem Zugang oder $0.02 mit einem bestehenden Anbieterschlüssel. Sie wird nicht erneut berechnet, wenn die Krypto-Überwachung dieselbe Wallet bereits geprüft hat. Eine Transaktion unterhalb Ihres Schwellenwerts oder eine Transaktion, die aufgezeichnet wurde, während Travel Rule ausgeschaltet war, wird stattdessen als Transaction Screening abgerechnet. Eingehende Transaktionen, wie die Teilstrecken, die Didit auf der Seite des Begünstigten erzeugt, werden nicht mit der Travel-Rule-Gebühr belegt.
Nein. Eine travelRule-Transaktion wird über eine einzige Position abgerechnet: Die Travel-Rule-Gebühr ($0.02) fällt an, wenn sie einen ausgehenden Austausch startet, andernfalls das Standard-Transaction-Screening. Die Abfrage der Blockchain-Analyse wird einmalig berechnet. Hat die Krypto-Überwachung die Ziel-Wallet der Transaktion bereits geprüft, verwendet die Zuordnung dieses gespeicherte Ergebnis ohne zusätzliche Kosten. Eingehende Teilstrecken, die Didit auf der Seite des Begünstigten erzeugt, werden niemals mit der Travel-Rule-Gebühr belastet.
Ja. Die KYT- und Transaktionsüberwachung, das AML- und Sanktions-Screening, die Wallet-Risikobewertung über Blockchain-Analyse und die Travel-Rule-Funktionen von Didit sind alle öffentlich auf docs.didit.me dokumentiert. Sie dürfen diese Seiten in einer aufsichtsrechtlichen Akte zitieren. Für eine formelle Produktfähigkeitsbeschreibung, die auf eine bestimmte Einreichung zugeschnitten ist, etwa einen Antrag auf VASP-Lizenzierung bei AIFC/AFSA, einen Antrag nach MiCA oder einen anderen Antrag auf VASP-Lizenzierung, wenden Sie sich an Ihr Didit-Kundenteam und nennen Sie das Format, das Ihre Aufsichtsbehörde verlangt.

Betrieb und Daten

Sie werden sofort auf NOT_APPLICABLE gesetzt: Es wird keine Schiene verwendet, und keine Identitätsdaten verlassen Didit. Die Transaktion wird als normales Transaction Screening abgerechnet, nicht mit der Travel-Rule-Gebühr. Didit vergleicht den Schwellenwert mit dem Betrag, der in die Standardwährung Ihrer Anwendung umgerechnet wurde. Kann Didit den Betrag nicht umrechnen, wird der Schwellenwert nicht angewendet, und der Austausch findet statt. Die EU-TFR kennt keinen Mindestbetrag, daher sollten EU-CASPs threshold_amount auf 0.00 belassen.
Der Transfer bleibt in AWAITING_COUNTERPARTY, bis confirmation_timeout_hours abgelaufen ist. Danach verschiebt ein Sweeper-Prozess ihn nach EXPIRED und wendet Ihr timeout_outcome auf die zugrunde liegende Transaktion an: HOLD zur Prüfung, REJECT zur Ablehnung oder PROCEED, um sie unverändert zu lassen. Die Preset-Regel tr_eu_expired_review meldet zusätzlich jeden Ablauf an Ihre Analysten. Ein Fall, in dem die Gegenpartei die Nachricht gar nicht erst entgegennimmt, ist anders: Didit wiederholt die Zustellung, und nach dem sechsten fehlgeschlagenen Versuch wechselt der Transfer zu COUNTERPARTY_VASP_NOT_REACHABLE (siehe Zustellung und Wiederholungsversuche).
Ja - dafür gibt es die EMAIL-Schiene. Der Compliance-Kontakt der Gegenpartei erhält einen einmaligen Abholungslink und kann den Austausch über eine gehostete Seite bestätigen oder ablehnen, ohne Didit-Konto, ohne API-Schlüssel und ohne Integration. Für Einzahlungen, die bereits abgewickelt wurden, bevor ein Austausch möglich war, nutzen Sie die nachträgliche Sunrise-Registrierung.
Geben Sie das Ziel als selbstverwahrte Wallet an (payment_method.method_type: "unhosted_wallet"). Didit überspringt das VASP-Routing und erhebt stattdessen einen Nachweis, dass Ihr Kunde die Wallet kontrolliert: Nachrichtensignatur, Satoshi-Test, Screenshot oder Selbstauskunft, über das Wallet-Ownership-Widget. Das ist die EU-TFR-Pflicht für selbstverwahrte Wallets in API-Form.
Ja. Bis die Wallet-Inhaberschaft auf Ihrer Seite bestätigt ist, werden die personenbezogenen Daten der Gegenpartei bei einem eingehenden Transfer maskiert, sowohl im Transfer-Objekt als auch im Gegenparteiobjekt der Transaktion (siehe Maskierte Gegenparteidaten). Seiten zur E-Mail-Abholung zeigen nur die Transferzusammenfassung (Name des sendenden VASP, Betrag, Ziel-Wallet), niemals die Payloads mit personenbezogenen Daten. Austausche über die Schienen laufen über HTTPS, und die Netzwerk-Schienen (GTR, TRUST, VERIFYVASP, SYGNA) verschlüsseln den IVMS-Payload zusätzlich mit dem öffentlichen Schlüssel des empfangenden VASP.
Ja. Wenn Travel Rule deaktiviert ist, wird jedes travel_rule_details, das Sie übermitteln (einschließlich eines vom Aufrufer angegebenen status, aktuell oder veraltet), passiv in der Transaktion gespeichert. Es wird keine Schiene ausgelöst, und nichts wird ausgehandelt. Nutzen Sie das, um Daten nachzutragen oder Ihren eigenen Prozess weiterzuführen, während Sie ein einziges Referenzsystem behalten.
Verwenden Sie eine Sandbox-Anwendung mit aktivierter Travel Rule. Die Sandbox überspringt Regeln, Abrechnung und die Webhooks transaction.created und transaction.status.updated. Jeder ausgehende Austausch geht über die Schiene TEST_VASP an den Didit Test VASP. Dieser antwortet innerhalb von Didit mit dem Szenario, das Sie wählen: Annahme, Ablehnung, Namensabweichung, nicht erreichbar, Zeitüberschreitung oder selbstverwahrt. Sie erhalten travel_rule.status.updated-Webhooks, die mit environment: sandbox gekennzeichnet sind, und keine Nachricht erreicht eine echte Gegenpartei. Für eingehende Transfers lassen Sie den Test-VASP mit Trigger Test VASP Inbound Transfer einen Transfer an Sie senden oder registrieren einen mit POST /v3/travel-rule/inbound/. Beide werden anhand Ihres Wallet-Adressbuchs entschieden: ON_HOLD, UNCONFIRMED_OWNERSHIP, COUNTERPARTY_MISMATCHED_DATA oder COMPLETED, danach FINISHED. Für einen Austausch mit einer anderen echten Anwendung verwenden Sie zwei Ihrer eigenen Live-Anwendungen über die Schiene INTERNAL. Die empfangende Anwendung muss auffindbar sein und die Kontrolle über die Ziel-Wallet mit einer signierten Nachricht oder einer Testeinzahlung nachweisen.

Nächste Schritte

Wallet-Ownership-Widget

Weisen Sie nach, dass ein Kunde eine Wallet kontrolliert: durch Signatur, Satoshi-Test, Screenshot oder Selbstauskunft.

Interoperabilität

Die Endpoints für Gegenparteien, über die andere VASPs Sie erreichen: TRP, Callbacks, E-Mail-Abholung, Sunrise.

Netzwerke

Was jede Schiene und jedes Netzwerk heute erreicht und was noch auf eine Mitgliedschaft wartet.

In der Sandbox testen

Testen Sie jedes Ergebnis vor dem Go-live mit dem Didit Test VASP.

Transaktionen übermitteln

So nehmen Sie Travel-Rule-Daten in die Create-Transaction-Payload auf.

Regelbibliothek

Der vollständige Katalog der Preset-Regeln, einschließlich des Travel-Rule-Bundles.

Webhooks

Abonnieren Sie travel_rule.status.updated und alle anderen Ereignisfamilien.

Konsolenhandbuch

Anzeige des Travel-Rule-Status in der Transaktionsdetailansicht.
Zuletzt geändert am 7. November 2026